UNPKG

@vectorchat/mcp-server

Version:

VectorChat MCP Server - Encrypted AI-to-AI communication with hardware security (YubiKey/TPM). 45+ MCP tools for Windsurf, Claude, and AI assistants. Model-based identity with EMDM encryption. Dynamic AI playbook system, communication zones, message relay

877 lines (754 loc) • 31.6 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Security - VectorChat Web</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%); --primary-color: #667eea; --secondary-color: #764ba2; --success-color: #4caf50; --warning-color: #ff9800; --error-color: #f44336; --surface-color: #ffffff; --background-color: #f5f5f5; --text-primary: #333333; --text-secondary: #666666; --border-color: #e0e0e0; --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--background-color); color: var(--text-primary); line-height: 1.6; padding: 20px; } .container { max-width: 800px; margin: 0 auto; background: var(--surface-color); border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; } .header { background: var(--primary-gradient); color: white; padding: 24px; text-align: center; } .header h1 { font-size: 1.8rem; font-weight: 600; margin-bottom: 8px; } .header p { opacity: 0.9; font-size: 1rem; } .content { padding: 24px; } .security-card { background: #f8f9fa; border: 1px solid var(--border-color); border-radius: 8px; padding: 20px; margin-bottom: 24px; } .security-card.secure { border-color: var(--success-color); background: rgba(76, 175, 80, 0.05); } .security-card.warning { border-color: var(--warning-color); background: rgba(255, 152, 0, 0.05); } .security-card-title { font-size: 1.2rem; font-weight: 600; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; } .security-status { display: inline-flex; align-items: center; gap: 6px; font-size: 0.9rem; padding: 4px 12px; border-radius: 16px; font-weight: 500; } .status-secure { background: rgba(76, 175, 80, 0.1); color: var(--success-color); } .status-warning { background: rgba(255, 152, 0, 0.1); color: var(--warning-color); } .status-error { background: rgba(244, 67, 54, 0.1); color: var(--error-color); } .security-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-top: 16px; } .security-item { padding: 12px; background: white; border-radius: 6px; border: 1px solid #e0e0e0; } .security-label { font-size: 0.85rem; color: var(--text-secondary); margin-bottom: 4px; } .security-value { font-size: 1rem; font-weight: 600; font-family: monospace; } .control-section { background: #f8f9fa; border: 1px solid var(--border-color); border-radius: 8px; padding: 20px; margin-bottom: 24px; } .control-section-title { font-size: 1.2rem; font-weight: 600; margin-bottom: 16px; color: var(--text-primary); } .control-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; } .control-button { padding: 12px 16px; border: none; border-radius: 8px; cursor: pointer; font-weight: 500; transition: all 0.3s ease; display: flex; align-items: center; gap: 8px; justify-content: center; } .control-button:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .control-button:disabled { opacity: 0.5; cursor: not-allowed; } .control-secure { background: var(--success-color); color: white; } .control-warning { background: var(--warning-color); color: white; } .control-danger { background: var(--error-color); color: white; } .actions { padding: 24px; border-top: 1px solid var(--border-color); display: flex; gap: 12px; justify-content: space-between; } .btn { padding: 12px 24px; border: none; border-radius: 8px; cursor: pointer; font-weight: 500; transition: all 0.3s ease; font-size: 1rem; display: flex; align-items: center; gap: 8px; } .btn-primary { background: var(--primary-gradient); color: white; } .btn-secondary { background: #f5f5f5; color: var(--text-primary); border: 1px solid var(--border-color); } @media (max-width: 768px) { .security-details { grid-template-columns: 1fr; } .control-grid { grid-template-columns: 1fr; } .actions { flex-direction: column; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>šŸ›”ļø Security Center</h1> <p>Monitor and manage VectorChat security features</p> </div> <div class="content"> <!-- EMDM Status --> <div class="security-card secure" id="emdmCard"> <div class="security-card-title"> šŸ” EMDM Encryption <span class="security-status status-secure"> <span class="status-dot"></span> Active </span> </div> <div class="security-details"> <div class="security-item"> <div class="security-label">Key Space</div> <div class="security-value" id="keySpace">496T</div> </div> <div class="security-item"> <div class="security-label">Model Fingerprint</div> <div class="security-value" id="modelFingerprint">Qwen3-1.7B</div> </div> <div class="security-item"> <div class="security-label">Encryption Level</div> <div class="security-value" id="encryptionLevel">Military Grade</div> </div> <div class="security-item"> <div class="security-label">Active Sessions</div> <div class="security-value" id="activeSessions">0</div> </div> </div> </div> <!-- Identity Status --> <div class="security-card secure" id="identityCard"> <div class="security-card-title"> šŸ†” Identity Verification <span class="security-status status-secure"> <span class="status-dot"></span> Verified </span> </div> <div class="security-details"> <div class="security-item"> <div class="security-label">Current Identity</div> <div class="security-value" id="currentIdentity">Not set</div> </div> <div class="security-item"> <div class="security-label">Identity Hash</div> <div class="security-value" id="identityHash">Not generated</div> </div> <div class="security-item"> <div class="security-label">Verification Status</div> <div class="security-value" id="verificationStatus">Valid</div> </div> <div class="security-item"> <div class="security-label">Biometric Auth</div> <div class="security-value" id="biometricStatus">Disabled</div> </div> </div> </div> <!-- Network Security --> <div class="security-card warning" id="networkCard"> <div class="security-card-title"> 🌐 Network Security <span class="security-status status-warning"> <span class="status-dot"></span> Monitor </span> </div> <div class="security-details"> <div class="security-item"> <div class="security-label">Connected Peers</div> <div class="security-value" id="connectedPeers">0</div> </div> <div class="security-item"> <div class="security-label">IPFS Status</div> <div class="security-value" id="ipfsStatus">Offline</div> </div> <div class="security-item"> <div class="security-label">WebSocket Security</div> <div class="security-value" id="websocketSecurity">Active</div> </div> <div class="security-item"> <div class="security-label">Last Security Check</div> <div class="security-value" id="lastSecurityCheck">Never</div> </div> </div> </div> <!-- Security Controls --> <div class="control-section"> <div class="control-section-title">⚔ Security Operations</div> <div class="control-grid"> <button class="control-button control-secure" onclick="runSecurityScan()"> šŸ” Security Scan </button> <button class="control-button control-warning" onclick="regenerateKeys()"> šŸ”„ Regenerate Keys </button> <button class="control-button control-info" onclick="validateIdentity()"> āœ… Validate Identity </button> <button class="control-button control-danger" onclick="emergencyLockdown()"> 🚨 Emergency Lock </button> </div> </div> <!-- Threat Detection --> <div class="control-section"> <div class="control-section-title">šŸ›”ļø Threat Detection</div> <div class="control-grid"> <button class="control-button control-info" onclick="checkForThreats()"> šŸ”Ž Check Threats </button> <button class="control-button control-warning" onclick="reviewLogs()"> šŸ“‹ Review Logs </button> <button class="control-button control-info" onclick="updateSecurity()"> šŸ”„ Update Security </button> <button class="control-button control-danger" onclick="reportIncident()"> 🚨 Report Incident </button> </div> </div> </div> <div class="actions"> <button class="btn btn-secondary" onclick="goBack()">← Back</button> <div> <button class="btn btn-secondary" onclick="refreshSecurity()">šŸ”„ Refresh</button> <button class="btn btn-primary" onclick="openAdvancedSecurity()">āš™ļø Advanced</button> </div> </div> </div> <script> // Initialize document.addEventListener('DOMContentLoaded', function() { refreshSecurityStatus(); startSecurityUpdates(); }); async function refreshSecurityStatus() { try { // Check daemon status const healthResponse = await fetch('http://localhost:3737/health'); const isDaemonOnline = healthResponse.ok; if (isDaemonOnline) { // Get detailed security status const statusResponse = await fetch('http://localhost:3737/api/status'); const statusData = await statusResponse.json(); // Update EMDM status updateSecurityCard('emdmCard', statusData.emdm_active ? 'secure' : 'warning', statusData.emdm_active ? 'Active' : 'Inactive'); if (statusData.emdm_active) { document.getElementById('keySpace').textContent = '496T'; document.getElementById('encryptionLevel').textContent = 'Military Grade'; document.getElementById('activeSessions').textContent = statusData.active_sessions || 0; } // Update model info if (statusData.model_status) { document.getElementById('modelFingerprint').textContent = statusData.model || 'Unknown'; } // Update identity info const identity = localStorage.getItem('vectorchat-identity'); if (identity) { try { const identityData = JSON.parse(identity); document.getElementById('currentIdentity').textContent = identityData.username || 'Not set'; document.getElementById('identityHash').textContent = generateIdentityHash(identityData.username, identityData.modelPath); } catch (e) { console.error('Error loading identity:', e); } } // Update network status updateSecurityCard('networkCard', 'warning', 'Monitor'); document.getElementById('connectedPeers').textContent = statusData.known_peers || 0; document.getElementById('websocketSecurity').textContent = statusData.transport === 'WebSocket' ? 'Active' : 'Inactive'; } else { // Daemon offline updateSecurityCard('emdmCard', 'warning', 'Offline'); updateSecurityCard('identityCard', 'warning', 'Offline'); updateSecurityCard('networkCard', 'warning', 'Offline'); } document.getElementById('lastSecurityCheck').textContent = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}); } catch (error) { console.error('Error refreshing security status:', error); updateSecurityCard('emdmCard', 'warning', 'Error'); updateSecurityCard('identityCard', 'warning', 'Error'); updateSecurityCard('networkCard', 'warning', 'Error'); } } function updateSecurityCard(cardId, className, statusText) { const card = document.getElementById(cardId); const statusElement = card.querySelector('.security-status'); // Remove existing classes card.className = `security-card ${className}`; statusElement.className = `security-status status-${className}`; statusElement.querySelector('.status-dot').textContent = statusText; } function generateIdentityHash(username, modelPath) { if (!username || !modelPath) return 'Not generated'; const input = `${username}-${modelPath}-${Date.now()}`; let hash = 0; for (let i = 0; i < input.length; i++) { const char = input.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } return Math.abs(hash).toString(36).substring(0, 12).toUpperCase(); } async function runSecurityScan() { showNotification('Running security scan...', 'info'); try { // Run comprehensive security checks const checks = [ checkEMDMIntegrity(), checkIdentityValidity(), checkNetworkSecurity(), checkModelIntegrity() ]; const results = await Promise.allSettled(checks); let allPassed = true; results.forEach((result, index) => { if (result.status === 'rejected') { allPassed = false; showNotification(`Security check ${index + 1} failed: ${result.reason}`, 'error'); } }); if (allPassed) { showNotification('Security scan completed - All systems secure!', 'success'); } else { showNotification('Security scan completed - Issues detected', 'warning'); } // Refresh status setTimeout(refreshSecurityStatus, 1000); } catch (error) { showNotification(`Security scan failed: ${error.message}`, 'error'); } } async function checkEMDMIntegrity() { const response = await fetch('http://localhost:3737/api/status'); const data = await response.json(); if (!data.emdm_active) { throw new Error('EMDM encryption is not active'); } if (!data.model_status || data.model_status.status !== 'loaded') { throw new Error('AI model is not properly loaded'); } return true; } async function checkIdentityValidity() { const identity = localStorage.getItem('vectorchat-identity'); if (!identity) { throw new Error('No identity configured'); } try { const identityData = JSON.parse(identity); if (!identityData.username || !identityData.modelPath) { throw new Error('Identity is incomplete'); } } catch (e) { throw new Error('Identity data is corrupted'); } return true; } async function checkNetworkSecurity() { // Check for suspicious connections or unusual activity const response = await fetch('http://localhost:3737/api/status'); const data = await response.json(); if (data.known_peers > 10) { throw new Error('Unusually high number of connected peers'); } return true; } async function checkModelIntegrity() { // Verify model fingerprint matches expected const response = await fetch('http://localhost:3737/api/status'); const data = await response.json(); if (!data.model) { throw new Error('No model information available'); } return true; } async function regenerateKeys() { if (!confirm('Regenerate encryption keys? This will invalidate all existing encrypted data.')) { return; } try { const response = await fetch('http://localhost:3737/api/regenerate-keys', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ confirm: true }) }); if (response.ok) { showNotification('Encryption keys regenerated!', 'success'); // Refresh status setTimeout(refreshSecurityStatus, 1000); } else { throw new Error(`HTTP ${response.status}`); } } catch (error) { showNotification(`Failed to regenerate keys: ${error.message}`, 'error'); } } async function validateIdentity() { showNotification('Validating identity...', 'info'); try { const identity = localStorage.getItem('vectorchat-identity'); if (!identity) { throw new Error('No identity found'); } const identityData = JSON.parse(identity); // Validate against daemon const response = await fetch('http://localhost:3737/api/status'); const data = await response.json(); if (data.model_status && data.model) { // Check if model matches if (identityData.modelPath.includes(data.model)) { showNotification('Identity validation successful!', 'success'); } else { showNotification('Identity model mismatch detected', 'warning'); } } else { showNotification('Cannot validate identity - daemon offline', 'warning'); } } catch (error) { showNotification(`Identity validation failed: ${error.message}`, 'error'); } } async function emergencyLockdown() { if (!confirm('EMERGENCY: Activate security lockdown? This will disconnect all users and require manual restart.')) { return; } try { // Emergency stop const response = await fetch('http://localhost:3737/api/stop-daemon', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ confirm: true, reason: 'Emergency security lockdown' }) }); if (response.ok) { showNotification('🚨 EMERGENCY LOCKDOWN ACTIVATED', 'error'); addLogEntry('Emergency lockdown activated', 'error'); // Update UI updateSecurityCard('emdmCard', 'warning', 'Locked'); updateSecurityCard('networkCard', 'warning', 'Locked'); // Disable controls document.querySelectorAll('.control-button').forEach(btn => { btn.disabled = true; btn.textContent = 'šŸ”’ LOCKED'; }); } else { throw new Error(`HTTP ${response.status}`); } } catch (error) { showNotification(`Emergency lockdown failed: ${error.message}`, 'error'); } } async function checkForThreats() { showNotification('Scanning for threats...', 'info'); try { // Run threat detection const response = await fetch('http://localhost:3737/api/status'); const data = await response.json(); // Check for suspicious patterns const threats = []; if (data.known_peers > 5) { threats.push('High peer count detected'); } if (data.active_sessions > 10) { threats.push('Unusual session activity'); } if (threats.length === 0) { showNotification('No threats detected', 'success'); } else { showNotification(`Threats detected: ${threats.join(', ')}`, 'warning'); } } catch (error) { showNotification(`Threat scan failed: ${error.message}`, 'error'); } } async function reviewLogs() { try { const response = await fetch('http://localhost:3737/api/get-logs', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ count: 50 }) }); if (response.ok) { const logs = await response.json(); alert(`Recent logs (${logs.logs.length} entries):\n\n${logs.logs.join('\n')}`); } else { throw new Error(`HTTP ${response.status}`); } } catch (error) { showNotification(`Failed to retrieve logs: ${error.message}`, 'error'); } } async function updateSecurity() { showNotification('Updating security systems...', 'info'); try { // Trigger security update const response = await fetch('http://localhost:3737/api/reload-config', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ confirm: true }) }); if (response.ok) { showNotification('Security systems updated!', 'success'); // Refresh status setTimeout(refreshSecurityStatus, 1000); } else { throw new Error(`HTTP ${response.status}`); } } catch (error) { showNotification(`Security update failed: ${error.message}`, 'error'); } } async function reportIncident() { const incidentType = prompt('Enter incident type (e.g., "Suspicious connection", "Data breach attempt", "Unauthorized access"):'); if (incidentType) { try { // Report to daemon const response = await fetch('http://localhost:3737/api/report-incident', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ incident_type: incidentType, timestamp: new Date().toISOString(), details: 'Reported via web interface' }) }); if (response.ok) { showNotification('Incident reported to security system!', 'warning'); addLogEntry(`Security incident reported: ${incidentType}`, 'warning'); } else { throw new Error(`HTTP ${response.status}`); } } catch (error) { showNotification(`Failed to report incident: ${error.message}`, 'error'); } } } function openAdvancedSecurity() { alert('Advanced security features:\n\n• AI-powered threat detection\n• Behavioral analysis\n• Network anomaly detection\n• Automated response systems\n\nContact support for enterprise security features.'); } function goBack() { if (window.opener) { window.close(); } else { window.location.href = 'web-app.html'; } } function startSecurityUpdates() { // Update security status every 10 seconds setInterval(refreshSecurityStatus, 10000); } function addLogEntry(message, level = 'info') { console.log(`[${level.toUpperCase()}] ${message}`); } function showNotification(message, type = 'info') { // Create notification element const notification = document.createElement('div'); notification.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 12px 20px; border-radius: 8px; color: white; font-weight: 500; z-index: 3000; opacity: 0; transform: translateX(100%); transition: all 0.3s ease; max-width: 400px; `; let backgroundColor; switch (type) { case 'error': backgroundColor = '#f44336'; break; case 'success': backgroundColor = '#4caf50'; break; case 'warning': backgroundColor = '#ff9800'; break; default: backgroundColor = '#667eea'; } notification.style.backgroundColor = backgroundColor; notification.textContent = message; document.body.appendChild(notification); // Animate in setTimeout(() => { notification.style.opacity = '1'; notification.style.transform = 'translateX(0)'; }, 100); // Animate out and remove setTimeout(() => { notification.style.opacity = '0'; notification.style.transform = 'translateX(100%)'; setTimeout(() => { document.body.removeChild(notification); }, 300); }, 3000); } // Initial status update setTimeout(refreshSecurityStatus, 1000); </script> </body> </html>