diff --git a/dashboard/README.md b/dashboard/README.md new file mode 100644 index 0000000..facd7a7 --- /dev/null +++ b/dashboard/README.md @@ -0,0 +1,316 @@ +# Multi-Agent Agentic Infrastructure Control Platform - Dashboard + +A comprehensive HTML dashboard for monitoring and managing the Multi-Agent Agentic Infrastructure Control Platform. + +## 🎯 Overview + +This interactive dashboard provides real-time monitoring, control, and visualization capabilities for a multi-agent infrastructure management system. Built with pure HTML5, CSS3, and JavaScript - no build process required. + +## ✨ Features + +### Main Dashboard (`index.html`) +- **Platform Overview**: Real-time status of the entire platform +- **Agent Status Panel**: Monitor all 4 agents (Policy, Intent, Deployment, Compliance) +- **Blast Radius Visualization**: Interactive charts showing deployment impact +- **Multi-Region Map**: Global infrastructure health visualization +- **Policy Enforcement**: Active policies and violation tracking +- **Cost Optimization**: Bandwidth, compute, storage, and cost metrics +- **Activity Feed**: Real-time updates on system activities + +### Policy Management (`policies.html`) +- View all active policies with OPA rules +- Policy statistics and enforcement metrics +- Search and filter policies +- Policy simulation capabilities +- Violation tracking + +### Script Library (`scripts.html`) +- Browse 150+ automation scripts +- Category-based filtering (Automation, Security, Monitoring, etc.) +- Multi-cloud support (AWS, Azure, GCP) +- Script ratings and download counts +- Adapter marketplace + +### Compliance Reports (`compliance.html`) +- Overall compliance score dashboard +- Framework compliance (SOC 2, HIPAA, PCI DSS) +- Audit trail viewer with search +- Compliance markers for key resources +- Trend analysis charts +- Export to PDF/CSV + +### Settings (`settings.html`) +- General platform configuration +- Agent-specific settings +- API endpoint configuration +- Cloud provider credentials (AWS, Azure, GCP) +- Notification preferences (Email, Slack, PagerDuty) + +## 🎨 Design + +### Color Scheme +- **Primary Purple**: `#5B4B8A`, `#7B68A6` +- **Dark Background**: `#2E2547` +- **Accent Orange**: `#FF6B35` +- **Success Green**: `#4CAF50` +- **Status Colors**: Warning (`#FFA726`), Error (`#EF5350`), Info (`#42A5F5`) + +### Visual Elements +- Lion logo with purple/orange gradient +- Modern card-based layout +- Responsive grid system +- Smooth animations and transitions +- Interactive charts via Chart.js + +## 🚀 Getting Started + +### Prerequisites +- Modern web browser (Chrome, Firefox, Safari, Edge) +- Web server (optional, for best experience) + +### Installation + +1. **Clone or download the repository** + ```bash + cd dashboard + ``` + +2. **Open in browser** + - **Option 1**: Open `index.html` directly in your browser + - **Option 2**: Use a local web server (recommended): + ```bash + # Python 3 + python -m http.server 8000 + + # Node.js + npx serve + ``` + - Navigate to `http://localhost:8000` + +### No Build Process Required +The dashboard uses CDN-hosted libraries: +- Chart.js (v4.4.0) for data visualization +- Font Awesome (v6.4.0) for icons + +## 📁 File Structure + +``` +/dashboard +├── index.html # Main dashboard +├── policies.html # Policy management +├── scripts.html # Script library +├── compliance.html # Compliance reports +├── settings.html # Settings page +├── css/ +│ ├── main.css # Main stylesheet with purple theme +│ ├── dashboard.css # Dashboard-specific styles +│ └── responsive.css # Mobile responsive styles +├── js/ +│ ├── dashboard.js # Main dashboard logic +│ ├── agents.js # Agent management +│ ├── charts.js # Chart configurations +│ ├── api.js # API integration layer +│ └── websocket.js # Real-time updates simulation +├── assets/ +│ ├── logo.svg # Lion logo +│ └── icons/ # (using Font Awesome) +├── data/ +│ └── mock-data.json # Mock data for demonstration +└── README.md # This file +``` + +## 🔌 API Integration + +### Mock Mode (Default) +The dashboard runs in mock mode by default, using `data/mock-data.json` for demonstration. + +### Connecting to Real API + +1. **Update API Configuration** in `js/api.js`: + ```javascript + constructor() { + this.baseUrl = 'https://your-api-endpoint.com/api'; + this.mockMode = false; // Disable mock mode + } + ``` + +2. **Configure WebSocket** in `js/websocket.js`: + ```javascript + connect(url = 'wss://your-websocket-endpoint.com') { + this.simulationMode = false; // Disable simulation + // ... rest of the code + } + ``` + +### API Endpoints Expected + +``` +GET /api/platform/status # Platform status +GET /api/agents # All agents +GET /api/agents/:id # Specific agent +POST /api/agents/:id/start # Start agent +POST /api/agents/:id/stop # Stop agent +GET /api/activities # Activity feed +GET /api/policies # All policies +GET /api/metrics # Metrics data +GET /api/regions # Region data +GET /api/blast-radius # Blast radius data +``` + +### WebSocket Events + +```javascript +// Agent status update +{ + type: 'agent_status', + payload: { + agentId: 'policy', + status: 'active', + timestamp: '2024-02-15T07:30:00Z' + } +} + +// New activity +{ + type: 'activity', + payload: { + type: 'policy', + title: 'Policy Check Completed', + description: 'All policies validated', + time: 'just now' + } +} + +// Metric update +{ + type: 'metric_update', + payload: { + type: 'system_health', + value: 98, + timestamp: '2024-02-15T07:30:00Z' + } +} +``` + +## 📱 Responsive Design + +The dashboard is fully responsive and works on: +- **Desktop**: Full feature set with side navigation +- **Tablet**: Optimized grid layouts +- **Mobile**: Collapsed navigation, stacked layouts + +Breakpoints: +- Desktop: > 1024px +- Tablet: 768px - 1024px +- Mobile: < 768px + +## 🔄 Real-Time Updates + +### Auto-Refresh +- Dashboard data refreshes every 30 seconds +- Agent metrics update every 5 seconds +- WebSocket provides instant updates (when connected) + +### Manual Refresh +Click the refresh button in the header to manually update all data. + +## 🎯 Features in Detail + +### Agent Management +- Start/stop individual agents +- View real-time metrics +- Monitor processing queues +- Track success rates + +### Policy Enforcement +- Search policies +- View OPA rules +- Simulate policy execution +- Track violations + +### Blast Radius Analysis +- Visual impact prediction +- Affected resources count +- Risk level indicators +- Approval workflow + +### Cost Optimization +- Bandwidth savings tracking +- Compute efficiency metrics +- Storage utilization +- Cost trend analysis + +## 🔧 Customization + +### Changing Colors +Edit `css/main.css`: +```css +:root { + --primary-purple: #5B4B8A; + --accent-orange: #FF6B35; + /* ... modify as needed */ +} +``` + +### Adding New Metrics +1. Add chart configuration in `js/charts.js` +2. Update mock data in `data/mock-data.json` +3. Add chart canvas in HTML +4. Initialize in dashboard + +### Custom Agents +Add new agent cards to `index.html` and update `data/mock-data.json` with agent configuration. + +## 🐛 Troubleshooting + +### Charts Not Displaying +- Ensure Chart.js CDN is accessible +- Check browser console for errors +- Verify canvas elements have valid IDs + +### WebSocket Not Connecting +- Simulation mode is enabled by default +- Check `simulationMode` in `js/websocket.js` +- Verify WebSocket URL if using real connection + +### Mock Data Not Loading +- Ensure `data/mock-data.json` exists +- Check file path is correct +- Verify JSON is valid + +## 📊 Browser Support + +- Chrome/Edge: Latest 2 versions +- Firefox: Latest 2 versions +- Safari: Latest 2 versions +- Mobile browsers: iOS Safari, Chrome Android + +## 🔒 Security Notes + +- Never commit real API keys or credentials +- Use environment variables for sensitive data +- Implement proper authentication in production +- Enable HTTPS for all API connections +- Sanitize user inputs + +## 📝 License + +This dashboard is part of the Multi-Agent Infrastructure Control Platform project. + +## 🤝 Contributing + +To contribute: +1. Follow existing code style +2. Test on multiple browsers +3. Ensure responsive design works +4. Update documentation as needed + +## 📧 Support + +For issues or questions, please refer to the main project repository. + +## 🎉 Acknowledgments + +- Chart.js for beautiful data visualization +- Font Awesome for comprehensive icon library +- Modern web standards for making this possible without a build process diff --git a/dashboard/assets/logo.svg b/dashboard/assets/logo.svg new file mode 100644 index 0000000..1066b68 --- /dev/null +++ b/dashboard/assets/logo.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard/compliance.html b/dashboard/compliance.html new file mode 100644 index 0000000..260e581 --- /dev/null +++ b/dashboard/compliance.html @@ -0,0 +1,633 @@ + + + + + + Compliance Reports - Multi-Agent Platform + + + + + + + + + + + +
+ + + +
+
+
+
+ +
+
+

Overall Score

+
96%
+

compliance rating

+
+
+
+
+ +
+
+

Audit Events

+
1,234
+

logged this month

+
+
+
+
+ +
+
+

Markers

+
45
+

active compliance points

+
+
+
+
+ +
+
+

Issues

+
11
+

require attention

+
+
+
+
+ + +
+

+ Compliance Frameworks +

+
+
+
+

SOC 2

+
98%
+
+
+
+
+
+
+
+
+ Controls + 156 +
+
+ Passed + 153 +
+
+ Failed + 3 +
+
+
+ +
+
+

HIPAA

+
95%
+
+
+
+
+
+
+
+
+ Controls + 89 +
+
+ Passed + 85 +
+
+ Failed + 4 +
+
+
+ +
+
+

PCI DSS

+
94%
+
+
+
+
+
+
+
+
+ Controls + 67 +
+
+ Passed + 63 +
+
+ Failed + 4 +
+
+
+
+
+ + + + + +
+

+ Recent Audit Events +

+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TimestampEvent TypeResourceUserStatusActions
2024-02-15 07:30:00Configuration Changes3://production-dataadmin@example.comCompliant
2024-02-15 07:25:00Access Eventrds://prod-dbuser@example.comCompliant
2024-02-15 07:20:00Policy Violationec2://i-1234567service-accountWarning
2024-02-15 07:15:00Configuration Changeiam://role/adminadmin@example.comCompliant
2024-02-15 07:10:00Access Events3://backup-storagebackup-serviceCompliant
+
+
+
+ + +
+

+ Compliance Markers +

+
+
+
+ +
+
+

Encryption at Rest

+

s3://production-data

+

Last checked: 2 minutes ago

+
+ Compliant +
+ +
+
+ +
+
+

Automated Backups

+

rds://prod-db

+

Last checked: 5 minutes ago

+
+ Compliant +
+ +
+
+ +
+
+

Access Logging

+

lb://production-lb

+

Last checked: 10 minutes ago

+
+ Warning +
+ +
+
+ +
+
+

Multi-Factor Auth

+

iam://root-account

+

Last checked: 1 hour ago

+
+ Compliant +
+
+
+
+ + + + + + diff --git a/dashboard/css/dashboard.css b/dashboard/css/dashboard.css new file mode 100644 index 0000000..b93a5e5 --- /dev/null +++ b/dashboard/css/dashboard.css @@ -0,0 +1,557 @@ +/* Dashboard Specific Styles */ + +/* Overview Section */ +.overview-section { + margin-bottom: 30px; +} + +.stat-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 20px; +} + +.stat-card { + background: linear-gradient(135deg, rgba(91, 75, 138, 0.3) 0%, rgba(46, 37, 71, 0.6) 100%); + border: 1px solid rgba(123, 104, 166, 0.3); + border-radius: 12px; + padding: 24px; + display: flex; + align-items: center; + gap: 20px; + transition: all 0.3s ease; +} + +.stat-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(123, 104, 166, 0.3); + border-color: var(--secondary-purple); +} + +.stat-icon { + width: 60px; + height: 60px; + background: linear-gradient(135deg, var(--accent-orange) 0%, #ff8555 100%); + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 28px; + color: var(--text-light); + flex-shrink: 0; +} + +.stat-content { + flex: 1; +} + +.stat-content h3 { + font-size: 14px; + color: var(--text-gray); + margin-bottom: 8px; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.stat-value { + font-size: 32px; + font-weight: 700; + color: var(--text-light); + margin-bottom: 4px; +} + +.stat-label { + font-size: 13px; + color: var(--text-gray); +} + +/* Agent Status Section */ +.agent-status-section { + margin-bottom: 30px; +} + +.agent-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 20px; +} + +.agent-card { + background: linear-gradient(145deg, rgba(91, 75, 138, 0.15) 0%, rgba(46, 37, 71, 0.4) 100%); + border: 1px solid rgba(123, 104, 166, 0.3); + border-radius: 12px; + padding: 20px; + transition: all 0.3s ease; +} + +.agent-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(123, 104, 166, 0.25); + border-color: var(--secondary-purple); +} + +.agent-header { + display: flex; + align-items: center; + gap: 15px; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 1px solid rgba(123, 104, 166, 0.2); +} + +.agent-icon { + width: 48px; + height: 48px; + background: linear-gradient(135deg, var(--primary-purple) 0%, var(--secondary-purple) 100%); + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 22px; + color: var(--text-light); +} + +.agent-info { + flex: 1; +} + +.agent-info h3 { + font-size: 18px; + margin-bottom: 4px; + color: var(--text-light); +} + +.agent-status { + display: inline-block; + padding: 2px 10px; + border-radius: 10px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; +} + +.agent-status.active { + background: rgba(76, 175, 80, 0.2); + color: var(--status-success); +} + +.agent-status.inactive { + background: rgba(239, 83, 80, 0.2); + color: var(--status-error); +} + +.agent-metrics { + display: flex; + flex-direction: column; + gap: 12px; +} + +.metric { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + background: rgba(91, 75, 138, 0.1); + border-radius: 8px; +} + +.metric-label { + font-size: 13px; + color: var(--text-gray); +} + +.metric-value { + font-size: 16px; + font-weight: 600; + color: var(--text-light); +} + +/* Two Column Layout */ +.two-column-layout { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); + gap: 20px; + margin-bottom: 30px; +} + +/* Blast Radius Section */ +.blast-radius-section { + margin-bottom: 30px; +} + +.blast-radius-header { + margin-bottom: 20px; +} + +.risk-indicator { + display: inline-flex; + flex-direction: column; + align-items: center; + padding: 15px 30px; + background: linear-gradient(135deg, rgba(255, 107, 53, 0.2) 0%, rgba(255, 107, 53, 0.1) 100%); + border: 2px solid var(--accent-orange); + border-radius: 12px; +} + +.risk-indicator.high { + border-color: var(--status-error); + background: linear-gradient(135deg, rgba(239, 83, 80, 0.2) 0%, rgba(239, 83, 80, 0.1) 100%); +} + +.risk-label { + font-size: 12px; + text-transform: uppercase; + color: var(--text-gray); + margin-bottom: 4px; +} + +.risk-value { + font-size: 20px; + font-weight: 700; + color: var(--accent-orange); +} + +.blast-radius-viz { + margin: 20px 0; + min-height: 250px; +} + +.blast-radius-stats { + display: flex; + justify-content: space-around; + margin: 20px 0; + padding: 20px 0; + border-top: 1px solid rgba(123, 104, 166, 0.2); + border-bottom: 1px solid rgba(123, 104, 166, 0.2); +} + +.blast-radius-stats .stat { + text-align: center; +} + +.blast-radius-stats .stat i { + font-size: 24px; + color: var(--accent-orange); + margin-bottom: 8px; + display: block; +} + +.stat-num { + display: block; + font-size: 28px; + font-weight: 700; + color: var(--text-light); + margin-bottom: 4px; +} + +.stat-text { + display: block; + font-size: 12px; + color: var(--text-gray); + text-transform: uppercase; +} + +.approval-workflow { + display: flex; + gap: 10px; + margin-top: 20px; +} + +.approval-workflow .btn { + flex: 1; +} + +/* Region Map Section */ +.region-map-section { + margin-bottom: 30px; +} + +.region-map { + position: relative; + width: 100%; + height: 300px; + background: linear-gradient(135deg, rgba(91, 75, 138, 0.1) 0%, rgba(46, 37, 71, 0.3) 100%); + border-radius: 12px; + margin-bottom: 20px; + overflow: hidden; +} + +.region { + position: absolute; + cursor: pointer; + transition: transform 0.3s ease; +} + +.region:hover { + transform: scale(1.1); + z-index: 10; +} + +.region-marker { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + color: var(--text-light); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + animation: regionPulse 2s infinite; +} + +.region-marker.healthy { + background: var(--status-success); +} + +.region-marker.warning { + background: var(--status-warning); +} + +.region-marker.error { + background: var(--status-error); +} + +@keyframes regionPulse { + 0%, 100% { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + } + 50% { + box-shadow: 0 4px 24px rgba(123, 104, 166, 0.6); + } +} + +.region-label { + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + margin-top: 8px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + white-space: nowrap; + color: var(--text-gray); +} + +.region-stats { + display: flex; + justify-content: center; + gap: 30px; +} + +.region-stat { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + color: var(--text-gray); +} + +/* Policy Section */ +.policy-section { + margin-bottom: 30px; +} + +.policy-header { + display: flex; + gap: 15px; + margin-bottom: 20px; +} + +.policy-list { + display: flex; + flex-direction: column; + gap: 12px; +} + +.policy-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + background: rgba(91, 75, 138, 0.1); + border: 1px solid rgba(123, 104, 166, 0.2); + border-radius: 8px; + transition: all 0.3s ease; +} + +.policy-item:hover { + background: rgba(91, 75, 138, 0.15); + border-color: var(--secondary-purple); +} + +.policy-info h4 { + font-size: 16px; + margin-bottom: 4px; + color: var(--text-light); +} + +.policy-info p { + font-size: 13px; + color: var(--text-gray); +} + +.policy-status { + display: flex; + align-items: center; + gap: 15px; +} + +.policy-count { + font-size: 13px; + color: var(--text-gray); +} + +/* Cost Section */ +.cost-section { + margin-bottom: 30px; +} + +.metrics-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 20px; +} + +.metric-card { + padding: 20px; +} + +.metric-card h3 { + font-size: 16px; + margin-bottom: 15px; + color: var(--text-light); +} + +.metric-card canvas { + max-height: 150px; +} + +.metric-footer { + margin-top: 15px; + padding-top: 15px; + border-top: 1px solid rgba(123, 104, 166, 0.2); + text-align: center; +} + +.trend-up { + color: var(--status-success); + font-weight: 600; + font-size: 14px; +} + +.trend-down { + color: var(--status-error); + font-weight: 600; + font-size: 14px; +} + +.trend-neutral { + color: var(--text-gray); + font-weight: 600; + font-size: 14px; +} + +/* Activity Section */ +.activity-section { + margin-bottom: 30px; +} + +.activity-filters { + display: flex; + gap: 10px; + margin-bottom: 20px; +} + +.filter-btn { + padding: 8px 16px; + background: rgba(91, 75, 138, 0.1); + border: 1px solid rgba(123, 104, 166, 0.2); + border-radius: 20px; + color: var(--text-gray); + font-size: 13px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; +} + +.filter-btn:hover { + background: rgba(91, 75, 138, 0.2); + color: var(--text-light); +} + +.filter-btn.active { + background: linear-gradient(135deg, var(--primary-purple) 0%, var(--secondary-purple) 100%); + color: var(--text-light); + border-color: var(--secondary-purple); +} + +.activity-feed { + max-height: 500px; + overflow-y: auto; +} + +.activity-item { + display: flex; + gap: 15px; + padding: 16px; + border-bottom: 1px solid rgba(123, 104, 166, 0.1); + transition: background 0.2s ease; +} + +.activity-item:last-child { + border-bottom: none; +} + +.activity-item:hover { + background: rgba(91, 75, 138, 0.05); +} + +.activity-icon { + width: 40px; + height: 40px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + flex-shrink: 0; +} + +.activity-icon.policy { + background: rgba(91, 75, 138, 0.3); + color: var(--secondary-purple); +} + +.activity-icon.deployment { + background: rgba(255, 107, 53, 0.2); + color: var(--accent-orange); +} + +.activity-icon.compliance { + background: rgba(76, 175, 80, 0.2); + color: var(--status-success); +} + +.activity-content { + flex: 1; +} + +.activity-title { + font-size: 14px; + font-weight: 600; + color: var(--text-light); + margin-bottom: 4px; +} + +.activity-description { + font-size: 13px; + color: var(--text-gray); + margin-bottom: 8px; +} + +.activity-time { + font-size: 12px; + color: var(--text-gray); +} diff --git a/dashboard/css/main.css b/dashboard/css/main.css new file mode 100644 index 0000000..2c06f9d --- /dev/null +++ b/dashboard/css/main.css @@ -0,0 +1,452 @@ +/* Main Stylesheet - Purple Theme */ +:root { + /* Color Palette */ + --primary-purple: #5B4B8A; + --secondary-purple: #7B68A6; + --dark-purple: #2E2547; + --accent-orange: #FF6B35; + --accent-green: #4CAF50; + --text-light: #FFFFFF; + --text-gray: #B8B8B8; + --text-dark: #1A1A1A; + + /* Status Colors */ + --status-success: #4CAF50; + --status-warning: #FFA726; + --status-error: #EF5350; + --status-info: #42A5F5; + + /* Shadows */ + --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.1); + --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.2); + --shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.3); + --shadow-xl: 0 12px 24px rgba(0, 0, 0, 0.4); + + /* Transitions */ + --transition-fast: 0.2s ease; + --transition-normal: 0.3s ease; + --transition-slow: 0.5s ease; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + background: var(--dark-purple); + color: var(--text-light); + line-height: 1.6; + display: flex; + min-height: 100vh; +} + +/* Sidebar Navigation */ +.sidebar { + width: 260px; + background: linear-gradient(180deg, #3a2e5a 0%, var(--dark-purple) 100%); + border-right: 1px solid rgba(123, 104, 166, 0.2); + display: flex; + flex-direction: column; + position: fixed; + height: 100vh; + overflow-y: auto; + z-index: 1000; +} + +.logo-container { + padding: 30px 20px; + text-align: center; + border-bottom: 1px solid rgba(123, 104, 166, 0.2); +} + +.logo { + width: 60px; + height: 60px; + margin-bottom: 10px; +} + +.logo-container h2 { + font-size: 16px; + font-weight: 600; + color: var(--text-light); + margin: 0; +} + +.nav-menu { + list-style: none; + padding: 20px 0; + flex: 1; +} + +.nav-item { + margin: 5px 0; +} + +.nav-item a { + display: flex; + align-items: center; + padding: 12px 20px; + color: var(--text-gray); + text-decoration: none; + transition: all var(--transition-fast); + border-left: 3px solid transparent; +} + +.nav-item a:hover { + background: rgba(123, 104, 166, 0.1); + color: var(--text-light); + border-left-color: var(--secondary-purple); +} + +.nav-item.active a { + background: rgba(123, 104, 166, 0.2); + color: var(--text-light); + border-left-color: var(--accent-orange); +} + +.nav-item i { + width: 24px; + margin-right: 12px; + font-size: 18px; +} + +.connection-status { + padding: 20px; + border-top: 1px solid rgba(123, 104, 166, 0.2); +} + +.status-indicator { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + color: var(--text-gray); +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--status-success); + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } +} + +/* Main Content */ +.main-content { + margin-left: 260px; + flex: 1; + padding: 30px; + overflow-y: auto; +} + +.page-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 30px; +} + +.page-header h1 { + font-size: 32px; + font-weight: 700; + background: linear-gradient(135deg, var(--text-light) 0%, var(--secondary-purple) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.header-actions { + display: flex; + align-items: center; + gap: 15px; +} + +.user-menu { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + background: rgba(123, 104, 166, 0.2); + border-radius: 20px; + cursor: pointer; + transition: background var(--transition-fast); +} + +.user-menu:hover { + background: rgba(123, 104, 166, 0.3); +} + +.user-menu i { + font-size: 20px; +} + +/* Buttons */ +.btn { + padding: 10px 20px; + border: none; + border-radius: 8px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all var(--transition-fast); + display: inline-flex; + align-items: center; + gap: 8px; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary-purple) 0%, var(--secondary-purple) 100%); + color: var(--text-light); + box-shadow: var(--shadow-sm); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); +} + +.btn-secondary { + background: rgba(123, 104, 166, 0.2); + color: var(--text-light); +} + +.btn-secondary:hover { + background: rgba(123, 104, 166, 0.3); +} + +.btn-success { + background: var(--status-success); + color: var(--text-light); +} + +.btn-success:hover { + background: #45a049; +} + +.btn-danger { + background: var(--status-error); + color: var(--text-light); +} + +.btn-danger:hover { + background: #e53935; +} + +.btn-icon { + background: transparent; + border: 1px solid rgba(123, 104, 166, 0.3); + color: var(--text-gray); + padding: 8px; + border-radius: 6px; + cursor: pointer; + transition: all var(--transition-fast); +} + +.btn-icon:hover { + background: rgba(123, 104, 166, 0.2); + color: var(--text-light); + border-color: var(--secondary-purple); +} + +/* Cards */ +.card { + background: linear-gradient(145deg, rgba(91, 75, 138, 0.1) 0%, rgba(46, 37, 71, 0.5) 100%); + border: 1px solid rgba(123, 104, 166, 0.2); + border-radius: 12px; + padding: 24px; + box-shadow: var(--shadow-md); + transition: all var(--transition-normal); +} + +.card:hover { + box-shadow: var(--shadow-lg); + border-color: rgba(123, 104, 166, 0.4); +} + +/* Section Titles */ +.section-title { + font-size: 20px; + font-weight: 700; + margin-bottom: 20px; + display: flex; + align-items: center; + gap: 10px; + color: var(--text-light); +} + +.section-title i { + color: var(--accent-orange); +} + +/* Badges */ +.badge { + display: inline-block; + padding: 4px 12px; + border-radius: 12px; + font-size: 12px; + font-weight: 600; + text-transform: uppercase; +} + +.badge.success { + background: rgba(76, 175, 80, 0.2); + color: var(--status-success); + border: 1px solid var(--status-success); +} + +.badge.warning { + background: rgba(255, 167, 38, 0.2); + color: var(--status-warning); + border: 1px solid var(--status-warning); +} + +.badge.error { + background: rgba(239, 83, 80, 0.2); + color: var(--status-error); + border: 1px solid var(--status-error); +} + +.badge.info { + background: rgba(66, 165, 245, 0.2); + color: var(--status-info); + border: 1px solid var(--status-info); +} + +/* Status Badges */ +.status-badge { + padding: 6px 16px; + border-radius: 20px; + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + display: inline-block; +} + +.status-badge.operational { + background: rgba(76, 175, 80, 0.2); + color: var(--status-success); + border: 2px solid var(--status-success); +} + +.status-badge.degraded { + background: rgba(255, 167, 38, 0.2); + color: var(--status-warning); + border: 2px solid var(--status-warning); +} + +.status-badge.down { + background: rgba(239, 83, 80, 0.2); + color: var(--status-error); + border: 2px solid var(--status-error); +} + +/* Form Elements */ +input[type="text"], +input[type="email"], +input[type="password"], +select, +textarea { + width: 100%; + padding: 12px 16px; + background: rgba(91, 75, 138, 0.1); + border: 1px solid rgba(123, 104, 166, 0.3); + border-radius: 8px; + color: var(--text-light); + font-size: 14px; + transition: all var(--transition-fast); +} + +input:focus, +select:focus, +textarea:focus { + outline: none; + border-color: var(--secondary-purple); + background: rgba(91, 75, 138, 0.2); +} + +input::placeholder { + color: var(--text-gray); +} + +/* Search Box */ +.search-box { + position: relative; + flex: 1; + max-width: 400px; +} + +.search-box i { + position: absolute; + left: 16px; + top: 50%; + transform: translateY(-50%); + color: var(--text-gray); +} + +.search-box input { + padding-left: 45px; +} + +/* Utility Classes */ +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.mt-1 { margin-top: 10px; } +.mt-2 { margin-top: 20px; } +.mt-3 { margin-top: 30px; } + +.mb-1 { margin-bottom: 10px; } +.mb-2 { margin-bottom: 20px; } +.mb-3 { margin-bottom: 30px; } + +.success { color: var(--status-success); } +.warning { color: var(--status-warning); } +.error { color: var(--status-error); } +.info { color: var(--status-info); } + +/* Loading Spinner */ +.spinner { + border: 3px solid rgba(123, 104, 166, 0.3); + border-top: 3px solid var(--secondary-purple); + border-radius: 50%; + width: 40px; + height: 40px; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Scrollbar Styling */ +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: rgba(91, 75, 138, 0.1); +} + +::-webkit-scrollbar-thumb { + background: var(--secondary-purple); + border-radius: 5px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--primary-purple); +} diff --git a/dashboard/css/responsive.css b/dashboard/css/responsive.css new file mode 100644 index 0000000..c2a4c9c --- /dev/null +++ b/dashboard/css/responsive.css @@ -0,0 +1,245 @@ +/* Responsive Styles */ + +/* Tablet and below */ +@media (max-width: 1024px) { + .stat-cards { + grid-template-columns: repeat(2, 1fr); + } + + .agent-grid { + grid-template-columns: repeat(2, 1fr); + } + + .two-column-layout { + grid-template-columns: 1fr; + } + + .metrics-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +/* Mobile */ +@media (max-width: 768px) { + body { + flex-direction: column; + } + + .sidebar { + width: 100%; + height: auto; + position: relative; + border-right: none; + border-bottom: 1px solid rgba(123, 104, 166, 0.2); + } + + .logo-container { + padding: 20px; + } + + .logo-container h2 { + font-size: 14px; + } + + .nav-menu { + display: flex; + overflow-x: auto; + padding: 10px 0; + } + + .nav-item { + margin: 0 5px; + } + + .nav-item a { + flex-direction: column; + padding: 10px 15px; + border-left: none; + border-bottom: 3px solid transparent; + white-space: nowrap; + } + + .nav-item.active a, + .nav-item a:hover { + border-left: none; + border-bottom-color: var(--accent-orange); + } + + .nav-item i { + margin-right: 0; + margin-bottom: 4px; + } + + .connection-status { + display: none; + } + + .main-content { + margin-left: 0; + padding: 20px 15px; + } + + .page-header { + flex-direction: column; + align-items: flex-start; + gap: 15px; + } + + .page-header h1 { + font-size: 24px; + } + + .header-actions { + width: 100%; + justify-content: space-between; + } + + .stat-cards { + grid-template-columns: 1fr; + } + + .stat-card { + padding: 20px; + } + + .stat-icon { + width: 50px; + height: 50px; + font-size: 24px; + } + + .stat-value { + font-size: 28px; + } + + .agent-grid { + grid-template-columns: 1fr; + } + + .two-column-layout { + grid-template-columns: 1fr; + } + + .policy-header { + flex-direction: column; + } + + .search-box { + max-width: 100%; + } + + .metrics-grid { + grid-template-columns: 1fr; + } + + .activity-filters { + overflow-x: auto; + } + + .filter-btn { + white-space: nowrap; + } + + .blast-radius-stats { + flex-direction: column; + gap: 15px; + } + + .approval-workflow { + flex-direction: column; + } + + .region-stats { + flex-direction: column; + gap: 10px; + } +} + +/* Small Mobile */ +@media (max-width: 480px) { + .page-header h1 { + font-size: 20px; + } + + .stat-value { + font-size: 24px; + } + + .stat-content h3 { + font-size: 12px; + } + + .agent-header { + flex-direction: column; + align-items: flex-start; + } + + .agent-controls { + align-self: flex-end; + } + + .policy-item { + flex-direction: column; + align-items: flex-start; + gap: 10px; + } + + .policy-status { + width: 100%; + justify-content: space-between; + } + + .region-map { + height: 200px; + } + + .region-marker { + width: 30px; + height: 30px; + font-size: 16px; + } + + .region-label { + font-size: 9px; + } +} + +/* Print Styles */ +@media print { + .sidebar, + .header-actions, + .agent-controls, + .approval-workflow, + .activity-filters { + display: none; + } + + .main-content { + margin-left: 0; + } + + .card { + break-inside: avoid; + } +} + +/* High DPI / Retina Displays */ +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + .logo { + image-rendering: -webkit-optimize-contrast; + } +} + +/* Dark Mode Support (for future enhancement) */ +@media (prefers-color-scheme: dark) { + /* Already in dark mode by default */ +} + +/* Reduced Motion */ +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/dashboard/data/mock-data.json b/dashboard/data/mock-data.json new file mode 100644 index 0000000..843b284 --- /dev/null +++ b/dashboard/data/mock-data.json @@ -0,0 +1,281 @@ +{ + "platform": { + "status": "operational", + "activeAgents": 4, + "queueSize": 12, + "systemHealth": 98 + }, + "agents": [ + { + "id": "policy", + "name": "Policy Agent", + "status": "active", + "metrics": { + "policiesEnforced": 247, + "violations": 3, + "lastCheck": "2 min ago" + } + }, + { + "id": "intent", + "name": "Intent Agent", + "status": "active", + "metrics": { + "activeIntents": 8, + "scriptsGenerated": 156, + "queueSize": 5 + } + }, + { + "id": "deployment", + "name": "Deployment Agent", + "status": "active", + "metrics": { + "activeDeployments": 12, + "regions": 5, + "successRate": "99.2%" + } + }, + { + "id": "compliance", + "name": "Compliance Agent", + "status": "active", + "metrics": { + "complianceScore": "96%", + "auditEvents": 1234, + "markers": 45 + } + } + ], + "activities": [ + { + "type": "policy", + "title": "Policy Violation Detected", + "description": "Cost threshold exceeded in us-east-1 region", + "time": "2 minutes ago" + }, + { + "type": "deployment", + "title": "Deployment Completed", + "description": "Successfully deployed version 2.1.4 to production", + "time": "15 minutes ago" + }, + { + "type": "compliance", + "title": "Compliance Check Passed", + "description": "All resources meet compliance requirements", + "time": "1 hour ago" + }, + { + "type": "policy", + "title": "Policy Updated", + "description": "Resource quota policy modified by admin", + "time": "2 hours ago" + }, + { + "type": "deployment", + "title": "Deployment Initiated", + "description": "Starting deployment to eu-central-1", + "time": "3 hours ago" + }, + { + "type": "compliance", + "title": "Audit Event Recorded", + "description": "Configuration change logged for security group sg-12345", + "time": "4 hours ago" + } + ], + "policies": [ + { + "id": "pol-1", + "name": "Resource Quota Enforcement", + "description": "Ensures CPU and memory limits are not exceeded", + "status": "active", + "enforced": 247, + "rules": [ + "cpu_limit < 80%", + "memory_limit < 90%" + ] + }, + { + "id": "pol-2", + "name": "Security Group Validation", + "description": "Validates security group rules against best practices", + "status": "active", + "enforced": 89, + "rules": [ + "no_public_ssh_access", + "encrypted_traffic_only" + ] + }, + { + "id": "pol-3", + "name": "Cost Threshold Alert", + "description": "Alerts when spending exceeds budget thresholds", + "status": "warning", + "violations": 3, + "checks": 156, + "rules": [ + "daily_cost < $500", + "monthly_cost < $15000" + ] + }, + { + "id": "pol-4", + "name": "Data Encryption Policy", + "description": "Ensures all data at rest is encrypted", + "status": "active", + "enforced": 312, + "rules": [ + "s3_encryption_enabled", + "ebs_encryption_enabled", + "rds_encryption_enabled" + ] + } + ], + "metrics": { + "bandwidth": { + "labels": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + "data": [65, 59, 80, 81, 56, 55, 40] + }, + "compute": { + "labels": ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00"], + "data": [75, 82, 88, 91, 85, 78] + }, + "storage": { + "used": 67, + "free": 33 + }, + "costTrend": { + "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], + "data": [1200, 1150, 1100, 1050, 1080, 1020] + } + }, + "regions": [ + { + "id": "us-east", + "name": "US East", + "status": "healthy", + "instances": 45, + "cpuUsage": 67, + "latency": 12 + }, + { + "id": "us-west", + "name": "US West", + "status": "healthy", + "instances": 38, + "cpuUsage": 72, + "latency": 15 + }, + { + "id": "eu-central", + "name": "EU Central", + "status": "healthy", + "instances": 52, + "cpuUsage": 58, + "latency": 25 + }, + { + "id": "asia-pacific", + "name": "Asia Pacific", + "status": "warning", + "instances": 29, + "cpuUsage": 89, + "latency": 45 + }, + { + "id": "south-america", + "name": "South America", + "status": "healthy", + "instances": 18, + "cpuUsage": 45, + "latency": 35 + } + ], + "blastRadius": { + "riskLevel": "medium", + "affectedResources": 24, + "impactedUsers": 156, + "estimatedDowntime": "2-5 minutes", + "categories": ["Compute", "Storage", "Network", "Security"], + "values": [12, 5, 4, 3], + "details": { + "compute": ["ec2-instance-1", "ec2-instance-2", "lambda-function-1"], + "storage": ["s3-bucket-prod", "ebs-volume-1"], + "network": ["load-balancer-1", "vpc-endpoint-1"], + "security": ["security-group-1", "iam-role-1"] + } + }, + "scripts": [ + { + "id": "script-1", + "name": "Auto-Scale Infrastructure", + "category": "Automation", + "description": "Automatically scales compute resources based on demand", + "language": "Python", + "cloudProvider": "AWS", + "downloads": 1234 + }, + { + "id": "script-2", + "name": "Cost Optimizer", + "category": "Optimization", + "description": "Identifies and terminates unused resources", + "language": "JavaScript", + "cloudProvider": "Multi-Cloud", + "downloads": 892 + }, + { + "id": "script-3", + "name": "Security Audit", + "category": "Security", + "description": "Runs comprehensive security checks across infrastructure", + "language": "Go", + "cloudProvider": "Azure", + "downloads": 567 + } + ], + "compliance": { + "score": 96, + "frameworks": [ + { + "name": "SOC 2", + "compliance": 98, + "controls": 156, + "passed": 153, + "failed": 3 + }, + { + "name": "HIPAA", + "compliance": 95, + "controls": 89, + "passed": 85, + "failed": 4 + }, + { + "name": "PCI DSS", + "compliance": 94, + "controls": 67, + "passed": 63, + "failed": 4 + } + ], + "markers": [ + { + "id": "marker-1", + "resource": "s3://production-data", + "requirement": "Encryption at rest", + "status": "compliant", + "lastChecked": "2024-02-15T07:30:00Z" + }, + { + "id": "marker-2", + "resource": "rds://prod-db", + "requirement": "Automated backups", + "status": "compliant", + "lastChecked": "2024-02-15T07:25:00Z" + } + ] + } +} diff --git a/dashboard/index.html b/dashboard/index.html new file mode 100644 index 0000000..5d7db8b --- /dev/null +++ b/dashboard/index.html @@ -0,0 +1,469 @@ + + + + + + Multi-Agent Infrastructure Control Platform - Dashboard + + + + + + + + + + + +
+ + + +
+
+
+
+ +
+
+

Platform Status

+
Operational
+

All systems running

+
+
+
+
+ +
+
+

Active Agents

+
4
+

of 4 agents online

+
+
+
+
+ +
+
+

Processing Queue

+
12
+

items pending

+
+
+
+
+ +
+
+

System Health

+
98%
+

excellent condition

+
+
+
+
+ + +
+

+ Agent Status +

+
+
+
+
+ +
+
+

Policy Agent

+ Active +
+
+ +
+
+
+
+ Policies Enforced + 247 +
+
+ Violations + 3 +
+
+ Last Check + 2 min ago +
+
+
+ +
+
+
+ +
+
+

Intent Agent

+ Active +
+
+ +
+
+
+
+ Active Intents + 8 +
+
+ Scripts Generated + 156 +
+
+ Queue Size + 5 +
+
+
+ +
+
+
+ +
+
+

Deployment Agent

+ Active +
+
+ +
+
+
+
+ Active Deployments + 12 +
+
+ Regions + 5 +
+
+ Success Rate + 99.2% +
+
+
+ +
+
+
+ +
+
+

Compliance Agent

+ Active +
+
+ +
+
+
+
+ Compliance Score + 96% +
+
+ Audit Events + 1,234 +
+
+ Markers + 45 +
+
+
+
+
+ + +
+ +
+

+ Blast Radius Prediction +

+
+
+
+ Risk Level + Medium +
+
+
+ +
+
+
+ + 24 + Affected Resources +
+
+ + 156 + Impacted Users +
+
+
+ + +
+
+
+ + +
+

+ Multi-Region Infrastructure +

+
+
+
+
+ +
+
US East
+
+
+
+ +
+
US West
+
+
+
+ +
+
EU Central
+
+
+
+ +
+
Asia Pacific
+
+
+
+ +
+
South America
+
+
+
+
+ + 4 Healthy +
+
+ + 1 Warning +
+
+ + 0 Down +
+
+
+
+
+ + +
+

+ Policy Enforcement +

+
+
+ + +
+
+
+
+

Resource Quota Enforcement

+

Ensures CPU and memory limits are not exceeded

+
+
+ Active + 247 enforced +
+
+
+
+

Security Group Validation

+

Validates security group rules against best practices

+
+
+ Active + 89 enforced +
+
+
+
+

Cost Threshold Alert

+

Alerts when spending exceeds budget thresholds

+
+
+ 3 violations + 156 checks +
+
+
+
+
+ + +
+

+ Cost Optimization +

+
+
+

Bandwidth Savings

+ + +
+
+

Compute Efficiency

+ + +
+
+

Storage Rebalancing

+ + +
+
+

Cost Trends

+ + +
+
+
+ + +
+

+ Recent Activities +

+
+
+ + + + +
+
+ +
+
+
+
+ + + + + + + + diff --git a/dashboard/js/agents.js b/dashboard/js/agents.js new file mode 100644 index 0000000..3d9cb20 --- /dev/null +++ b/dashboard/js/agents.js @@ -0,0 +1,207 @@ +// Agent Management Module +class AgentManager { + constructor() { + this.agents = []; + this.updateInterval = null; + } + + async initialize() { + await this.loadAgents(); + this.setupEventListeners(); + this.startAutoUpdate(); + } + + async loadAgents() { + try { + const data = await api.getDefaultMockData(); + this.agents = data.agents; + this.updateAgentCards(); + } catch (error) { + console.error('Failed to load agents:', error); + } + } + + updateAgentCards() { + this.agents.forEach(agent => { + const card = document.querySelector(`.agent-card[data-agent="${agent.id}"]`); + if (!card) return; + + // Update status + const statusElement = card.querySelector('.agent-status'); + if (statusElement) { + statusElement.textContent = agent.status.charAt(0).toUpperCase() + agent.status.slice(1); + statusElement.className = `agent-status ${agent.status}`; + } + + // Update metrics + const metrics = card.querySelectorAll('.metric-value'); + const metricValues = Object.values(agent.metrics); + + metrics.forEach((metric, index) => { + if (metricValues[index] !== undefined) { + metric.textContent = metricValues[index]; + } + }); + }); + } + + setupEventListeners() { + // Agent control buttons + document.querySelectorAll('.agent-card .btn-icon').forEach(button => { + button.addEventListener('click', (e) => { + const card = e.target.closest('.agent-card'); + const agentId = card.dataset.agent; + this.toggleAgent(agentId); + }); + }); + + // Listen to WebSocket updates + wsManager.on('agentStatus', (data) => { + this.handleAgentStatusUpdate(data); + }); + } + + async toggleAgent(agentId) { + const agent = this.agents.find(a => a.id === agentId); + if (!agent) return; + + try { + if (agent.status === 'active') { + await api.stopAgent(agentId); + agent.status = 'inactive'; + this.showNotification(`${agent.name} stopped`, 'info'); + } else { + await api.startAgent(agentId); + agent.status = 'active'; + this.showNotification(`${agent.name} started`, 'success'); + } + + this.updateAgentCards(); + this.updateActiveAgentsCount(); + } catch (error) { + console.error(`Failed to toggle agent ${agentId}:`, error); + this.showNotification('Failed to update agent', 'error'); + } + } + + handleAgentStatusUpdate(data) { + const agent = this.agents.find(a => a.id === data.agentId); + if (!agent) return; + + agent.status = data.status; + this.updateAgentCards(); + this.updateActiveAgentsCount(); + } + + updateActiveAgentsCount() { + const activeCount = this.agents.filter(a => a.status === 'active').length; + const element = document.getElementById('activeAgents'); + if (element) { + element.textContent = activeCount; + } + } + + startAutoUpdate() { + // Update agent metrics every 5 seconds + this.updateInterval = setInterval(async () => { + await this.loadAgents(); + }, 5000); + } + + stopAutoUpdate() { + if (this.updateInterval) { + clearInterval(this.updateInterval); + this.updateInterval = null; + } + } + + showNotification(message, type = 'info') { + // Create notification element + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.innerHTML = ` + + ${message} + `; + + notification.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + padding: 15px 20px; + background: ${this.getNotificationColor(type)}; + color: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 10000; + display: flex; + align-items: center; + gap: 10px; + animation: slideIn 0.3s ease; + `; + + document.body.appendChild(notification); + + // Remove after 3 seconds + setTimeout(() => { + notification.style.animation = 'slideOut 0.3s ease'; + setTimeout(() => { + document.body.removeChild(notification); + }, 300); + }, 3000); + } + + getNotificationIcon(type) { + const icons = { + success: 'check-circle', + error: 'exclamation-circle', + warning: 'exclamation-triangle', + info: 'info-circle' + }; + return icons[type] || 'info-circle'; + } + + getNotificationColor(type) { + const colors = { + success: 'rgba(76, 175, 80, 0.95)', + error: 'rgba(239, 83, 80, 0.95)', + warning: 'rgba(255, 167, 38, 0.95)', + info: 'rgba(66, 165, 245, 0.95)' + }; + return colors[type] || colors.info; + } + + destroy() { + this.stopAutoUpdate(); + } +} + +// Add notification animations +const style = document.createElement('style'); +style.textContent = ` + @keyframes slideIn { + from { + transform: translateX(400px); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } + } + + @keyframes slideOut { + from { + transform: translateX(0); + opacity: 1; + } + to { + transform: translateX(400px); + opacity: 0; + } + } +`; +document.head.appendChild(style); + +// Export agent manager instance +const agentManager = new AgentManager(); diff --git a/dashboard/js/api.js b/dashboard/js/api.js new file mode 100644 index 0000000..06524f9 --- /dev/null +++ b/dashboard/js/api.js @@ -0,0 +1,252 @@ +// API Integration Layer +class API { + constructor() { + this.baseUrl = '/api'; // Change to actual API endpoint + this.mockMode = true; // Set to false when real API is available + } + + // Generic request method + async request(endpoint, options = {}) { + if (this.mockMode) { + return this.mockRequest(endpoint, options); + } + + try { + const response = await fetch(`${this.baseUrl}${endpoint}`, { + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers, + }, + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('API request failed:', error); + throw error; + } + } + + // Mock request handler for development + async mockRequest(endpoint, options = {}) { + // Simulate network delay + await new Promise(resolve => setTimeout(resolve, 300)); + + // Load mock data + const mockData = await this.loadMockData(); + + // Route mock requests + if (endpoint.includes('/agents')) { + return mockData.agents; + } else if (endpoint.includes('/activities')) { + return mockData.activities; + } else if (endpoint.includes('/policies')) { + return mockData.policies; + } else if (endpoint.includes('/metrics')) { + return mockData.metrics; + } else if (endpoint.includes('/regions')) { + return mockData.regions; + } else if (endpoint.includes('/blast-radius')) { + return mockData.blastRadius; + } + + return mockData; + } + + // Load mock data from JSON file + async loadMockData() { + try { + const response = await fetch('data/mock-data.json'); + return await response.json(); + } catch (error) { + console.error('Failed to load mock data:', error); + return this.getDefaultMockData(); + } + } + + // Default mock data if JSON file is not available + getDefaultMockData() { + return { + platform: { + status: 'operational', + activeAgents: 4, + queueSize: 12, + systemHealth: 98 + }, + agents: [ + { + id: 'policy', + name: 'Policy Agent', + status: 'active', + metrics: { + policiesEnforced: 247, + violations: 3, + lastCheck: '2 min ago' + } + }, + { + id: 'intent', + name: 'Intent Agent', + status: 'active', + metrics: { + activeIntents: 8, + scriptsGenerated: 156, + queueSize: 5 + } + }, + { + id: 'deployment', + name: 'Deployment Agent', + status: 'active', + metrics: { + activeDeployments: 12, + regions: 5, + successRate: '99.2%' + } + }, + { + id: 'compliance', + name: 'Compliance Agent', + status: 'active', + metrics: { + complianceScore: '96%', + auditEvents: 1234, + markers: 45 + } + } + ], + activities: [ + { + type: 'policy', + title: 'Policy Violation Detected', + description: 'Cost threshold exceeded in us-east-1', + time: '2 minutes ago' + }, + { + type: 'deployment', + title: 'Deployment Completed', + description: 'Successfully deployed version 2.1.4 to production', + time: '15 minutes ago' + }, + { + type: 'compliance', + title: 'Compliance Check Passed', + description: 'All resources meet compliance requirements', + time: '1 hour ago' + } + ], + policies: [ + { + id: 'pol-1', + name: 'Resource Quota Enforcement', + description: 'Ensures CPU and memory limits are not exceeded', + status: 'active', + enforced: 247 + }, + { + id: 'pol-2', + name: 'Security Group Validation', + description: 'Validates security group rules against best practices', + status: 'active', + enforced: 89 + }, + { + id: 'pol-3', + name: 'Cost Threshold Alert', + description: 'Alerts when spending exceeds budget thresholds', + status: 'warning', + violations: 3, + checks: 156 + } + ], + metrics: { + bandwidth: { + labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + data: [65, 59, 80, 81, 56, 55, 40] + }, + compute: { + labels: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'], + data: [75, 82, 88, 91, 85, 78] + }, + storage: { + used: 67, + free: 33 + }, + costTrend: { + labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], + data: [1200, 1150, 1100, 1050, 1080, 1020] + } + }, + regions: [ + { id: 'us-east', name: 'US East', status: 'healthy' }, + { id: 'us-west', name: 'US West', status: 'healthy' }, + { id: 'eu-central', name: 'EU Central', status: 'healthy' }, + { id: 'asia-pacific', name: 'Asia Pacific', status: 'warning' }, + { id: 'south-america', name: 'South America', status: 'healthy' } + ], + blastRadius: { + riskLevel: 'medium', + affectedResources: 24, + impactedUsers: 156, + categories: ['Compute', 'Storage', 'Network', 'Security'], + values: [12, 5, 4, 3] + } + }; + } + + // API Methods + async getPlatformStatus() { + return this.request('/platform/status'); + } + + async getAgents() { + return this.request('/agents'); + } + + async getAgentStatus(agentId) { + return this.request(`/agents/${agentId}`); + } + + async startAgent(agentId) { + return this.request(`/agents/${agentId}/start`, { method: 'POST' }); + } + + async stopAgent(agentId) { + return this.request(`/agents/${agentId}/stop`, { method: 'POST' }); + } + + async getActivities(filter = 'all') { + return this.request(`/activities?filter=${filter}`); + } + + async getPolicies() { + return this.request('/policies'); + } + + async getMetrics() { + return this.request('/metrics'); + } + + async getRegions() { + return this.request('/regions'); + } + + async getBlastRadius() { + return this.request('/blast-radius'); + } + + async simulatePolicy(policyId) { + return this.request(`/policies/${policyId}/simulate`, { method: 'POST' }); + } + + async exportComplianceReport(format = 'pdf') { + return this.request(`/compliance/export?format=${format}`); + } +} + +// Export API instance +const api = new API(); diff --git a/dashboard/js/charts.js b/dashboard/js/charts.js new file mode 100644 index 0000000..ecdbbdc --- /dev/null +++ b/dashboard/js/charts.js @@ -0,0 +1,320 @@ +// Chart.js Configurations +class ChartManager { + constructor() { + this.charts = {}; + this.defaultOptions = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + labels: { + color: '#B8B8B8', + font: { + family: 'Inter, sans-serif' + } + } + } + }, + scales: { + y: { + ticks: { + color: '#B8B8B8' + }, + grid: { + color: 'rgba(123, 104, 166, 0.1)' + } + }, + x: { + ticks: { + color: '#B8B8B8' + }, + grid: { + color: 'rgba(123, 104, 166, 0.1)' + } + } + } + }; + } + + initializeCharts(metricsData) { + this.createBlastRadiusChart(); + this.createBandwidthChart(metricsData.bandwidth); + this.createComputeChart(metricsData.compute); + this.createStorageChart(metricsData.storage); + this.createCostTrendChart(metricsData.costTrend); + } + + createBlastRadiusChart() { + const ctx = document.getElementById('blastRadiusChart'); + if (!ctx) return; + + this.charts.blastRadius = new Chart(ctx, { + type: 'doughnut', + data: { + labels: ['Compute', 'Storage', 'Network', 'Security'], + datasets: [{ + data: [12, 5, 4, 3], + backgroundColor: [ + 'rgba(91, 75, 138, 0.8)', + 'rgba(123, 104, 166, 0.8)', + 'rgba(255, 107, 53, 0.8)', + 'rgba(76, 175, 80, 0.8)' + ], + borderColor: [ + 'rgb(91, 75, 138)', + 'rgb(123, 104, 166)', + 'rgb(255, 107, 53)', + 'rgb(76, 175, 80)' + ], + borderWidth: 2 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'bottom', + labels: { + color: '#B8B8B8', + padding: 15, + font: { + family: 'Inter, sans-serif', + size: 12 + } + } + }, + tooltip: { + backgroundColor: 'rgba(46, 37, 71, 0.95)', + titleColor: '#FFFFFF', + bodyColor: '#B8B8B8', + borderColor: 'rgba(123, 104, 166, 0.5)', + borderWidth: 1, + padding: 12, + displayColors: true + } + } + } + }); + } + + createBandwidthChart(data) { + const ctx = document.getElementById('bandwidthChart'); + if (!ctx) return; + + this.charts.bandwidth = new Chart(ctx, { + type: 'line', + data: { + labels: data.labels, + datasets: [{ + label: 'Bandwidth Savings (GB)', + data: data.data, + borderColor: 'rgb(76, 175, 80)', + backgroundColor: 'rgba(76, 175, 80, 0.1)', + tension: 0.4, + fill: true, + pointBackgroundColor: 'rgb(76, 175, 80)', + pointBorderColor: '#fff', + pointBorderWidth: 2, + pointRadius: 4 + }] + }, + options: { + ...this.defaultOptions, + plugins: { + legend: { + display: false + }, + tooltip: { + backgroundColor: 'rgba(46, 37, 71, 0.95)', + titleColor: '#FFFFFF', + bodyColor: '#B8B8B8', + borderColor: 'rgba(76, 175, 80, 0.5)', + borderWidth: 1 + } + } + } + }); + } + + createComputeChart(data) { + const ctx = document.getElementById('computeChart'); + if (!ctx) return; + + this.charts.compute = new Chart(ctx, { + type: 'bar', + data: { + labels: data.labels, + datasets: [{ + label: 'Utilization (%)', + data: data.data, + backgroundColor: 'rgba(91, 75, 138, 0.8)', + borderColor: 'rgb(91, 75, 138)', + borderWidth: 2, + borderRadius: 6 + }] + }, + options: { + ...this.defaultOptions, + plugins: { + legend: { + display: false + }, + tooltip: { + backgroundColor: 'rgba(46, 37, 71, 0.95)', + titleColor: '#FFFFFF', + bodyColor: '#B8B8B8' + } + }, + scales: { + ...this.defaultOptions.scales, + y: { + ...this.defaultOptions.scales.y, + max: 100, + ticks: { + color: '#B8B8B8', + callback: function(value) { + return value + '%'; + } + } + } + } + } + }); + } + + createStorageChart(data) { + const ctx = document.getElementById('storageChart'); + if (!ctx) return; + + this.charts.storage = new Chart(ctx, { + type: 'doughnut', + data: { + labels: ['Used', 'Free'], + datasets: [{ + data: [data.used, data.free], + backgroundColor: [ + 'rgba(255, 107, 53, 0.8)', + 'rgba(123, 104, 166, 0.3)' + ], + borderColor: [ + 'rgb(255, 107, 53)', + 'rgb(123, 104, 166)' + ], + borderWidth: 2 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'bottom', + labels: { + color: '#B8B8B8', + font: { + family: 'Inter, sans-serif', + size: 12 + } + } + }, + tooltip: { + backgroundColor: 'rgba(46, 37, 71, 0.95)', + titleColor: '#FFFFFF', + bodyColor: '#B8B8B8', + callbacks: { + label: function(context) { + return context.label + ': ' + context.parsed + '%'; + } + } + } + } + } + }); + } + + createCostTrendChart(data) { + const ctx = document.getElementById('costTrendChart'); + if (!ctx) return; + + this.charts.costTrend = new Chart(ctx, { + type: 'line', + data: { + labels: data.labels, + datasets: [{ + label: 'Cost ($)', + data: data.data, + borderColor: 'rgb(255, 107, 53)', + backgroundColor: 'rgba(255, 107, 53, 0.1)', + tension: 0.4, + fill: true, + pointBackgroundColor: 'rgb(255, 107, 53)', + pointBorderColor: '#fff', + pointBorderWidth: 2, + pointRadius: 4 + }] + }, + options: { + ...this.defaultOptions, + plugins: { + legend: { + display: false + }, + tooltip: { + backgroundColor: 'rgba(46, 37, 71, 0.95)', + titleColor: '#FFFFFF', + bodyColor: '#B8B8B8', + callbacks: { + label: function(context) { + return '$' + context.parsed.y.toLocaleString(); + } + } + } + }, + scales: { + ...this.defaultOptions.scales, + y: { + ...this.defaultOptions.scales.y, + ticks: { + color: '#B8B8B8', + callback: function(value) { + return '$' + value; + } + } + } + } + } + }); + } + + updateChart(chartName, newData) { + const chart = this.charts[chartName]; + if (!chart) return; + + if (newData.labels) { + chart.data.labels = newData.labels; + } + if (newData.datasets) { + chart.data.datasets = newData.datasets; + } + + chart.update(); + } + + destroyChart(chartName) { + const chart = this.charts[chartName]; + if (chart) { + chart.destroy(); + delete this.charts[chartName]; + } + } + + destroyAllCharts() { + Object.keys(this.charts).forEach(chartName => { + this.destroyChart(chartName); + }); + } +} + +// Export chart manager instance +const chartManager = new ChartManager(); diff --git a/dashboard/js/dashboard.js b/dashboard/js/dashboard.js new file mode 100644 index 0000000..6cce17a --- /dev/null +++ b/dashboard/js/dashboard.js @@ -0,0 +1,272 @@ +// Main Dashboard JavaScript +class Dashboard { + constructor() { + this.currentFilter = 'all'; + this.activities = []; + this.refreshInterval = null; + } + + async initialize() { + await this.loadDashboardData(); + this.setupEventListeners(); + this.startAutoRefresh(); + + // Initialize sub-modules + await agentManager.initialize(); + } + + async loadDashboardData() { + try { + const data = await api.getDefaultMockData(); + + // Update platform status + this.updatePlatformStatus(data.platform); + + // Update activities + this.activities = data.activities; + this.renderActivities(); + + // Initialize charts + chartManager.initializeCharts(data.metrics); + + } catch (error) { + console.error('Failed to load dashboard data:', error); + } + } + + updatePlatformStatus(platform) { + // Update platform status badge + const statusElement = document.getElementById('platformStatus'); + if (statusElement) { + statusElement.textContent = platform.status.charAt(0).toUpperCase() + platform.status.slice(1); + statusElement.className = `status-badge ${platform.status}`; + } + + // Update stats + this.updateStat('activeAgents', platform.activeAgents); + this.updateStat('queueSize', platform.queueSize); + this.updateStat('systemHealth', platform.systemHealth + '%'); + } + + updateStat(id, value) { + const element = document.getElementById(id); + if (element) { + element.textContent = value; + } + } + + renderActivities() { + const feedElement = document.getElementById('activityFeed'); + if (!feedElement) return; + + const filteredActivities = this.currentFilter === 'all' + ? this.activities + : this.activities.filter(a => a.type === this.currentFilter); + + if (filteredActivities.length === 0) { + feedElement.innerHTML = ` +
+ +

No activities to display

+
+ `; + return; + } + + feedElement.innerHTML = filteredActivities.map(activity => ` +
+
+ +
+
+
${activity.title}
+
${activity.description}
+
+ ${activity.time} +
+
+
+ `).join(''); + } + + getActivityIcon(type) { + const icons = { + policy: 'shield-alt', + deployment: 'rocket', + compliance: 'clipboard-check', + alert: 'exclamation-triangle' + }; + return icons[type] || 'info-circle'; + } + + setupEventListeners() { + // Refresh button + const refreshBtn = document.getElementById('refreshBtn'); + if (refreshBtn) { + refreshBtn.addEventListener('click', () => { + this.refresh(); + }); + } + + // Activity filters + document.querySelectorAll('.filter-btn').forEach(button => { + button.addEventListener('click', (e) => { + // Update active state + document.querySelectorAll('.filter-btn').forEach(btn => { + btn.classList.remove('active'); + }); + e.target.classList.add('active'); + + // Update filter and re-render + this.currentFilter = e.target.dataset.filter; + this.renderActivities(); + }); + }); + + // Policy search + const policySearch = document.getElementById('policySearch'); + if (policySearch) { + policySearch.addEventListener('input', (e) => { + this.searchPolicies(e.target.value); + }); + } + + // Simulate policy button + const simulatePolicyBtn = document.getElementById('simulatePolicyBtn'); + if (simulatePolicyBtn) { + simulatePolicyBtn.addEventListener('click', () => { + this.simulatePolicy(); + }); + } + + // Listen to WebSocket events + wsManager.on('activity', (activity) => { + this.addActivity(activity); + }); + + wsManager.on('metricUpdate', (data) => { + this.handleMetricUpdate(data); + }); + } + + async refresh() { + const refreshBtn = document.getElementById('refreshBtn'); + const icon = refreshBtn.querySelector('i'); + + // Add rotation animation + icon.style.animation = 'spin 1s linear'; + + await this.loadDashboardData(); + + // Remove animation after 1 second + setTimeout(() => { + icon.style.animation = ''; + }, 1000); + + agentManager.showNotification('Dashboard refreshed', 'success'); + } + + addActivity(activity) { + // Add to beginning of activities array + this.activities.unshift(activity); + + // Keep only last 50 activities + if (this.activities.length > 50) { + this.activities = this.activities.slice(0, 50); + } + + // Re-render if current filter matches + if (this.currentFilter === 'all' || this.currentFilter === activity.type) { + this.renderActivities(); + } + } + + handleMetricUpdate(data) { + if (data.type === 'system_health') { + this.updateStat('systemHealth', data.value + '%'); + } + } + + searchPolicies(query) { + const policyItems = document.querySelectorAll('.policy-item'); + const searchLower = query.toLowerCase(); + + policyItems.forEach(item => { + const title = item.querySelector('h4').textContent.toLowerCase(); + const description = item.querySelector('p').textContent.toLowerCase(); + + if (title.includes(searchLower) || description.includes(searchLower)) { + item.style.display = 'flex'; + } else { + item.style.display = 'none'; + } + }); + } + + async simulatePolicy() { + agentManager.showNotification('Running policy simulation...', 'info'); + + // Simulate delay + await new Promise(resolve => setTimeout(resolve, 2000)); + + const results = { + passed: Math.floor(Math.random() * 50) + 150, + failed: Math.floor(Math.random() * 10), + warnings: Math.floor(Math.random() * 20) + }; + + const message = `Simulation complete: ${results.passed} passed, ${results.failed} failed, ${results.warnings} warnings`; + agentManager.showNotification(message, results.failed > 0 ? 'warning' : 'success'); + } + + startAutoRefresh() { + // Auto-refresh every 30 seconds + this.refreshInterval = setInterval(() => { + this.loadDashboardData(); + }, 30000); + } + + stopAutoRefresh() { + if (this.refreshInterval) { + clearInterval(this.refreshInterval); + this.refreshInterval = null; + } + } + + destroy() { + this.stopAutoRefresh(); + chartManager.destroyAllCharts(); + agentManager.destroy(); + } +} + +// Add rotation animation for refresh button +const rotationStyle = document.createElement('style'); +rotationStyle.textContent = ` + @keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } + } +`; +document.head.appendChild(rotationStyle); + +// Initialize dashboard when DOM is ready +let dashboard; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + dashboard = new Dashboard(); + dashboard.initialize(); + }); +} else { + dashboard = new Dashboard(); + dashboard.initialize(); +} + +// Cleanup on page unload +window.addEventListener('beforeunload', () => { + if (dashboard) { + dashboard.destroy(); + } + wsManager.disconnect(); +}); diff --git a/dashboard/js/websocket.js b/dashboard/js/websocket.js new file mode 100644 index 0000000..9be66d4 --- /dev/null +++ b/dashboard/js/websocket.js @@ -0,0 +1,244 @@ +// WebSocket Manager for Real-Time Updates +class WebSocketManager { + constructor() { + this.ws = null; + this.reconnectAttempts = 0; + this.maxReconnectAttempts = 5; + this.reconnectDelay = 3000; + this.listeners = {}; + this.simulationMode = true; // Set to false when real WebSocket is available + this.simulationInterval = null; + } + + connect(url = 'ws://localhost:8080') { + if (this.simulationMode) { + this.startSimulation(); + return; + } + + try { + this.ws = new WebSocket(url); + + this.ws.onopen = () => { + console.log('WebSocket connected'); + this.reconnectAttempts = 0; + this.updateConnectionStatus(true); + this.emit('connected'); + }; + + this.ws.onmessage = (event) => { + try { + const data = JSON.parse(event.data); + this.handleMessage(data); + } catch (error) { + console.error('Failed to parse WebSocket message:', error); + } + }; + + this.ws.onerror = (error) => { + console.error('WebSocket error:', error); + this.emit('error', error); + }; + + this.ws.onclose = () => { + console.log('WebSocket disconnected'); + this.updateConnectionStatus(false); + this.emit('disconnected'); + this.attemptReconnect(); + }; + } catch (error) { + console.error('Failed to connect WebSocket:', error); + this.updateConnectionStatus(false); + } + } + + disconnect() { + if (this.simulationMode) { + this.stopSimulation(); + } else if (this.ws) { + this.ws.close(); + this.ws = null; + } + } + + send(message) { + if (this.simulationMode) { + console.log('Simulation mode: Message not sent', message); + return; + } + + if (this.ws && this.ws.readyState === WebSocket.OPEN) { + this.ws.send(JSON.stringify(message)); + } else { + console.warn('WebSocket is not connected'); + } + } + + on(event, callback) { + if (!this.listeners[event]) { + this.listeners[event] = []; + } + this.listeners[event].push(callback); + } + + off(event, callback) { + if (!this.listeners[event]) return; + + this.listeners[event] = this.listeners[event].filter( + listener => listener !== callback + ); + } + + emit(event, data) { + if (!this.listeners[event]) return; + + this.listeners[event].forEach(callback => { + try { + callback(data); + } catch (error) { + console.error('Error in event listener:', error); + } + }); + } + + handleMessage(data) { + const { type, payload } = data; + + switch (type) { + case 'agent_status': + this.emit('agentStatus', payload); + break; + case 'activity': + this.emit('activity', payload); + break; + case 'metric_update': + this.emit('metricUpdate', payload); + break; + case 'policy_violation': + this.emit('policyViolation', payload); + break; + case 'deployment_event': + this.emit('deploymentEvent', payload); + break; + case 'compliance_alert': + this.emit('complianceAlert', payload); + break; + default: + console.log('Unknown message type:', type); + } + } + + attemptReconnect() { + if (this.reconnectAttempts >= this.maxReconnectAttempts) { + console.error('Max reconnection attempts reached'); + return; + } + + this.reconnectAttempts++; + console.log(`Reconnecting... Attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`); + + setTimeout(() => { + this.connect(); + }, this.reconnectDelay); + } + + updateConnectionStatus(connected) { + const statusElement = document.getElementById('wsStatus'); + if (!statusElement) return; + + const statusDot = statusElement.querySelector('.status-dot'); + const statusText = statusElement.querySelector('.status-text'); + + if (connected) { + statusDot.style.background = 'var(--status-success)'; + statusText.textContent = 'Connected'; + } else { + statusDot.style.background = 'var(--status-error)'; + statusText.textContent = 'Disconnected'; + } + } + + // Simulation mode methods + startSimulation() { + console.log('Starting WebSocket simulation mode'); + this.updateConnectionStatus(true); + this.emit('connected'); + + // Simulate real-time updates every 5 seconds + this.simulationInterval = setInterval(() => { + this.simulateUpdate(); + }, 5000); + } + + stopSimulation() { + if (this.simulationInterval) { + clearInterval(this.simulationInterval); + this.simulationInterval = null; + } + this.updateConnectionStatus(false); + } + + simulateUpdate() { + const updateTypes = [ + 'agent_status', + 'activity', + 'metric_update' + ]; + + const randomType = updateTypes[Math.floor(Math.random() * updateTypes.length)]; + + switch (randomType) { + case 'agent_status': + this.emit('agentStatus', { + agentId: ['policy', 'intent', 'deployment', 'compliance'][Math.floor(Math.random() * 4)], + status: 'active', + timestamp: new Date().toISOString() + }); + break; + + case 'activity': + const activities = [ + { + type: 'policy', + title: 'Policy Check Completed', + description: 'All policies validated successfully', + time: 'just now' + }, + { + type: 'deployment', + title: 'Deployment Initiated', + description: 'Starting deployment to us-west-2', + time: 'just now' + }, + { + type: 'compliance', + title: 'Audit Event Recorded', + description: 'Configuration change logged', + time: 'just now' + } + ]; + this.emit('activity', activities[Math.floor(Math.random() * activities.length)]); + break; + + case 'metric_update': + this.emit('metricUpdate', { + type: 'system_health', + value: 95 + Math.floor(Math.random() * 5), + timestamp: new Date().toISOString() + }); + break; + } + } +} + +// Export WebSocket manager instance +const wsManager = new WebSocketManager(); + +// Auto-connect on page load +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + wsManager.connect(); + }); +} else { + wsManager.connect(); +} diff --git a/dashboard/policies.html b/dashboard/policies.html new file mode 100644 index 0000000..eb1db4e --- /dev/null +++ b/dashboard/policies.html @@ -0,0 +1,382 @@ + + + + + + Policy Management - Multi-Agent Platform + + + + + + + + + + +
+ + + +
+
+
+
+ +
+
+

Active Policies

+
4
+

enforcing compliance

+
+
+
+
+ +
+
+

Policies Enforced

+
648
+

total checks today

+
+
+
+
+ +
+
+

Violations

+
3
+

require attention

+
+
+
+
+ +
+
+

Success Rate

+
99.5%
+

compliance score

+
+
+
+
+ + +
+

+ All Policies +

+
+
+ + +
+ +
+ +
+
+
+

Resource Quota Enforcement

+ Active +
+
+ + + +
+
+

Ensures CPU and memory limits are not exceeded across all resources

+
+
+ Enforced Today + 247 +
+
+ Violations + 0 +
+
+ Last Run + 2 min ago +
+
+
+ OPA Rules: +
package kubernetes.admission
+deny[msg] {
+  input.request.kind.kind == "Pod"
+  container := input.request.object.spec.containers[_]
+  not container.resources.limits.cpu
+  msg := "CPU limit required"
+}
+
+
+ + +
+
+
+

Security Group Validation

+ Active +
+
+ + + +
+
+

Validates security group rules against best practices

+
+
+ Enforced Today + 89 +
+
+ Violations + 0 +
+
+ Last Run + 5 min ago +
+
+
+ OPA Rules: +
package aws.security_groups
+deny[msg] {
+  rule := input.rules[_]
+  rule.from_port == 22
+  rule.cidr_blocks[_] == "0.0.0.0/0"
+  msg := "SSH should not be open to public"
+}
+
+
+ + +
+
+
+

Cost Threshold Alert

+ Warning +
+
+ + + +
+
+

Alerts when spending exceeds budget thresholds

+
+
+ Checks Today + 156 +
+
+ Violations + 3 +
+
+ Last Run + 10 min ago +
+
+
+ OPA Rules: +
package cost.thresholds
+deny[msg] {
+  daily_cost := input.metrics.cost.daily
+  daily_cost > 500
+  msg := sprintf("Daily cost $%v exceeds threshold", [daily_cost])
+}
+
+
+ + +
+
+
+

Data Encryption Policy

+ Active +
+
+ + + +
+
+

Ensures all data at rest is encrypted

+
+
+ Enforced Today + 312 +
+
+ Violations + 0 +
+
+ Last Run + 1 min ago +
+
+
+ OPA Rules: +
package aws.encryption
+deny[msg] {
+  resource := input.resources[_]
+  resource.type == "s3_bucket"
+  not resource.encryption.enabled
+  msg := "S3 bucket must have encryption enabled"
+}
+
+
+
+
+
+
+ + + + diff --git a/dashboard/scripts.html b/dashboard/scripts.html new file mode 100644 index 0000000..61af3d3 --- /dev/null +++ b/dashboard/scripts.html @@ -0,0 +1,533 @@ + + + + + + Script Library - Multi-Agent Platform + + + + + + + + + + +
+ + + +
+
+
+
+ +
+
+

Total Scripts

+
156
+

available adapters

+
+
+
+
+ +
+
+

Total Downloads

+
2.7K
+

this month

+
+
+
+
+ +
+
+

Cloud Providers

+
5
+

supported platforms

+
+
+
+
+ +
+
+

Average Rating

+
4.8
+

out of 5 stars

+
+
+
+
+ + +
+

+ Browse by Category +

+
+ + + + + + + +
+
+ + +
+
+ +
+
+
+ +
+
+ Python + AWS +
+
+

Auto-Scale Infrastructure

+

Automatically scales compute resources based on demand using predictive algorithms

+
+ 1,234 + 4.9 +
+ +
+ + +
+
+
+ +
+
+ JavaScript + Multi-Cloud +
+
+

Cost Optimizer

+

Identifies and terminates unused resources to reduce infrastructure costs

+
+ 892 + 4.7 +
+ +
+ + +
+
+
+ +
+
+ Go + Azure +
+
+

Security Audit

+

Runs comprehensive security checks across infrastructure and reports vulnerabilities

+
+ 567 + 4.8 +
+ +
+ + +
+
+
+ +
+
+ Python + GCP +
+
+

Health Monitor

+

Monitors system health metrics and sends alerts for anomalies

+
+ 445 + 4.6 +
+ +
+ + +
+
+
+ +
+
+ Bash + AWS +
+
+

Automated Backup

+

Schedules and executes regular backups of critical data with rotation

+
+ 678 + 4.9 +
+ +
+ + +
+
+
+ +
+
+ Python + Multi-Cloud +
+
+

Blue-Green Deployer

+

Implements blue-green deployment strategy with automatic rollback

+
+ 823 + 4.8 +
+ +
+
+
+ + +
+

+ Adapter Marketplace +

+
+

+ Browse and install community-contributed adapters for various cloud providers and tools +

+
+
+ +

AWS Adapter

+

56 scripts

+
+
+ +

Azure Adapter

+

42 scripts

+
+
+ +

GCP Adapter

+

38 scripts

+
+
+ +

Kubernetes Adapter

+

29 scripts

+
+
+
+
+
+ + + + diff --git a/dashboard/settings.html b/dashboard/settings.html new file mode 100644 index 0000000..24feb86 --- /dev/null +++ b/dashboard/settings.html @@ -0,0 +1,659 @@ + + + + + + Settings - Multi-Agent Platform + + + + + + + + + + +
+ + + +
+
+ + + + + +
+
+ + +
+

+ General Settings +

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ +
+
+
+ + +
+

+ Agent Configuration +

+ +
+
+

Policy Agent

+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ +
+

Intent Agent

+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ +
+

Deployment Agent

+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ +
+

Compliance Agent

+
+ + +
+
+ + +
+
+ +
+
+ +
+
+
+
+ + +
+

+ API Endpoints +

+
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+ +
+
+ +

+ Test Connection +

+
+

+ Test your API connection to ensure everything is configured correctly +

+ + +
+
+ + +
+

+ Cloud Provider Credentials +

+ +
+
+
+ +

Amazon Web Services

+
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+ +

Microsoft Azure

+
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+ +

Google Cloud Platform

+
+
+ + +
+
+ + +
+ +
+
+
+ + +
+

+ Notification Preferences +

+ +
+

Email Notifications

+
+ + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+

Slack Integration

+
+ + +
+
+ + +
+
+ +
+
+ +
+

PagerDuty Integration

+
+ + +
+
+ + +
+
+ +
+
+
+
+ + + + + +