diff --git a/api/internal/api/stubs.go b/api/internal/api/stubs.go index 33464b70..fbd3ca5b 100644 --- a/api/internal/api/stubs.go +++ b/api/internal/api/stubs.go @@ -1,3 +1,43 @@ +// Package api provides HTTP handlers and WebSocket endpoints for the StreamSpace API. +// This file contains stub implementations, backwards compatibility handlers, +// Kubernetes resource management, and compliance endpoint stubs. +// +// STUB ENDPOINTS OVERVIEW: +// +// This file serves multiple purposes: +// 1. Backwards compatibility for routes migrated to specialized handlers +// 2. Kubernetes resource CRUD operations (generic resource management) +// 3. Stub endpoints for optional plugins (compliance, etc.) +// 4. WebSocket upgrader configuration with origin validation +// +// KUBERNETES RESOURCE MANAGEMENT: +// +// Generic endpoints for managing any Kubernetes resource: +// - CreateResource: Create any K8s resource (Deployment, Service, ConfigMap, etc.) +// - UpdateResource: Update existing K8s resources +// - DeleteResource: Delete K8s resources by type and name +// - ListNodes, ListPods, ListServices, etc.: List cluster resources +// - GetPodLogs: Stream or retrieve pod logs +// +// BACKWARDS COMPATIBILITY: +// +// Some endpoints like ListNodes() are stubs that redirect to specialized handlers: +// - Node management is now in handlers/nodes.go (NodeHandler) +// - User management is in handlers/users.go (UserHandler) +// - These stubs remain for API backwards compatibility during migration +// +// COMPLIANCE STUBS: +// +// The compliance endpoints return stub data when streamspace-compliance plugin +// is not installed. When the plugin is installed, it registers real handlers +// that override these stubs. +// +// WEBSOCKET CONFIGURATION: +// +// The WebSocket upgrader checks allowed origins from ALLOWED_ORIGINS environment +// variable to prevent CSRF attacks. Set to "*" to allow all origins (development only). +// +// Example ALLOWED_ORIGINS: "http://localhost:3000,https://streamspace.example.com" package api import ( @@ -26,7 +66,19 @@ var ( } ) -// WebSocket upgrader +// upgrader configures the WebSocket upgrader with security checks. +// It validates the Origin header to prevent CSRF attacks on WebSocket connections. +// +// Origin Validation: +// - Reads ALLOWED_ORIGINS environment variable (comma-separated list) +// - Default: "http://localhost:3000,http://localhost:5173" (development) +// - Production: Set to your actual domains (e.g., "https://streamspace.example.com") +// - "*" allows all origins (DANGEROUS - development only, never in production) +// +// Security Note: +// WebSocket connections cannot send custom headers from browsers, so we use +// query parameter authentication (?token=...) combined with Origin validation +// to prevent unauthorized cross-origin WebSocket connections. var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, @@ -602,7 +654,24 @@ func (h *Handler) UpdateConfig(c *gin.Context) { // are fully implemented in api/internal/handlers/users.go by UserHandler. // Those should be used instead of stub implementations. -// GetMetrics returns cluster metrics including nodes, sessions, resources, and users +// GetMetrics returns comprehensive cluster metrics for the admin dashboard. +// +// This endpoint aggregates data from multiple sources: +// - Kubernetes: Node count, resource capacity, allocatable resources, pod counts +// - Database: Session counts by state, user counts, active users (24hr) +// - Calculations: Resource utilization percentages +// +// Returned Metrics: +// - cluster.nodes: Total, ready, and not-ready node counts +// - cluster.sessions: Total, running, hibernated, and terminated session counts +// - cluster.resources: CPU, memory, and pod capacity/usage/percentages +// - cluster.users: Total user count and active users (logged in last 24 hours) +// +// Resource Estimates: +// Used CPU/memory are estimates based on running session count (1 core, 2GB per session). +// For accurate resource usage, deploy metrics-server and query real pod metrics. +// +// GET /api/v1/metrics func (h *Handler) GetMetrics(c *gin.Context) { ctx := c.Request.Context() diff --git a/ui/src/hooks/useEnterpriseWebSocket.ts b/ui/src/hooks/useEnterpriseWebSocket.ts index c8e20318..b1e93678 100644 --- a/ui/src/hooks/useEnterpriseWebSocket.ts +++ b/ui/src/hooks/useEnterpriseWebSocket.ts @@ -29,8 +29,61 @@ interface UseEnterpriseWebSocketReturn { } /** - * Custom hook for managing enterprise WebSocket connections - * Provides automatic reconnection, message handling, and connection status + * Custom hook for managing enterprise WebSocket connections. + * + * Provides a high-level WebSocket interface with automatic reconnection, + * message handling, and connection status. Designed for enterprise features + * like webhooks, security alerts, node health monitoring, and compliance. + * + * Features: + * - Automatic reconnection with custom backoff (30s, 15s, 15s, then 60s) + * - Authentication via query parameter (reactive to token changes) + * - Page visibility handling (reconnects when page becomes visible) + * - Typed message handling with WebSocketMessage interface + * - Manual connection control (connect, disconnect) + * + * Message Format: + * All messages follow the WebSocketMessage interface: + * ```ts + * { + * type: string; // Event type (e.g., 'webhook.delivery', 'security.alert') + * timestamp: string; // ISO 8601 timestamp + * data: object; // Event-specific data payload + * } + * ``` + * + * Reconnection Strategy: + * - 1st retry: 30 seconds after disconnect + * - 2nd retry: 15 seconds + * - 3rd retry: 15 seconds + * - 4th+ retries: 60 seconds each (up to maxReconnectAttempts) + * + * @param options - WebSocket configuration options + * @param options.onMessage - Optional callback when message received + * @param options.onError - Optional callback when error occurs + * @param options.onClose - Optional callback when connection closes + * @param options.onOpen - Optional callback when connection opens + * @param options.autoReconnect - Enable automatic reconnection (default: true) + * @param options.reconnectInterval - Ignored (kept for backwards compatibility) + * @param options.maxReconnectAttempts - Maximum reconnection attempts (default: 10) + * + * @returns WebSocket connection state and controls + * @returns isConnected - Boolean indicating if WebSocket is currently connected + * @returns lastMessage - Most recent WebSocketMessage received (or null) + * @returns sendMessage - Function to send JSON message (auto-stringified) + * @returns connect - Function to manually initiate connection + * @returns disconnect - Function to close connection and prevent reconnection + * @returns reconnectAttempts - Number of reconnection attempts made + * + * @example + * ```tsx + * const { isConnected, lastMessage } = useEnterpriseWebSocket({ + * onMessage: (message) => { + * console.log('Received:', message.type, message.data); + * }, + * onError: (error) => console.error('WebSocket error:', error), + * }); + * ``` */ export function useEnterpriseWebSocket( options: UseEnterpriseWebSocketOptions = {} @@ -278,7 +331,25 @@ export function useEnterpriseWebSocket( }; } -// Hook for listening to specific event types +/** + * Hook for listening to specific WebSocket event types. + * + * Filters WebSocket messages by event type and calls the handler only when + * messages of the specified type are received. Uses useEnterpriseWebSocket + * internally for connection management. + * + * @param eventType - Event type to listen for (e.g., 'webhook.delivery') + * @param handler - Callback function called when matching event received + * @param handler.data - Event data payload from message.data + * @param enabled - Whether event handling is enabled (default: true) + * + * @example + * ```tsx + * useWebSocketEvent('security.alert', (data) => { + * showNotification(`Security Alert: ${data.message}`); + * }); + * ``` + */ export function useWebSocketEvent( eventType: string, handler: (data: any) => void, @@ -302,55 +373,90 @@ export function useWebSocketEvent( }, [lastMessage, eventType, enabled]); } -// Predefined hooks for enterprise events +// ============================================================================ +// Predefined Event Hooks +// ============================================================================ +// +// These hooks provide convenient type-specific event listeners for common +// enterprise WebSocket events. Each hook uses useWebSocketEvent internally +// to filter messages by event type. +// +// Event Types: +// - webhook.delivery: Webhook delivery status updates +// - security.alert: Security alerts and violations +// - schedule.event: Session schedule events (start, stop, missed) +// - node.health: Kubernetes node health changes +// - scaling.event: Auto-scaling events (scale up/down) +// - compliance.violation: Compliance policy violations +// - user.event: User creation, updates, deletions +// - group.event: Group membership changes +// - quota.event: Quota threshold warnings +// - plugin.event: Plugin install, update, uninstall events +// - template.event: Template catalog updates +// - repository.event: Repository sync status changes +// - integration.event: Third-party integration events + +/** Hook for webhook delivery status updates */ export function useWebhookDeliveryEvents(handler: (data: any) => void) { useWebSocketEvent('webhook.delivery', handler); } +/** Hook for security alerts and violations */ export function useSecurityAlertEvents(handler: (data: any) => void) { useWebSocketEvent('security.alert', handler); } +/** Hook for session schedule events */ export function useScheduleEvents(handler: (data: any) => void) { useWebSocketEvent('schedule.event', handler); } +/** Hook for node health changes */ export function useNodeHealthEvents(handler: (data: any) => void) { useWebSocketEvent('node.health', handler); } +/** Hook for auto-scaling events */ export function useScalingEvents(handler: (data: any) => void) { useWebSocketEvent('scaling.event', handler); } +/** Hook for compliance policy violations */ export function useComplianceViolationEvents(handler: (data: any) => void) { useWebSocketEvent('compliance.violation', handler); } +/** Hook for user lifecycle events */ export function useUserEvents(handler: (data: any) => void) { useWebSocketEvent('user.event', handler); } +/** Hook for group membership changes */ export function useGroupEvents(handler: (data: any) => void) { useWebSocketEvent('group.event', handler); } +/** Hook for quota threshold warnings */ export function useQuotaEvents(handler: (data: any) => void) { useWebSocketEvent('quota.event', handler); } +/** Hook for plugin lifecycle events */ export function usePluginEvents(handler: (data: any) => void) { useWebSocketEvent('plugin.event', handler); } +/** Hook for template catalog updates */ export function useTemplateEvents(handler: (data: any) => void) { useWebSocketEvent('template.event', handler); } +/** Hook for repository sync status changes */ export function useRepositoryEvents(handler: (data: any) => void) { useWebSocketEvent('repository.event', handler); } +/** Hook for third-party integration events */ export function useIntegrationEvents(handler: (data: any) => void) { useWebSocketEvent('integration.event', handler); } diff --git a/ui/src/hooks/useWebSocket.ts b/ui/src/hooks/useWebSocket.ts index 5b42eae2..3dc805f8 100644 --- a/ui/src/hooks/useWebSocket.ts +++ b/ui/src/hooks/useWebSocket.ts @@ -19,10 +19,44 @@ interface UseWebSocketReturn { } /** - * Custom hook for WebSocket connections with automatic reconnection + * Custom hook for WebSocket connections with automatic reconnection. + * + * Features: + * - Automatic reconnection with custom backoff strategy (30s, 15s, 15s, then 60s) + * - Stable callbacks using refs to prevent reconnection loops + * - Connection state management + * - Manual connection control (send, close) + * + * Reconnection Strategy: + * - 1st retry: 30 seconds (allows transient issues to resolve) + * - 2nd retry: 15 seconds (quicker retry if still failing) + * - 3rd retry: 15 seconds + * - 4th+ retries: 60 seconds each (prevents hammering the server) * * @param options - WebSocket configuration options + * @param options.url - WebSocket URL to connect to (empty string disables connection) + * @param options.onMessage - Callback when message received (data is pre-parsed JSON) + * @param options.onError - Optional callback when error occurs + * @param options.onOpen - Optional callback when connection opens + * @param options.onClose - Optional callback when connection closes + * @param options.reconnectInterval - Ignored (kept for backwards compatibility) + * @param options.maxReconnectAttempts - Maximum reconnection attempts (default: 10) + * * @returns WebSocket connection state and controls + * @returns isConnected - Boolean indicating if WebSocket is currently connected + * @returns reconnectAttempts - Number of reconnection attempts made + * @returns sendMessage - Function to send JSON message (auto-stringified) + * @returns close - Function to close connection and prevent reconnection + * + * @example + * ```tsx + * const { isConnected, sendMessage } = useWebSocket({ + * url: 'wss://example.com/ws', + * onMessage: (data) => console.log('Received:', data), + * onError: (error) => console.error('WebSocket error:', error), + * maxReconnectAttempts: 5, + * }); + * ``` */ export function useWebSocket({ url, @@ -176,9 +210,28 @@ export function useWebSocket({ } /** - * Hook for subscribing to session updates via WebSocket - * Only connects when a valid authentication token is available - * Uses Zustand store for reactive token updates + * Hook for subscribing to real-time session updates via WebSocket. + * + * Automatically connects to the sessions WebSocket endpoint when a valid + * authentication token is available. Disconnects when token is removed. + * + * Features: + * - Reactive to authentication state (auto-connects/disconnects with token changes) + * - Receives real-time session creation, updates, and deletion events + * - Uses Zustand store for seamless token reactivity + * - Automatically parses and filters 'sessions_update' events + * + * @param onUpdate - Callback function called when sessions are updated + * @param onUpdate.sessions - Array of updated session objects + * + * @returns WebSocket connection state from useWebSocket hook + * + * @example + * ```tsx + * const { isConnected } = useSessionsWebSocket((sessions) => { + * setMySessions(sessions); + * }); + * ``` */ export function useSessionsWebSocket(onUpdate: (sessions: any[]) => void) { // Get token directly from Zustand store - automatically reactive @@ -219,9 +272,28 @@ export function useSessionsWebSocket(onUpdate: (sessions: any[]) => void) { } /** - * Hook for subscribing to cluster metrics via WebSocket - * Only connects when a valid authentication token is available - * Uses Zustand store for reactive token updates + * Hook for subscribing to real-time cluster metrics via WebSocket. + * + * Provides live updates of cluster resource usage, node health, and session counts. + * Only connects when authenticated (requires admin or operator role on backend). + * + * Features: + * - Reactive to authentication state + * - Receives real-time cluster metrics updates (CPU, memory, nodes, sessions) + * - Automatically parses and filters 'metrics_update' events + * - Admin/operator only (regular users will get 403 Forbidden) + * + * @param onUpdate - Callback function called when cluster metrics are updated + * @param onUpdate.metrics - Object containing cluster metrics (nodes, resources, sessions, users) + * + * @returns WebSocket connection state from useWebSocket hook + * + * @example + * ```tsx + * const { isConnected } = useMetricsWebSocket((metrics) => { + * setClusterMetrics(metrics); + * }); + * ``` */ export function useMetricsWebSocket(onUpdate: (metrics: any) => void) { // Get token directly from Zustand store - automatically reactive @@ -262,9 +334,34 @@ export function useMetricsWebSocket(onUpdate: (metrics: any) => void) { } /** - * Hook for subscribing to pod logs via WebSocket - * Only connects when a valid authentication token is available - * Uses Zustand store for reactive token updates + * Hook for streaming pod logs in real-time via WebSocket. + * + * Tails pod logs and streams each new log line as it's written. Useful for + * debugging session pods or monitoring system components. + * + * Features: + * - Real-time log streaming (follows logs as they're written) + * - Reactive to authentication state + * - Admin/operator only (regular users will get 403 Forbidden) + * - Automatically reconnects if connection drops + * + * @param namespace - Kubernetes namespace containing the pod + * @param podName - Name of the pod to stream logs from + * @param onLog - Callback function called for each log line + * @param onLog.log - Single log line as a string + * + * @returns WebSocket connection state from useWebSocket hook + * + * @example + * ```tsx + * const { isConnected } = useLogsWebSocket( + * 'streamspace', + * 'session-user1-firefox-abc123', + * (log) => { + * appendLog(log); + * } + * ); + * ``` */ export function useLogsWebSocket(namespace: string, podName: string, onLog: (log: string) => void) { // Get token directly from Zustand store - automatically reactive diff --git a/ui/src/pages/admin/Compliance.tsx b/ui/src/pages/admin/Compliance.tsx index 15f94c3f..6b221895 100644 --- a/ui/src/pages/admin/Compliance.tsx +++ b/ui/src/pages/admin/Compliance.tsx @@ -1,3 +1,46 @@ +/** + * Compliance Admin Page + * + * Provides comprehensive compliance management for StreamSpace administrators. + * + * Features: + * - View compliance dashboard with framework and violation metrics + * - Manage compliance frameworks (SOC2, HIPAA, GDPR, PCI-DSS, etc.) + * - Create and manage compliance policies + * - Track and resolve policy violations + * - Real-time compliance violation alerts via WebSocket + * - Violation severity filtering (critical, high, medium, low) + * - Framework-specific policy templates + * + * Compliance Frameworks: + * Supports industry-standard compliance frameworks: + * - SOC 2: Service Organization Control 2 + * - HIPAA: Health Insurance Portability and Accountability Act + * - GDPR: General Data Protection Regulation + * - PCI-DSS: Payment Card Industry Data Security Standard + * - ISO 27001: Information Security Management + * - NIST: National Institute of Standards and Technology + * + * Policy Types: + * - Data Retention: Automatically delete data after specified period + * - Access Control: Enforce MFA, SSO, role-based access + * - Audit Logging: Comprehensive activity logging + * - Encryption: Data encryption at rest and in transit + * - Session Timeout: Auto-logout after inactivity + * - Network Isolation: IP whitelisting, VPN requirements + * + * Violation Management: + * - View all open and resolved violations + * - Filter by severity, framework, and policy + * - Manually resolve violations with notes + * - Auto-generated violation reports + * + * Plugin Integration: + * This page shows stub data when the streamspace-compliance plugin is not installed. + * Install the plugin from Admin → Plugins to enable full compliance features. + * + * @component + */ import { useState, useEffect } from 'react'; import { Box, diff --git a/ui/src/pages/admin/Nodes.tsx b/ui/src/pages/admin/Nodes.tsx index 6f024ac5..c02242ef 100644 --- a/ui/src/pages/admin/Nodes.tsx +++ b/ui/src/pages/admin/Nodes.tsx @@ -1,3 +1,36 @@ +/** + * Nodes Admin Page + * + * Provides comprehensive Kubernetes node management for StreamSpace administrators. + * + * Features: + * - View all cluster nodes with health status (Ready, NotReady) + * - Monitor node resources (CPU, memory, pods) and utilization + * - Add/remove node labels for session pod scheduling + * - Add/remove node taints for workload isolation + * - Cordon nodes to prevent new pod scheduling + * - Uncordon nodes to resume scheduling + * - Drain nodes to evict pods for maintenance + * - Real-time updates via WebSocket (node health events) + * - Cluster-wide statistics (total capacity, allocatable resources) + * + * Node Operations: + * - Label Management: Click "Manage Labels" to add labels like `gpu=true` + * - Taint Management: Click "Manage Taints" to add taints (NoSchedule, PreferNoSchedule, NoExecute) + * - Cordon: Mark node as unschedulable (existing pods continue running) + * - Drain: Evict all pods gracefully with configurable grace period + * + * Typical Workflow (Node Maintenance): + * 1. Cordon node to prevent new sessions from scheduling + * 2. Drain node to move existing sessions to other nodes + * 3. Perform maintenance (OS updates, hardware changes, etc.) + * 4. Uncordon node to resume normal scheduling + * + * Real-time Updates: + * Subscribes to `node.health` WebSocket events for live node status changes. + * + * @component + */ import { useState, useEffect, useRef } from 'react'; import { Box,