Documentation
¶
Overview ¶
Package handlers provides HTTP handlers for the StreamSpace API. This file implements session activity tracking and heartbeat management.
ACTIVITY TRACKING: - Session heartbeat recording to prevent auto-hibernation - Activity status queries (active, idle, hibernation eligibility) - Idle duration calculation - Last activity timestamp tracking
HEARTBEAT MECHANISM: - Clients send periodic heartbeats to indicate active usage - Updates session's lastActivity timestamp - Prevents idle timeout and auto-hibernation - Typically sent every 30-60 seconds from active sessions
ACTIVITY STATUS: - Is session currently active (recent heartbeat) - Is session idle (exceeded idle threshold) - Time since last activity - Should session be hibernated (idle + threshold exceeded) - Configurable idle thresholds per session
USE CASES: - Auto-hibernation prevention for active sessions - Resource optimization by hibernating idle sessions - User activity analytics - Session health monitoring
API Endpoints: - POST /api/v1/sessions/:id/heartbeat - Record session heartbeat - GET /api/v1/sessions/:id/activity - Get session activity status
Thread Safety: - Activity tracker is thread-safe with mutex protection - Kubernetes client operations are thread-safe
Dependencies: - Kubernetes: Session CRDs with status updates - Activity Tracker: In-memory tracking with persistence - External Services: None
Example Usage:
handler := NewActivityHandler(k8sClient, activityTracker)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements the WebSocket handler for agent connections.
AGENT WEBSOCKET CONNECTION: - Agents connect to GET /api/v1/agents/connect?agent_id=xxx - Connection is upgraded from HTTP to WebSocket - Agent sends heartbeats every 10 seconds - Control Plane sends commands to agent - Agent sends back ack/complete/failed/status messages
MESSAGE FLOW: Control Plane → Agent:
- command: Execute a session command
- ping: Keep-alive ping
- shutdown: Graceful shutdown
Agent → Control Plane:
- heartbeat: Regular status update
- ack: Command acknowledged
- complete: Command completed
- failed: Command failed
- status: Session status update
CONNECTION LIFECYCLE: 1. Agent sends HTTP GET to /api/v1/agents/connect?agent_id=xxx 2. Handler validates agent exists in database 3. HTTP connection upgraded to WebSocket 4. Connection registered with AgentHub 5. readPump and writePump goroutines started 6. Agent sends heartbeats every 10 seconds 7. On disconnect, connection unregistered from hub
Thread Safety: - readPump and writePump run concurrently - Each connection has dedicated Send/Receive channels - Hub handles all synchronization
Package handlers provides HTTP handlers for the StreamSpace API. This file implements agent registration and management for the v2.0 multi-platform architecture.
AGENT ARCHITECTURE: - Agents are platform-specific execution agents (Kubernetes, Docker, VM, Cloud) - Agents connect to Control Plane via outbound WebSocket connection - Agents receive commands to start/stop/hibernate sessions - Agents tunnel VNC traffic back to Control Plane - Agents send heartbeats every 10 seconds
AGENT PLATFORMS: - kubernetes: Kubernetes cluster agent - docker: Docker host agent - vm: Virtual machine agent - cloud: Cloud provider agent (AWS, Azure, GCP)
AGENT STATUS: - online: Agent is connected and healthy - offline: Agent is disconnected - draining: Agent is not accepting new sessions
API Endpoints: - POST /api/v1/agents/register - Register agent (or re-register) - GET /api/v1/agents - List all agents (with filters) - GET /api/v1/agents/:agent_id - Get agent details - DELETE /api/v1/agents/:agent_id - Deregister agent - POST /api/v1/agents/:agent_id/heartbeat - Update heartbeat - POST /api/v1/agents/:agent_id/command - Send command to agent
Thread Safety: - All database operations are thread-safe
Dependencies: - Database: agents table (v2.0 schema) - Models: api/internal/models/agent.go - AgentHub: WebSocket connection manager - CommandDispatcher: Command queuing and dispatch
Example Usage:
handler := NewAgentHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements API key management for programmatic API access.
API KEY FEATURES: - Secure API key generation with cryptographic randomness - API key CRUD operations (create, list, revoke, delete) - Key metadata (name, description, scopes, rate limits) - Expiration support with configurable durations - Usage tracking (last used timestamp, use count) - Active/inactive state management
SECURITY: - Keys hashed with SHA-256 before storage (never stored in plaintext) - Prefix-based identification (first 8 characters for UI display) - Keys prefixed with "sk_" for easy identification - 32 bytes of cryptographic randomness (256 bits) - Keys only shown once during creation (cannot be retrieved later)
API KEY STRUCTURE: - Format: sk_{base64_encoded_random_bytes} - Storage: SHA-256 hash in database - Display: First 8 characters (sk_xxxxx...)
SCOPE MANAGEMENT: - Configurable scopes limit API key permissions - Examples: sessions:read, sessions:write, admin:all - Scope validation during API requests
RATE LIMITING: - Per-key rate limits independent of user limits - Configurable requests per time window - Tracked via use_count and last_used_at
EXPIRATION: - Optional expiration with duration strings (30d, 1y, etc.) - Automatic enforcement during authentication - Expired keys cannot authenticate
API Endpoints: - POST /api/v1/apikeys - Create new API key - GET /api/v1/apikeys - List user's API keys - GET /api/v1/apikeys/:id - Get API key details - PUT /api/v1/apikeys/:id - Update API key metadata - DELETE /api/v1/apikeys/:id - Delete/revoke API key - POST /api/v1/apikeys/:id/rotate - Rotate API key (generate new)
Thread Safety: - All database operations are thread-safe via connection pooling - Cryptographic random generation is thread-safe
Dependencies: - Database: api_keys table - External Services: None
Example Usage:
handler := NewAPIKeyHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements installed application management endpoints.
APPLICATION FEATURES: - Install applications from catalog templates - Custom display names for user dashboards - Application configuration management - Enable/disable applications - Group-based access control
ACCESS CONTROL: - Grant/revoke group access to applications - Multiple access levels (view, launch, admin) - Filter applications by user's group membership
API Endpoints: - GET /api/v1/applications - List all installed applications - POST /api/v1/applications - Install a new application - GET /api/v1/applications/:id - Get application details - PUT /api/v1/applications/:id - Update application - DELETE /api/v1/applications/:id - Delete application - PUT /api/v1/applications/:id/enabled - Enable/disable application - GET /api/v1/applications/:id/groups - Get groups with access - POST /api/v1/applications/:id/groups - Add group access - PUT /api/v1/applications/:id/groups/:groupId - Update group access level - DELETE /api/v1/applications/:id/groups/:groupId - Remove group access - GET /api/v1/applications/:id/config - Get template config options - GET /api/v1/applications/user - Get applications accessible to current user
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: installed_applications, application_group_access tables
Example Usage:
handler := NewApplicationHandler(database, publisher, "kubernetes")
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements audit log retrieval and export for compliance and security.
AUDIT LOG VIEWER: - Retrieve audit logs with filtering and pagination - Export audit logs for compliance reports (CSV/JSON) - Search and analyze security events - Track user activity and system changes
COMPLIANCE SUPPORT: - SOC2: Audit trail of all system changes (1 year retention) - HIPAA: PHI access logging (6 year retention) - GDPR: Data processing activity records - ISO 27001: User activity logging
FILTERING CAPABILITIES: - Filter by user ID or username - Filter by action (GET, POST, PUT, DELETE) - Filter by resource type (/api/sessions, /api/users, etc.) - Filter by date range (start_date, end_date) - Filter by IP address (security investigations) - Filter by status code (200, 401, 500, etc.)
EXPORT FORMATS: - JSON: Machine-readable, full details - CSV: Human-readable, spreadsheet-compatible - Both formats include all relevant fields for compliance
USE CASES: - Security incident investigation - Compliance audits and reporting - User activity analysis - System change tracking - Failed access attempt detection
API Endpoints: - GET /api/v1/admin/audit - List audit logs (with filters) - GET /api/v1/admin/audit/:id - Get specific audit log entry - GET /api/v1/admin/audit/export - Export audit logs to CSV/JSON
Thread Safety: - Database operations are thread-safe - Read-only queries, no state modification
Dependencies: - Database: PostgreSQL audit_log table - Middleware: Audit logging middleware (captures all requests)
Example Usage:
handler := NewAuditHandler(database)
handler.RegisterRoutes(router.Group("/api/v1/admin"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements batch operations for bulk resource management.
BATCH OPERATION FEATURES: - Bulk session operations (terminate, hibernate, wake, delete) - Bulk snapshot operations (create, delete) - Bulk template operations (install, delete) - Asynchronous job execution with progress tracking - Job status monitoring and cancellation
OPERATION TYPES: - terminate: Stop multiple running sessions - hibernate: Put multiple sessions into hibernated state - wake: Resume multiple hibernated sessions - delete: Remove multiple sessions/snapshots/templates - update: Bulk update tags or resource limits
BATCH JOB LIFECYCLE: 1. Job creation: Create batch_operations record 2. Async execution: Process items in background goroutine 3. Progress tracking: Update processed/success/failure counts 4. Completion: Mark job as completed or failed 5. Cleanup: Jobs can be cancelled or deleted
JOB STATUS TRACKING: - Total items to process - Processed items count - Success count - Failure count - Errors array for failed items - Created/completed timestamps
ASYNC EXECUTION: - All batch operations run asynchronously - Immediate job ID returned to client - Client polls job status endpoint for progress - WebSocket notifications for real-time updates
ERROR HANDLING: - Partial failures: Continue processing remaining items - Error collection: Record all errors for debugging - Job status reflects overall success/failure
API Endpoints: - POST /api/v1/batch/sessions/terminate - Terminate multiple sessions - POST /api/v1/batch/sessions/hibernate - Hibernate multiple sessions - POST /api/v1/batch/sessions/wake - Wake multiple sessions - POST /api/v1/batch/sessions/delete - Delete multiple sessions - POST /api/v1/batch/sessions/update-tags - Update session tags - POST /api/v1/batch/sessions/update-resources - Update resource limits - POST /api/v1/batch/snapshots/delete - Delete multiple snapshots - POST /api/v1/batch/snapshots/create - Create multiple snapshots - POST /api/v1/batch/templates/install - Install multiple templates - POST /api/v1/batch/templates/delete - Delete multiple templates - GET /api/v1/batch/jobs - List batch jobs - GET /api/v1/batch/jobs/:id - Get batch job status - DELETE /api/v1/batch/jobs/:id - Cancel batch job
Thread Safety: - All database operations are thread-safe via connection pooling - Goroutines for async execution are properly managed
Dependencies: - Database: batch_operations, sessions, snapshots, templates tables - External Services: None
Example Usage:
handler := NewBatchHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements template catalog browsing, ratings, and statistics.
CATALOG FEATURES: - Template discovery with advanced search and filtering - Featured, trending, and popular template lists - User ratings and reviews system - View and install tracking for analytics
SEARCH AND FILTERING: - Full-text search across template names and descriptions - Filter by category, tags, app type - Sort by popularity, rating, recency, or install count - Pagination support with customizable page size
RATINGS AND REVIEWS: - Add, update, and delete template ratings - Star ratings (1-5 scale) - User comments and reviews - Average rating calculation - Rating count tracking
STATISTICS: - View count tracking (catalog impressions) - Install count tracking (template usage) - Trending calculation based on recent activity - Popular templates based on install count
API Endpoints: - GET /api/v1/catalog/templates - List templates with filters and search - GET /api/v1/catalog/templates/:id - Get template details - GET /api/v1/catalog/templates/featured - List featured templates - GET /api/v1/catalog/templates/trending - List trending templates - GET /api/v1/catalog/templates/popular - List popular templates - POST /api/v1/catalog/templates/:id/ratings - Add rating/review - GET /api/v1/catalog/templates/:id/ratings - Get template ratings - PUT /api/v1/catalog/templates/:id/ratings/:ratingId - Update rating - DELETE /api/v1/catalog/templates/:id/ratings/:ratingId - Delete rating - POST /api/v1/catalog/templates/:id/view - Record template view - POST /api/v1/catalog/templates/:id/install - Record template install
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: catalog_templates, repositories, template_ratings tables - External Services: Repository sync for template metadata
Example Usage:
handler := NewCatalogHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers - collaboration.go ¶
This file implements real-time collaboration features for StreamSpace sessions.
Collaboration System Overview ¶
The collaboration system enables multiple users to work together in a single session with features like chat, annotations, cursor tracking, and screen sharing. This transforms StreamSpace from single-user isolated sessions into a collaborative platform for remote teamwork.
Use Cases ¶
**Pair Programming**:
- Developer A creates session with VS Code
- Developer B joins as collaborator with control permissions
- Both can see cursor positions and type code
- Chat for quick questions without switching context
**Teaching/Training**:
- Instructor creates session with training application
- Students join as viewers (read-only)
- Instructor uses annotations to highlight important areas
- Follow mode keeps students in sync with instructor's view
**Support/Troubleshooting**:
- User creates session with problematic application
- Support agent joins with control permissions
- Agent diagnoses issue while user watches
- Chat for real-time communication
**Design Review**:
- Designer creates session with design tool
- Team joins as participants
- Annotations for feedback directly on designs
- Hand-raise feature for structured Q&A
Architecture ¶
Collaboration combines WebSocket (real-time) + database (persistence):
┌────────────────────────────────────────────────────────┐
│ Collaboration Session │
│ - Owner creates session │
│ - Participants join via invite/link │
│ - Real-time sync via WebSocket │
│ - State persisted to database │
└──────────────┬─────────────────────────────────────────┘
│
┌───────┴───────┬─────────────┬─────────────┐
▼ ▼ ▼ ▼
Owner Presenter Participant Viewer
(Full access) (Can control) (Can chat) (Read-only)
**WebSocket Integration**:
- Cursor movements broadcast to all participants
- Chat messages delivered in real-time
- Annotations synced across all viewers
- Presence updates (user joined/left)
**Database Persistence**:
- Collaboration sessions stored in collaboration_sessions table
- Participants tracked in collaboration_participants table
- Chat history in collaboration_messages table
- Annotations in collaboration_annotations table
Permission Model ¶
Collaboration uses a role-based permission system:
**Owner Role** (session creator):
- Full control over session
- Can change settings
- Can promote/demote participants
- Can end collaboration
- Cannot be removed
**Presenter Role** (co-host):
- Can control the session
- Can annotate and chat
- Can invite others
- Others can follow their view
- Can be demoted by owner
**Participant Role** (active user):
- Can chat and annotate
- Can view cursor positions
- Cannot control session
- Limited to max participants count
**Viewer Role** (read-only):
- Can only view session
- Cannot interact or chat
- Unlimited viewers allowed
- Useful for webinars/demos
Permissions are granular:
- can_control: Mouse/keyboard input
- can_annotate: Draw on screen
- can_chat: Send messages
- can_invite: Add participants
- can_manage: Change settings
- can_record: Start recording
Real-Time Features ¶
**Cursor Tracking**:
- Each user's cursor shown with their color and label
- Position updated every 50ms (throttled)
- Cursors fade after 5s of inactivity
- Can be disabled in settings
**Chat System**:
- Text messages with timestamps
- System messages (user joined, settings changed)
- Reactions (emoji responses to messages)
- Message history persisted
- Can be disabled by owner
**Annotations**:
- Drawing tools: line, arrow, rectangle, circle, freehand
- Text annotations
- Color and thickness customization
- Persistent vs temporary (expires after 30s)
- Can be cleared by owner/presenter
**Follow Mode**:
- Follow presenter: Viewers automatically pan/zoom with presenter
- Follow owner: Alternative mode for presentations
- Can be toggled on/off by participants
- Prevents viewer viewport drift
Concurrency Handling ¶
Multiple users interacting simultaneously requires careful synchronization:
- **Optimistic Locking**: Annotations use version numbers
- **Event Ordering**: WebSocket messages timestamped for consistency
- **Conflict Resolution**: Last-write-wins for cursor positions
- **Rate Limiting**: Max 100 events/sec per user (prevent spam)
Example conflict scenario:
- User A and User B both create annotation at same time
- Both annotations stored with timestamps
- UI renders both (no conflict)
- If same annotation ID, newer timestamp wins
Performance Characteristics ¶
Performance metrics (tested with 50 concurrent collaborators):
- **Cursor latency**: <50ms from movement to display on other screens
- **Chat latency**: <100ms from send to delivery
- **Annotation sync**: <200ms for complex drawings
- **Memory per session**: ~5 MB (includes cursor positions, annotations)
- **Database queries**: ~10 queries/sec for active 10-user session
Scaling limits:
- **Recommended max**: 10 active participants (can_control)
- **Tested max**: 50 viewers (read-only)
- **Bottleneck**: WebSocket broadcast bandwidth
Security Considerations ¶
Collaboration introduces new attack vectors:
- **Invitation System**: Only owner can invite (no public join)
- **Approval Mode**: Owner approves join requests (optional)
- **Permission Enforcement**: Server validates all actions
- **Input Sanitization**: Chat messages and annotations sanitized
- **Rate Limiting**: Prevent spam/DoS via excessive cursors/annotations
Prevented attacks:
- **Unauthorized join**: JWT + session ownership verified
- **Privilege escalation**: Roles cannot be self-promoted
- **XSS in chat**: All messages HTML-escaped
- **DoS via annotations**: Max 100 annotations per user
Database Schema ¶
**collaboration_sessions**:
- id, session_id, owner_id, settings, status, created_at, ended_at
**collaboration_participants**:
- id, collaboration_id, user_id, role, permissions, joined_at, last_seen_at
**collaboration_messages**:
- id, collaboration_id, user_id, message, message_type, created_at
**collaboration_annotations**:
- id, collaboration_id, user_id, type, points, is_persistent, created_at
**collaboration_cursors** (in-memory only, not persisted):
- user_id, x, y, timestamp, color
Known Limitations ¶
- **Single instance**: No cross-server collaboration (yet)
- **No video/audio**: Text chat only (no voice calling)
- **No screen regions**: Can't restrict viewer to specific area
- **No undo/redo**: Annotations permanent until deleted
- **No file sharing**: Chat is text-only
Future enhancements:
- WebRTC for audio/video calling
- Multi-server collaboration via Redis
- Recording collaboration sessions
- Annotation history with undo/redo
- File sharing in chat
- Breakout rooms for sub-groups
Example Usage ¶
**Creating a collaboration session**:
POST /api/sessions/{sessionId}/collaboration
{
"settings": {
"follow_mode": "follow_presenter",
"max_participants": 10,
"require_approval": true,
"show_cursor_labels": true
}
}
**Joining a collaboration session**:
POST /api/collaboration/{collabId}/join
{
"role": "participant"
}
**Sending chat message**:
POST /api/collaboration/{collabId}/chat
{
"message": "Hello team!"
}
**Creating annotation**:
POST /api/collaboration/{collabId}/annotations
{
"type": "arrow",
"points": [{"x": 100, "y": 100}, {"x": 200, "y": 200}],
"color": "#FF0000",
"is_persistent": true
}
Package handlers provides HTTP handlers for the StreamSpace API. This file implements system configuration management for platform settings.
SYSTEM CONFIGURATION: - CRUD operations for platform-wide settings - Category-based organization (Ingress, Storage, Resources, Features, Session, Security, Compliance) - Type-aware validation (string, boolean, number, duration, enum, array) - Configuration testing before applying changes - Change history tracking
CONFIGURATION CATEGORIES: 1. Ingress: domain, TLS settings 2. Storage: storage class, default sizes, allowed classes 3. Resources: default CPU/memory limits, max limits 4. Features: feature toggles (metrics, hibernation, recordings) 5. Session: idle timeout, max duration, allowed images 6. Security: MFA required, SAML/OIDC enabled, IP whitelist 7. Compliance: frameworks enabled, retention days, archiving
USE CASES: - Platform deployment configuration - Feature flag management - Resource limit enforcement - Security policy configuration - Compliance settings management
API Endpoints: - GET /api/v1/admin/config - List all settings (optional category filter) - GET /api/v1/admin/config/:key - Get specific setting - PUT /api/v1/admin/config/:key - Update setting with validation - POST /api/v1/admin/config/bulk - Bulk update multiple settings
Thread Safety: - Database operations are thread-safe - Validation happens before update
Dependencies: - Database: PostgreSQL configuration table
Example Usage:
handler := NewConfigurationHandler(database)
handler.RegisterRoutes(router.Group("/api/v1/admin"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements console access and file management for sessions.
CONSOLE FEATURES: - Interactive terminal access to sessions via WebSocket - File manager for browsing session filesystems - File operations (create, delete, rename, copy, move, upload, download) - Multi-shell support (bash, sh, zsh) - Terminal resize and configuration
TERMINAL SESSIONS: - WebSocket-based terminal connections - Configurable rows and columns - Shell type selection (bash, sh, zsh) - Activity tracking and idle timeout - Terminal status monitoring
FILE MANAGEMENT: - Directory browsing with file metadata - File/directory creation and deletion - File rename, copy, and move operations - File upload and download - Permissions, ownership, and size information - MIME type detection - Symlink target resolution
FILE OPERATIONS: - Create: Create new files or directories - Delete: Remove files or directories - Rename: Rename files or directories - Copy: Duplicate files or directories - Move: Move files between locations - Upload: Upload files to session - Download: Download files from session
SECURITY: - Access control via session ownership or sharing - User authentication required - Path validation to prevent directory traversal - Permission checks for file operations
API Endpoints: - POST /api/v1/sessions/:sessionId/console - Create console session - GET /api/v1/console/:consoleId - Get console session details - DELETE /api/v1/console/:consoleId - Disconnect console session - GET /api/v1/console/:consoleId/files - List files in directory - POST /api/v1/console/:consoleId/files - Create file/directory - DELETE /api/v1/console/:consoleId/files - Delete file/directory - PUT /api/v1/console/:consoleId/files/rename - Rename file/directory - POST /api/v1/console/:consoleId/files/copy - Copy file/directory - POST /api/v1/console/:consoleId/files/move - Move file/directory - POST /api/v1/console/:consoleId/files/upload - Upload files - GET /api/v1/console/:consoleId/files/download - Download files
Thread Safety: - All database operations are thread-safe via connection pooling - File operations are isolated per session
Dependencies: - Database: console_sessions, sessions, session_shares tables - External Services: Session container filesystem access
Example Usage:
// Create console handler (integrated in main handler)
handler.RegisterConsoleRoutes(router.Group("/api/v1"))
Package handlers defines constants for HTTP handlers.
This file centralizes all "magic numbers" and timeout values to: - Make configuration changes easier (single source of truth) - Improve code readability (named constants vs. bare numbers) - Document the reasoning behind specific values - Enable easy tuning for different environments
SECURITY FIX (2025-11-14): Extracted all magic numbers to named constants as part of code quality improvements. This makes it easier to understand security-critical values like rate limits, timeouts, and buffer sizes.
Categories: - MFA: Multi-factor authentication limits and timing - WebSocket: Connection parameters and buffer sizes - Webhook: Retry logic and timeouts - Session: Verification and expiry times
Package handlers provides HTTP handlers for the StreamSpace API. This file implements dashboard statistics and resource usage queries.
DASHBOARD FEATURES: - Platform-wide statistics (users, sessions, templates, connections) - Resource usage tracking (CPU, memory, storage quotas) - Recent activity metrics (last 24 hours) - Real-time data from Kubernetes and database
PLATFORM STATISTICS: - Total and active user counts - Session counts by state (running, hibernated, total) - Template count from Kubernetes CRDs - Active connection count - 24-hour activity metrics
RESOURCE USAGE: - Quota utilization per user or platform-wide - CPU usage (millicores) - Memory usage (bytes/GB) - Storage usage (bytes/GB) - Session count against quotas
DATA SOURCES: - Database: User, session, connection tables - Kubernetes: Template CRDs, resource quotas - Hybrid queries for comprehensive metrics
API Endpoints: - GET /api/v1/dashboard/platform-stats - Overall platform statistics - GET /api/v1/dashboard/resource-usage - Resource usage metrics
Thread Safety: - All database operations are thread-safe via connection pooling - Kubernetes client operations are thread-safe
Dependencies: - Database: users, sessions, connections tables - Kubernetes: Template CRDs, namespace resources - External Services: None
Example Usage:
handler := NewDashboardHandler(database, k8sClient) // Routes registered in main API router
Package handlers provides HTTP handlers for the StreamSpace API. This file implements API documentation endpoints serving OpenAPI/Swagger specification and interactive documentation UI.
ENDPOINTS: - GET /api/docs - Swagger UI (interactive documentation) - GET /api/docs/ - Swagger UI (with trailing slash) - GET /api/openapi.yaml - OpenAPI 3.0 specification (YAML) - GET /api/openapi.json - OpenAPI 3.0 specification (JSON)
FEATURES: - Embedded Swagger UI via CDN (no local assets required) - OpenAPI 3.0 compliant specification - YAML and JSON format support - No authentication required (public documentation)
Package handlers provides HTTP handlers for the StreamSpace API. This file implements group management and group-level resource operations.
GROUP MANAGEMENT: - Group CRUD operations (list, create, read, update, delete) - Group filtering by type or parent group (supports hierarchical groups) - Group member management (add, remove, update roles) - Member enrichment with user information
GROUP MEMBERSHIP: - Add users to groups with specific roles - Remove users from groups - Update member roles within groups - List all members with enriched user details - User existence validation before adding to groups
GROUP QUOTAS: - Shared resource quotas for group members - Group-level limits for sessions, CPU, memory, storage - Quota retrieval and modification
API Endpoints: - GET /api/v1/groups - List all groups with optional filters - POST /api/v1/groups - Create new group - GET /api/v1/groups/:id - Get group by ID - PATCH /api/v1/groups/:id - Update group information - DELETE /api/v1/groups/:id - Delete group - GET /api/v1/groups/:id/members - List group members - POST /api/v1/groups/:id/members - Add user to group - DELETE /api/v1/groups/:id/members/:userId - Remove user from group - PATCH /api/v1/groups/:id/members/:userId - Update member role - GET /api/v1/groups/:id/quota - Get group quota - PUT /api/v1/groups/:id/quota - Set group quota
Security: - Password hashes removed from user objects in member lists - User existence validated before membership operations
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: groups, group_members, group_quotas, users tables - External Services: None
Example Usage:
handler := NewGroupHandler(groupDB, userDB)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements enterprise integration features including webhooks and external API integrations.
Security Features: - Webhook HMAC signature validation (prevents spoofing) - SSRF protection for webhook URLs (prevents internal network access) - Input validation for all integration configurations - Secret management (webhooks secrets never exposed in GET responses) - Authorization enumeration prevention (consistent error responses)
CRITICAL SECURITY FIXES (2025-11-14): 1. SSRF Protection: validateWebhookURL prevents webhooks from targeting:
Private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
Loopback addresses (127.0.0.0/8)
Link-local addresses (169.254.0.0/16)
Cloud metadata endpoints (169.254.169.254)
Internal hostnames (metadata.google.internal, localhost, etc.)
2. Secret Protection: Webhook secrets use json:"-" tags and separate response structs to ensure secrets are only shown during creation, never in GET endpoints.
3. Authorization Enumeration Fixes: UpdateWebhook, DeleteWebhook, TestWebhook, and TestIntegration all return consistent "not found" errors for both non-existent resources AND unauthorized access (prevents attacker enumeration).
4. Input Validation: Comprehensive validation for all webhook and integration fields including URL format, name length, event counts, retry configuration, etc.
Webhook Delivery: - Automatic retries with exponential backoff - HMAC-SHA256 signature in X-Webhook-Signature header - 10-second timeout per delivery attempt - Real-time delivery status updates via WebSocket
Integrations: - External API connections (Slack, Discord, PagerDuty, etc.) - OAuth 2.0 token management - API key storage and rotation - Connection health monitoring
Package handlers provides HTTP handlers for the StreamSpace API. This file implements license management for platform licensing and feature enforcement.
LICENSE MANAGEMENT: - License activation and validation - Feature toggling based on tier (Community, Pro, Enterprise) - Resource limit enforcement (users, sessions, nodes) - Usage tracking and trending - License expiration monitoring
LICENSE TIERS: - Community (Free): 10 users, 20 sessions, 3 nodes, basic auth only - Pro: 100 users, 200 sessions, 10 nodes, SAML/OIDC/MFA/recordings - Enterprise: Unlimited users/sessions/nodes, all features + SLA
API Endpoints: - GET /api/v1/admin/license - Get current license details - POST /api/v1/admin/license/activate - Activate new license key - PUT /api/v1/admin/license/update - Update/renew license - GET /api/v1/admin/license/usage - Current usage vs. limits - POST /api/v1/admin/license/validate - Validate license key - GET /api/v1/admin/license/history - Usage history
Thread Safety: - Database operations are thread-safe - License checks cached for performance
Dependencies: - Database: PostgreSQL licenses and license_usage tables
Example Usage:
handler := NewLicenseHandler(database)
handler.RegisterRoutes(router.Group("/api/v1/admin"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements load balancing policies and node distribution strategies for sessions.
LOAD BALANCING FEATURES: - Multiple load balancing strategies (round robin, least loaded, resource-based, geographic, weighted) - Node health monitoring and status tracking - Resource-based scheduling (CPU, memory thresholds) - Session affinity (sticky sessions) - Node selector and taints support - Geographic distribution preferences - Weighted node distribution
LOAD BALANCING STRATEGIES: - round_robin: Distribute sessions evenly across nodes in rotation - least_loaded: Schedule on node with fewest active sessions - resource_based: Schedule based on available CPU/memory resources - geographic: Prefer nodes in specific regions/zones - weighted: Distribute based on configured node weights
NODE HEALTH MONITORING: - Periodic health checks with configurable intervals - Failure and pass thresholds before status changes - Node readiness tracking from Kubernetes - Resource utilization monitoring - Health status: healthy, unhealthy, unknown
RESOURCE THRESHOLDS: - Maximum CPU percentage before avoiding node - Maximum memory percentage before avoiding node - Maximum concurrent sessions per node - Minimum free CPU cores required - Minimum free memory required
SESSION AFFINITY: - Sticky sessions to maintain user experience - Session-to-node mapping persistence - Reconnection to same node
API Endpoints: - GET /api/v1/loadbalancing/policies - List load balancing policies - POST /api/v1/loadbalancing/policies - Create load balancing policy - GET /api/v1/loadbalancing/policies/:id - Get policy details - PUT /api/v1/loadbalancing/policies/:id - Update policy - DELETE /api/v1/loadbalancing/policies/:id - Delete policy - GET /api/v1/loadbalancing/nodes - List cluster nodes with status - GET /api/v1/loadbalancing/nodes/:name - Get node details - GET /api/v1/loadbalancing/nodes/:name/sessions - Get sessions on node - POST /api/v1/loadbalancing/select-node - Select best node for session
Thread Safety: - All database operations are thread-safe via connection pooling - Kubernetes client operations are thread-safe
Dependencies: - Database: load_balancing_policies table - Kubernetes: Node metrics, resource status - External Services: Kubernetes metrics server
Example Usage:
// Create load balancing handler (integrated in main handler)
handler.RegisterLoadBalancingRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements monitoring, metrics, health checks, and alerting endpoints.
MONITORING FEATURES: - Prometheus-compatible metrics export - Custom application metrics (sessions, users, resources) - Health check endpoints (liveness, readiness) - Performance metrics (response times, throughput) - System resource metrics (CPU, memory, goroutines) - Alert management (create, acknowledge, resolve)
METRICS EXPORT: - Prometheus format (/monitoring/metrics/prometheus) - Session metrics (total, running, hibernated) - User metrics (total, active) - Resource metrics (CPU, memory, storage usage) - Performance metrics (response time percentiles)
HEALTH CHECKS: - Basic health: /monitoring/health (200 if API is responding) - Detailed health: Database, storage, Kubernetes connectivity - Database health: Connection pool status, query latency - Storage health: NFS mount status, disk space
SYSTEM METRICS: - Go runtime stats (goroutines, memory, GC) - Build information (version, git commit, build time) - Uptime and request counts - Resource usage trends
ALERTING: - Create, read, update, delete alerts - Acknowledge and resolve workflows - Alert severity levels (info, warning, error, critical) - Alert filtering and querying
API Endpoints: - GET /api/v1/monitoring/metrics/prometheus - Prometheus metrics - GET /api/v1/monitoring/metrics/sessions - Session metrics - GET /api/v1/monitoring/metrics/resources - Resource metrics - GET /api/v1/monitoring/metrics/users - User metrics - GET /api/v1/monitoring/metrics/performance - Performance metrics - GET /api/v1/monitoring/health - Basic health check - GET /api/v1/monitoring/health/detailed - Detailed health check - GET /api/v1/monitoring/health/database - Database health - GET /api/v1/monitoring/health/storage - Storage health - GET /api/v1/monitoring/system/info - System information - GET /api/v1/monitoring/system/stats - System statistics - GET /api/v1/monitoring/alerts - List alerts - POST /api/v1/monitoring/alerts - Create alert - GET /api/v1/monitoring/alerts/:id - Get alert - PUT /api/v1/monitoring/alerts/:id - Update alert - DELETE /api/v1/monitoring/alerts/:id - Delete alert - POST /api/v1/monitoring/alerts/:id/acknowledge - Acknowledge alert - POST /api/v1/monitoring/alerts/:id/resolve - Resolve alert
Thread Safety: - All database operations are thread-safe via connection pooling - Runtime metrics are thread-safe
Dependencies: - Database: sessions, users, alerts tables - External Services: Prometheus scraping (optional)
Example Usage:
handler := NewMonitoringHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file contains DEPRECATED stub handlers for node management.
⚠️ DEPRECATED: Node management has been moved to the streamspace-node-manager plugin.
MIGRATION GUIDE:
The node management functionality has been extracted into a plugin for better modularity. To restore node management functionality:
1. Install the streamspace-node-manager plugin:
- Via Admin UI: Admin → Plugins → Browse → streamspace-node-manager → Install
- Via CLI: kubectl apply -f https://plugins.streamspace.io/node-manager/install.yaml
2. API endpoints will be available at:
- /api/plugins/streamspace-node-manager/nodes (list)
- /api/plugins/streamspace-node-manager/nodes/:name (get)
- /api/plugins/streamspace-node-manager/nodes/:name/labels (add/remove)
- /api/plugins/streamspace-node-manager/nodes/:name/taints (add/remove)
- /api/plugins/streamspace-node-manager/nodes/:name/cordon (cordon)
- /api/plugins/streamspace-node-manager/nodes/:name/uncordon (uncordon)
- /api/plugins/streamspace-node-manager/nodes/:name/drain (drain)
- /api/plugins/streamspace-node-manager/nodes/stats (cluster stats)
3. The plugin provides enhanced features:
- Auto-scaling integration
- Advanced health monitoring
- Node selection strategies
- Metrics collection (requires metrics-server)
- Alert integration
- Configurable health checks
WHY WAS THIS MOVED TO A PLUGIN?
- Reduced core complexity: Node management is advanced functionality not needed by all users - Optional dependency: Single-node deployments don't need cluster management - Enhanced features: Plugin can provide more advanced capabilities - Modular architecture: Easier to maintain and extend independently - Performance: Core stays lean for basic deployments
BACKWARDS COMPATIBILITY:
These stub handlers remain in core to provide clear migration messages to existing users. They will be removed in v2.0.0.
Package handlers provides HTTP handlers for the StreamSpace API. This file implements notification delivery and management across multiple channels.
NOTIFICATION FEATURES: - In-app notification management (create, read, delete) - Email notifications via SMTP - Webhook notifications with HMAC signatures - Multiple notification types (session events, quotas, teams, alerts) - Priority levels (low, normal, high, urgent) - Read/unread tracking - Notification preferences per user
NOTIFICATION TYPES: - session.created: New session launched - session.idle: Session idle timeout warning - session.shared: Session shared with user - quota.warning: Approaching quota limits (80% threshold) - quota.exceeded: Quota limits exceeded - team.invitation: Invited to join team - system.alert: System-wide alerts
NOTIFICATION CHANNELS: - In-app: Stored in database, retrieved via API - Email: Sent via SMTP with HTML templates - Webhook: HTTP POST to user-configured URLs - Integration: Slack, Teams, Discord (via integrations handler)
PRIORITY LEVELS: - low: Non-urgent informational messages - normal: Standard notifications - high: Important notifications requiring attention - urgent: Critical notifications requiring immediate action
IN-APP NOTIFICATIONS: - Persistent storage in database - Unread count tracking - Mark as read individually or in bulk - Delete individually or clear all - Action URLs for quick navigation - Pagination support
EMAIL NOTIFICATIONS: - HTML template rendering - SMTP configuration (host, port, auth) - Configurable from/reply-to addresses - Environment variable configuration - Test email endpoint for debugging
WEBHOOK NOTIFICATIONS: - HMAC-SHA256 signature for verification - JSON payload with notification data - User-configured webhook URLs - Test webhook endpoint for debugging
API Endpoints: - GET /api/v1/notifications - List user notifications - GET /api/v1/notifications/unread - Get unread notifications - GET /api/v1/notifications/count - Get unread count - POST /api/v1/notifications/:id/read - Mark as read - POST /api/v1/notifications/read-all - Mark all as read - DELETE /api/v1/notifications/:id - Delete notification - DELETE /api/v1/notifications/clear-all - Clear all notifications - POST /api/v1/notifications/send - Send notification (admin) - GET /api/v1/notifications/preferences - Get notification preferences - PUT /api/v1/notifications/preferences - Update notification preferences - POST /api/v1/notifications/test/email - Test email delivery - POST /api/v1/notifications/test/webhook - Test webhook delivery
Thread Safety: - All database operations are thread-safe via connection pooling - SMTP client is created per-request
Dependencies: - Database: notifications, user_preferences tables - External Services: SMTP server for email delivery
Example Usage:
handler := NewNotificationsHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP request handlers for the StreamSpace API.
The plugin_marketplace.go file implements HTTP handlers for the plugin marketplace, which provides a higher-level API that combines catalog management, installation, and runtime lifecycle management.
Marketplace vs Catalog:
Catalog (plugins.go): - Database-driven plugin catalog (catalog_plugins table) - Install by ID, manage by ID - Tracks ratings, statistics, metadata - More suitable for production UI with detailed plugin info Marketplace (plugin_marketplace.go): - Runtime-driven plugin marketplace (PluginMarketplace + RuntimeV2) - Install by name, manage by name - Immediate load/unload (affects runtime state) - Catalog sync from external repositories - More suitable for programmatic API access
API Endpoint Structure:
Marketplace Catalog: GET /api/plugins/marketplace/catalog - List available plugins POST /api/plugins/marketplace/sync - Force catalog sync GET /api/plugins/marketplace/catalog/:name - Get plugin details Plugin Installation (immediate load/unload): POST /api/plugins/marketplace/install/:name - Install + load plugin DELETE /api/plugins/marketplace/uninstall/:name - Unload + uninstall plugin POST /api/plugins/marketplace/enable/:name - Enable plugin POST /api/plugins/marketplace/disable/:name - Unload + disable plugin Installed Plugins (runtime queries): GET /api/plugins/marketplace/installed - List loaded plugins GET /api/plugins/marketplace/installed/:name - Get loaded plugin PUT /api/plugins/marketplace/installed/:name/config - Update config
Design Decisions:
Immediate Effect: Install/uninstall/enable/disable affect runtime immediately - plugins.go: Changes database only, requires restart/reload - marketplace.go: Changes database AND runtime state
Plugin Identification: Uses plugin name instead of database ID - plugins.go: Uses database ID (/api/plugins/123) - marketplace.go: Uses plugin name (/api/plugins/marketplace/install/slack-notifications)
Catalog Sync: External repository synchronization - POST /api/plugins/marketplace/sync fetches latest plugins from repository - Populates catalog_plugins and catalog_repositories tables
Example Usage Flow:
Sync catalog from external repository: POST /api/plugins/marketplace/sync (Updates catalog_plugins from https://plugins.streamspace.io)
Browse available plugins: GET /api/plugins/marketplace/catalog
Install and load plugin immediately: POST /api/plugins/marketplace/install/slack-notifications Body: {"config": {"webhook_url": "..."}} (Plugin installed to database AND loaded into runtime)
Disable plugin (unloads from runtime): POST /api/plugins/marketplace/disable/slack-notifications (Plugin unloaded AND marked disabled in database)
Package handlers provides HTTP request handlers for the StreamSpace API.
The plugins.go file implements HTTP handlers for plugin management, including catalog browsing, installation, configuration, and lifecycle management.
API Endpoint Structure:
Plugin Catalog (browse/install): GET /api/plugins/catalog - Browse available plugins GET /api/plugins/catalog/:id - Get catalog plugin details POST /api/plugins/catalog/:id/rate - Rate a plugin (1-5 stars) POST /api/plugins/catalog/:id/install - Install plugin from catalog Installed Plugins (CRUD): GET /api/plugins - List installed plugins GET /api/plugins/:id - Get installed plugin details PATCH /api/plugins/:id - Update plugin config DELETE /api/plugins/:id - Uninstall plugin POST /api/plugins/:id/enable - Enable plugin POST /api/plugins/:id/disable - Disable plugin
Database Tables:
catalog_plugins: - Plugins available for installation - Includes metadata (name, version, description, icon, tags) - Tracks install count, ratings, view count installed_plugins: - Plugins currently installed - References catalog_plugins via catalog_plugin_id - Includes enabled status and configuration plugin_ratings: - User ratings for catalog plugins (1-5 stars + review) - One rating per user per plugin (upsert on conflict) plugin_stats: - Plugin usage statistics (views, installs, last accessed) - Updated asynchronously (non-blocking)
Design Patterns:
- Async stats updates: View/install counts updated in goroutines
- Graceful errors: Individual row parsing errors don't fail entire query
- SQL injection prevention: Parameterized queries with $1, $2, etc.
- User context: user_id extracted from auth middleware via c.GetString()
Example Usage Flow:
User browses catalog: GET /api/plugins/catalog?category=analytics&sort=popular
User views plugin details: GET /api/plugins/catalog/42 (View count incremented async)
User installs plugin: POST /api/plugins/catalog/42/install Body: {"config": {"api_key": "..."}} (Plugin added to installed_plugins, install count incremented)
User enables/disables plugin: POST /api/plugins/123/enable (Plugin enabled in database, runtime loads it on next restart/reload)
Package handlers provides HTTP handlers for the StreamSpace API. This file implements user preference management and customization settings.
PREFERENCE FEATURES: - User-specific preference storage (JSON-based) - UI preferences (theme, layout, language, timezone) - Notification preferences (enabled channels, frequency) - Default session settings (resources, templates) - Favorite templates management - Recent session tracking
PREFERENCE CATEGORIES:
1. UI Preferences:
- Theme (light, dark, auto)
- Layout preferences (sidebar, density)
- Language and locale
- Timezone for timestamps
- Default view modes
2. Notification Preferences:
- Email notifications enabled/disabled
- In-app notifications enabled/disabled
- Webhook notifications
- Notification types to receive
- Notification frequency/batching
3. Default Session Settings:
- Default template selection
- Default resource allocations (CPU, memory)
- Default idle timeout
- Default hibernation settings
- Auto-start preferences
4. Favorites:
- Favorite template list
- Quick access templates
- Template ordering
5. Recent Sessions:
- Recently accessed sessions
- Session history limit
- Timestamp tracking
PREFERENCE STORAGE: - JSON-based flexible schema - Per-user preference isolation - Default preferences for new users - Merge strategy for partial updates
API Endpoints: - GET /api/v1/preferences - Get all user preferences - PUT /api/v1/preferences - Update all preferences - DELETE /api/v1/preferences - Reset to defaults - GET /api/v1/preferences/ui - Get UI preferences - PUT /api/v1/preferences/ui - Update UI preferences - GET /api/v1/preferences/notifications - Get notification preferences - PUT /api/v1/preferences/notifications - Update notification preferences - GET /api/v1/preferences/defaults - Get default session settings - PUT /api/v1/preferences/defaults - Update default session settings - GET /api/v1/preferences/favorites - Get favorite templates - POST /api/v1/preferences/favorites/:templateName - Add favorite - DELETE /api/v1/preferences/favorites/:templateName - Remove favorite - GET /api/v1/preferences/recent - Get recent sessions
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: user_preferences table - External Services: None
Example Usage:
handler := NewPreferencesHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements resource quota management and enforcement.
RESOURCE QUOTA SYSTEM OVERVIEW:
The quota system prevents resource exhaustion and ensures fair usage by limiting: - Number of concurrent sessions per user or team - Total CPU allocation (measured in millicores, e.g., 1000m = 1 CPU core) - Total memory allocation (measured in megabytes) - Total storage usage (measured in gigabytes)
QUOTA HIERARCHY:
StreamSpace supports three levels of quotas, applied in this order:
1. Default Quotas (global):
- Applies to all users unless overridden
- Configurable by platform admins
- Example: 10 sessions, 4 cores, 8GB RAM, 100GB storage per user
2. User-Specific Quotas:
- Overrides defaults for specific users
- Allows customization for power users or restricted accounts
- Example: Premium user gets 50 sessions, 20 cores, 40GB RAM
3. Team/Group Quotas:
- Shared quota pool for all team members
- Prevents one team from monopolizing resources
- Example: Engineering team gets 200 sessions, 100 cores
QUOTA ENFORCEMENT:
Quotas are enforced at multiple points: - Session creation: CheckQuota endpoint verifies before creating session - Session startup: Controller checks quotas before scheduling pods - API responses: Quota status shown in user dashboards - Violations logged: Audit trail of quota violations for compliance
USAGE CALCULATION:
Resource usage is calculated in real-time from: - Active sessions: Sessions in "running", "starting", or "pending" states - Resource requests: CPU and memory from session specs (not actual usage) - Storage: Sum of snapshot sizes plus persistent home directories
Note: Quotas are based on REQUESTED resources (reservations), not actual usage. This ensures predictable capacity planning. If a session requests 2GB RAM but only uses 500MB, it still counts as 2GB toward the quota.
QUOTA STATUS LEVELS:
- "ok": Usage below 80% of quota (green) - "warning": Usage between 80-100% of quota (yellow) - "exceeded": Usage above 100% of quota (red, blocks new sessions)
EXAMPLE QUOTA LIFECYCLE:
1. User has quota: 10 sessions, 10000m CPU, 20480 MB memory 2. User creates 8 sessions using 8000m CPU, 16384 MB memory 3. Status: "ok" (80% of session quota, 80% of resources) 4. User creates 2 more sessions using 2000m CPU, 4096 MB memory 5. Status: "warning" (100% of session quota) 6. User tries to create 11th session 7. System blocks request with "quota exceeded" error
TEAM QUOTAS VS USER QUOTAS:
Team quotas are SHARED across all members: - Team of 10 users with team quota of 50 sessions - Each user can create sessions up to the team limit - If 5 users create 10 sessions each = 50 total (team quota reached) - Remaining 5 users cannot create any sessions until others terminate
User quotas are INDIVIDUAL limits: - Even within a team, each user has their own session limit - User quota prevents one team member from using all team resources
STORAGE QUOTA DETAILS:
Storage quota includes: - Session snapshots: Saved states of sessions for resume/backup - Persistent home directories: User's /home directory across sessions - Template storage: Custom container images (future feature)
Storage usage is calculated as: - Sum of completed snapshot sizes (in-progress snapshots not counted) - Estimated persistent home size (10GB default, actual size if available)
Package handlers provides HTTP handlers for the StreamSpace API. This file implements session scheduling and calendar integration features.
SCHEDULING SYSTEM OVERVIEW:
The scheduling system allows users to create sessions that start automatically at specific times or on recurring schedules. This is useful for: - Regular team meetings or training sessions - Pre-warming environments before work hours - Demo environments that start/stop on a schedule - Resource optimization by scheduling sessions during off-peak hours
SUPPORTED SCHEDULE TYPES:
1. One-Time (once): Session starts at a specific date/time, runs once
- Example: Demo session on Friday at 2 PM
- Requires: start_time field
2. Daily (daily): Session starts every day at a specific time
- Example: Development environment ready at 9 AM every weekday
- Requires: time_of_day field (HH:MM format)
3. Weekly (weekly): Session starts on specific days of the week
- Example: Training sessions every Monday and Wednesday at 10 AM
- Requires: days_of_week array (0=Sunday, 6=Saturday), time_of_day
4. Monthly (monthly): Session starts on a specific day of each month
- Example: Monthly report review on the 1st at 9 AM
- Requires: day_of_month (1-31), time_of_day
5. Cron Expression (cron): Advanced scheduling using cron syntax
- Example: "0 9 * * 1-5" for weekdays at 9 AM
- Requires: cron_expr field
- Uses standard cron format: minute hour day month weekday
CONFLICT DETECTION:
The system prevents scheduling conflicts by checking if proposed schedules would overlap with existing sessions. This prevents: - Resource quota violations (too many concurrent sessions) - Node capacity issues - User confusion from overlapping sessions
CALENDAR INTEGRATION:
Sessions can be automatically synced to external calendars: - Google Calendar (via Google Calendar API) - Microsoft Outlook (via Microsoft Graph API) - iCal export for other calendar applications
This allows users to see their scheduled sessions alongside other events and get calendar notifications/reminders.
PRE-WARMING AND AUTO-TERMINATION:
Pre-warming: Start session N minutes before scheduled time Useful for sessions with slow startup (large container images)
Auto-termination: Automatically stop session N minutes after start Prevents runaway sessions and saves resources
TIMEZONE HANDLING:
All schedules are stored with timezone information. The system converts between timezones when calculating next run times to ensure schedules work correctly for users in different locations.
Package handlers provides HTTP handlers for the StreamSpace API. This file implements advanced search, filtering, and saved search functionality.
SEARCH FEATURES: - Universal search across templates, sessions, users - Full-text search with relevance scoring - Advanced filtering (category, tags, app type) - Auto-complete suggestions - Saved search queries - Search history tracking
SEARCH TYPES: - Universal: Search across all resource types - Templates: Search template catalog - Sessions: Search user sessions - Suggestions: Auto-complete for search input - Advanced: Multi-filter complex queries
SEARCH RESULTS: - Type-specific results (template, session, user) - Relevance scoring - Result metadata (category, tags, icons) - Pagination support
FILTERING: - Categories: Filter by template/session category - Tags: Filter by tags - App Types: Filter by application type - Multiple filters combined with AND logic
SAVED SEARCHES: - Save frequently used search queries - Named searches for quick access - Execute saved searches - Update and delete saved searches - User-specific saved searches
SEARCH HISTORY: - Track user search queries - Timestamp tracking - Result count tracking - History limits per user
API Endpoints: - GET /api/v1/search - Universal search - GET /api/v1/search/templates - Template-specific search - GET /api/v1/search/sessions - Session search - GET /api/v1/search/suggest - Auto-complete suggestions - GET /api/v1/search/advanced - Advanced multi-filter search - GET /api/v1/search/filters/categories - List all categories - GET /api/v1/search/filters/tags - List popular tags - GET /api/v1/search/filters/app-types - List app types - GET /api/v1/search/saved - List saved searches - POST /api/v1/search/saved - Create saved search - GET /api/v1/search/saved/:id - Get saved search - PUT /api/v1/search/saved/:id - Update saved search - DELETE /api/v1/search/saved/:id - Delete saved search - POST /api/v1/search/saved/:id/execute - Execute saved search - GET /api/v1/search/history - Get search history
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: catalog_templates, sessions, users, saved_searches, search_history tables - External Services: None
Example Usage:
handler := NewSearchHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements enterprise security features including:
Security Features: - Multi-Factor Authentication (TOTP, SMS*, Email*) *Note: SMS/Email under development - IP Whitelisting for access control - MFA backup codes for account recovery - Rate limiting on MFA verification (5 attempts/minute) - Database transactions for data consistency - Secret protection (never expose secrets in API responses) - Input validation for all security-sensitive operations
Security Fixes Applied (2025-11-14): 1. Disabled incomplete SMS/Email MFA to prevent authentication bypass 2. Added rate limiting to MFA verification (prevents brute force) 3. Wrapped MFA setup in database transactions (ensures consistency) 4. Protected secrets with json:"-" tags (never returned in GET responses) 5. Fixed authorization enumeration in DeleteIPWhitelist 6. Added comprehensive input validation 7. Proper error handling for JSON unmarshal operations
Thread Safety: - All database operations are thread-safe via connection pooling - Rate limiting uses thread-safe in-memory storage with mutex - No shared mutable state between handlers
Package handlers provides HTTP request handlers for the StreamSpace API.
This file implements the Selkies/HTTP proxy handler for HTTP-based streaming protocols.
HTTP Streaming Traffic Flow (v2.0):
UI Client → Control Plane HTTP Proxy → Session Service → Pod (Selkies Web Interface)
The Selkies proxy:
- Receives HTTP/WebSocket requests from UI clients
- Verifies user has access to the session
- Proxies HTTP/WebSocket traffic directly to session Service (in-cluster)
- Session Service routes to pod's Selkies web interface (port 3000, 6901, etc.)
Architecture:
- Control plane runs IN the Kubernetes cluster
- Can access ClusterIP services via Kubernetes DNS
- Uses Go's httputil.ReverseProxy for HTTP and WebSocket proxying
Supported Protocols:
- Selkies: LinuxServer images (port 3000, path /websockify)
- Kasm: Kasm Workspaces images (port 6901, path /websockify)
- Guacamole: Apache Guacamole (port 8080, path /guacamole)
Security:
- Requires valid JWT token
- Verifies user has access to the session
- Proxies only to authorized session pods
Example:
UI connects to: http://control-plane/api/v1/http/:sessionId/ Proxy forwards to: http://sessionId.streamspace.svc.cluster.local:3000/
Package handlers provides HTTP handlers for the StreamSpace API. This file implements session activity logging and audit trail functionality.
SESSION ACTIVITY FEATURES: - Comprehensive session event logging - Activity timeline and audit trail - Event categorization (lifecycle, connection, state, configuration, access, error) - User action tracking with IP addresses and user agents - Activity statistics and analytics - Activity export for compliance
EVENT CATEGORIES: - lifecycle: Session creation, startup, termination, deletion - connection: User connections, disconnections, heartbeats - state: State changes (running, hibernated, stopped) - configuration: Resource updates, config changes, tag updates - access: Permission grants, denials, sharing events - error: Error occurrences and exceptions
EVENT TYPES: - session.created, session.started, session.stopped, session.hibernated - session.woken, session.terminated, session.deleted - user.connected, user.disconnected, user.heartbeat - state.changed, resources.updated, config.updated, tags.updated - access.granted, access.denied, share.created, share.revoked - error.occurred
ACTIVITY LOGGING: - Automatic event logging for all session operations - Manual event logging via API - Metadata capture (user ID, IP address, user agent) - Timestamp tracking with millisecond precision
ACTIVITY QUERIES: - List session activity timeline - Filter by event type or category - Date range filtering - Pagination support - Export to CSV/JSON for compliance
ACTIVITY STATISTICS: - Event count by type - Activity heatmap data - User activity patterns - Session usage analytics
API Endpoints: - POST /api/v1/sessions/:id/activity/log - Log activity event - GET /api/v1/sessions/:id/activity - Get session activity timeline - GET /api/v1/sessions/:id/activity/stats - Get activity statistics - GET /api/v1/sessions/:id/activity/export - Export activity data
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: session_activity_events table - External Services: None
Example Usage:
handler := NewSessionActivityHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements custom session template management and presets.
SESSION TEMPLATE FEATURES: - User-defined session configuration templates - Template CRUD operations (create, read, update, delete) - Template visibility (private, team, public) - Template cloning and versioning - Template sharing within teams - Create templates from existing sessions - Usage tracking and analytics
TEMPLATE VISIBILITY: - private: Only visible to template owner - team: Visible to team members - public: Visible to all users (requires approval)
TEMPLATE STRUCTURE: - Based on catalog template (base template reference) - Custom configuration overrides - Resource allocations (CPU, memory) - Environment variables - Tags and categorization - Version tracking
TEMPLATE OPERATIONS: - Create: Define new template from scratch or from session - Clone: Duplicate existing template - Use: Launch session from template - Publish/Unpublish: Make template public or private - Share: Share with specific users or teams
TEMPLATE SHARING: - Share templates with users or teams - Permission levels (view, use, edit) - Revoke shares - Track who has access
TEMPLATE VERSIONING: - Version history tracking - Restore previous versions - Version comparison - Change logs
QUICK ACTIONS: - Create template from running session - Set as default template for user - Clone template with modifications
API Endpoints: - GET /api/v1/session-templates - List session templates - POST /api/v1/session-templates - Create session template - GET /api/v1/session-templates/:id - Get template details - PUT /api/v1/session-templates/:id - Update template - DELETE /api/v1/session-templates/:id - Delete template - POST /api/v1/session-templates/:id/clone - Clone template - POST /api/v1/session-templates/:id/use - Launch session from template - POST /api/v1/session-templates/:id/publish - Make template public - POST /api/v1/session-templates/:id/unpublish - Make template private - GET /api/v1/session-templates/:id/shares - List template shares - POST /api/v1/session-templates/:id/share - Share template - DELETE /api/v1/session-templates/:id/shares/:shareId - Revoke share - GET /api/v1/session-templates/:id/versions - List template versions - POST /api/v1/session-templates/:id/versions - Create version - POST /api/v1/session-templates/:id/versions/:version/restore - Restore version - POST /api/v1/session-templates/from-session/:sessionId - Create from session
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: session_templates, template_shares, template_versions tables - External Services: None
Example Usage:
handler := NewSessionTemplatesHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements the first-run setup wizard for admin user onboarding.
Purpose: - Provides a secure setup wizard for initial admin password configuration - Enables account recovery when admin password is lost or not set - Automatically disables after admin account is configured - Works as fallback when Helm secret or environment variable not available
Security Features: - Only accessible when admin account has no password set - Password strength validation (minimum 12 characters) - Password confirmation to prevent typos - Email validation for admin contact - Single-use wizard (auto-disables after setup) - Atomic database transaction - Input sanitization and validation
Integration: - Part of multi-layered admin onboarding strategy - Priority 3 fallback after Helm secret and environment variable - Works with database migration admin user creation - Compatible with all authentication modes (local, SAML, OIDC)
Thread Safety: - All database operations are thread-safe via connection pooling - No shared mutable state between requests
Package handlers provides HTTP handlers for the StreamSpace API. This file implements session sharing and collaboration features.
SESSION SHARING FEATURES: - Direct user-to-user session sharing with permission levels - Shareable invitation links with expiration and usage limits - Share revocation and ownership transfer - Collaborator tracking and activity monitoring
PERMISSION LEVELS: - view: Read-only access to view the session - collaborate: Can interact but has limited control - control: Full control equivalent to owner
SHARING METHODS:
1. Direct Shares:
- Share with specific users by user ID
- Owner-only operation
- Requires user existence validation
- Supports expiration timestamps
- Generates unique share tokens
2. Invitation Links:
- Generate shareable invitation tokens
- Configurable max uses and expiration
- Anyone with link can accept (until exhausted/expired)
- Tracks usage count
OWNERSHIP TRANSFER: - Transfer session ownership to another user - Requires current owner authorization - Validates new owner exists
COLLABORATOR MANAGEMENT: - Track active collaborators in sessions - Update activity timestamps - Remove collaborators - Permission inheritance from shares
API Endpoints: - POST /api/v1/sessions/:id/share - Create direct share with user - GET /api/v1/sessions/:id/shares - List all shares for session - DELETE /api/v1/sessions/:id/shares/:shareId - Revoke a share - POST /api/v1/sessions/:id/transfer - Transfer ownership - POST /api/v1/sessions/:id/invitations - Create invitation link - GET /api/v1/sessions/:id/invitations - List invitations - DELETE /api/v1/invitations/:token - Revoke invitation - POST /api/v1/invitations/:token/accept - Accept invitation - GET /api/v1/sessions/:id/collaborators - List active collaborators - POST /api/v1/sessions/:id/collaborators/:userId/activity - Update activity - DELETE /api/v1/sessions/:id/collaborators/:userId - Remove collaborator - GET /api/v1/shared-sessions - List sessions shared with user
Security: - Owner-only operations for sharing and transfer - User existence validation - Expiration and usage limit enforcement - Authorization checks for all operations
Thread Safety: - All database operations are thread-safe via connection pooling - Atomic upsert operations for collaborators and shares
Dependencies: - Database: sessions, session_shares, session_share_invitations, session_collaborators, users tables - External Services: None
Example Usage:
handler := NewSharingHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements team-based Role-Based Access Control (RBAC) operations.
TEAM RBAC FEATURES: - Team permissions and role management - User permission queries within teams - Team session access control - Permission checking for authorization
TEAM PERMISSIONS: - Role-based permissions (owner, admin, member, viewer, etc.) - Permission inheritance from team roles - User-specific permission queries - Permission validation for resource access
TEAM SESSIONS: - List sessions belonging to a specific team - Permission-based access control (requires team.sessions.view) - Team member authorization
API Endpoints: - GET /api/v1/teams/:teamId/permissions - Get all team role permissions - GET /api/v1/teams/:teamId/role-info - Get available team roles - GET /api/v1/teams/:teamId/my-permissions - Get current user's permissions - GET /api/v1/teams/:teamId/check-permission/:permission - Check specific permission - GET /api/v1/teams/:teamId/sessions - List team sessions (requires permission) - GET /api/v1/teams/my-teams - Get current user's team memberships
Security: - Authentication required for all endpoints - Permission-based authorization for sensitive operations - Safe type assertions to prevent panics
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: teams, team_members, team_role_permissions, sessions tables - Middleware: TeamRBAC for permission checks - External Services: None
Example Usage:
handler := NewTeamHandler(database)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file implements template versioning, testing, and inheritance management.
TEMPLATE VERSIONING FEATURES: - Semantic versioning (major.minor.patch) - Version lifecycle (draft, testing, stable, deprecated) - Version testing and validation - Template inheritance (parent-child relationships) - Version comparison and diff - Rollback to previous versions
VERSION LIFECYCLE: - draft: Work in progress, not ready for use - testing: Undergoing validation tests - stable: Production-ready, recommended for use - deprecated: Old version, migration recommended
VERSION MANAGEMENT: - Create new versions with semantic versioning - Set default version for template - Publish versions for public use - Deprecate outdated versions - Track version metadata (changelog, test results)
TEMPLATE TESTING: - Automated template validation - Test types: startup, smoke, functional, performance - Test status tracking: pending, running, passed, failed - Test results with duration and error messages - Test execution history
TEMPLATE INHERITANCE: - Parent-child template relationships - Field inheritance and overrides - Inherited field tracking - Override visualization - Template family trees
VERSION COMPARISON: - Compare configurations between versions - Highlight differences - Migration guides between versions
API Endpoints: - POST /api/v1/templates/:id/versions - Create template version - GET /api/v1/templates/:id/versions - List template versions - GET /api/v1/templates/:id/versions/:version - Get version details - PUT /api/v1/templates/:id/versions/:version - Update version - DELETE /api/v1/templates/:id/versions/:version - Delete version - POST /api/v1/templates/:id/versions/:version/publish - Publish version - POST /api/v1/templates/:id/versions/:version/deprecate - Deprecate version - POST /api/v1/templates/:id/versions/:version/test - Run version tests - GET /api/v1/templates/:id/versions/:version/tests - Get test results - GET /api/v1/templates/:id/inheritance - Get template inheritance tree - POST /api/v1/templates/:id/inherit-from - Set parent template
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: template_versions, template_tests, template_inheritance tables - External Services: Test execution infrastructure
Example Usage:
// Create version handler (integrated in main handler)
handler.RegisterTemplateVersioningRoutes(router.Group("/api/v1"))
Package handlers provides HTTP handlers for the StreamSpace API. This file defines common response types used across all handler files.
COMMON TYPES: - ErrorResponse: Standardized error response format - SuccessResponse: Standardized success message format
These types provide consistency across all API endpoints for error handling and success messaging. All handlers in this package use these types to ensure uniform API response structures.
Thread Safety: - These are simple data structures with no shared state
Dependencies: - None (pure data types)
Package handlers provides HTTP handlers for the StreamSpace API. This file implements user management and user-level resource quota operations.
USER MANAGEMENT: - User CRUD operations (list, create, read, update, delete) - User profile management (/me endpoints for current user) - User filtering by role, provider, or active status - Password hash sanitization (never exposed in responses)
QUOTA MANAGEMENT: - Per-user resource quotas (sessions, CPU, memory, storage) - Quota retrieval for current user and specific users - Admin quota management (list all, set, delete/reset) - Username-based quota operations for admin convenience
USER ASSOCIATIONS: - User sessions (redirects to /sessions?user=id) - User group memberships
API Endpoints: - GET /api/v1/users - List all users with optional filters - POST /api/v1/users - Create new user account - GET /api/v1/users/me - Get current authenticated user - GET /api/v1/users/me/quota - Get current user's quota - GET /api/v1/users/:id - Get user by ID - PATCH /api/v1/users/:id - Update user information - DELETE /api/v1/users/:id - Delete user account - GET /api/v1/users/:id/sessions - Get user's sessions - GET /api/v1/users/:id/quota - Get user's resource quota - PUT /api/v1/users/:id/quota - Set user's resource quota - GET /api/v1/users/:id/groups - Get user's group memberships - GET /api/v1/admin/quotas - List all user quotas (admin) - GET /api/v1/admin/quotas/:username - Get quota by username (admin) - PUT /api/v1/admin/quotas - Set quota by username (admin) - DELETE /api/v1/admin/quotas/:username - Reset quota to defaults (admin)
Security: - Password hashes are sanitized before returning user objects - Safe type assertions prevent panics - Authentication required via middleware for protected endpoints
Thread Safety: - All database operations are thread-safe via connection pooling
Dependencies: - Database: users, user_quotas, user_groups tables - External Services: None
Example Usage:
handler := NewUserHandler(userDB, groupDB)
handler.RegisterRoutes(router.Group("/api/v1"))
Package handlers - websocket.go ¶
This file implements the WebSocket handler for real-time updates in StreamSpace.
Real-Time Communication Architecture ¶
The WebSocket system enables bidirectional communication between the server and connected clients for instant updates about sessions, notifications, metrics, and alerts. This eliminates the need for polling and provides a better UX.
Architecture pattern: **Hub-and-Spoke** (centralized message routing)
┌─────────────────────────────────────────────────────────────┐
│ WebSocket Hub │
│ - Maintains registry of connected clients │
│ - Routes broadcast messages to matching clients │
│ - Handles client registration/unregistration │
│ - Filters messages based on subscriptions │
└──────────────┬──────────────────────────────────────────────┘
│
┌───────┴──────┬─────────────┬─────────────┬──────────┐
▼ ▼ ▼ ▼ ▼
Client 1 Client 2 Client 3 Client 4 Client N
(User A) (User B) (User A) (Admin) (User C)
[Filters: [Filters: [Filters: [Filters: [Filters:
UserID=A] UserID=B] UserID=A] All] UserID=C]
Message Flow ¶
**Outbound (Server → Clients)**:
- API handler emits event (e.g., session.created)
- Event serialized to BroadcastMessage
- Message sent to hub's broadcast channel
- Hub filters and routes to matching clients
- Clients receive message via WebSocket
**Inbound (Clients → Server)**:
- Client sends message via WebSocket
- Message parsed (subscription updates, heartbeats)
- Client filters updated accordingly
- Future: Plugin event triggers, RPC calls
Subscription Filtering ¶
Clients can subscribe to specific event types to reduce bandwidth:
- **Session IDs**: Only updates for specific sessions
- **User ID**: Only updates for this user's resources
- **Team ID**: Only updates for team resources
- **Event Types**: Only specific events (created, updated, deleted)
Example filter: User viewing "my sessions" page subscribes to:
{
"userId": "user-123",
"eventTypes": ["session.created", "session.updated", "session.deleted"]
}
This ensures they only receive their own session updates, not all platform events.
Connection Lifecycle ¶
WebSocket connection lifecycle:
- **Handshake**: HTTP upgrade request with auth token
- **Validation**: Origin check, auth verification
- **Registration**: Client added to hub's sessions map
- **Active**: Bidirectional communication (read/write pumps)
- **Heartbeat**: Periodic pings to detect dead connections
- **Unregistration**: Client removed on disconnect/error
- **Cleanup**: Goroutines stopped, channels closed
Concurrency Model ¶
The hub uses the **Actor pattern** with channels for synchronization:
- **Hub goroutine**: Single goroutine processes all registration/broadcast
- **Read pump per client**: Goroutine reads messages from WebSocket
- **Write pump per client**: Goroutine writes messages to WebSocket
- **Channel-based**: No mutexes in pumps, only in hub
Why this pattern?
- Simplifies concurrent access to sessions map
- Prevents race conditions in WebSocket writes
- Enables efficient broadcast to thousands of clients
- Matches Gorilla WebSocket best practices
Performance Characteristics ¶
Performance metrics (measured with 1000 concurrent connections):
- **Message latency**: <10ms from broadcast to client receive (p99)
- **Throughput**: 10,000+ messages/sec per hub instance
- **Memory per client**: ~100 KB (goroutines + buffers)
- **CPU overhead**: ~5% for 1000 clients with 100 msg/sec
Scaling limits:
- **Single instance**: ~10,000 concurrent connections (tested)
- **Bottleneck**: Network bandwidth and file descriptors
- **Horizontal scaling**: Use Redis pub/sub to sync multiple instances
Message Types ¶
The platform emits these event types:
**Session Events**:
- session.created: New session requested
- session.started: Session pod running
- session.updated: Session metadata changed
- session.stopped: Session stopped by user
- session.hibernated: Auto-hibernation triggered
- session.woken: Session resumed from hibernation
- session.deleted: Session permanently removed
**Notification Events**:
- notification.created: New notification for user
- notification.read: Notification marked as read
**Metric Events**:
- metrics.updated: Real-time resource usage updates
**Alert Events**:
- alert.triggered: Platform alert fired
- alert.resolved: Alert condition cleared
Security Considerations ¶
WebSocket security measures:
- **Origin validation**: Blocks CSRF by checking Origin header
- **Authentication**: JWT token required in initial handshake
- **Authorization**: Filters ensure users only see their own data
- **Rate limiting**: Future: Limit messages per client per second
- **Message validation**: Inbound messages validated before processing
Vulnerabilities prevented:
- **CSRF**: Origin check prevents cross-site WebSocket hijacking
- **Data leakage**: Filters prevent users seeing other users' data
- **DoS**: Connection limits prevent resource exhaustion
Error Handling ¶
The hub is resilient to client failures:
- **Write errors**: Client disconnected, removed from hub
- **Read errors**: Connection closed, cleanup triggered
- **Broadcast overflow**: Slow clients dropped (non-blocking)
- **Hub errors**: Logged but hub continues (fail gracefully)
Why drop slow clients?
- Prevents one slow client from blocking the entire hub
- Clients can reconnect and resync state
- Better UX for fast clients (no global slowdown)
Known Limitations ¶
- **Single instance**: No cross-instance message routing (yet)
- **No persistence**: Messages not stored (missed if offline)
- **No compression**: WebSocket compression not enabled
- **No reconnection**: Clients must implement reconnect logic
- **No backpressure**: Fast sender can overflow slow receivers
Future enhancements:
- Redis pub/sub for multi-instance deployments
- Message persistence for offline clients
- WebSocket compression for bandwidth optimization
- Automatic reconnection with exponential backoff
- Per-client rate limiting and backpressure
Example Usage ¶
**Client (JavaScript)**:
const ws = new WebSocket('wss://api.streamspace.io/ws/sessions');
// Send auth token after connection
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'subscribe',
filters: {
userId: 'user-123',
eventTypes: ['session.created', 'session.updated']
}
}));
};
// Handle messages
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Event:', message.event, 'Data:', message.data);
};
**Server (API handler)**:
// Broadcast session update to all connected clients
wsHandler.Broadcast(&BroadcastMessage{
Type: "update",
Event: "session.created",
SessionID: session.ID,
UserID: session.UserID,
Data: sessionData,
Timestamp: time.Now(),
})
Package handlers provides HTTP and WebSocket handlers for the StreamSpace API. This file implements enterprise WebSocket functionality for real-time updates.
Security Features: - Origin validation to prevent Cross-Site WebSocket Hijacking (CSWSH) - Race condition protection with proper mutex usage - User authentication required for all connections - Graceful disconnect handling
Architecture: - Hub-and-spoke model: Central hub broadcasts to all clients - Each client has dedicated read/write goroutines - Buffered channels prevent blocking - Automatic cleanup of disconnected clients
Index ¶
- Constants
- Variables
- func BroadcastComplianceViolation(userID string, violationID int, policyID int, severity string)
- func BroadcastNodeHealthUpdate(nodeName string, status string, cpu float64, memory float64)
- func BroadcastScalingEvent(policyID int, action string, result string)
- func BroadcastScheduledSessionEvent(userID string, scheduleID int, event string, sessionID string)
- func BroadcastSecurityAlert(userID string, alertType string, severity string, message string)
- func BroadcastWebhookDelivery(userID string, webhookID int, deliveryID int, status string)
- func GetSwaggerSpec() []byte
- func GetSwaggerSpecPath() string
- func HandleEnterpriseWebSocket(c *gin.Context)
- func IsDocsPath(path string) bool
- type APIKey
- type APIKeyHandler
- func (h *APIKeyHandler) CreateAPIKey(c *gin.Context)
- func (h *APIKeyHandler) DeleteAPIKey(c *gin.Context)
- func (h *APIKeyHandler) GetAPIKeyUsage(c *gin.Context)
- func (h *APIKeyHandler) ListAPIKeys(c *gin.Context)
- func (h *APIKeyHandler) ListAllAPIKeys(c *gin.Context)
- func (h *APIKeyHandler) RevokeAPIKey(c *gin.Context)
- type AcceptInvitationRequest
- type AccessLog
- type ActivateLicenseRequest
- type ActivityHandler
- type ActivityResponse
- type AgentHandler
- func (h *AgentHandler) ApproveAgent(c *gin.Context)
- func (h *AgentHandler) DeregisterAgent(c *gin.Context)
- func (h *AgentHandler) GenerateAPIKey(c *gin.Context)
- func (h *AgentHandler) GetAgent(c *gin.Context)
- func (h *AgentHandler) ListAgents(c *gin.Context)
- func (h *AgentHandler) RegisterAdminRoutes(router *gin.RouterGroup)
- func (h *AgentHandler) RegisterAgent(c *gin.Context)
- func (h *AgentHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *AgentHandler) RejectAgent(c *gin.Context)
- func (h *AgentHandler) RotateAPIKey(c *gin.Context)
- func (h *AgentHandler) SendCommand(c *gin.Context)
- func (h *AgentHandler) UpdateHeartbeat(c *gin.Context)
- type AgentWebSocketHandler
- type Annotation
- type ApplicationHandler
- func (h *ApplicationHandler) AddGroupAccess(c *gin.Context)
- func (h *ApplicationHandler) DeleteApplication(c *gin.Context)
- func (h *ApplicationHandler) GetApplication(c *gin.Context)
- func (h *ApplicationHandler) GetApplicationGroups(c *gin.Context)
- func (h *ApplicationHandler) GetApplicationIcon(c *gin.Context)
- func (h *ApplicationHandler) GetTemplateConfig(c *gin.Context)
- func (h *ApplicationHandler) GetUserApplications(c *gin.Context)
- func (h *ApplicationHandler) InstallApplication(c *gin.Context)
- func (h *ApplicationHandler) ListApplications(c *gin.Context)
- func (h *ApplicationHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *ApplicationHandler) RemoveGroupAccess(c *gin.Context)
- func (h *ApplicationHandler) SetApplicationEnabled(c *gin.Context)
- func (h *ApplicationHandler) UpdateApplication(c *gin.Context)
- func (h *ApplicationHandler) UpdateGroupAccess(c *gin.Context)
- type AuditHandler
- type AuditLog
- type AuditLogListResponse
- type AutoScalingPolicy
- type BackupCode
- type BatchHandler
- func (h *BatchHandler) CancelBatchJob(c *gin.Context)
- func (h *BatchHandler) CreateSnapshots(c *gin.Context)
- func (h *BatchHandler) DeleteSessions(c *gin.Context)
- func (h *BatchHandler) DeleteSnapshots(c *gin.Context)
- func (h *BatchHandler) DeleteTemplates(c *gin.Context)
- func (h *BatchHandler) GetBatchJob(c *gin.Context)
- func (h *BatchHandler) HibernateSessions(c *gin.Context)
- func (h *BatchHandler) InstallTemplates(c *gin.Context)
- func (h *BatchHandler) ListBatchJobs(c *gin.Context)
- func (h *BatchHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *BatchHandler) TerminateSessions(c *gin.Context)
- func (h *BatchHandler) UpdateSessionResources(c *gin.Context)
- func (h *BatchHandler) UpdateSessionTags(c *gin.Context)
- func (h *BatchHandler) WakeSessions(c *gin.Context)
- type BatchOperation
- type BroadcastMessage
- type BulkUpdateRequest
- type CalendarEvent
- type CalendarIntegration
- type CatalogHandler
- func (h *CatalogHandler) AddRating(c *gin.Context)
- func (h *CatalogHandler) DeleteRating(c *gin.Context)
- func (h *CatalogHandler) GetFeaturedTemplates(c *gin.Context)
- func (h *CatalogHandler) GetPopularTemplates(c *gin.Context)
- func (h *CatalogHandler) GetRatings(c *gin.Context)
- func (h *CatalogHandler) GetTemplateDetails(c *gin.Context)
- func (h *CatalogHandler) GetTrendingTemplates(c *gin.Context)
- func (h *CatalogHandler) ListTemplates(c *gin.Context)
- func (h *CatalogHandler) RecordInstall(c *gin.Context)
- func (h *CatalogHandler) RecordView(c *gin.Context)
- func (h *CatalogHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *CatalogHandler) UpdateRating(c *gin.Context)
- type ChatMessage
- type CheckQuotaRequest
- type CollaborationHandler
- func (h *CollaborationHandler) ClearAllAnnotations(c *gin.Context)
- func (h *CollaborationHandler) CreateAnnotation(c *gin.Context)
- func (h *CollaborationHandler) CreateCollaborationSession(c *gin.Context)
- func (h *CollaborationHandler) DeleteAnnotation(c *gin.Context)
- func (h *CollaborationHandler) GetAnnotations(c *gin.Context)
- func (h *CollaborationHandler) GetChatHistory(c *gin.Context)
- func (h *CollaborationHandler) GetCollaborationParticipants(c *gin.Context)
- func (h *CollaborationHandler) GetCollaborationStats(c *gin.Context)
- func (h *CollaborationHandler) JoinCollaborationSession(c *gin.Context)
- func (h *CollaborationHandler) LeaveCollaborationSession(c *gin.Context)
- func (h *CollaborationHandler) SendChatMessage(c *gin.Context)
- func (h *CollaborationHandler) UpdateParticipantRole(c *gin.Context)
- type CollaborationPermissions
- type CollaborationSession
- type CollaborationSettings
- type CollaborationUser
- type Configuration
- type ConfigurationHandler
- func (h *ConfigurationHandler) BulkUpdateConfigurations(c *gin.Context)
- func (h *ConfigurationHandler) GetConfiguration(c *gin.Context)
- func (h *ConfigurationHandler) ListConfigurations(c *gin.Context)
- func (h *ConfigurationHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *ConfigurationHandler) UpdateConfiguration(c *gin.Context)
- type ConfigurationListResponse
- type ConsoleHandler
- func (h *ConsoleHandler) CreateConsoleSession(c *gin.Context)
- func (h *ConsoleHandler) CreateDirectory(c *gin.Context)
- func (h *ConsoleHandler) DeleteFile(c *gin.Context)
- func (h *ConsoleHandler) DisconnectConsoleSession(c *gin.Context)
- func (h *ConsoleHandler) DownloadFile(c *gin.Context)
- func (h *ConsoleHandler) GetFileContent(c *gin.Context)
- func (h *ConsoleHandler) GetFileOperationHistory(c *gin.Context)
- func (h *ConsoleHandler) ListConsoleSessions(c *gin.Context)
- func (h *ConsoleHandler) ListFiles(c *gin.Context)
- func (h *ConsoleHandler) RenameFile(c *gin.Context)
- func (h *ConsoleHandler) UploadFile(c *gin.Context)
- type ConsoleSession
- type CreateAPIKeyRequest
- type CreateIntegrationRequest
- type CreateInvitationRequest
- type CreatePolicyRequest
- type CreateSessionTemplateRequest
- type CreateShareRequest
- type CreateWebhookRequest
- type CurrentLicenseResponse
- type CursorPosition
- type DashboardHandler
- func (h *DashboardHandler) GetActivityTimeline(c *gin.Context)
- func (h *DashboardHandler) GetPlatformStats(c *gin.Context)
- func (h *DashboardHandler) GetResourceUsage(c *gin.Context)
- func (h *DashboardHandler) GetTemplateUsageStats(c *gin.Context)
- func (h *DashboardHandler) GetUserDashboard(c *gin.Context)
- func (h *DashboardHandler) GetUserUsageStats(c *gin.Context)
- type DevicePosture
- type DocsHandler
- type ErrorResponse
- type FileInfo
- type FileOperation
- type GeoRestriction
- type GroupHandler
- func (h *GroupHandler) AddGroupMember(c *gin.Context)
- func (h *GroupHandler) CreateGroup(c *gin.Context)
- func (h *GroupHandler) DeleteGroup(c *gin.Context)
- func (h *GroupHandler) GetGroup(c *gin.Context)
- func (h *GroupHandler) GetGroupMembers(c *gin.Context)
- func (h *GroupHandler) GetGroupQuota(c *gin.Context)
- func (h *GroupHandler) ListGroups(c *gin.Context)
- func (h *GroupHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *GroupHandler) RemoveGroupMember(c *gin.Context)
- func (h *GroupHandler) SetGroupQuota(c *gin.Context)
- func (h *GroupHandler) UpdateGroup(c *gin.Context)
- func (h *GroupHandler) UpdateMemberRole(c *gin.Context)
- type HealthCheckConfig
- type HeartbeatRequest
- type IPWhitelist
- type Integration
- type IntegrationsHandler
- func (h *IntegrationsHandler) CreateIntegration(c *gin.Context)
- func (h *IntegrationsHandler) CreateWebhook(c *gin.Context)
- func (h *IntegrationsHandler) DeleteWebhook(c *gin.Context)
- func (h *IntegrationsHandler) GetAvailableEvents(c *gin.Context)
- func (h *IntegrationsHandler) GetWebhookDeliveries(c *gin.Context)
- func (h *IntegrationsHandler) ListIntegrations(c *gin.Context)
- func (h *IntegrationsHandler) ListWebhooks(c *gin.Context)
- func (h *IntegrationsHandler) TestIntegration(c *gin.Context)
- func (h *IntegrationsHandler) TestWebhook(c *gin.Context)
- func (h *IntegrationsHandler) UpdateWebhook(c *gin.Context)
- type License
- type LicenseHandler
- func (h *LicenseHandler) ActivateLicense(c *gin.Context)
- func (h *LicenseHandler) GetCurrentLicense(c *gin.Context)
- func (h *LicenseHandler) GetLicenseUsage(c *gin.Context)
- func (h *LicenseHandler) GetUsageHistory(c *gin.Context)
- func (h *LicenseHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *LicenseHandler) UpdateLicense(c *gin.Context)
- func (h *LicenseHandler) ValidateLicense(c *gin.Context)
- type LicenseUsage
- type LicenseUsageStats
- type LimitWarning
- type LoadBalancingHandler
- func (h *LoadBalancingHandler) CreateAutoScalingPolicy(c *gin.Context)
- func (h *LoadBalancingHandler) CreateLoadBalancingPolicy(c *gin.Context)
- func (h *LoadBalancingHandler) GetNodeStatus(c *gin.Context)
- func (h *LoadBalancingHandler) GetScalingHistory(c *gin.Context)
- func (h *LoadBalancingHandler) ListAutoScalingPolicies(c *gin.Context)
- func (h *LoadBalancingHandler) ListLoadBalancingPolicies(c *gin.Context)
- func (h *LoadBalancingHandler) SelectNode(c *gin.Context)
- func (h *LoadBalancingHandler) TriggerScaling(c *gin.Context)
- type LoadBalancingPolicy
- type MFAMethod
- type MFASetupResponse
- type MonitoringHandler
- func (h *MonitoringHandler) AcknowledgeAlert(c *gin.Context)
- func (h *MonitoringHandler) CreateAlert(c *gin.Context)
- func (h *MonitoringHandler) DatabaseHealth(c *gin.Context)
- func (h *MonitoringHandler) DeleteAlert(c *gin.Context)
- func (h *MonitoringHandler) DetailedHealthCheck(c *gin.Context)
- func (h *MonitoringHandler) GetAlert(c *gin.Context)
- func (h *MonitoringHandler) GetAlerts(c *gin.Context)
- func (h *MonitoringHandler) HealthCheck(c *gin.Context)
- func (h *MonitoringHandler) PerformanceMetrics(c *gin.Context)
- func (h *MonitoringHandler) PrometheusMetrics(c *gin.Context)
- func (h *MonitoringHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *MonitoringHandler) ResolveAlert(c *gin.Context)
- func (h *MonitoringHandler) ResourceMetrics(c *gin.Context)
- func (h *MonitoringHandler) SessionMetrics(c *gin.Context)
- func (h *MonitoringHandler) StorageHealth(c *gin.Context)
- func (h *MonitoringHandler) SystemInfo(c *gin.Context)
- func (h *MonitoringHandler) SystemStats(c *gin.Context)
- func (h *MonitoringHandler) UpdateAlert(c *gin.Context)
- func (h *MonitoringHandler) UserMetrics(c *gin.Context)
- type NodeHandler
- func (h *NodeHandler) AddNodeLabel(c *gin.Context)
- func (h *NodeHandler) AddNodeTaint(c *gin.Context)
- func (h *NodeHandler) CordonNode(c *gin.Context)
- func (h *NodeHandler) DrainNode(c *gin.Context)
- func (h *NodeHandler) GetClusterStats(c *gin.Context)
- func (h *NodeHandler) GetNode(c *gin.Context)
- func (h *NodeHandler) ListNodes(c *gin.Context)
- func (h *NodeHandler) RemoveNodeLabel(c *gin.Context)
- func (h *NodeHandler) RemoveNodeTaint(c *gin.Context)
- func (h *NodeHandler) UncordonNode(c *gin.Context)
- type NodeStatus
- type Notification
- type NotificationsHandler
- func (h *NotificationsHandler) ClearAllNotifications(c *gin.Context)
- func (h *NotificationsHandler) DeleteNotification(c *gin.Context)
- func (h *NotificationsHandler) GetNotificationPreferences(c *gin.Context)
- func (h *NotificationsHandler) GetUnreadCount(c *gin.Context)
- func (h *NotificationsHandler) GetUnreadNotifications(c *gin.Context)
- func (h *NotificationsHandler) ListNotifications(c *gin.Context)
- func (h *NotificationsHandler) MarkAllAsRead(c *gin.Context)
- func (h *NotificationsHandler) MarkAsRead(c *gin.Context)
- func (h *NotificationsHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *NotificationsHandler) SendNotification(c *gin.Context)
- func (h *NotificationsHandler) TestEmailNotification(c *gin.Context)
- func (h *NotificationsHandler) TestWebhookNotification(c *gin.Context)
- func (h *NotificationsHandler) UpdateNotificationPreferences(c *gin.Context)
- type PluginHandler
- func (h *PluginHandler) BrowsePluginCatalog(c *gin.Context)
- func (h *PluginHandler) DisablePlugin(c *gin.Context)
- func (h *PluginHandler) EnablePlugin(c *gin.Context)
- func (h *PluginHandler) GetCatalogPlugin(c *gin.Context)
- func (h *PluginHandler) GetInstalledPlugin(c *gin.Context)
- func (h *PluginHandler) InstallPlugin(c *gin.Context)
- func (h *PluginHandler) ListInstalledPlugins(c *gin.Context)
- func (h *PluginHandler) RatePlugin(c *gin.Context)
- func (h *PluginHandler) RegisterRoutes(r *gin.RouterGroup)
- func (h *PluginHandler) UninstallPlugin(c *gin.Context)
- func (h *PluginHandler) UpdateInstalledPlugin(c *gin.Context)
- type PluginMarketplaceHandler
- func (h *PluginMarketplaceHandler) DisablePlugin(c *gin.Context)
- func (h *PluginMarketplaceHandler) EnablePlugin(c *gin.Context)
- func (h *PluginMarketplaceHandler) GetInstalledPlugin(c *gin.Context)
- func (h *PluginMarketplaceHandler) GetPluginDetails(c *gin.Context)
- func (h *PluginMarketplaceHandler) InstallPlugin(c *gin.Context)
- func (h *PluginMarketplaceHandler) ListAvailablePlugins(c *gin.Context)
- func (h *PluginMarketplaceHandler) ListInstalledPlugins(c *gin.Context)
- func (h *PluginMarketplaceHandler) RegisterRoutes(r *gin.RouterGroup)
- func (h *PluginMarketplaceHandler) SyncCatalog(c *gin.Context)
- func (h *PluginMarketplaceHandler) UninstallPlugin(c *gin.Context)
- func (h *PluginMarketplaceHandler) UpdatePluginConfig(c *gin.Context)
- type Point
- type PredictiveScalingConfig
- type PreferencesHandler
- func (h *PreferencesHandler) AddFavorite(c *gin.Context)
- func (h *PreferencesHandler) GetDefaultsPreferences(c *gin.Context)
- func (h *PreferencesHandler) GetFavorites(c *gin.Context)
- func (h *PreferencesHandler) GetNotificationPreferences(c *gin.Context)
- func (h *PreferencesHandler) GetPreferences(c *gin.Context)
- func (h *PreferencesHandler) GetRecentSessions(c *gin.Context)
- func (h *PreferencesHandler) GetUIPreferences(c *gin.Context)
- func (h *PreferencesHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *PreferencesHandler) RemoveFavorite(c *gin.Context)
- func (h *PreferencesHandler) ResetPreferences(c *gin.Context)
- func (h *PreferencesHandler) UpdateDefaultsPreferences(c *gin.Context)
- func (h *PreferencesHandler) UpdateNotificationPreferences(c *gin.Context)
- func (h *PreferencesHandler) UpdatePreferences(c *gin.Context)
- func (h *PreferencesHandler) UpdateUIPreferences(c *gin.Context)
- type QuotaPolicyRequest
- type QuotasHandler
- func (h *QuotasHandler) CheckQuota(c *gin.Context)
- func (h *QuotasHandler) CreatePolicy(c *gin.Context)
- func (h *QuotasHandler) DeletePolicy(c *gin.Context)
- func (h *QuotasHandler) DeleteTeamQuota(c *gin.Context)
- func (h *QuotasHandler) DeleteUserQuota(c *gin.Context)
- func (h *QuotasHandler) GetDefaultQuotas(c *gin.Context)
- func (h *QuotasHandler) GetPolicies(c *gin.Context)
- func (h *QuotasHandler) GetPolicy(c *gin.Context)
- func (h *QuotasHandler) GetQuotaViolations(c *gin.Context)
- func (h *QuotasHandler) GetTeamQuota(c *gin.Context)
- func (h *QuotasHandler) GetTeamQuotaStatus(c *gin.Context)
- func (h *QuotasHandler) GetTeamUsage(c *gin.Context)
- func (h *QuotasHandler) GetUserQuota(c *gin.Context)
- func (h *QuotasHandler) GetUserQuotaStatus(c *gin.Context)
- func (h *QuotasHandler) GetUserUsage(c *gin.Context)
- func (h *QuotasHandler) ListAllQuotas(c *gin.Context)
- func (h *QuotasHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *QuotasHandler) SetDefaultQuotas(c *gin.Context)
- func (h *QuotasHandler) SetTeamQuota(c *gin.Context)
- func (h *QuotasHandler) SetUserQuota(c *gin.Context)
- func (h *QuotasHandler) UpdatePolicy(c *gin.Context)
- type Recording
- type RecordingHandler
- func (h *RecordingHandler) CreatePolicy(c *gin.Context)
- func (h *RecordingHandler) DeletePolicy(c *gin.Context)
- func (h *RecordingHandler) DeleteRecording(c *gin.Context)
- func (h *RecordingHandler) DownloadRecording(c *gin.Context)
- func (h *RecordingHandler) GetPolicy(c *gin.Context)
- func (h *RecordingHandler) GetRecording(c *gin.Context)
- func (h *RecordingHandler) GetRecordingAccessLog(c *gin.Context)
- func (h *RecordingHandler) ListPolicies(c *gin.Context)
- func (h *RecordingHandler) ListRecordings(c *gin.Context)
- func (h *RecordingHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *RecordingHandler) StartRecording(c *gin.Context)
- func (h *RecordingHandler) StopRecording(c *gin.Context)
- func (h *RecordingHandler) UpdatePolicy(c *gin.Context)
- type RecordingPolicy
- type ResourceConfig
- type ResourceThresholds
- type SavedSearch
- type ScalePolicy
- type ScalingEvent
- type ScheduleConfig
- type ScheduledSession
- type SchedulingHandler
- func (h *SchedulingHandler) CalendarOAuthCallback(c *gin.Context)
- func (h *SchedulingHandler) ConnectCalendar(c *gin.Context)
- func (h *SchedulingHandler) CreateScheduledSession(c *gin.Context)
- func (h *SchedulingHandler) DeleteScheduledSession(c *gin.Context)
- func (h *SchedulingHandler) DisableScheduledSession(c *gin.Context)
- func (h *SchedulingHandler) DisconnectCalendar(c *gin.Context)
- func (h *SchedulingHandler) EnableScheduledSession(c *gin.Context)
- func (h *SchedulingHandler) ExportICalendar(c *gin.Context)
- func (h *SchedulingHandler) GetScheduledSession(c *gin.Context)
- func (h *SchedulingHandler) ListCalendarIntegrations(c *gin.Context)
- func (h *SchedulingHandler) ListScheduledSessions(c *gin.Context)
- func (h *SchedulingHandler) SyncCalendar(c *gin.Context)
- func (h *SchedulingHandler) UpdateScheduledSession(c *gin.Context)
- type SearchHandler
- func (h *SearchHandler) AdvancedSearch(c *gin.Context)
- func (h *SearchHandler) ClearSearchHistory(c *gin.Context)
- func (h *SearchHandler) CreateSavedSearch(c *gin.Context)
- func (h *SearchHandler) DeleteSavedSearch(c *gin.Context)
- func (h *SearchHandler) ExecuteSavedSearch(c *gin.Context)
- func (h *SearchHandler) GetAppTypes(c *gin.Context)
- func (h *SearchHandler) GetCategories(c *gin.Context)
- func (h *SearchHandler) GetPopularTags(c *gin.Context)
- func (h *SearchHandler) GetSavedSearch(c *gin.Context)
- func (h *SearchHandler) GetSearchHistory(c *gin.Context)
- func (h *SearchHandler) ListSavedSearches(c *gin.Context)
- func (h *SearchHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *SearchHandler) Search(c *gin.Context)
- func (h *SearchHandler) SearchSessions(c *gin.Context)
- func (h *SearchHandler) SearchSuggestions(c *gin.Context)
- func (h *SearchHandler) SearchTemplates(c *gin.Context)
- func (h *SearchHandler) UpdateSavedSearch(c *gin.Context)
- type SearchResult
- type SecurityHandler
- func (h *SecurityHandler) CheckDevicePosture(c *gin.Context)
- func (h *SecurityHandler) CheckIPAccess(c *gin.Context)
- func (h *SecurityHandler) CreateIPWhitelist(c *gin.Context)
- func (h *SecurityHandler) DeleteIPWhitelist(c *gin.Context)
- func (h *SecurityHandler) DisableMFA(c *gin.Context)
- func (h *SecurityHandler) GenerateBackupCodes(c *gin.Context)
- func (h *SecurityHandler) GetSecurityAlerts(c *gin.Context)
- func (h *SecurityHandler) ListIPWhitelist(c *gin.Context)
- func (h *SecurityHandler) ListMFAMethods(c *gin.Context)
- func (h *SecurityHandler) SetupMFA(c *gin.Context)
- func (h *SecurityHandler) VerifyMFA(c *gin.Context)
- func (h *SecurityHandler) VerifyMFASetup(c *gin.Context)
- func (h *SecurityHandler) VerifySession(c *gin.Context)
- type SelkiesProxyHandler
- type SendCommandRequest
- type SessionActivityEvent
- type SessionActivityHandler
- func (h *SessionActivityHandler) GetActivityStats(c *gin.Context)
- func (h *SessionActivityHandler) GetSessionActivity(c *gin.Context)
- func (h *SessionActivityHandler) GetSessionTimeline(c *gin.Context)
- func (h *SessionActivityHandler) GetUserSessionActivity(c *gin.Context)
- func (h *SessionActivityHandler) LogActivityEvent(c *gin.Context)
- type SessionTemplate
- type SessionTemplatesHandler
- func (h *SessionTemplatesHandler) CloneSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) CreateSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) CreateTemplateFromSession(c *gin.Context)
- func (h *SessionTemplatesHandler) CreateTemplateVersion(c *gin.Context)
- func (h *SessionTemplatesHandler) DeleteSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) GetDefaultTemplates(c *gin.Context)
- func (h *SessionTemplatesHandler) GetSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) ListPublicTemplates(c *gin.Context)
- func (h *SessionTemplatesHandler) ListSessionTemplates(c *gin.Context)
- func (h *SessionTemplatesHandler) ListTeamTemplates(c *gin.Context)
- func (h *SessionTemplatesHandler) ListTemplateShares(c *gin.Context)
- func (h *SessionTemplatesHandler) ListTemplateVersions(c *gin.Context)
- func (h *SessionTemplatesHandler) PublishSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *SessionTemplatesHandler) RestoreTemplateVersion(c *gin.Context)
- func (h *SessionTemplatesHandler) RevokeTemplateShare(c *gin.Context)
- func (h *SessionTemplatesHandler) SetAsDefaultTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) ShareSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) UnpublishSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) UpdateSessionTemplate(c *gin.Context)
- func (h *SessionTemplatesHandler) UseSessionTemplate(c *gin.Context)
- type SessionVerification
- type SetApplicationEnabledRequest
- type SetDefaultQuotasRequest
- type SetQuotaRequest
- type SetupAdminRequest
- type SetupAdminResponse
- type SetupHandler
- type SetupStatusResponse
- type SharingHandler
- func (h *SharingHandler) AcceptInvitation(c *gin.Context)
- func (h *SharingHandler) CreateInvitation(c *gin.Context)
- func (h *SharingHandler) CreateShare(c *gin.Context)
- func (h *SharingHandler) ListCollaborators(c *gin.Context)
- func (h *SharingHandler) ListInvitations(c *gin.Context)
- func (h *SharingHandler) ListSharedSessions(c *gin.Context)
- func (h *SharingHandler) ListShares(c *gin.Context)
- func (h *SharingHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *SharingHandler) RemoveCollaborator(c *gin.Context)
- func (h *SharingHandler) RevokeInvitation(c *gin.Context)
- func (h *SharingHandler) RevokeShare(c *gin.Context)
- func (h *SharingHandler) TransferOwnership(c *gin.Context)
- func (h *SharingHandler) UpdateCollaboratorActivity(c *gin.Context)
- type SubscriptionFilters
- type SuccessResponse
- type TeamHandler
- func (h *TeamHandler) CheckPermission(c *gin.Context)
- func (h *TeamHandler) GetMyTeamPermissions(c *gin.Context)
- func (h *TeamHandler) GetMyTeams(c *gin.Context)
- func (h *TeamHandler) GetTeamPermissions(c *gin.Context)
- func (h *TeamHandler) GetTeamRoleInfo(c *gin.Context)
- func (h *TeamHandler) ListTeamSessions(c *gin.Context)
- func (h *TeamHandler) RegisterRoutes(router *gin.RouterGroup)
- type TemplateInheritance
- type TemplateShare
- type TemplateSnapshot
- type TemplateTest
- type TemplateVersion
- type TemplateVersioningHandler
- func (h *TemplateVersioningHandler) CloneTemplateVersion(c *gin.Context)
- func (h *TemplateVersioningHandler) CreateTemplateTest(c *gin.Context)
- func (h *TemplateVersioningHandler) CreateTemplateVersion(c *gin.Context)
- func (h *TemplateVersioningHandler) DeprecateTemplateVersion(c *gin.Context)
- func (h *TemplateVersioningHandler) GetTemplateInheritance(c *gin.Context)
- func (h *TemplateVersioningHandler) GetTemplateVersion(c *gin.Context)
- func (h *TemplateVersioningHandler) ListTemplateTests(c *gin.Context)
- func (h *TemplateVersioningHandler) ListTemplateVersions(c *gin.Context)
- func (h *TemplateVersioningHandler) PublishTemplateVersion(c *gin.Context)
- func (h *TemplateVersioningHandler) SetDefaultTemplateVersion(c *gin.Context)
- func (h *TemplateVersioningHandler) UpdateTemplateTestStatus(c *gin.Context)
- type TransferOwnershipRequest
- type TrustedDevice
- type UpdateConfigurationRequest
- type UpdateLicenseRequest
- type UpdateSessionTemplateRequest
- type UpdateWebhookRequest
- type UserHandler
- func (h *UserHandler) CreateUser(c *gin.Context)
- func (h *UserHandler) DeleteAdminUserQuota(c *gin.Context)
- func (h *UserHandler) DeleteUser(c *gin.Context)
- func (h *UserHandler) GetAdminUserQuota(c *gin.Context)
- func (h *UserHandler) GetCurrentUser(c *gin.Context)
- func (h *UserHandler) GetCurrentUserQuota(c *gin.Context)
- func (h *UserHandler) GetUser(c *gin.Context)
- func (h *UserHandler) GetUserGroups(c *gin.Context)
- func (h *UserHandler) GetUserQuota(c *gin.Context)
- func (h *UserHandler) GetUserSessions(c *gin.Context)
- func (h *UserHandler) ListAllUserQuotas(c *gin.Context)
- func (h *UserHandler) ListUsers(c *gin.Context)
- func (h *UserHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *UserHandler) SetAdminUserQuota(c *gin.Context)
- func (h *UserHandler) SetUserQuota(c *gin.Context)
- func (h *UserHandler) UpdateUser(c *gin.Context)
- type ValidateLicenseRequest
- type ValidateLicenseResponse
- type WebSocketClient
- type WebSocketHandler
- func (h *WebSocketHandler) AlertUpdates(c *gin.Context)
- func (h *WebSocketHandler) BroadcastAlertEvent(event string, data map[string]interface{})
- func (h *WebSocketHandler) BroadcastNotificationEvent(event string, userID string, data map[string]interface{})
- func (h *WebSocketHandler) BroadcastSessionEvent(event string, sessionID string, userID string, data map[string]interface{})
- func (h *WebSocketHandler) DisconnectUser(userID string)
- func (h *WebSocketHandler) GetClientsByUser(userID string) []*WebSocketSession
- func (h *WebSocketHandler) GetConnectedClients() int
- func (h *WebSocketHandler) MetricsUpdates(c *gin.Context)
- func (h *WebSocketHandler) NotificationUpdates(c *gin.Context)
- func (h *WebSocketHandler) RegisterRoutes(router *gin.RouterGroup)
- func (h *WebSocketHandler) SessionUpdates(c *gin.Context)
- type WebSocketHub
- type WebSocketMessage
- type WebSocketSession
- type Webhook
- type WebhookDelivery
- type WebhookEvent
- type WebhookFilters
- type WebhookRetryPolicy
- type WebhookWithSecret
Constants ¶
const ( // BackupCodesCount is the number of backup codes to generate BackupCodesCount = 10 // BackupCodeLength is the length of each backup code BackupCodeLength = 8 // MFAMaxAttemptsPerMinute is the maximum MFA verification attempts per minute MFAMaxAttemptsPerMinute = 5 // MFARateLimitWindow is the time window for MFA rate limiting MFARateLimitWindow = 1 * time.Minute )
MFA Constants control multi-factor authentication behavior.
These values balance security (preventing brute force) with usability (not frustrating legitimate users).
const ( // WebSocketPingInterval is how often to send ping messages WebSocketPingInterval = 54 * time.Second // WebSocketWriteDeadline is the deadline for write operations WebSocketWriteDeadline = 10 * time.Second // WebSocketReadDeadline is the deadline for read operations WebSocketReadDeadline = 60 * time.Second // WebSocketBufferSize is the size of the send buffer for each client WebSocketBufferSize = 256 // WebSocketReadBufferSize is the size of the read buffer WebSocketReadBufferSize = 1024 // WebSocketWriteBufferSize is the size of the write buffer WebSocketWriteBufferSize = 1024 )
WebSocket Constants
const ( // WebhookDefaultMaxRetries is the default number of retry attempts WebhookDefaultMaxRetries = 3 // WebhookDefaultRetryDelay is the default delay between retries in seconds WebhookDefaultRetryDelay = 60 // WebhookDefaultBackoffMultiplier is the default exponential backoff multiplier WebhookDefaultBackoffMultiplier = 2.0 // WebhookTimeout is the timeout for webhook HTTP requests WebhookTimeout = 10 * time.Second )
Webhook Constants
const ( NotificationTypeSessionCreated = "session.created" NotificationTypeSessionIdle = "session.idle" NotificationTypeQuotaWarning = "quota.warning" NotificationTypeQuotaExceeded = "quota.exceeded" NotificationTypeTeamInvitation = "team.invitation" NotificationTypeSystemAlert = "system.alert" )
Notification types
const ( EventCategoryLifecycle = "lifecycle" EventCategoryConnection = "connection" EventCategoryState = "state" EventCategoryConfiguration = "configuration" EventCategoryAccess = "access" EventCategoryError = "error" )
Event categories for classification
const ( EventSessionCreated = "session.created" EventSessionStarted = "session.started" EventSessionStopped = "session.stopped" EventSessionHibernated = "session.hibernated" EventSessionWoken = "session.woken" EventSessionTerminated = "session.terminated" EventSessionDeleted = "session.deleted" EventUserConnected = "user.connected" EventUserDisconnected = "user.disconnected" EventUserHeartbeat = "user.heartbeat" EventStateChanged = "state.changed" EventResourcesUpdated = "resources.updated" EventConfigUpdated = "config.updated" EventTagsUpdated = "tags.updated" EventAccessGranted = "access.granted" EventAccessDenied = "access.denied" EventError = "error.occurred" )
Event types for tracking
const ( // SessionVerificationTimeout is how long a session verification is valid SessionVerificationTimeout = 60 * time.Second )
Session Constants
Variables ¶
var ( Version = "dev" GitCommit = "unknown" BuildTime = "unknown" )
Version information - can be set at build time with linker flags: go build -ldflags "-X github.com/streamspace-dev/streamspace/api/internal/handlers.Version=v1.2.3"
var AvailableEvents = []string{
"session.created",
"session.started",
"session.hibernated",
"session.terminated",
"session.failed",
"user.created",
"user.deleted",
"dlp.violation",
"recording.started",
"recording.completed",
"template.created",
"template.updated",
"workflow.started",
"workflow.completed",
"workflow.failed",
"collaboration.started",
"collaboration.ended",
"alert.triggered",
}
Available webhook events
Functions ¶
func BroadcastComplianceViolation ¶
BroadcastComplianceViolation sends compliance violation alerts.
This notifies users (or admins) of compliance policy violations such as: - Data retention policy violations - Unauthorized resource access attempts - Quota exceeded violations - Security policy violations
If userID is provided, sends to that specific user. If userID is empty, broadcasts to all admins for system-wide violations.
Parameters:
- userID: User who caused the violation (empty string for admin broadcast)
- violationID: Database ID of the violation record
- policyID: The compliance policy that was violated
- severity: Violation severity ("low", "medium", "high", "critical")
Example usage:
// User-specific violation
BroadcastComplianceViolation("user123", 456, 789, "high")
// System-wide violation (admin broadcast)
BroadcastComplianceViolation("", 457, 790, "critical")
func BroadcastNodeHealthUpdate ¶
BroadcastNodeHealthUpdate sends Kubernetes node health updates to admins.
This provides real-time cluster monitoring in the admin dashboard. Admins can see node health, CPU, and memory usage updating live without refreshing.
SECURITY: This is broadcast to ALL connected clients. The frontend should filter this message type to only display for admin users.
Parameters:
- nodeName: Kubernetes node name (e.g., "worker-01")
- status: Health status ("healthy", "degraded", "unhealthy", "unknown")
- cpu: CPU usage as percentage (0.0 to 100.0)
- memory: Memory usage as percentage (0.0 to 100.0)
Example usage:
BroadcastNodeHealthUpdate("worker-01", "healthy", 45.2, 67.8)
func BroadcastScalingEvent ¶
BroadcastScalingEvent sends auto-scaling events to admins.
This notifies admins when the platform automatically scales up or down in response to resource usage or scaling policies. Admins see these events live in the admin dashboard.
SECURITY: This is broadcast to ALL connected clients. The frontend should filter this message type to only display for admin users.
Parameters:
- policyID: The scaling policy ID that triggered this event
- action: Scaling action ("scale_up", "scale_down")
- result: Action result ("success", "failed")
Example usage:
BroadcastScalingEvent(123, "scale_up", "success")
func BroadcastScheduledSessionEvent ¶
BroadcastScheduledSessionEvent sends updates about scheduled session execution.
This notifies users when their scheduled sessions start, complete, or fail. Users can see session status updating live without refreshing the page.
Parameters:
- userID: The user who scheduled the session
- scheduleID: The schedule configuration ID
- event: Event type ("started", "completed", "failed")
- sessionID: The Kubernetes session ID (for linking to logs/details)
Example usage:
BroadcastScheduledSessionEvent("user123", 789, "started", "user123-firefox-abc")
func BroadcastSecurityAlert ¶
BroadcastSecurityAlert sends security alerts to a user in real-time.
This provides immediate notification of security events such as: - Failed MFA attempts - Unusual login locations - API key usage from new IPs - Password change attempts - Session hijacking attempts
The user sees these alerts instantly in a notification banner or modal.
Parameters:
- userID: The user being alerted
- alertType: Type of alert ("mfa_failed", "new_login", "api_key_used", etc.)
- severity: Alert severity ("low", "medium", "high", "critical")
- message: Human-readable alert message
Example usage:
BroadcastSecurityAlert("user123", "mfa_failed", "high",
"Multiple failed MFA attempts detected from IP 203.0.113.42")
func BroadcastWebhookDelivery ¶
BroadcastWebhookDelivery sends webhook delivery status updates to a user.
This is called after a webhook HTTP request completes to notify the user of success or failure in real-time. The user can see webhook deliveries updating live in their dashboard without polling or refreshing.
Parameters:
- userID: The user who owns the webhook
- webhookID: The webhook configuration ID
- deliveryID: The specific delivery attempt ID (for tracking retries)
- status: Delivery status ("success", "failed", "retrying")
Example usage:
BroadcastWebhookDelivery("user123", 456, 789, "success")
func GetSwaggerSpec ¶
func GetSwaggerSpec() []byte
GetSwaggerSpec returns the raw swagger specification bytes (for testing)
func GetSwaggerSpecPath ¶
func GetSwaggerSpecPath() string
GetSwaggerSpecPath returns the OpenAPI spec URL path
func HandleEnterpriseWebSocket ¶
HandleEnterpriseWebSocket is the HTTP handler for WebSocket upgrade requests.
This function: 1. Upgrades the HTTP connection to WebSocket protocol 2. Authenticates the user (via middleware context) 3. Creates a WebSocketClient instance 4. Registers the client with the hub 5. Starts read/write goroutines 6. Sends a welcome message
SECURITY: - Origin validation is enforced by the upgrader's CheckOrigin function - User authentication is required (set by auth middleware before this handler) - Unauthenticated requests are rejected by closing the connection
Flow:
HTTP Request (with Upgrade: websocket header) ↓ CheckOrigin validation (prevents CSWSH attacks) ↓ WebSocket upgrade (protocol switch) ↓ Authentication check (requires auth middleware) ↓ Client creation and registration ↓ Start read/write goroutines (run until disconnect) ↓ Send welcome message
Parameters:
- c: Gin context containing the HTTP request and response
Middleware Requirements:
- Authentication middleware must set "userID" in context
func IsDocsPath ¶
IsDocsPath checks if a path is a documentation path (for middleware exclusion)
Types ¶
type APIKey ¶
type APIKey struct {
ID int `json:"id"`
KeyPrefix string `json:"keyPrefix"` // First 8 chars for identification
Name string `json:"name"`
Description string `json:"description,omitempty"`
UserID string `json:"userId"`
Scopes []string `json:"scopes,omitempty"`
RateLimit int `json:"rateLimit"`
ExpiresAt *time.Time `json:"expiresAt,omitempty"`
LastUsedAt *time.Time `json:"lastUsedAt,omitempty"`
UseCount int `json:"useCount"`
IsActive bool `json:"isActive"`
CreatedAt time.Time `json:"createdAt"`
CreatedBy string `json:"createdBy,omitempty"`
}
APIKey represents an API key with its metadata
type APIKeyHandler ¶
type APIKeyHandler struct {
// contains filtered or unexported fields
}
APIKeyHandler handles API key management
func NewAPIKeyHandler ¶
func NewAPIKeyHandler(database *db.Database) *APIKeyHandler
NewAPIKeyHandler creates a new API key handler
func (*APIKeyHandler) CreateAPIKey ¶
func (h *APIKeyHandler) CreateAPIKey(c *gin.Context)
CreateAPIKey creates a new API key
func (*APIKeyHandler) DeleteAPIKey ¶
func (h *APIKeyHandler) DeleteAPIKey(c *gin.Context)
DeleteAPIKey permanently deletes an API key
func (*APIKeyHandler) GetAPIKeyUsage ¶
func (h *APIKeyHandler) GetAPIKeyUsage(c *gin.Context)
GetAPIKeyUsage returns usage statistics for an API key
func (*APIKeyHandler) ListAPIKeys ¶
func (h *APIKeyHandler) ListAPIKeys(c *gin.Context)
ListAPIKeys returns all API keys for the current user
func (*APIKeyHandler) ListAllAPIKeys ¶
func (h *APIKeyHandler) ListAllAPIKeys(c *gin.Context)
ListAllAPIKeys returns all API keys in the system (admin only)
func (*APIKeyHandler) RevokeAPIKey ¶
func (h *APIKeyHandler) RevokeAPIKey(c *gin.Context)
RevokeAPIKey revokes (deactivates) an API key
type AcceptInvitationRequest ¶
type AcceptInvitationRequest struct {
UserId string `json:"userId" binding:"required" validate:"required,min=1,max=100"`
}
AcceptInvitationRequest represents a request to accept a session invitation
type AccessLog ¶
type AccessLog struct {
ID int64 `json:"id"`
RecordingID int64 `json:"recording_id"`
UserID *string `json:"user_id"`
Action string `json:"action"`
AccessedAt time.Time `json:"accessed_at"`
IPAddress *string `json:"ip_address"`
UserAgent *string `json:"user_agent"`
// Computed fields
UserName string `json:"user_name,omitempty"`
}
AccessLog represents a recording access log entry
type ActivateLicenseRequest ¶
type ActivateLicenseRequest struct {
LicenseKey string `json:"license_key" binding:"required" validate:"required,min=10,max=256"`
}
ActivateLicenseRequest represents license activation request
type ActivityHandler ¶
type ActivityHandler struct {
// contains filtered or unexported fields
}
ActivityHandler handles session activity-related endpoints
func NewActivityHandler ¶
func NewActivityHandler(k8sClient *k8s.Client, tracker *activity.Tracker, database *db.Database) *ActivityHandler
NewActivityHandler creates a new activity handler
func (*ActivityHandler) GetActivity ¶
func (h *ActivityHandler) GetActivity(c *gin.Context)
GetActivity godoc @Summary Get session activity status @Description Returns the current activity status of a session including idle state @Tags sessions, activity @Accept json @Produce json @Param id path string true "Session ID" @Success 200 {object} ActivityResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/sessions/{id}/activity [get]
func (*ActivityHandler) RecordHeartbeat ¶
func (h *ActivityHandler) RecordHeartbeat(c *gin.Context)
RecordHeartbeat godoc @Summary Record session activity heartbeat @Description Updates the lastActivity timestamp for a session to indicate it's being actively used @Tags sessions, activity @Accept json @Produce json @Param id path string true "Session ID" @Success 200 {object} map[string]interface{} @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/sessions/{id}/heartbeat [post]
func (*ActivityHandler) RegisterRoutes ¶
func (h *ActivityHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers activity-related routes
type ActivityResponse ¶
type ActivityResponse struct {
SessionID string `json:"sessionId"`
IsActive bool `json:"isActive"`
IsIdle bool `json:"isIdle"`
LastActivity *string `json:"lastActivity"`
IdleDuration int64 `json:"idleDuration"` // seconds
IdleThreshold int64 `json:"idleThreshold"` // seconds
ShouldHibernate bool `json:"shouldHibernate"`
}
ActivityResponse represents session activity status
type AgentHandler ¶
type AgentHandler struct {
// contains filtered or unexported fields
}
AgentHandler handles agent registration and management
func NewAgentHandler ¶
func NewAgentHandler(database *db.Database, hub *websocket.AgentHub, dispatcher *services.CommandDispatcher) *AgentHandler
NewAgentHandler creates a new agent handler
func (*AgentHandler) ApproveAgent ¶
func (h *AgentHandler) ApproveAgent(c *gin.Context)
ApproveAgent godoc @Summary Approve pending agent @Description Approves a pending agent and generates API key @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Success 200 {object} map[string]interface{} "Agent approved" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/{agent_id}/approve [post] @Security ApiKeyAuth
func (*AgentHandler) DeregisterAgent ¶
func (h *AgentHandler) DeregisterAgent(c *gin.Context)
DeregisterAgent godoc @Summary Deregister an agent @Description Removes an agent from the Control Plane. CASCADE will delete related commands. @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Success 200 {object} map[string]interface{} "Agent deregistered successfully" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/{agent_id} [delete]
func (*AgentHandler) GenerateAPIKey ¶
func (h *AgentHandler) GenerateAPIKey(c *gin.Context)
GenerateAPIKey godoc @Summary Generate API key for an agent (admin only) @Description Generates a new API key for an agent. The plaintext key is returned ONCE and must be saved by the administrator. The key is hashed with bcrypt before storage. @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Success 200 {object} map[string]interface{} "API key generated successfully" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /admin/agents/{agent_id}/generate-key [post] @Security BearerAuth
func (*AgentHandler) GetAgent ¶
func (h *AgentHandler) GetAgent(c *gin.Context)
GetAgent godoc @Summary Get agent details @Description Retrieves details for a specific agent by agent_id @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Success 200 {object} models.Agent "Agent details" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/{agent_id} [get]
func (*AgentHandler) ListAgents ¶
func (h *AgentHandler) ListAgents(c *gin.Context)
ListAgents godoc @Summary List all agents @Description Retrieves all registered agents with optional filters @Tags agents @Accept json @Produce json @Param platform query string false "Filter by platform (kubernetes, docker, vm, cloud)" @Param status query string false "Filter by status (online, offline, draining)" @Param region query string false "Filter by region" @Success 200 {object} map[string]interface{} "List of agents" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents [get]
func (*AgentHandler) RegisterAdminRoutes ¶
func (h *AgentHandler) RegisterAdminRoutes(router *gin.RouterGroup)
RegisterAdminRoutes registers admin-only agent management routes (requires JWT admin auth) These routes are used by admin UI to manage agents
func (*AgentHandler) RegisterAgent ¶
func (h *AgentHandler) RegisterAgent(c *gin.Context)
RegisterAgent godoc @Summary Register an agent with the Control Plane @Description Registers a new agent or re-registers an existing agent. Agents use this endpoint when they first connect or reconnect. @Tags agents @Accept json @Produce json @Param request body models.AgentRegistrationRequest true "Agent registration request" @Success 201 {object} models.Agent "Agent registered successfully (new)" @Success 200 {object} models.Agent "Agent re-registered successfully (existing)" @Failure 400 {object} map[string]interface{} "Invalid request" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/register [post]
func (*AgentHandler) RegisterRoutes ¶
func (h *AgentHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers agent routes (for agent self-service - requires API key) These routes are used by agents themselves, not by admin UI Note: router is already prefixed with /agents from main.go
func (*AgentHandler) RejectAgent ¶
func (h *AgentHandler) RejectAgent(c *gin.Context)
RejectAgent godoc @Summary Reject pending agent @Description Rejects a pending agent registration @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Success 200 {object} map[string]interface{} "Agent rejected" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/{agent_id}/reject [post] @Security ApiKeyAuth
func (*AgentHandler) RotateAPIKey ¶
func (h *AgentHandler) RotateAPIKey(c *gin.Context)
RotateAPIKey godoc @Summary Rotate API key for an agent (admin only) @Description Generates a new API key and immediately invalidates the old one. The plaintext key is returned ONCE. @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Success 200 {object} map[string]interface{} "API key rotated successfully" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /admin/agents/{agent_id}/rotate-key [post] @Security BearerAuth
func (*AgentHandler) SendCommand ¶
func (h *AgentHandler) SendCommand(c *gin.Context)
func (*AgentHandler) UpdateHeartbeat ¶
func (h *AgentHandler) UpdateHeartbeat(c *gin.Context)
UpdateHeartbeat godoc @Summary Update agent heartbeat @Description Updates the last heartbeat timestamp and optionally the status and capacity @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Param request body models.AgentHeartbeatRequest true "Heartbeat request" @Success 200 {object} map[string]interface{} "Heartbeat updated successfully" @Failure 400 {object} map[string]interface{} "Invalid request" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/{agent_id}/heartbeat [post]
type AgentWebSocketHandler ¶
type AgentWebSocketHandler struct {
// contains filtered or unexported fields
}
AgentWebSocketHandler handles WebSocket connections for agents.
The handler is responsible for:
- Upgrading HTTP connections to WebSocket
- Validating agent authentication
- Managing connection lifecycle
- Starting read/write pumps
func NewAgentWebSocketHandler ¶
func NewAgentWebSocketHandler(hub *wsocket.AgentHub, database *db.Database) *AgentWebSocketHandler
NewAgentWebSocketHandler creates a new WebSocket handler for agents.
Example:
handler := NewAgentWebSocketHandler(hub, database)
router.GET("/api/v1/agents/connect", handler.HandleAgentConnection)
func (*AgentWebSocketHandler) HandleAgentConnection ¶
func (h *AgentWebSocketHandler) HandleAgentConnection(c *gin.Context)
HandleAgentConnection handles the WebSocket upgrade and connection lifecycle.
Query Parameters:
- agent_id (required): The unique identifier for the agent
Flow:
- Validate agent_id query parameter
- Verify agent exists in database
- Upgrade HTTP connection to WebSocket
- Create AgentConnection with channels
- Register connection with hub
- Start readPump and writePump goroutines
- Wait for connection to close
Example Agent Connection:
ws, err := websocket.Dial("ws://localhost:8080/api/v1/agents/connect?agent_id=k8s-prod-us-east-1", "", "http://localhost/")
func (*AgentWebSocketHandler) RegisterRoutes ¶
func (h *AgentWebSocketHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers WebSocket routes for agent connections.
Example:
handler := NewAgentWebSocketHandler(hub, database)
handler.RegisterRoutes(router.Group("/api/v1"))
type Annotation ¶
type Annotation struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
Type string `json:"type"` // "line", "arrow", "rectangle", "circle", "text", "freehand"
Color string `json:"color"`
Thickness int `json:"thickness"`
Points []Point `json:"points"`
Text string `json:"text,omitempty"`
IsPersistent bool `json:"is_persistent"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
Annotation represents a drawing/annotation on the session
type ApplicationHandler ¶
type ApplicationHandler struct {
// contains filtered or unexported fields
}
ApplicationHandler handles installed application endpoints
func NewApplicationHandler ¶
func NewApplicationHandler(database *db.Database, publisher *events.Publisher, k8sClient *k8s.Client, platform string) *ApplicationHandler
NewApplicationHandler creates a new application handler
func (*ApplicationHandler) AddGroupAccess ¶
func (h *ApplicationHandler) AddGroupAccess(c *gin.Context)
AddGroupAccess godoc @Summary Grant group access to an application @Description Add a group with specified access level @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Param request body models.AddGroupAccessRequest true "Access request" @Success 201 {object} map[string]interface{} @Failure 400 {object} ErrorResponse @Router /api/v1/applications/{id}/groups [post]
func (*ApplicationHandler) DeleteApplication ¶
func (h *ApplicationHandler) DeleteApplication(c *gin.Context)
DeleteApplication godoc @Summary Delete an application @Description Remove an installed application and all its access rules @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Success 200 {object} map[string]interface{} @Failure 500 {object} ErrorResponse @Router /api/v1/applications/{id} [delete]
func (*ApplicationHandler) GetApplication ¶
func (h *ApplicationHandler) GetApplication(c *gin.Context)
GetApplication godoc @Summary Get application details @Description Get detailed information about an installed application @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Success 200 {object} models.InstalledApplication @Failure 404 {object} ErrorResponse @Router /api/v1/applications/{id} [get]
func (*ApplicationHandler) GetApplicationGroups ¶
func (h *ApplicationHandler) GetApplicationGroups(c *gin.Context)
GetApplicationGroups godoc @Summary Get groups with access to an application @Description List all groups that have access to this application @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Success 200 {object} map[string]interface{} @Failure 500 {object} ErrorResponse @Router /api/v1/applications/{id}/groups [get]
func (*ApplicationHandler) GetApplicationIcon ¶
func (h *ApplicationHandler) GetApplicationIcon(c *gin.Context)
GetApplicationIcon godoc @Summary Get application icon @Description Get the icon image for an installed application @Tags applications @Produce image/png,image/svg+xml,image/jpeg @Param id path string true "Application ID" @Success 200 {file} binary @Failure 404 {object} ErrorResponse @Router /api/v1/applications/{id}/icon [get]
func (*ApplicationHandler) GetTemplateConfig ¶
func (h *ApplicationHandler) GetTemplateConfig(c *gin.Context)
GetTemplateConfig godoc @Summary Get application template configuration options @Description Get the configurable options from the template manifest @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Success 200 {object} map[string]interface{} @Failure 500 {object} ErrorResponse @Router /api/v1/applications/{id}/config [get]
func (*ApplicationHandler) GetUserApplications ¶
func (h *ApplicationHandler) GetUserApplications(c *gin.Context)
GetUserApplications godoc @Summary Get applications accessible to current user @Description Get all applications the user can access via their groups @Tags applications @Accept json @Produce json @Success 200 {object} models.ApplicationListResponse @Failure 401 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/applications/user [get]
func (*ApplicationHandler) InstallApplication ¶
func (h *ApplicationHandler) InstallApplication(c *gin.Context)
InstallApplication godoc @Summary Install a new application @Description Install an application from the catalog. This creates both a Kubernetes Template CRD and a database record for the installed application. The K8s Template is required for users to launch sessions from this application. @Tags applications @Accept json @Produce json @Param request body models.InstallApplicationRequest true "Installation request" @Success 201 {object} models.InstalledApplication @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/applications [post]
Installation Flow: 1. Validate request and authenticate user 2. Fetch template manifest from catalog_templates database 3. Create installed_applications database record (status: pending) 4. Grant group access permissions if specified 5. Publish NATS event for controller to process 6. Return the created application with full details
The controller subscribes to NATS events and creates platform-specific resources (Kubernetes Template CRD, Docker container, Hyper-V VM, etc.). This pattern decouples the API from platform-specific operations.
func (*ApplicationHandler) ListApplications ¶
func (h *ApplicationHandler) ListApplications(c *gin.Context)
ListApplications godoc @Summary List all installed applications @Description Get all installed applications with optional filtering @Tags applications @Accept json @Produce json @Param enabled query boolean false "Filter by enabled status" @Success 200 {object} models.ApplicationListResponse @Failure 500 {object} ErrorResponse @Router /api/v1/applications [get]
func (*ApplicationHandler) RegisterRoutes ¶
func (h *ApplicationHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers application-related routes
func (*ApplicationHandler) RemoveGroupAccess ¶
func (h *ApplicationHandler) RemoveGroupAccess(c *gin.Context)
RemoveGroupAccess godoc @Summary Remove group access from an application @Description Revoke a group's access to an application @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Param groupId path string true "Group ID" @Success 200 {object} map[string]interface{} @Failure 500 {object} ErrorResponse @Router /api/v1/applications/{id}/groups/{groupId} [delete]
func (*ApplicationHandler) SetApplicationEnabled ¶
func (h *ApplicationHandler) SetApplicationEnabled(c *gin.Context)
func (*ApplicationHandler) UpdateApplication ¶
func (h *ApplicationHandler) UpdateApplication(c *gin.Context)
UpdateApplication godoc @Summary Update an application @Description Update display name, configuration, or enabled status @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Param request body models.UpdateApplicationRequest true "Update request" @Success 200 {object} models.InstalledApplication @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Router /api/v1/applications/{id} [put]
func (*ApplicationHandler) UpdateGroupAccess ¶
func (h *ApplicationHandler) UpdateGroupAccess(c *gin.Context)
UpdateGroupAccess godoc @Summary Update group access level @Description Change a group's access level for an application @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Param groupId path string true "Group ID" @Param request body models.UpdateGroupAccessRequest true "Access level" @Success 200 {object} map[string]interface{} @Failure 400 {object} ErrorResponse @Router /api/v1/applications/{id}/groups/{groupId} [put]
type AuditHandler ¶
type AuditHandler struct {
// contains filtered or unexported fields
}
AuditHandler handles audit log retrieval endpoints
func NewAuditHandler ¶
func NewAuditHandler(database *db.Database) *AuditHandler
NewAuditHandler creates a new audit handler
func (*AuditHandler) ExportAuditLogs ¶
func (h *AuditHandler) ExportAuditLogs(c *gin.Context)
ExportAuditLogs godoc @Summary Export audit logs to CSV or JSON @Description Exports filtered audit logs for compliance reports and analysis @Tags admin, audit @Accept json @Produce text/csv,application/json @Param format query string true "Export format: 'csv' or 'json'" Enums(csv, json) @Param user_id query string false "Filter by user ID" @Param action query string false "Filter by action" @Param resource_type query string false "Filter by resource type" @Param start_date query string false "Filter from date" @Param end_date query string false "Filter to date" @Param limit query int false "Maximum records to export (default: 10000, max: 100000)" @Success 200 {file} file "CSV or JSON file" @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/audit/export [get]
func (*AuditHandler) GetAuditLog ¶
func (h *AuditHandler) GetAuditLog(c *gin.Context)
GetAuditLog godoc @Summary Get specific audit log entry @Description Retrieves a single audit log entry by ID with full details @Tags admin, audit @Accept json @Produce json @Param id path int true "Audit Log ID" @Success 200 {object} AuditLog @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/audit/{id} [get]
func (*AuditHandler) ListAuditLogs ¶
func (h *AuditHandler) ListAuditLogs(c *gin.Context)
ListAuditLogs godoc @Summary List audit logs with filtering and pagination @Description Retrieves audit logs with optional filters for compliance and security investigations @Tags admin, audit @Accept json @Produce json @Param user_id query string false "Filter by user ID" @Param username query string false "Filter by username (searches in changes JSONB)" @Param action query string false "Filter by action (GET, POST, PUT, DELETE, etc.)" @Param resource_type query string false "Filter by resource type (/api/sessions, etc.)" @Param resource_id query string false "Filter by specific resource ID" @Param ip_address query string false "Filter by IP address" @Param status_code query int false "Filter by HTTP status code" @Param start_date query string false "Filter from date (ISO 8601: 2025-01-01T00:00:00Z)" @Param end_date query string false "Filter to date (ISO 8601: 2025-12-31T23:59:59Z)" @Param page query int false "Page number (default: 1)" @Param page_size query int false "Page size (default: 100, max: 1000)" @Success 200 {object} AuditLogListResponse @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/audit [get]
func (*AuditHandler) RegisterRoutes ¶
func (h *AuditHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers audit log routes
type AuditLog ¶
type AuditLog struct {
ID int64 `json:"id"`
UserID string `json:"user_id,omitempty"`
Action string `json:"action"`
ResourceType string `json:"resource_type"`
ResourceID string `json:"resource_id,omitempty"`
Changes map[string]interface{} `json:"changes,omitempty"`
Timestamp time.Time `json:"timestamp"`
IPAddress string `json:"ip_address"`
}
AuditLog represents an audit log entry from the database
type AuditLogListResponse ¶
type AuditLogListResponse struct {
Logs []AuditLog `json:"logs"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
TotalPages int `json:"total_pages"`
}
AuditLogListResponse represents a paginated list of audit logs
type AutoScalingPolicy ¶
type AutoScalingPolicy struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
TargetType string `json:"target_type"` // "deployment", "statefulset", "template"
TargetID string `json:"target_id"` // Template ID or deployment name
Enabled bool `json:"enabled"`
ScalingMode string `json:"scaling_mode"` // "horizontal", "vertical", "both"
MinReplicas int `json:"min_replicas"`
MaxReplicas int `json:"max_replicas"`
MetricType string `json:"metric_type"` // "cpu", "memory", "custom", "schedule"
TargetMetricValue float64 `json:"target_metric_value"`
ScaleUpPolicy ScalePolicy `json:"scale_up_policy"`
ScaleDownPolicy ScalePolicy `json:"scale_down_policy"`
PredictiveScaling PredictiveScalingConfig `json:"predictive_scaling"`
CooldownPeriod int `json:"cooldown_period_seconds"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
AutoScalingPolicy defines auto-scaling rules for sessions
type BackupCode ¶
type BackupCode struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
Code string `json:"code"` // Hashed in DB
Used bool `json:"used"`
UsedAt time.Time `json:"used_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
BackupCode represents MFA backup recovery codes
type BatchHandler ¶
type BatchHandler struct {
// contains filtered or unexported fields
}
BatchHandler handles batch operations on multiple resources
func NewBatchHandler ¶
func NewBatchHandler(database *db.Database) *BatchHandler
NewBatchHandler creates a new batch handler
func (*BatchHandler) CancelBatchJob ¶
func (h *BatchHandler) CancelBatchJob(c *gin.Context)
CancelBatchJob cancels a running batch job
func (*BatchHandler) CreateSnapshots ¶
func (h *BatchHandler) CreateSnapshots(c *gin.Context)
CreateSnapshots creates snapshots for multiple sessions
func (*BatchHandler) DeleteSessions ¶
func (h *BatchHandler) DeleteSessions(c *gin.Context)
DeleteSessions deletes multiple sessions
func (*BatchHandler) DeleteSnapshots ¶
func (h *BatchHandler) DeleteSnapshots(c *gin.Context)
DeleteSnapshots deletes multiple snapshots
func (*BatchHandler) DeleteTemplates ¶
func (h *BatchHandler) DeleteTemplates(c *gin.Context)
DeleteTemplates deletes multiple templates
func (*BatchHandler) GetBatchJob ¶
func (h *BatchHandler) GetBatchJob(c *gin.Context)
GetBatchJob retrieves a specific batch job
func (*BatchHandler) HibernateSessions ¶
func (h *BatchHandler) HibernateSessions(c *gin.Context)
HibernateSessions hibernates multiple sessions
func (*BatchHandler) InstallTemplates ¶
func (h *BatchHandler) InstallTemplates(c *gin.Context)
InstallTemplates installs multiple templates
func (*BatchHandler) ListBatchJobs ¶
func (h *BatchHandler) ListBatchJobs(c *gin.Context)
ListBatchJobs lists user's batch jobs
func (*BatchHandler) RegisterRoutes ¶
func (h *BatchHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers batch operation routes
func (*BatchHandler) TerminateSessions ¶
func (h *BatchHandler) TerminateSessions(c *gin.Context)
TerminateSessions terminates multiple sessions
func (*BatchHandler) UpdateSessionResources ¶
func (h *BatchHandler) UpdateSessionResources(c *gin.Context)
UpdateSessionResources updates resources for multiple sessions
func (*BatchHandler) UpdateSessionTags ¶
func (h *BatchHandler) UpdateSessionTags(c *gin.Context)
UpdateSessionTags updates tags for multiple sessions
func (*BatchHandler) WakeSessions ¶
func (h *BatchHandler) WakeSessions(c *gin.Context)
WakeSessions wakes multiple hibernated sessions
type BatchOperation ¶
type BatchOperation struct {
ID string `json:"id"`
UserID string `json:"userId"`
OperationType string `json:"operationType"` // terminate, hibernate, wake, delete, update
ResourceType string `json:"resourceType"` // sessions, snapshots, etc.
Status string `json:"status"` // pending, running, completed, failed
TotalItems int `json:"totalItems"`
ProcessedItems int `json:"processedItems"`
SuccessCount int `json:"successCount"`
FailureCount int `json:"failureCount"`
Errors []string `json:"errors,omitempty"`
CreatedAt time.Time `json:"createdAt"`
CompletedAt *time.Time `json:"completedAt,omitempty"`
}
BatchOperation represents a batch operation job
type BroadcastMessage ¶
type BroadcastMessage struct {
Type string `json:"type"`
Event string `json:"event"`
SessionID string `json:"sessionId,omitempty"`
UserID string `json:"userId,omitempty"`
TeamID string `json:"teamId,omitempty"`
Data map[string]interface{} `json:"data"`
Timestamp time.Time `json:"timestamp"`
}
BroadcastMessage represents a message to be broadcast
type BulkUpdateRequest ¶
BulkUpdateRequest represents a request to update multiple configurations
type CalendarEvent ¶
type CalendarEvent struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
ScheduleID int64 `json:"schedule_id"`
CalendarID string `json:"calendar_id"`
EventID string `json:"event_id"`
Provider string `json:"provider"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
Timezone string `json:"timezone,omitempty"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
LastSyncedAt *time.Time `json:"last_synced_at,omitempty"`
}
CalendarEvent represents a calendar event for a session (DEPRECATED)
type CalendarIntegration ¶
type CalendarIntegration struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
Provider string `json:"provider"`
AccountEmail string `json:"account_email"`
AccessToken string `json:"-"`
RefreshToken string `json:"-"`
TokenExpiry time.Time `json:"token_expiry,omitempty"`
CalendarID string `json:"calendar_id,omitempty"`
Enabled bool `json:"enabled"`
SyncEnabled bool `json:"sync_enabled"`
AutoCreate bool `json:"auto_create_events"`
CreatedAt time.Time `json:"created_at"`
LastSyncAt *time.Time `json:"last_sync_at,omitempty"`
}
CalendarIntegration represents a calendar connection (DEPRECATED)
type CatalogHandler ¶
type CatalogHandler struct {
// contains filtered or unexported fields
}
CatalogHandler handles template catalog-related endpoints
func NewCatalogHandler ¶
func NewCatalogHandler(database *db.Database) *CatalogHandler
NewCatalogHandler creates a new catalog handler
func (*CatalogHandler) AddRating ¶
func (h *CatalogHandler) AddRating(c *gin.Context)
AddRating godoc @Summary Add or update template rating @Description Rate a template with 1-5 stars and optional review @Tags catalog, ratings @Accept json @Produce json @Param id path int true "Template ID" @Param rating body object true "Rating data" @Success 201 {object} map[string]interface{} @Failure 400 {object} ErrorResponse @Router /api/v1/catalog/templates/{id}/ratings [post]
func (*CatalogHandler) DeleteRating ¶
func (h *CatalogHandler) DeleteRating(c *gin.Context)
DeleteRating deletes a rating
func (*CatalogHandler) GetFeaturedTemplates ¶
func (h *CatalogHandler) GetFeaturedTemplates(c *gin.Context)
GetFeaturedTemplates godoc @Summary Get featured templates @Description Get curated featured templates @Tags catalog @Accept json @Produce json @Success 200 {object} map[string]interface{} @Router /api/v1/catalog/templates/featured [get]
func (*CatalogHandler) GetPopularTemplates ¶
func (h *CatalogHandler) GetPopularTemplates(c *gin.Context)
GetPopularTemplates godoc @Summary Get popular templates @Description Get most installed templates @Tags catalog @Accept json @Produce json @Success 200 {object} map[string]interface{} @Router /api/v1/catalog/templates/popular [get]
func (*CatalogHandler) GetRatings ¶
func (h *CatalogHandler) GetRatings(c *gin.Context)
GetRatings godoc @Summary Get template ratings @Description Get all ratings and reviews for a template @Tags catalog, ratings @Accept json @Produce json @Param id path int true "Template ID" @Success 200 {object} map[string]interface{} @Router /api/v1/catalog/templates/{id}/ratings [get]
func (*CatalogHandler) GetTemplateDetails ¶
func (h *CatalogHandler) GetTemplateDetails(c *gin.Context)
GetTemplateDetails godoc @Summary Get detailed template information @Description Get complete template details including ratings and stats @Tags catalog @Accept json @Produce json @Param id path int true "Template ID" @Success 200 {object} map[string]interface{} @Failure 404 {object} ErrorResponse @Router /api/v1/catalog/templates/{id} [get]
func (*CatalogHandler) GetTrendingTemplates ¶
func (h *CatalogHandler) GetTrendingTemplates(c *gin.Context)
GetTrendingTemplates godoc @Summary Get trending templates @Description Get templates with recent activity @Tags catalog @Accept json @Produce json @Success 200 {object} map[string]interface{} @Router /api/v1/catalog/templates/trending [get]
func (*CatalogHandler) ListTemplates ¶
func (h *CatalogHandler) ListTemplates(c *gin.Context)
ListTemplates godoc @Summary List catalog templates with advanced filtering @Description Get templates from catalog with search, filtering, and sorting @Tags catalog @Accept json @Produce json @Param search query string false "Search query" @Param category query string false "Filter by category" @Param tag query string false "Filter by tag" @Param appType query string false "Filter by app type" @Param featured query boolean false "Show only featured" @Param sort query string false "Sort by (popular, rating, recent, installs)" @Param page query int false "Page number" default(1) @Param limit query int false "Items per page" default(20) @Success 200 {object} map[string]interface{} @Failure 500 {object} ErrorResponse @Router /api/v1/catalog/templates [get]
func (*CatalogHandler) RecordInstall ¶
func (h *CatalogHandler) RecordInstall(c *gin.Context)
RecordInstall records a template installation
func (*CatalogHandler) RecordView ¶
func (h *CatalogHandler) RecordView(c *gin.Context)
RecordView records a template view
func (*CatalogHandler) RegisterRoutes ¶
func (h *CatalogHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers catalog-related routes
func (*CatalogHandler) UpdateRating ¶
func (h *CatalogHandler) UpdateRating(c *gin.Context)
UpdateRating updates a rating
type ChatMessage ¶
type ChatMessage struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
Username string `json:"username"`
Message string `json:"message"`
MessageType string `json:"message_type"` // "text", "system", "reaction"
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
ChatMessage represents a collaboration chat message
type CheckQuotaRequest ¶
type CheckQuotaRequest struct {
UserID string `json:"userId" binding:"required" validate:"required,min=1,max=100"`
CPU int `json:"cpu" validate:"gte=0,lte=100000"`
Memory int `json:"memory" validate:"gte=0,lte=1000000"`
AddSessions int `json:"addSessions" validate:"gte=0,lte=100"`
}
CheckQuotaRequest represents a request to check quota availability
type CollaborationHandler ¶
type CollaborationHandler struct {
// DB is the database connection for collaboration queries and updates.
DB *db.Database
}
Handler handles collaboration-related HTTP requests.
func NewCollaborationHandler ¶
func NewCollaborationHandler(database *db.Database) *CollaborationHandler
NewCollaborationHandler creates a new collaboration handler.
func (*CollaborationHandler) ClearAllAnnotations ¶
func (h *CollaborationHandler) ClearAllAnnotations(c *gin.Context)
ClearAllAnnotations removes all annotations
func (*CollaborationHandler) CreateAnnotation ¶
func (h *CollaborationHandler) CreateAnnotation(c *gin.Context)
CreateAnnotation creates a new annotation
func (*CollaborationHandler) CreateCollaborationSession ¶
func (h *CollaborationHandler) CreateCollaborationSession(c *gin.Context)
CreateCollaborationSession creates a new collaboration session
func (*CollaborationHandler) DeleteAnnotation ¶
func (h *CollaborationHandler) DeleteAnnotation(c *gin.Context)
DeleteAnnotation removes an annotation
func (*CollaborationHandler) GetAnnotations ¶
func (h *CollaborationHandler) GetAnnotations(c *gin.Context)
GetAnnotations retrieves active annotations
func (*CollaborationHandler) GetChatHistory ¶
func (h *CollaborationHandler) GetChatHistory(c *gin.Context)
GetChatHistory retrieves chat history
func (*CollaborationHandler) GetCollaborationParticipants ¶
func (h *CollaborationHandler) GetCollaborationParticipants(c *gin.Context)
GetCollaborationParticipants lists all participants
func (*CollaborationHandler) GetCollaborationStats ¶
func (h *CollaborationHandler) GetCollaborationStats(c *gin.Context)
GetCollaborationStats returns collaboration statistics
func (*CollaborationHandler) JoinCollaborationSession ¶
func (h *CollaborationHandler) JoinCollaborationSession(c *gin.Context)
JoinCollaborationSession allows a user to join a collaboration
func (*CollaborationHandler) LeaveCollaborationSession ¶
func (h *CollaborationHandler) LeaveCollaborationSession(c *gin.Context)
LeaveCollaborationSession removes a user from collaboration
func (*CollaborationHandler) SendChatMessage ¶
func (h *CollaborationHandler) SendChatMessage(c *gin.Context)
SendChatMessage sends a message to the collaboration chat
func (*CollaborationHandler) UpdateParticipantRole ¶
func (h *CollaborationHandler) UpdateParticipantRole(c *gin.Context)
UpdateParticipantRole updates a participant's role and permissions
type CollaborationPermissions ¶
type CollaborationPermissions struct {
CanControl bool `json:"can_control"` // Can interact with session
CanAnnotate bool `json:"can_annotate"` // Can create annotations
CanChat bool `json:"can_chat"` // Can send messages
CanInvite bool `json:"can_invite"` // Can invite others
CanManage bool `json:"can_manage"` // Can change settings
CanRecord bool `json:"can_record"` // Can start recording
CanViewOnly bool `json:"can_view_only"` // View-only mode
}
CollaborationPermissions defines what a user can do
type CollaborationSession ¶
type CollaborationSession struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
OwnerID string `json:"owner_id"`
Participants []CollaborationUser `json:"participants"`
Settings CollaborationSettings `json:"settings"`
ActiveUsers int `json:"active_users"`
ChatEnabled bool `json:"chat_enabled"`
AnnotationsEnabled bool `json:"annotations_enabled"`
CursorTracking bool `json:"cursor_tracking"`
Status string `json:"status"` // "active", "paused", "ended"
CreatedAt time.Time `json:"created_at"`
EndedAt *time.Time `json:"ended_at,omitempty"`
}
CollaborationSession represents a collaborative multi-user session.
A collaboration session wraps a regular StreamSpace session with real-time collaboration features. Multiple users can join the same session and interact via chat, annotations, cursor tracking, and shared control.
Lifecycle:
- Owner creates collaboration session from their StreamSpace session
- Participants join via invitation or link
- Real-time interaction via WebSocket (chat, cursors, annotations)
- Owner ends collaboration (session continues, collaboration stops)
State transitions:
- "active": Collaboration in progress, users can join
- "paused": Temporarily stopped, can be resumed
- "ended": Permanently ended, read-only access to history
Persistence:
- Session metadata stored in collaboration_sessions table
- Chat history, annotations preserved after session ends
- Cursor positions ephemeral (not stored in database)
type CollaborationSettings ¶
type CollaborationSettings struct {
FollowMode string `json:"follow_mode"` // "none", "follow_presenter", "follow_owner"
MaxParticipants int `json:"max_participants"`
RequireApproval bool `json:"require_approval"`
AllowAnonymous bool `json:"allow_anonymous"`
LockOnPresenter bool `json:"lock_on_presenter"`
AutoMuteJoiners bool `json:"auto_mute_joiners"`
ShowCursorLabels bool `json:"show_cursor_labels"`
EnableHandRaise bool `json:"enable_hand_raise"`
}
CollaborationSettings defines session behavior
type CollaborationUser ¶
type CollaborationUser struct {
UserID string `json:"user_id"`
Username string `json:"username"`
Role string `json:"role"` // "owner", "presenter", "participant", "viewer"
Permissions CollaborationPermissions `json:"permissions"`
CursorPosition *CursorPosition `json:"cursor_position,omitempty"`
IsActive bool `json:"is_active"`
JoinedAt time.Time `json:"joined_at"`
LastSeenAt time.Time `json:"last_seen_at"`
Color string `json:"color"` // User color for cursor/annotations
}
CollaborationUser represents a user in a collaborative session
type Configuration ¶
type Configuration struct {
Key string `json:"key"`
Value string `json:"value"`
Type string `json:"type"` // string, boolean, number, duration, enum, array
Category string `json:"category"`
Description string `json:"description"`
UpdatedAt time.Time `json:"updated_at"`
UpdatedBy string `json:"updated_by,omitempty"`
}
Configuration represents a single configuration setting
type ConfigurationHandler ¶
type ConfigurationHandler struct {
// contains filtered or unexported fields
}
ConfigurationHandler handles system configuration endpoints
func NewConfigurationHandler ¶
func NewConfigurationHandler(database *db.Database) *ConfigurationHandler
NewConfigurationHandler creates a new configuration handler
func (*ConfigurationHandler) BulkUpdateConfigurations ¶
func (h *ConfigurationHandler) BulkUpdateConfigurations(c *gin.Context)
BulkUpdateConfigurations godoc @Summary Bulk update multiple configuration settings @Description Updates multiple configuration settings in a single transaction @Tags admin, configuration @Accept json @Produce json @Param body body BulkUpdateRequest true "Configuration updates" @Success 200 {object} map[string]interface{} @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/config/bulk [post]
func (*ConfigurationHandler) GetConfiguration ¶
func (h *ConfigurationHandler) GetConfiguration(c *gin.Context)
GetConfiguration godoc @Summary Get specific configuration setting @Description Retrieves a single configuration setting by key @Tags admin, configuration @Accept json @Produce json @Param key path string true "Configuration key" @Success 200 {object} Configuration @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/config/{key} [get]
func (*ConfigurationHandler) ListConfigurations ¶
func (h *ConfigurationHandler) ListConfigurations(c *gin.Context)
ListConfigurations godoc @Summary List all configuration settings @Description Retrieves all platform configuration settings, optionally filtered by category @Tags admin, configuration @Accept json @Produce json @Param category query string false "Filter by category (ingress, storage, resources, features, session, security, compliance)" @Success 200 {object} ConfigurationListResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/config [get]
func (*ConfigurationHandler) RegisterRoutes ¶
func (h *ConfigurationHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers configuration routes
func (*ConfigurationHandler) UpdateConfiguration ¶
func (h *ConfigurationHandler) UpdateConfiguration(c *gin.Context)
UpdateConfiguration godoc @Summary Update configuration setting @Description Updates a single configuration setting with validation @Tags admin, configuration @Accept json @Produce json @Param key path string true "Configuration key" @Param body body UpdateConfigurationRequest true "New value" @Success 200 {object} Configuration @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/config/{key} [put]
type ConfigurationListResponse ¶
type ConfigurationListResponse struct {
Configurations []Configuration `json:"configurations"`
Grouped map[string][]Configuration `json:"grouped"`
}
ConfigurationListResponse represents a list of configurations grouped by category
type ConsoleHandler ¶
Handler is the console handler with database access.
func NewConsoleHandler ¶
func NewConsoleHandler(database *db.Database) *ConsoleHandler
NewConsoleHandler creates a new console handler.
func (*ConsoleHandler) CreateConsoleSession ¶
func (h *ConsoleHandler) CreateConsoleSession(c *gin.Context)
CreateConsoleSession creates a new console session for a workspace session
func (*ConsoleHandler) CreateDirectory ¶
func (h *ConsoleHandler) CreateDirectory(c *gin.Context)
CreateDirectory creates a new directory
func (*ConsoleHandler) DeleteFile ¶
func (h *ConsoleHandler) DeleteFile(c *gin.Context)
DeleteFile deletes a file or directory
func (*ConsoleHandler) DisconnectConsoleSession ¶
func (h *ConsoleHandler) DisconnectConsoleSession(c *gin.Context)
DisconnectConsoleSession disconnects an active console session
func (*ConsoleHandler) DownloadFile ¶
func (h *ConsoleHandler) DownloadFile(c *gin.Context)
DownloadFile downloads a file from the session
func (*ConsoleHandler) GetFileContent ¶
func (h *ConsoleHandler) GetFileContent(c *gin.Context)
GetFileContent retrieves the content of a file
func (*ConsoleHandler) GetFileOperationHistory ¶
func (h *ConsoleHandler) GetFileOperationHistory(c *gin.Context)
GetFileOperationHistory retrieves file operation history
func (*ConsoleHandler) ListConsoleSessions ¶
func (h *ConsoleHandler) ListConsoleSessions(c *gin.Context)
ListConsoleSessions lists all console sessions for a workspace session
func (*ConsoleHandler) ListFiles ¶
func (h *ConsoleHandler) ListFiles(c *gin.Context)
ListFiles lists files in a directory
func (*ConsoleHandler) RenameFile ¶
func (h *ConsoleHandler) RenameFile(c *gin.Context)
RenameFile renames a file or directory
func (*ConsoleHandler) UploadFile ¶
func (h *ConsoleHandler) UploadFile(c *gin.Context)
UploadFile uploads a file to the session
type ConsoleSession ¶
type ConsoleSession struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
Type string `json:"type"` // "terminal", "file_manager"
Status string `json:"status"` // "active", "idle", "disconnected"
WebSocketURL string `json:"websocket_url,omitempty"`
CurrentPath string `json:"current_path,omitempty"`
ShellType string `json:"shell_type,omitempty"` // "bash", "sh", "zsh"
Columns int `json:"columns,omitempty"` // Terminal columns
Rows int `json:"rows,omitempty"` // Terminal rows
Metadata map[string]interface{} `json:"metadata,omitempty"`
ConnectedAt time.Time `json:"connected_at"`
LastActivityAt time.Time `json:"last_activity_at"`
DisconnectedAt *time.Time `json:"disconnected_at,omitempty"`
}
ConsoleSession represents an active console session
type CreateAPIKeyRequest ¶
type CreateAPIKeyRequest struct {
Name string `json:"name" binding:"required" validate:"required,min=3,max=100"`
Description string `json:"description" validate:"omitempty,max=500"`
Scopes []string `json:"scopes" validate:"omitempty,dive,min=3,max=50"`
RateLimit int `json:"rateLimit" validate:"omitempty,gte=0,lte=100000"`
ExpiresIn string `json:"expiresIn" validate:"omitempty,min=2,max=10"` // Duration string like "30d", "1y"
}
CreateAPIKeyRequest is the request body for creating an API key
type CreateIntegrationRequest ¶
type CreateIntegrationRequest struct {
Type string `json:"type" binding:"required" validate:"required,oneof=custom"`
Name string `json:"name" binding:"required" validate:"required,min=1,max=200"`
Description string `json:"description" validate:"omitempty,max=1000"`
Config map[string]interface{} `json:"config"`
Enabled bool `json:"enabled"`
Events []string `json:"events" validate:"omitempty,max=50,dive,min=3,max=100"`
TestMode bool `json:"test_mode"`
}
CreateIntegrationRequest is the request body for creating an integration
type CreateInvitationRequest ¶
type CreateInvitationRequest struct {
PermissionLevel string `json:"permissionLevel" binding:"required" validate:"required,oneof=view collaborate control"`
MaxUses int `json:"maxUses" validate:"omitempty,gte=1,lte=1000"`
ExpiresAt *time.Time `json:"expiresAt"`
}
CreateInvitationRequest represents a request to create a shareable invitation link
type CreatePolicyRequest ¶
type CreatePolicyRequest struct {
Name string `json:"name" binding:"required"`
Description *string `json:"description"`
AutoRecord bool `json:"auto_record"`
RecordingFormat string `json:"recording_format"`
RetentionDays int `json:"retention_days"`
ApplyToUsers map[string]interface{} `json:"apply_to_users"`
ApplyToTeams map[string]interface{} `json:"apply_to_teams"`
ApplyToTemplates map[string]interface{} `json:"apply_to_templates"`
RequireReason bool `json:"require_reason"`
AllowUserPlayback bool `json:"allow_user_playback"`
AllowUserDownload bool `json:"allow_user_download"`
RequireApproval bool `json:"require_approval"`
NotifyOnRecording bool `json:"notify_on_recording"`
Metadata map[string]interface{} `json:"metadata"`
Enabled bool `json:"enabled"`
Priority int `json:"priority"`
}
CreatePolicyRequest represents a policy creation request
type CreateSessionTemplateRequest ¶
type CreateSessionTemplateRequest struct {
Name string `json:"name" binding:"required" validate:"required,min=3,max=100"`
Description string `json:"description" validate:"omitempty,max=1000"`
Icon string `json:"icon" validate:"omitempty,max=100"`
Category string `json:"category" validate:"omitempty,min=2,max=50"`
Tags []string `json:"tags" validate:"omitempty,dive,min=2,max=50"`
Visibility string `json:"visibility" validate:"omitempty,oneof=private team public"`
TeamID string `json:"teamId" validate:"omitempty,uuid"`
BaseTemplate string `json:"baseTemplate" binding:"required" validate:"required,min=3,max=100"`
Configuration map[string]interface{} `json:"configuration"`
Resources map[string]interface{} `json:"resources"`
Environment map[string]string `json:"environment" validate:"omitempty,dive,keys,min=1,max=100,endkeys,min=0,max=10000"`
IsDefault bool `json:"isDefault"`
}
CreateSessionTemplateRequest is the request body for creating a session template
type CreateShareRequest ¶
type CreateShareRequest struct {
}
CreateShareRequest represents a request to share a session with a user
type CreateWebhookRequest ¶
type CreateWebhookRequest struct {
Name string `json:"name" binding:"required" validate:"required,min=1,max=200"`
Description string `json:"description" validate:"omitempty,max=1000"`
URL string `json:"url" binding:"required" validate:"required,url,max=2048"`
Secret string `json:"secret" validate:"omitempty,min=16,max=256"`
Events []string `json:"events" binding:"required" validate:"required,min=1,max=50,dive,min=3,max=100"`
Headers map[string]string `json:"headers" validate:"omitempty,max=50,dive,keys,max=100,endkeys,max=1000"`
Enabled bool `json:"enabled"`
RetryPolicy WebhookRetryPolicy `json:"retry_policy"`
Filters WebhookFilters `json:"filters"`
Metadata map[string]interface{} `json:"metadata"`
}
CreateWebhookRequest is the request body for creating a webhook
type CurrentLicenseResponse ¶
type CurrentLicenseResponse struct {
License License `json:"license"`
Usage LicenseUsageStats `json:"usage"`
DaysUntilExpiry int `json:"days_until_expiry"`
IsExpired bool `json:"is_expired"`
IsExpiringSoon bool `json:"is_expiring_soon"` // < 30 days
LimitWarnings []LimitWarning `json:"limit_warnings"`
}
CurrentLicenseResponse represents current license with usage information
type CursorPosition ¶
type CursorPosition struct {
X int `json:"x"`
Y int `json:"y"`
Timestamp time.Time `json:"timestamp"`
}
CursorPosition represents cursor location
type DashboardHandler ¶
type DashboardHandler struct {
// contains filtered or unexported fields
}
DashboardHandler handles dashboard and resource usage queries
func NewDashboardHandler ¶
func NewDashboardHandler(database *db.Database, k8sClient *k8s.Client) *DashboardHandler
NewDashboardHandler creates a new dashboard handler
func (*DashboardHandler) GetActivityTimeline ¶
func (h *DashboardHandler) GetActivityTimeline(c *gin.Context)
GetActivityTimeline returns activity timeline data for charts
func (*DashboardHandler) GetPlatformStats ¶
func (h *DashboardHandler) GetPlatformStats(c *gin.Context)
GetPlatformStats returns overall platform statistics
func (*DashboardHandler) GetResourceUsage ¶
func (h *DashboardHandler) GetResourceUsage(c *gin.Context)
GetResourceUsage returns resource usage statistics
func (*DashboardHandler) GetTemplateUsageStats ¶
func (h *DashboardHandler) GetTemplateUsageStats(c *gin.Context)
GetTemplateUsageStats returns per-template usage statistics
func (*DashboardHandler) GetUserDashboard ¶
func (h *DashboardHandler) GetUserDashboard(c *gin.Context)
GetUserDashboard returns personalized dashboard for the current user
func (*DashboardHandler) GetUserUsageStats ¶
func (h *DashboardHandler) GetUserUsageStats(c *gin.Context)
GetUserUsageStats returns per-user usage statistics
type DevicePosture ¶
type DevicePosture struct {
DeviceID string `json:"device_id"`
OSVersion string `json:"os_version"`
BrowserVersion string `json:"browser_version"`
ScreenResolution string `json:"screen_resolution"`
Timezone string `json:"timezone"`
Language string `json:"language"`
Plugins []string `json:"plugins"`
Extensions []string `json:"extensions"`
AntivirusEnabled bool `json:"antivirus_enabled"`
FirewallEnabled bool `json:"firewall_enabled"`
EncryptionEnabled bool `json:"encryption_enabled"`
LastChecked time.Time `json:"last_checked"`
Compliant bool `json:"compliant"`
Issues []string `json:"issues,omitempty"`
}
DevicePosture represents device security posture
type DocsHandler ¶
type DocsHandler struct{}
DocsHandler handles API documentation endpoints
func NewDocsHandler ¶
func NewDocsHandler() *DocsHandler
NewDocsHandler creates a new documentation handler
func (*DocsHandler) OpenAPIJSON ¶
func (h *DocsHandler) OpenAPIJSON(c *gin.Context)
OpenAPIJSON serves the OpenAPI specification in JSON format @Summary OpenAPI Specification (JSON) @Description Get the OpenAPI 3.0 specification in JSON format @Tags documentation @Produce application/json @Success 200 {object} map[string]interface{} "OpenAPI JSON specification" @Router /api/openapi.json [get]
func (*DocsHandler) OpenAPIYAML ¶
func (h *DocsHandler) OpenAPIYAML(c *gin.Context)
OpenAPIYAML serves the OpenAPI specification in YAML format @Summary OpenAPI Specification (YAML) @Description Get the OpenAPI 3.0 specification in YAML format @Tags documentation @Produce application/x-yaml @Success 200 {string} string "OpenAPI YAML specification" @Router /api/openapi.yaml [get]
func (*DocsHandler) RegisterRoutes ¶
func (h *DocsHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers documentation routes (no auth required)
func (*DocsHandler) SwaggerUI ¶
func (h *DocsHandler) SwaggerUI(c *gin.Context)
SwaggerUI serves the Swagger UI HTML page @Summary API Documentation UI @Description Interactive Swagger UI for exploring the StreamSpace API @Tags documentation @Produce html @Success 200 {string} string "HTML page" @Router /api/docs [get]
type ErrorResponse ¶
ErrorResponse represents an error response
type FileInfo ¶
type FileInfo struct {
Name string `json:"name"`
Path string `json:"path"`
Size int64 `json:"size"`
IsDirectory bool `json:"is_directory"`
Permissions string `json:"permissions"`
Owner string `json:"owner"`
Group string `json:"group"`
ModifiedAt time.Time `json:"modified_at"`
MimeType string `json:"mime_type,omitempty"`
SymlinkTarget string `json:"symlink_target,omitempty"`
}
FileInfo represents file/directory information
type FileOperation ¶
type FileOperation struct {
Operation string `json:"operation"` // "create", "delete", "rename", "copy", "move", "upload", "download"
SourcePath string `json:"source_path"`
TargetPath string `json:"target_path,omitempty"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
BytesProcessed int64 `json:"bytes_processed,omitempty"`
}
FileOperation represents a file operation result
type GeoRestriction ¶
type GeoRestriction struct {
ID int64 `json:"id"`
UserID string `json:"user_id,omitempty"` // Empty for org-wide
Countries []string `json:"countries"` // ISO country codes
Action string `json:"action"` // "allow" or "deny"
Enabled bool `json:"enabled"`
Description string `json:"description,omitempty"`
}
GeoRestriction represents geographic access controls
type GroupHandler ¶
type GroupHandler struct {
// contains filtered or unexported fields
}
GroupHandler handles group-related API requests
func NewGroupHandler ¶
func NewGroupHandler(groupDB *db.GroupDB, userDB *db.UserDB) *GroupHandler
NewGroupHandler creates a new group handler
func (*GroupHandler) AddGroupMember ¶
func (h *GroupHandler) AddGroupMember(c *gin.Context)
AddGroupMember godoc @Summary Add group member @Description Add a user to a group @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Param member body models.AddGroupMemberRequest true "Member add request" @Success 200 {object} SuccessResponse @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id}/members [post]
func (*GroupHandler) CreateGroup ¶
func (h *GroupHandler) CreateGroup(c *gin.Context)
CreateGroup godoc @Summary Create a new group @Description Create a new group/team @Tags groups @Accept json @Produce json @Param group body models.CreateGroupRequest true "Group creation request" @Success 201 {object} models.Group @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups [post]
func (*GroupHandler) DeleteGroup ¶
func (h *GroupHandler) DeleteGroup(c *gin.Context)
DeleteGroup godoc @Summary Delete group @Description Delete a group/team @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Success 200 {object} SuccessResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id} [delete]
func (*GroupHandler) GetGroup ¶
func (h *GroupHandler) GetGroup(c *gin.Context)
GetGroup godoc @Summary Get group by ID @Description Get detailed information about a specific group @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Success 200 {object} models.Group @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id} [get]
func (*GroupHandler) GetGroupMembers ¶
func (h *GroupHandler) GetGroupMembers(c *gin.Context)
GetGroupMembers godoc @Summary Get group members @Description Get all members of a group @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Success 200 {object} gin.H @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id}/members [get]
func (*GroupHandler) GetGroupQuota ¶
func (h *GroupHandler) GetGroupQuota(c *gin.Context)
GetGroupQuota godoc @Summary Get group quota @Description Get resource quota for a group @Tags groups, quotas @Accept json @Produce json @Param id path string true "Group ID" @Success 200 {object} models.GroupQuota @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id}/quota [get]
func (*GroupHandler) ListGroups ¶
func (h *GroupHandler) ListGroups(c *gin.Context)
ListGroups godoc @Summary List all groups @Description Get a list of all groups with optional filtering @Tags groups @Accept json @Produce json @Param type query string false "Filter by group type" @Param parentId query string false "Filter by parent group" @Success 200 {array} models.Group @Failure 500 {object} ErrorResponse @Router /api/v1/groups [get]
func (*GroupHandler) RegisterRoutes ¶
func (h *GroupHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers group management routes
func (*GroupHandler) RemoveGroupMember ¶
func (h *GroupHandler) RemoveGroupMember(c *gin.Context)
RemoveGroupMember godoc @Summary Remove group member @Description Remove a user from a group @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Param userId path string true "User ID" @Success 200 {object} SuccessResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id}/members/{userId} [delete]
func (*GroupHandler) SetGroupQuota ¶
func (h *GroupHandler) SetGroupQuota(c *gin.Context)
SetGroupQuota godoc @Summary Set group quota @Description Set or update resource quota for a group @Tags groups, quotas @Accept json @Produce json @Param id path string true "Group ID" @Param quota body models.SetQuotaRequest true "Quota settings" @Success 200 {object} models.GroupQuota @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id}/quota [put]
func (*GroupHandler) UpdateGroup ¶
func (h *GroupHandler) UpdateGroup(c *gin.Context)
UpdateGroup godoc @Summary Update group @Description Update group information @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Param group body models.UpdateGroupRequest true "Group update request" @Success 200 {object} models.Group @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id} [patch]
func (*GroupHandler) UpdateMemberRole ¶
func (h *GroupHandler) UpdateMemberRole(c *gin.Context)
UpdateMemberRole godoc @Summary Update member role @Description Update a user's role in a group @Tags groups @Accept json @Produce json @Param id path string true "Group ID" @Param userId path string true "User ID" @Param role body gin.H true "Role update" @Success 200 {object} SuccessResponse @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/groups/{id}/members/{userId} [patch]
type HealthCheckConfig ¶
type HealthCheckConfig struct {
Enabled bool `json:"enabled"`
Interval int `json:"interval_seconds"` // How often to check
Timeout int `json:"timeout_seconds"` // Timeout for each check
FailThreshold int `json:"fail_threshold"` // Failures before marking unhealthy
PassThreshold int `json:"pass_threshold"` // Successes before marking healthy
Endpoint string `json:"endpoint,omitempty"` // Health check endpoint
}
HealthCheckConfig defines node health checking
type HeartbeatRequest ¶
type HeartbeatRequest struct {
SessionID string `json:"sessionId"`
}
HeartbeatRequest represents a session heartbeat request
type IPWhitelist ¶
type IPWhitelist struct {
ID int64 `json:"id"`
UserID string `json:"user_id,omitempty"` // Empty for org-wide rules
IPAddress string `json:"ip_address"` // Single IP or CIDR
Description string `json:"description,omitempty"`
Enabled bool `json:"enabled"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at,omitempty"`
}
IPWhitelist represents IP access control rules
type Integration ¶
type Integration struct {
ID int64 `json:"id"`
Type string `json:"type"` // "slack", "teams", "discord", "pagerduty", "email", "custom"
Name string `json:"name"`
Description string `json:"description"`
Config map[string]interface{} `json:"config"`
Enabled bool `json:"enabled"`
Events []string `json:"events"`
TestMode bool `json:"test_mode"`
LastTestAt *time.Time `json:"last_test_at,omitempty"`
LastSuccessAt *time.Time `json:"last_success_at,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Integration represents an external integration
type IntegrationsHandler ¶
IntegrationsHandler handles webhook and external integration requests.
func NewIntegrationsHandler ¶
func NewIntegrationsHandler(database *db.Database) *IntegrationsHandler
NewIntegrationsHandler creates a new integrations handler.
func (*IntegrationsHandler) CreateIntegration ¶
func (h *IntegrationsHandler) CreateIntegration(c *gin.Context)
CreateIntegration creates a new integration
func (*IntegrationsHandler) CreateWebhook ¶
func (h *IntegrationsHandler) CreateWebhook(c *gin.Context)
CreateWebhook creates a new webhook
func (*IntegrationsHandler) DeleteWebhook ¶
func (h *IntegrationsHandler) DeleteWebhook(c *gin.Context)
DeleteWebhook deletes a webhook
func (*IntegrationsHandler) GetAvailableEvents ¶
func (h *IntegrationsHandler) GetAvailableEvents(c *gin.Context)
GetAvailableEvents returns list of available webhook events
func (*IntegrationsHandler) GetWebhookDeliveries ¶
func (h *IntegrationsHandler) GetWebhookDeliveries(c *gin.Context)
GetWebhookDeliveries retrieves delivery history
func (*IntegrationsHandler) ListIntegrations ¶
func (h *IntegrationsHandler) ListIntegrations(c *gin.Context)
ListIntegrations lists all integrations
func (*IntegrationsHandler) ListWebhooks ¶
func (h *IntegrationsHandler) ListWebhooks(c *gin.Context)
ListWebhooks lists all webhooks
func (*IntegrationsHandler) TestIntegration ¶
func (h *IntegrationsHandler) TestIntegration(c *gin.Context)
TestIntegration tests an integration
func (*IntegrationsHandler) TestWebhook ¶
func (h *IntegrationsHandler) TestWebhook(c *gin.Context)
TestWebhook sends a test event to a webhook
func (*IntegrationsHandler) UpdateWebhook ¶
func (h *IntegrationsHandler) UpdateWebhook(c *gin.Context)
UpdateWebhook updates an existing webhook
type License ¶
type License struct {
ID int `json:"id"`
LicenseKey string `json:"license_key"`
Tier string `json:"tier"` // community, pro, enterprise
Features map[string]interface{} `json:"features"`
MaxUsers *int `json:"max_users"` // nil = unlimited
MaxSessions *int `json:"max_sessions"` // nil = unlimited
MaxNodes *int `json:"max_nodes"` // nil = unlimited
IssuedAt time.Time `json:"issued_at"`
ExpiresAt time.Time `json:"expires_at"`
ActivatedAt *time.Time `json:"activated_at"`
Status string `json:"status"` // active, expired, revoked
Metadata map[string]interface{} `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
License represents a platform license
type LicenseHandler ¶
type LicenseHandler struct {
// contains filtered or unexported fields
}
LicenseHandler handles license management endpoints
func NewLicenseHandler ¶
func NewLicenseHandler(database *db.Database) *LicenseHandler
NewLicenseHandler creates a new license handler
func (*LicenseHandler) ActivateLicense ¶
func (h *LicenseHandler) ActivateLicense(c *gin.Context)
ActivateLicense godoc @Summary Activate a new license key @Description Activates a new license key and deactivates the current license @Tags admin, license @Accept json @Produce json @Param body body ActivateLicenseRequest true "License key to activate" @Success 200 {object} License @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/license/activate [post]
func (*LicenseHandler) GetCurrentLicense ¶
func (h *LicenseHandler) GetCurrentLicense(c *gin.Context)
GetCurrentLicense godoc @Summary Get current active license @Description Retrieves the currently active license with usage statistics @Tags admin, license @Accept json @Produce json @Success 200 {object} CurrentLicenseResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/license [get]
func (*LicenseHandler) GetLicenseUsage ¶
func (h *LicenseHandler) GetLicenseUsage(c *gin.Context)
GetLicenseUsage godoc @Summary Get current license usage @Description Retrieves current usage statistics vs. license limits @Tags admin, license @Accept json @Produce json @Success 200 {object} LicenseUsageStats @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/license/usage [get]
func (*LicenseHandler) GetUsageHistory ¶
func (h *LicenseHandler) GetUsageHistory(c *gin.Context)
GetUsageHistory godoc @Summary Get usage history @Description Retrieves historical usage data for the active license @Tags admin, license @Accept json @Produce json @Param days query int false "Number of days to retrieve (default: 30)" @Success 200 {array} LicenseUsage @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/license/history [get]
func (*LicenseHandler) RegisterRoutes ¶
func (h *LicenseHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers license routes
func (*LicenseHandler) UpdateLicense ¶
func (h *LicenseHandler) UpdateLicense(c *gin.Context)
UpdateLicense godoc @Summary Update/renew license @Description Updates the current license (for renewals or upgrades) @Tags admin, license @Accept json @Produce json @Param body body UpdateLicenseRequest true "New license key" @Success 200 {object} License @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/license/update [put]
func (*LicenseHandler) ValidateLicense ¶
func (h *LicenseHandler) ValidateLicense(c *gin.Context)
ValidateLicense godoc @Summary Validate a license key @Description Validates a license key without activating it @Tags admin, license @Accept json @Produce json @Param body body ValidateLicenseRequest true "License key to validate" @Success 200 {object} ValidateLicenseResponse @Failure 400 {object} ErrorResponse @Router /api/v1/admin/license/validate [post]
type LicenseUsage ¶
type LicenseUsage struct {
ID int `json:"id"`
LicenseID int `json:"license_id"`
SnapshotDate string `json:"snapshot_date"` // YYYY-MM-DD
ActiveUsers int `json:"active_users"`
ActiveSessions int `json:"active_sessions"`
ActiveNodes int `json:"active_nodes"`
CreatedAt time.Time `json:"created_at"`
}
LicenseUsage represents usage snapshot for a specific date
type LicenseUsageStats ¶
type LicenseUsageStats struct {
CurrentUsers int `json:"current_users"`
CurrentSessions int `json:"current_sessions"`
CurrentNodes int `json:"current_nodes"`
MaxUsers *int `json:"max_users"` // nil = unlimited
MaxSessions *int `json:"max_sessions"` // nil = unlimited
MaxNodes *int `json:"max_nodes"` // nil = unlimited
UserPercent *float64 `json:"user_percent"` // nil if unlimited
SessionPercent *float64 `json:"session_percent"` // nil if unlimited
NodePercent *float64 `json:"node_percent"` // nil if unlimited
}
LicenseUsageStats represents current usage statistics
type LimitWarning ¶
type LimitWarning struct {
Resource string `json:"resource"` // users, sessions, nodes
Current int `json:"current"`
Limit int `json:"limit"`
Percentage float64 `json:"percentage"`
Severity string `json:"severity"` // warning (80%), critical (90%), exceeded (100%)
Message string `json:"message"`
}
LimitWarning represents a warning when approaching limits
type LoadBalancingHandler ¶
LoadBalancingHandler handles load balancing and node distribution requests.
func NewLoadBalancingHandler ¶
func NewLoadBalancingHandler(database *db.Database) *LoadBalancingHandler
NewLoadBalancingHandler creates a new load balancing handler.
func (*LoadBalancingHandler) CreateAutoScalingPolicy ¶
func (h *LoadBalancingHandler) CreateAutoScalingPolicy(c *gin.Context)
CreateAutoScalingPolicy creates a new auto-scaling policy
func (*LoadBalancingHandler) CreateLoadBalancingPolicy ¶
func (h *LoadBalancingHandler) CreateLoadBalancingPolicy(c *gin.Context)
CreateLoadBalancingPolicy creates a new load balancing policy
func (*LoadBalancingHandler) GetNodeStatus ¶
func (h *LoadBalancingHandler) GetNodeStatus(c *gin.Context)
GetNodeStatus gets current status of all cluster nodes
func (*LoadBalancingHandler) GetScalingHistory ¶
func (h *LoadBalancingHandler) GetScalingHistory(c *gin.Context)
GetScalingHistory gets scaling event history
func (*LoadBalancingHandler) ListAutoScalingPolicies ¶
func (h *LoadBalancingHandler) ListAutoScalingPolicies(c *gin.Context)
ListAutoScalingPolicies lists all auto-scaling policies
func (*LoadBalancingHandler) ListLoadBalancingPolicies ¶
func (h *LoadBalancingHandler) ListLoadBalancingPolicies(c *gin.Context)
ListLoadBalancingPolicies lists all load balancing policies
func (*LoadBalancingHandler) SelectNode ¶
func (h *LoadBalancingHandler) SelectNode(c *gin.Context)
SelectNode selects best node for a new session based on policy
func (*LoadBalancingHandler) TriggerScaling ¶
func (h *LoadBalancingHandler) TriggerScaling(c *gin.Context)
TriggerScaling manually triggers a scaling action
type LoadBalancingPolicy ¶
type LoadBalancingPolicy struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Strategy string `json:"strategy"` // "round_robin", "least_loaded", "resource_based", "geographic", "weighted"
Enabled bool `json:"enabled"`
SessionAffinity bool `json:"session_affinity"` // Sticky sessions
HealthCheckConfig HealthCheckConfig `json:"health_check_config"`
NodeSelector map[string]string `json:"node_selector,omitempty"` // Kubernetes node selector
NodeWeights map[string]int `json:"node_weights,omitempty"` // For weighted distribution
GeoPreferences []string `json:"geo_preferences,omitempty"` // Preferred regions
ResourceThresholds ResourceThresholds `json:"resource_thresholds"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
LoadBalancingPolicy defines how sessions are distributed across nodes
type MFAMethod ¶
type MFAMethod struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
Type string `json:"type"` // "totp", "sms", "email", "backup_codes"
Enabled bool `json:"enabled"`
Secret string `json:"-"` // SECURITY: Never expose secret in API responses
PhoneNumber string `json:"phone_number,omitempty"`
Email string `json:"email,omitempty"`
IsPrimary bool `json:"is_primary"`
Verified bool `json:"verified"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt time.Time `json:"last_used_at,omitempty"`
}
MFAMethod represents different MFA verification methods
type MFASetupResponse ¶
type MFASetupResponse struct {
ID int64 `json:"id"`
Type string `json:"type"`
Secret string `json:"secret,omitempty"` // Only for TOTP setup
QRCode string `json:"qr_code,omitempty"` // Only for TOTP setup
Message string `json:"message"`
}
MFASetupResponse is used only for SetupMFA response to show secret/QR once
type MonitoringHandler ¶
type MonitoringHandler struct {
// contains filtered or unexported fields
}
MonitoringHandler handles monitoring and metrics endpoints
func NewMonitoringHandler ¶
func NewMonitoringHandler(database *db.Database) *MonitoringHandler
NewMonitoringHandler creates a new monitoring handler
func (*MonitoringHandler) AcknowledgeAlert ¶
func (h *MonitoringHandler) AcknowledgeAlert(c *gin.Context)
AcknowledgeAlert acknowledges an alert
func (*MonitoringHandler) CreateAlert ¶
func (h *MonitoringHandler) CreateAlert(c *gin.Context)
CreateAlert creates a new alert
func (*MonitoringHandler) DatabaseHealth ¶
func (h *MonitoringHandler) DatabaseHealth(c *gin.Context)
DatabaseHealth returns database-specific health metrics
func (*MonitoringHandler) DeleteAlert ¶
func (h *MonitoringHandler) DeleteAlert(c *gin.Context)
DeleteAlert deletes an alert
func (*MonitoringHandler) DetailedHealthCheck ¶
func (h *MonitoringHandler) DetailedHealthCheck(c *gin.Context)
DetailedHealthCheck returns detailed component health
func (*MonitoringHandler) GetAlert ¶
func (h *MonitoringHandler) GetAlert(c *gin.Context)
GetAlert returns a specific alert
func (*MonitoringHandler) GetAlerts ¶
func (h *MonitoringHandler) GetAlerts(c *gin.Context)
GetAlerts returns all alerts
func (*MonitoringHandler) HealthCheck ¶
func (h *MonitoringHandler) HealthCheck(c *gin.Context)
HealthCheck returns basic health status
func (*MonitoringHandler) PerformanceMetrics ¶
func (h *MonitoringHandler) PerformanceMetrics(c *gin.Context)
PerformanceMetrics returns system performance metrics
func (*MonitoringHandler) PrometheusMetrics ¶
func (h *MonitoringHandler) PrometheusMetrics(c *gin.Context)
PrometheusMetrics returns metrics in Prometheus format
func (*MonitoringHandler) RegisterRoutes ¶
func (h *MonitoringHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers monitoring routes
func (*MonitoringHandler) ResolveAlert ¶
func (h *MonitoringHandler) ResolveAlert(c *gin.Context)
ResolveAlert resolves an alert
func (*MonitoringHandler) ResourceMetrics ¶
func (h *MonitoringHandler) ResourceMetrics(c *gin.Context)
ResourceMetrics returns resource utilization metrics
func (*MonitoringHandler) SessionMetrics ¶
func (h *MonitoringHandler) SessionMetrics(c *gin.Context)
SessionMetrics returns detailed session metrics
func (*MonitoringHandler) StorageHealth ¶
func (h *MonitoringHandler) StorageHealth(c *gin.Context)
StorageHealth returns storage-specific health metrics
func (*MonitoringHandler) SystemInfo ¶
func (h *MonitoringHandler) SystemInfo(c *gin.Context)
SystemInfo returns static system information
func (*MonitoringHandler) SystemStats ¶
func (h *MonitoringHandler) SystemStats(c *gin.Context)
SystemStats returns current system statistics
func (*MonitoringHandler) UpdateAlert ¶
func (h *MonitoringHandler) UpdateAlert(c *gin.Context)
UpdateAlert updates an alert
func (*MonitoringHandler) UserMetrics ¶
func (h *MonitoringHandler) UserMetrics(c *gin.Context)
UserMetrics returns user activity metrics
type NodeHandler ¶
type NodeHandler struct {
// contains filtered or unexported fields
}
NodeHandler provides deprecated stub handlers for node management
func NewNodeHandler ¶
func NewNodeHandler(database *db.Database, k8sClient *k8s.Client, publisher *events.Publisher, platform string) *NodeHandler
NewNodeHandler creates a new node handler (deprecated)
func (*NodeHandler) AddNodeLabel ¶
func (h *NodeHandler) AddNodeLabel(c *gin.Context)
AddNodeLabel returns a deprecation message
func (*NodeHandler) AddNodeTaint ¶
func (h *NodeHandler) AddNodeTaint(c *gin.Context)
AddNodeTaint returns a deprecation message
func (*NodeHandler) CordonNode ¶
func (h *NodeHandler) CordonNode(c *gin.Context)
CordonNode returns a deprecation message
func (*NodeHandler) DrainNode ¶
func (h *NodeHandler) DrainNode(c *gin.Context)
DrainNode returns a deprecation message
func (*NodeHandler) GetClusterStats ¶
func (h *NodeHandler) GetClusterStats(c *gin.Context)
GetClusterStats returns a deprecation message
func (*NodeHandler) GetNode ¶
func (h *NodeHandler) GetNode(c *gin.Context)
GetNode returns a deprecation message
func (*NodeHandler) ListNodes ¶
func (h *NodeHandler) ListNodes(c *gin.Context)
ListNodes returns a deprecation message
func (*NodeHandler) RemoveNodeLabel ¶
func (h *NodeHandler) RemoveNodeLabel(c *gin.Context)
RemoveNodeLabel returns a deprecation message
func (*NodeHandler) RemoveNodeTaint ¶
func (h *NodeHandler) RemoveNodeTaint(c *gin.Context)
RemoveNodeTaint returns a deprecation message
func (*NodeHandler) UncordonNode ¶
func (h *NodeHandler) UncordonNode(c *gin.Context)
UncordonNode returns a deprecation message
type NodeStatus ¶
type NodeStatus struct {
NodeName string `json:"node_name"`
Status string `json:"status"` // "ready", "not_ready", "unknown"
CPUAllocated float64 `json:"cpu_allocated"`
CPUCapacity float64 `json:"cpu_capacity"`
CPUPercent float64 `json:"cpu_percent"`
MemoryAllocated int64 `json:"memory_allocated"`
MemoryCapacity int64 `json:"memory_capacity"`
MemoryPercent float64 `json:"memory_percent"`
ActiveSessions int `json:"active_sessions"`
HealthStatus string `json:"health_status"` // "healthy", "unhealthy", "unknown"
LastHealthCheck time.Time `json:"last_health_check"`
Region string `json:"region,omitempty"`
Zone string `json:"zone,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
Taints []string `json:"taints,omitempty"`
Weight int `json:"weight"` // For weighted load balancing
}
NodeStatus represents current status of a cluster node
type Notification ¶
type Notification struct {
ID string `json:"id"`
UserID string `json:"userId"`
Type string `json:"type"`
Title string `json:"title"`
Message string `json:"message"`
Data map[string]interface{} `json:"data,omitempty"`
Priority string `json:"priority"` // low, normal, high, urgent
Read bool `json:"read"`
ActionURL string `json:"actionUrl,omitempty"`
ActionText string `json:"actionText,omitempty"`
CreatedAt time.Time `json:"createdAt"`
ReadAt *time.Time `json:"readAt,omitempty"`
}
Notification represents an in-app notification
type NotificationsHandler ¶
type NotificationsHandler struct {
// contains filtered or unexported fields
}
NotificationsHandler handles notification delivery and management
func NewNotificationsHandler ¶
func NewNotificationsHandler(database *db.Database) *NotificationsHandler
NewNotificationsHandler creates a new notifications handler
func (*NotificationsHandler) ClearAllNotifications ¶
func (h *NotificationsHandler) ClearAllNotifications(c *gin.Context)
ClearAllNotifications deletes all read notifications
func (*NotificationsHandler) DeleteNotification ¶
func (h *NotificationsHandler) DeleteNotification(c *gin.Context)
DeleteNotification deletes a notification
func (*NotificationsHandler) GetNotificationPreferences ¶
func (h *NotificationsHandler) GetNotificationPreferences(c *gin.Context)
GetNotificationPreferences returns user's notification preferences
func (*NotificationsHandler) GetUnreadCount ¶
func (h *NotificationsHandler) GetUnreadCount(c *gin.Context)
GetUnreadCount returns count of unread notifications
func (*NotificationsHandler) GetUnreadNotifications ¶
func (h *NotificationsHandler) GetUnreadNotifications(c *gin.Context)
GetUnreadNotifications returns only unread notifications
func (*NotificationsHandler) ListNotifications ¶
func (h *NotificationsHandler) ListNotifications(c *gin.Context)
ListNotifications returns paginated user notifications
func (*NotificationsHandler) MarkAllAsRead ¶
func (h *NotificationsHandler) MarkAllAsRead(c *gin.Context)
MarkAllAsRead marks all notifications as read
func (*NotificationsHandler) MarkAsRead ¶
func (h *NotificationsHandler) MarkAsRead(c *gin.Context)
MarkAsRead marks a notification as read
func (*NotificationsHandler) RegisterRoutes ¶
func (h *NotificationsHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers notification routes
func (*NotificationsHandler) SendNotification ¶
func (h *NotificationsHandler) SendNotification(c *gin.Context)
SendNotification sends a notification via all enabled channels
func (*NotificationsHandler) TestEmailNotification ¶
func (h *NotificationsHandler) TestEmailNotification(c *gin.Context)
TestEmailNotification sends a test email
func (*NotificationsHandler) TestWebhookNotification ¶
func (h *NotificationsHandler) TestWebhookNotification(c *gin.Context)
TestWebhookNotification sends a test webhook
func (*NotificationsHandler) UpdateNotificationPreferences ¶
func (h *NotificationsHandler) UpdateNotificationPreferences(c *gin.Context)
UpdateNotificationPreferences updates user's notification preferences
type PluginHandler ¶
type PluginHandler struct {
// contains filtered or unexported fields
}
PluginHandler handles plugin-related HTTP requests.
This handler provides HTTP endpoints for:
- Browsing the plugin catalog (search, filter, sort)
- Installing plugins from the catalog
- Managing installed plugins (enable, disable, configure, uninstall)
- Rating plugins (user reviews)
All methods interact with the database to query/modify plugin data.
func NewPluginHandler ¶
func NewPluginHandler(database *db.Database, pluginDir string) *PluginHandler
NewPluginHandler creates a new plugin handler.
Parameters:
- database: Database connection for plugin operations
- pluginDir: Directory where plugins will be installed
Returns:
- Configured PluginHandler ready to register routes
Example:
handler := NewPluginHandler(db, "/plugins")
handler.RegisterRoutes(router.Group("/api"))
func (*PluginHandler) BrowsePluginCatalog ¶
func (h *PluginHandler) BrowsePluginCatalog(c *gin.Context)
BrowsePluginCatalog browses available plugins from the catalog.
Endpoint: GET /api/plugins/catalog
Query Parameters:
- category: Filter by category (e.g., "analytics", "notifications")
- type: Filter by plugin type (e.g., "builtin", "community")
- search: Search in display_name, description, tags (case-insensitive)
- sort: Sort order (popular, rating, newest, name) - default: popular
Response: JSON with plugins array and total count
Example Requests:
GET /api/plugins/catalog?category=analytics&sort=rating GET /api/plugins/catalog?search=slack&sort=popular GET /api/plugins/catalog?type=builtin&sort=name
Example Response:
{
"plugins": [
{
"id": 1,
"name": "analytics-tracker",
"display_name": "Analytics Tracker",
"description": "Track session usage metrics",
"category": "analytics",
"plugin_type": "community",
"icon_url": "https://...",
"tags": ["analytics", "metrics"],
"install_count": 1500,
"avg_rating": 4.5,
"rating_count": 42
}
],
"total": 1
}
Sorting Options:
- popular: By install count desc, then rating desc
- rating: By average rating desc, then rating count desc
- newest: By created_at desc
- name: By display_name asc
HTTP Status Codes:
- 200: Success (may return empty array if no matches)
- 500: Database error
func (*PluginHandler) DisablePlugin ¶
func (h *PluginHandler) DisablePlugin(c *gin.Context)
DisablePlugin disables an installed plugin.
Endpoint: POST /api/plugins/:id/disable
Path Parameters:
- id: Installed plugin ID
Behavior:
- Sets enabled=false in database
- Plugin runtime should unload the plugin on next reload
Example Request:
POST /api/plugins/123/disable
HTTP Status Codes:
- 200: Plugin disabled successfully
- 404: Plugin not found
- 500: Database error
func (*PluginHandler) EnablePlugin ¶
func (h *PluginHandler) EnablePlugin(c *gin.Context)
EnablePlugin enables an installed plugin.
Endpoint: POST /api/plugins/:id/enable
Path Parameters:
- id: Installed plugin ID
Behavior:
- Sets enabled=true in database
- Plugin runtime should load the plugin on next startup/reload
Example Request:
POST /api/plugins/123/enable
HTTP Status Codes:
- 200: Plugin enabled successfully
- 404: Plugin not found
- 500: Database error
func (*PluginHandler) GetCatalogPlugin ¶
func (h *PluginHandler) GetCatalogPlugin(c *gin.Context)
GetCatalogPlugin gets a specific plugin from the catalog by ID.
Endpoint: GET /api/plugins/catalog/:id
Path Parameters:
- id: Catalog plugin ID
Response: JSON with complete plugin details including repository info
Side Effects:
- Increments view count asynchronously (non-blocking)
- Updates last_viewed_at timestamp
Example Request:
GET /api/plugins/catalog/42
Example Response:
{
"id": 42,
"name": "slack-notifications",
"version": "1.2.3",
"display_name": "Slack Notifications",
"description": "Send session notifications to Slack",
"category": "notifications",
"plugin_type": "community",
"icon_url": "https://...",
"manifest": {...},
"tags": ["notifications", "slack"],
"install_count": 500,
"avg_rating": 4.8,
"rating_count": 20,
"repository": {
"id": 1,
"name": "official",
"url": "https://plugins.streamspace.io",
"type": "official"
}
}
HTTP Status Codes:
- 200: Success
- 404: Plugin not found
- 500: Database error
func (*PluginHandler) GetInstalledPlugin ¶
func (h *PluginHandler) GetInstalledPlugin(c *gin.Context)
GetInstalledPlugin gets details of a specific installed plugin.
Endpoint: GET /api/plugins/:id
Path Parameters:
- id: Installed plugin ID (not catalog ID)
Response: JSON with complete plugin details
Example Request:
GET /api/plugins/123
HTTP Status Codes:
- 200: Success
- 404: Plugin not found
- 500: Database error
func (*PluginHandler) InstallPlugin ¶
func (h *PluginHandler) InstallPlugin(c *gin.Context)
InstallPlugin installs a plugin from the catalog.
Endpoint: POST /api/plugins/catalog/:id/install
Path Parameters:
- id: Catalog plugin ID to install
Request Body (optional):
{
"config": {"api_key": "..."} // Plugin-specific configuration
}
Behavior:
- Fetches plugin details from catalog_plugins
- Checks if already installed (returns 409 if yes)
- Inserts into installed_plugins with enabled=true
- Increments install count asynchronously
- Updates plugin_stats table
Side Effects:
- Plugin install count incremented (async, non-blocking)
- Plugin stats updated with last_installed_at timestamp
- user_id saved as installed_by
Example Request:
POST /api/plugins/catalog/42/install
{
"config": {
"webhook_url": "https://hooks.slack.com/...",
"channel": "#general"
}
}
Example Response:
{
"message": "Plugin installed successfully",
"pluginId": 123
}
HTTP Status Codes:
- 201: Plugin installed successfully
- 404: Catalog plugin not found
- 409: Plugin already installed
- 500: Database error
func (*PluginHandler) ListInstalledPlugins ¶
func (h *PluginHandler) ListInstalledPlugins(c *gin.Context)
ListInstalledPlugins lists all installed plugins.
Endpoint: GET /api/plugins
Query Parameters:
- enabled: Filter by enabled status ("true" for enabled only)
Response: JSON with plugins array and total count
Example Requests:
GET /api/plugins // All installed plugins GET /api/plugins?enabled=true // Only enabled plugins
Example Response:
{
"plugins": [
{
"id": 123,
"catalog_plugin_id": 42,
"name": "slack-notifications",
"version": "1.2.3",
"enabled": true,
"config": {"webhook_url": "..."},
"installed_by": "user123",
"installed_at": "2025-01-15T10:30:00Z",
"display_name": "Slack Notifications",
"description": "...",
"plugin_type": "community",
"icon_url": "..."
}
],
"total": 1
}
HTTP Status Codes:
- 200: Success (may return empty array if no plugins installed)
- 500: Database error
func (*PluginHandler) RatePlugin ¶
func (h *PluginHandler) RatePlugin(c *gin.Context)
RatePlugin allows a user to rate a catalog plugin.
Endpoint: POST /api/plugins/catalog/:id/rate
Path Parameters:
- id: Catalog plugin ID to rate
Request Body:
{
"rating": 5, // Required: 1-5 stars
"review": "Great!" // Optional: Text review
}
Behavior:
- Upserts rating (inserts new or updates existing for this user)
- Updates plugin's avg_rating and rating_count
- user_id extracted from auth middleware (c.GetString("user_id"))
Example Request:
POST /api/plugins/catalog/42/rate
{
"rating": 5,
"review": "Excellent plugin, works perfectly!"
}
HTTP Status Codes:
- 200: Rating submitted successfully
- 400: Invalid rating (not 1-5) or invalid request body
- 500: Database error
func (*PluginHandler) RegisterRoutes ¶
func (h *PluginHandler) RegisterRoutes(r *gin.RouterGroup)
RegisterRoutes registers plugin routes to the provided router group.
Mounts all plugin endpoints under /plugins prefix:
- Catalog endpoints: /plugins/catalog, /plugins/catalog/:id, etc.
- Installed endpoints: /plugins, /plugins/:id, /plugins/:id/enable, etc.
Parameters:
- r: Gin router group to mount routes on (typically /api)
Example:
api := router.Group("/api")
handler.RegisterRoutes(api)
// Routes available at: /api/plugins/catalog, /api/plugins, etc.
func (*PluginHandler) UninstallPlugin ¶
func (h *PluginHandler) UninstallPlugin(c *gin.Context)
UninstallPlugin removes a plugin from the system.
Endpoint: DELETE /api/plugins/:id
Path Parameters:
- id: Installed plugin ID
Behavior:
- Deletes plugin from installed_plugins table
- Plugin runtime should unload the plugin
WARNING: This does not clean up plugin data tables or configuration. Plugin should implement cleanup in OnUnload hook.
Example Request:
DELETE /api/plugins/123
HTTP Status Codes:
- 200: Plugin uninstalled successfully
- 404: Plugin not found
- 500: Database error
func (*PluginHandler) UpdateInstalledPlugin ¶
func (h *PluginHandler) UpdateInstalledPlugin(c *gin.Context)
UpdateInstalledPlugin updates a plugin's configuration or enabled status.
Endpoint: PATCH /api/plugins/:id
Path Parameters:
- id: Installed plugin ID
Request Body (all fields optional):
{
"enabled": true, // Enable/disable plugin
"config": {"api_key": "new..."} // Update configuration
}
Behavior:
- Only provided fields are updated
- updated_at timestamp automatically set
Example Request:
PATCH /api/plugins/123
{
"config": {"webhook_url": "https://new-url.com"}
}
HTTP Status Codes:
- 200: Plugin updated successfully
- 400: Invalid request body
- 404: Plugin not found
- 500: Database error
type PluginMarketplaceHandler ¶
type PluginMarketplaceHandler struct {
// contains filtered or unexported fields
}
PluginMarketplaceHandler handles plugin marketplace HTTP requests.
This handler provides higher-level plugin management endpoints that:
- Sync catalog from external repositories
- Install/uninstall with immediate runtime effect
- Query runtime state directly (loaded plugins)
Dependencies:
- database: For plugin metadata and state persistence
- marketplace: For catalog sync and plugin discovery
- runtime: For immediate load/unload operations
func NewPluginMarketplaceHandler ¶
func NewPluginMarketplaceHandler(database *db.Database, marketplace *plugins.PluginMarketplace, runtime *plugins.RuntimeV2) *PluginMarketplaceHandler
NewPluginMarketplaceHandler creates a new plugin marketplace handler.
Parameters:
- database: Database connection
- marketplace: Plugin marketplace for catalog operations
- runtime: Plugin runtime for load/unload operations
Returns:
- Configured PluginMarketplaceHandler ready to register routes
Example:
marketplace := plugins.NewPluginMarketplace(db, repoURL)
runtime := plugins.NewRuntimeV2(db)
handler := NewPluginMarketplaceHandler(db, marketplace, runtime)
handler.RegisterRoutes(router.Group("/api"))
func (*PluginMarketplaceHandler) DisablePlugin ¶
func (h *PluginMarketplaceHandler) DisablePlugin(c *gin.Context)
DisablePlugin unloads and disables a plugin.
Endpoint: POST /api/plugins/marketplace/disable/:name
Path Parameters:
- name: Plugin name to disable
Behavior:
- Calls runtime.UnloadPlugin (unloads from runtime)
- Sets enabled=false in database
Example Request:
POST /api/plugins/marketplace/disable/slack-notifications
HTTP Status Codes:
- 200: Plugin disabled successfully
- 500: Database update failed
func (*PluginMarketplaceHandler) EnablePlugin ¶
func (h *PluginMarketplaceHandler) EnablePlugin(c *gin.Context)
EnablePlugin enables a plugin in the database.
Endpoint: POST /api/plugins/marketplace/enable/:name
Path Parameters:
- name: Plugin name to enable
Behavior:
- Sets enabled=true in installed_plugins table
- TODO: Should load plugin into runtime (not currently implemented)
Example Request:
POST /api/plugins/marketplace/enable/slack-notifications
HTTP Status Codes:
- 200: Plugin enabled successfully
- 500: Database update failed
func (*PluginMarketplaceHandler) GetInstalledPlugin ¶
func (h *PluginMarketplaceHandler) GetInstalledPlugin(c *gin.Context)
GetInstalledPlugin gets details of a specific loaded plugin from runtime.
Endpoint: GET /api/plugins/marketplace/installed/:name
Path Parameters:
- name: Plugin name
Response: JSON with loaded plugin details
Example Request:
GET /api/plugins/marketplace/installed/slack-notifications
HTTP Status Codes:
- 200: Success
- 404: Plugin not loaded in runtime
func (*PluginMarketplaceHandler) GetPluginDetails ¶
func (h *PluginMarketplaceHandler) GetPluginDetails(c *gin.Context)
GetPluginDetails gets details for a specific plugin from the marketplace catalog.
Endpoint: GET /api/plugins/marketplace/catalog/:name
Path Parameters:
- name: Plugin name (e.g., "slack-notifications")
Response: JSON with complete plugin metadata and manifest
Example Request:
GET /api/plugins/marketplace/catalog/slack-notifications
Example Response:
{
"name": "slack-notifications",
"version": "1.2.3",
"display_name": "Slack Notifications",
"description": "Send session notifications to Slack",
"manifest": {
"permissions": ["sessions.read", "users.read"],
"config_schema": {...}
}
}
HTTP Status Codes:
- 200: Success
- 404: Plugin not found in catalog
- 500: Database or marketplace error
func (*PluginMarketplaceHandler) InstallPlugin ¶
func (h *PluginMarketplaceHandler) InstallPlugin(c *gin.Context)
InstallPlugin installs a plugin from the marketplace and loads it immediately.
Endpoint: POST /api/plugins/marketplace/install/:name
Path Parameters:
- name: Plugin name to install
Request Body:
{
"config": {"api_key": "..."} // Plugin-specific configuration
}
Behavior:
- Calls marketplace.InstallPlugin (adds to installed_plugins table)
- Fetches plugin metadata from marketplace.GetPlugin
- Calls runtime.LoadPluginWithConfig (loads into runtime immediately)
This is the key difference from plugins.go:
- plugins.go: Install to database only, requires restart/reload
- marketplace.go: Install to database AND load into runtime
Example Request:
POST /api/plugins/marketplace/install/slack-notifications
{
"config": {
"webhook_url": "https://hooks.slack.com/...",
"channel": "#general"
}
}
Example Response:
{
"message": "Plugin installed and activated successfully",
"plugin": {
"name": "slack-notifications",
"version": "1.2.3",
"manifest": {...}
}
}
HTTP Status Codes:
- 200: Plugin installed and loaded successfully
- 400: Invalid request body
- 500: Install or load failed
func (*PluginMarketplaceHandler) ListAvailablePlugins ¶
func (h *PluginMarketplaceHandler) ListAvailablePlugins(c *gin.Context)
ListAvailablePlugins lists all plugins available in the marketplace.
Endpoint: GET /api/plugins/marketplace/catalog
Response: JSON with plugins array and count
Data Source:
- marketplace.ListAvailable() queries catalog_plugins table
- Populated by POST /sync or periodic background sync
Example Request:
GET /api/plugins/marketplace/catalog
Example Response:
{
"plugins": [
{
"name": "slack-notifications",
"version": "1.2.3",
"display_name": "Slack Notifications",
"description": "...",
"manifest": {...}
}
],
"count": 1
}
HTTP Status Codes:
- 200: Success (may return empty array if catalog not synced)
- 500: Database or marketplace error
func (*PluginMarketplaceHandler) ListInstalledPlugins ¶
func (h *PluginMarketplaceHandler) ListInstalledPlugins(c *gin.Context)
ListInstalledPlugins lists all plugins currently loaded in the runtime.
Endpoint: GET /api/plugins/marketplace/installed
Response: JSON with plugins array and count
Data Source:
- runtime.ListPlugins() returns currently loaded plugins from memory
- This shows runtime state, not database state
Example Request:
GET /api/plugins/marketplace/installed
Example Response:
{
"plugins": [
{
"name": "slack-notifications",
"version": "1.2.3",
"enabled": true,
"loaded_at": "2025-01-15T10:30:00Z",
"is_builtin": false
}
],
"count": 1
}
HTTP Status Codes:
- 200: Success (always succeeds, may return empty array)
func (*PluginMarketplaceHandler) RegisterRoutes ¶
func (h *PluginMarketplaceHandler) RegisterRoutes(r *gin.RouterGroup)
RegisterRoutes registers plugin marketplace routes to the provided router group.
Mounts all marketplace endpoints under /plugins/marketplace prefix:
- Catalog endpoints: /plugins/marketplace/catalog, /plugins/marketplace/sync
- Installation endpoints: /plugins/marketplace/install/:name, etc.
- Installed endpoints: /plugins/marketplace/installed
Parameters:
- r: Gin router group to mount routes on (typically /api)
Example:
api := router.Group("/api")
handler.RegisterRoutes(api)
// Routes available at: /api/plugins/marketplace/catalog, etc.
func (*PluginMarketplaceHandler) SyncCatalog ¶
func (h *PluginMarketplaceHandler) SyncCatalog(c *gin.Context)
SyncCatalog forces a synchronization of the plugin catalog from external repository.
Endpoint: POST /api/plugins/marketplace/sync
Behavior:
- Fetches latest plugin list from configured repository URL
- Updates catalog_plugins table with new/updated plugins
- Updates catalog_repositories table with repository metadata
Example Request:
POST /api/plugins/marketplace/sync
Example Response:
{
"message": "Catalog synced successfully"
}
Use Cases:
- Manual catalog refresh after repository update
- Troubleshooting catalog sync issues
- Initial catalog population
HTTP Status Codes:
- 200: Catalog synced successfully
- 500: Sync failed (network error, invalid catalog format, etc.)
func (*PluginMarketplaceHandler) UninstallPlugin ¶
func (h *PluginMarketplaceHandler) UninstallPlugin(c *gin.Context)
UninstallPlugin unloads and uninstalls a plugin.
Endpoint: DELETE /api/plugins/marketplace/uninstall/:name
Path Parameters:
- name: Plugin name to uninstall
Behavior:
- Calls runtime.UnloadPlugin (unloads from runtime)
- Calls marketplace.UninstallPlugin (removes from database)
Note: Unload errors are logged but don't fail the request (plugin might not be loaded).
Example Request:
DELETE /api/plugins/marketplace/uninstall/slack-notifications
HTTP Status Codes:
- 200: Plugin uninstalled successfully
- 500: Uninstall failed
func (*PluginMarketplaceHandler) UpdatePluginConfig ¶
func (h *PluginMarketplaceHandler) UpdatePluginConfig(c *gin.Context)
UpdatePluginConfig updates a plugin's configuration.
Endpoint: PUT /api/plugins/marketplace/installed/:name/config
Path Parameters:
- name: Plugin name
Request Body:
{
"config": {"api_key": "new-value"}
}
TODO: Implementation needed
- Update installed_plugins.config column
- Reload plugin with new config
Example Request:
PUT /api/plugins/marketplace/installed/slack-notifications/config
{
"config": {"webhook_url": "https://new-url.com"}
}
HTTP Status Codes:
- 200: Config updated (currently always succeeds - TODO)
- 400: Invalid request body
type PredictiveScalingConfig ¶
type PredictiveScalingConfig struct {
Enabled bool `json:"enabled"`
SchedulePattern map[string]int `json:"schedule_pattern,omitempty"` // Hour -> replica count
LookAheadMinutes int `json:"look_ahead_minutes"` // Pre-scale before demand
}
PredictiveScalingConfig for schedule-based scaling
type PreferencesHandler ¶
type PreferencesHandler struct {
// contains filtered or unexported fields
}
PreferencesHandler handles user preferences and settings
func NewPreferencesHandler ¶
func NewPreferencesHandler(database *db.Database) *PreferencesHandler
NewPreferencesHandler creates a new preferences handler
func (*PreferencesHandler) AddFavorite ¶
func (h *PreferencesHandler) AddFavorite(c *gin.Context)
AddFavorite adds a template to favorites
func (*PreferencesHandler) GetDefaultsPreferences ¶
func (h *PreferencesHandler) GetDefaultsPreferences(c *gin.Context)
GetDefaultsPreferences returns default session preferences
func (*PreferencesHandler) GetFavorites ¶
func (h *PreferencesHandler) GetFavorites(c *gin.Context)
GetFavorites returns user's favorite templates
func (*PreferencesHandler) GetNotificationPreferences ¶
func (h *PreferencesHandler) GetNotificationPreferences(c *gin.Context)
GetNotificationPreferences returns notification preferences
func (*PreferencesHandler) GetPreferences ¶
func (h *PreferencesHandler) GetPreferences(c *gin.Context)
GetPreferences returns all user preferences
func (*PreferencesHandler) GetRecentSessions ¶
func (h *PreferencesHandler) GetRecentSessions(c *gin.Context)
GetRecentSessions returns user's recent sessions
func (*PreferencesHandler) GetUIPreferences ¶
func (h *PreferencesHandler) GetUIPreferences(c *gin.Context)
GetUIPreferences returns UI-specific preferences
func (*PreferencesHandler) RegisterRoutes ¶
func (h *PreferencesHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers preference routes
func (*PreferencesHandler) RemoveFavorite ¶
func (h *PreferencesHandler) RemoveFavorite(c *gin.Context)
RemoveFavorite removes a template from favorites
func (*PreferencesHandler) ResetPreferences ¶
func (h *PreferencesHandler) ResetPreferences(c *gin.Context)
Reset Preferences resets to defaults
func (*PreferencesHandler) UpdateDefaultsPreferences ¶
func (h *PreferencesHandler) UpdateDefaultsPreferences(c *gin.Context)
UpdateDefaultsPreferences updates default session preferences
func (*PreferencesHandler) UpdateNotificationPreferences ¶
func (h *PreferencesHandler) UpdateNotificationPreferences(c *gin.Context)
UpdateNotificationPreferences updates notification preferences
func (*PreferencesHandler) UpdatePreferences ¶
func (h *PreferencesHandler) UpdatePreferences(c *gin.Context)
UpdatePreferences updates user preferences
func (*PreferencesHandler) UpdateUIPreferences ¶
func (h *PreferencesHandler) UpdateUIPreferences(c *gin.Context)
UpdateUIPreferences updates UI-specific preferences
type QuotaPolicyRequest ¶
type QuotaPolicyRequest struct {
Name string `json:"name" binding:"required" validate:"required,min=1,max=200"`
Description string `json:"description" validate:"omitempty,max=1000"`
Rules string `json:"rules" binding:"required" validate:"required,max=10000"`
Priority int `json:"priority" validate:"gte=0,lte=100"`
Enabled bool `json:"enabled"`
}
QuotaPolicyRequest represents a quota policy create/update request
type QuotasHandler ¶
type QuotasHandler struct {
// contains filtered or unexported fields
}
QuotasHandler handles resource quotas and limits.
This handler provides endpoints for: - Getting and setting quotas for users and teams - Checking current resource usage against quotas - Detecting and reporting quota violations - Managing quota policies and rules
func NewQuotasHandler ¶
func NewQuotasHandler(database *db.Database) *QuotasHandler
NewQuotasHandler creates a new quotas handler
func (*QuotasHandler) CheckQuota ¶
func (h *QuotasHandler) CheckQuota(c *gin.Context)
CheckQuota checks if a quota would be exceeded
func (*QuotasHandler) CreatePolicy ¶
func (h *QuotasHandler) CreatePolicy(c *gin.Context)
CreatePolicy creates a new quota policy
func (*QuotasHandler) DeletePolicy ¶
func (h *QuotasHandler) DeletePolicy(c *gin.Context)
DeletePolicy deletes a quota policy
func (*QuotasHandler) DeleteTeamQuota ¶
func (h *QuotasHandler) DeleteTeamQuota(c *gin.Context)
DeleteTeamQuota deletes quota for a specific team
func (*QuotasHandler) DeleteUserQuota ¶
func (h *QuotasHandler) DeleteUserQuota(c *gin.Context)
DeleteUserQuota deletes quota for a specific user
func (*QuotasHandler) GetDefaultQuotas ¶
func (h *QuotasHandler) GetDefaultQuotas(c *gin.Context)
GetDefaultQuotas returns default quotas
func (*QuotasHandler) GetPolicies ¶
func (h *QuotasHandler) GetPolicies(c *gin.Context)
GetPolicies returns all quota policies
func (*QuotasHandler) GetPolicy ¶
func (h *QuotasHandler) GetPolicy(c *gin.Context)
GetPolicy returns a specific quota policy
func (*QuotasHandler) GetQuotaViolations ¶
func (h *QuotasHandler) GetQuotaViolations(c *gin.Context)
GetQuotaViolations returns users/teams exceeding quotas
func (*QuotasHandler) GetTeamQuota ¶
func (h *QuotasHandler) GetTeamQuota(c *gin.Context)
GetTeamQuota returns quota for a specific team
func (*QuotasHandler) GetTeamQuotaStatus ¶
func (h *QuotasHandler) GetTeamQuotaStatus(c *gin.Context)
GetTeamQuotaStatus returns quota vs usage status for a team
func (*QuotasHandler) GetTeamUsage ¶
func (h *QuotasHandler) GetTeamUsage(c *gin.Context)
GetTeamUsage returns current resource usage for a team
func (*QuotasHandler) GetUserQuota ¶
func (h *QuotasHandler) GetUserQuota(c *gin.Context)
GetUserQuota returns quota for a specific user
func (*QuotasHandler) GetUserQuotaStatus ¶
func (h *QuotasHandler) GetUserQuotaStatus(c *gin.Context)
GetUserQuotaStatus returns quota vs usage status for a user
func (*QuotasHandler) GetUserUsage ¶
func (h *QuotasHandler) GetUserUsage(c *gin.Context)
GetUserUsage returns current resource usage for a user
func (*QuotasHandler) ListAllQuotas ¶
func (h *QuotasHandler) ListAllQuotas(c *gin.Context)
ListAllQuotas returns all configured quotas
func (*QuotasHandler) RegisterRoutes ¶
func (h *QuotasHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers quota routes
func (*QuotasHandler) SetDefaultQuotas ¶
func (h *QuotasHandler) SetDefaultQuotas(c *gin.Context)
SetDefaultQuotas sets default quotas (stored in config or database)
func (*QuotasHandler) SetTeamQuota ¶
func (h *QuotasHandler) SetTeamQuota(c *gin.Context)
SetTeamQuota sets quota for a specific team
func (*QuotasHandler) SetUserQuota ¶
func (h *QuotasHandler) SetUserQuota(c *gin.Context)
SetUserQuota sets quota for a specific user
func (*QuotasHandler) UpdatePolicy ¶
func (h *QuotasHandler) UpdatePolicy(c *gin.Context)
UpdatePolicy updates a quota policy
type Recording ¶
type Recording struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
RecordingType string `json:"recording_type"`
StoragePath string `json:"storage_path"`
FileSizeBytes int64 `json:"file_size_bytes"`
DurationSeconds int `json:"duration_seconds"`
StartedAt *time.Time `json:"started_at"`
EndedAt *time.Time `json:"ended_at"`
Status string `json:"status"`
ErrorMessage *string `json:"error_message"`
CreatedBy *string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Computed fields
SessionName string `json:"session_name,omitempty"`
UserName string `json:"user_name,omitempty"`
FileSizeMB float64 `json:"file_size_mb,omitempty"`
DurationFormatted string `json:"duration_formatted,omitempty"`
}
Recording represents a session recording
type RecordingHandler ¶
type RecordingHandler struct {
// contains filtered or unexported fields
}
RecordingHandler handles session recording management
func NewRecordingHandler ¶
func NewRecordingHandler(database *db.Database) *RecordingHandler
NewRecordingHandler creates a new recording handler
func (*RecordingHandler) CreatePolicy ¶
func (h *RecordingHandler) CreatePolicy(c *gin.Context)
CreatePolicy creates a new recording policy
func (*RecordingHandler) DeletePolicy ¶
func (h *RecordingHandler) DeletePolicy(c *gin.Context)
DeletePolicy deletes a recording policy
func (*RecordingHandler) DeleteRecording ¶
func (h *RecordingHandler) DeleteRecording(c *gin.Context)
DeleteRecording deletes a recording
func (*RecordingHandler) DownloadRecording ¶
func (h *RecordingHandler) DownloadRecording(c *gin.Context)
DownloadRecording downloads a recording file
func (*RecordingHandler) GetPolicy ¶
func (h *RecordingHandler) GetPolicy(c *gin.Context)
GetPolicy gets a specific recording policy
func (*RecordingHandler) GetRecording ¶
func (h *RecordingHandler) GetRecording(c *gin.Context)
GetRecording gets a specific recording
func (*RecordingHandler) GetRecordingAccessLog ¶
func (h *RecordingHandler) GetRecordingAccessLog(c *gin.Context)
GetRecordingAccessLog gets access log for a recording
func (*RecordingHandler) ListPolicies ¶
func (h *RecordingHandler) ListPolicies(c *gin.Context)
ListPolicies lists all recording policies
func (*RecordingHandler) ListRecordings ¶
func (h *RecordingHandler) ListRecordings(c *gin.Context)
ListRecordings lists all recordings with filtering
func (*RecordingHandler) RegisterRoutes ¶
func (h *RecordingHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers recording routes
func (*RecordingHandler) StartRecording ¶
func (h *RecordingHandler) StartRecording(c *gin.Context)
StartRecording starts a recording for a session
func (*RecordingHandler) StopRecording ¶
func (h *RecordingHandler) StopRecording(c *gin.Context)
StopRecording stops a recording
func (*RecordingHandler) UpdatePolicy ¶
func (h *RecordingHandler) UpdatePolicy(c *gin.Context)
UpdatePolicy updates a recording policy
type RecordingPolicy ¶
type RecordingPolicy struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description *string `json:"description"`
AutoRecord bool `json:"auto_record"`
RecordingFormat string `json:"recording_format"`
RetentionDays int `json:"retention_days"`
ApplyToUsers map[string]interface{} `json:"apply_to_users"`
ApplyToTeams map[string]interface{} `json:"apply_to_teams"`
ApplyToTemplates map[string]interface{} `json:"apply_to_templates"`
RequireReason bool `json:"require_reason"`
AllowUserPlayback bool `json:"allow_user_playback"`
AllowUserDownload bool `json:"allow_user_download"`
RequireApproval bool `json:"require_approval"`
NotifyOnRecording bool `json:"notify_on_recording"`
Metadata map[string]interface{} `json:"metadata"`
Enabled bool `json:"enabled"`
Priority int `json:"priority"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
RecordingPolicy represents a recording policy
type ResourceConfig ¶
type ResourceConfig struct {
Memory string `json:"memory" validate:"required,min=2,max=20"` // e.g., "512Mi", "2Gi"
CPU string `json:"cpu" validate:"required,min=1,max=20"` // e.g., "100m", "2"
Storage string `json:"storage,omitempty" validate:"omitempty,max=20"` // e.g., "1Gi", "10Gi"
GPUCount int `json:"gpu_count,omitempty" validate:"omitempty,gte=0,lte=8"`
}
ResourceConfig for scheduled sessions
type ResourceThresholds ¶
type ResourceThresholds struct {
CPUPercent float64 `json:"cpu_percent"` // Max CPU % before avoiding node
MemoryPercent float64 `json:"memory_percent"` // Max memory % before avoiding node
MaxSessions int `json:"max_sessions"` // Max concurrent sessions per node
MinFreeCPU float64 `json:"min_free_cpu"` // Min free CPU cores required
MinFreeMemory int64 `json:"min_free_memory"` // Min free memory in bytes
}
ResourceThresholds for load balancing decisions
type SavedSearch ¶
type SavedSearch struct {
ID string `json:"id"`
UserID string `json:"userId"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Query string `json:"query"`
Filters map[string]interface{} `json:"filters,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
SavedSearch represents a saved search query
type ScalePolicy ¶
type ScalePolicy struct {
Threshold float64 `json:"threshold"` // Metric threshold to trigger
Increment int `json:"increment"` // How many replicas to add/remove
Stabilization int `json:"stabilization_seconds"` // Wait before next action
MaxIncrement int `json:"max_increment"` // Max replicas to add at once
}
ScalePolicy defines how to scale up or down
type ScalingEvent ¶
type ScalingEvent struct {
ID int64 `json:"id"`
PolicyID int64 `json:"policy_id"`
TargetType string `json:"target_type"`
TargetID string `json:"target_id"`
Action string `json:"action"` // "scale_up", "scale_down"
PreviousReplicas int `json:"previous_replicas"`
NewReplicas int `json:"new_replicas"`
Trigger string `json:"trigger"` // "metric", "schedule", "manual"
MetricValue float64 `json:"metric_value,omitempty"`
Reason string `json:"reason"`
Status string `json:"status"` // "pending", "in_progress", "completed", "failed"
CreatedAt time.Time `json:"created_at"`
}
ScalingEvent represents a scaling action
type ScheduleConfig ¶
type ScheduleConfig struct {
Type string `json:"type" validate:"required,oneof=once daily weekly monthly cron"`
StartTime time.Time `json:"start_time,omitempty"`
CronExpr string `json:"cron_expr,omitempty" validate:"omitempty,max=100"`
DaysOfWeek []int `json:"days_of_week,omitempty" validate:"omitempty,dive,gte=0,lte=6"` // 0=Sunday, 6=Saturday
DayOfMonth int `json:"day_of_month,omitempty" validate:"omitempty,gte=1,lte=31"`
TimeOfDay string `json:"time_of_day,omitempty" validate:"omitempty,len=5"` // HH:MM format (5 chars)
EndDate time.Time `json:"end_date,omitempty"`
Exceptions []string `json:"exceptions,omitempty" validate:"omitempty,dive,len=10"` // YYYY-MM-DD format (10 chars)
}
ScheduleConfig defines when a session should run
type ScheduledSession ¶
type ScheduledSession struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
TemplateID string `json:"template_id" validate:"required,min=1,max=100"`
Name string `json:"name" validate:"required,min=1,max=200"`
Description string `json:"description,omitempty" validate:"omitempty,max=1000"`
Timezone string `json:"timezone" validate:"required,min=1,max=50"`
Schedule ScheduleConfig `json:"schedule" validate:"required"`
Resources ResourceConfig `json:"resources" validate:"required"`
AutoTerminate bool `json:"auto_terminate"`
TerminateAfter int `json:"terminate_after_minutes,omitempty" validate:"omitempty,gte=1,lte=1440"` // 1-1440 minutes (24 hours)
PreWarm bool `json:"pre_warm"`
PreWarmMinutes int `json:"pre_warm_minutes,omitempty" validate:"omitempty,gte=1,lte=120"` // 1-120 minutes
PostCleanup bool `json:"post_cleanup"`
Enabled bool `json:"enabled"`
NextRunAt time.Time `json:"next_run_at,omitempty"`
LastRunAt time.Time `json:"last_run_at,omitempty"`
LastSessionID string `json:"last_session_id,omitempty"`
LastRunStatus string `json:"last_run_status,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ScheduledSession represents a scheduled workspace session that starts automatically.
This struct defines a session that will be created at specific times based on the configured schedule. Unlike on-demand sessions, scheduled sessions are managed by a background scheduler process that monitors next_run_at timestamps.
Lifecycle: 1. User creates scheduled session via API 2. System calculates next_run_at based on schedule configuration 3. Scheduler daemon checks for due schedules every minute 4. When next_run_at is reached, system creates actual Session resource 5. After session is created, next_run_at is recalculated for recurring schedules 6. System optionally terminates session after terminate_after minutes
Example use cases: - Development environment that starts at 9 AM and terminates at 6 PM - Weekly demo session every Friday at 2 PM - Training environment that pre-warms 15 minutes before scheduled time
type SchedulingHandler ¶
SchedulingHandler handles session scheduling and calendar integration requests.
func NewSchedulingHandler ¶
func NewSchedulingHandler(database *db.Database) *SchedulingHandler
NewSchedulingHandler creates a new scheduling handler.
func (*SchedulingHandler) CalendarOAuthCallback ¶
func (h *SchedulingHandler) CalendarOAuthCallback(c *gin.Context)
CalendarOAuthCallback handles OAuth callback (DEPRECATED)
func (*SchedulingHandler) ConnectCalendar ¶
func (h *SchedulingHandler) ConnectCalendar(c *gin.Context)
ConnectCalendar initiates calendar OAuth flow (DEPRECATED)
func (*SchedulingHandler) CreateScheduledSession ¶
func (h *SchedulingHandler) CreateScheduledSession(c *gin.Context)
CreateScheduledSession creates a new scheduled session.
This endpoint allows users to schedule sessions that will start automatically at specific times. The system performs several validations and checks before accepting the schedule:
VALIDATION STEPS:
1. Schedule Validation:
- Ensures required fields are present for the schedule type
- For "daily": requires time_of_day
- For "weekly": requires time_of_day and days_of_week
- For "monthly": requires time_of_day and day_of_month
- For "cron": validates cron expression syntax
- For "once": requires start_time
2. Next Run Calculation:
- Computes when the schedule will next trigger
- Uses the user's timezone for proper time conversion
- For recurring schedules, calculates first occurrence after current time
3. Conflict Detection:
- Checks if the proposed schedule would overlap with existing schedules
- Prevents double-booking that could violate quotas or confuse users
- Considers session duration (terminate_after) when detecting overlaps
- Returns HTTP 409 Conflict if overlaps are found
CONFLICT DETECTION LOGIC:
Two schedules conflict if their time windows overlap: - Schedule A: [next_run_at, next_run_at + terminate_after] - Schedule B: [next_run_at, next_run_at + terminate_after] - Conflict if: A.start < B.end AND B.start < A.end
EXAMPLE REQUEST:
{
"name": "Daily Dev Environment",
"template_id": "vscode",
"timezone": "America/New_York",
"schedule": {
"type": "daily",
"time_of_day": "09:00"
},
"terminate_after": 540, // 9 hours
"pre_warm": true,
"pre_warm_minutes": 15
}
RESPONSE:
{
"id": 42,
"message": "Scheduled session created",
"next_run_at": "2025-11-17T09:00:00-05:00",
"schedule": { ... }
}
SECURITY:
- User can only create schedules for themselves (userID enforced) - Schedule is validated to prevent malicious cron expressions - Timezone must be valid IANA timezone name
func (*SchedulingHandler) DeleteScheduledSession ¶
func (h *SchedulingHandler) DeleteScheduledSession(c *gin.Context)
DeleteScheduledSession deletes a scheduled session
func (*SchedulingHandler) DisableScheduledSession ¶
func (h *SchedulingHandler) DisableScheduledSession(c *gin.Context)
DisableScheduledSession disables a schedule
func (*SchedulingHandler) DisconnectCalendar ¶
func (h *SchedulingHandler) DisconnectCalendar(c *gin.Context)
DisconnectCalendar removes a calendar integration (DEPRECATED)
func (*SchedulingHandler) EnableScheduledSession ¶
func (h *SchedulingHandler) EnableScheduledSession(c *gin.Context)
EnableScheduledSession enables a schedule
func (*SchedulingHandler) ExportICalendar ¶
func (h *SchedulingHandler) ExportICalendar(c *gin.Context)
ExportICalendar exports scheduled sessions as iCal format (DEPRECATED)
func (*SchedulingHandler) GetScheduledSession ¶
func (h *SchedulingHandler) GetScheduledSession(c *gin.Context)
GetScheduledSession gets details of a scheduled session
func (*SchedulingHandler) ListCalendarIntegrations ¶
func (h *SchedulingHandler) ListCalendarIntegrations(c *gin.Context)
ListCalendarIntegrations lists user's calendar integrations (DEPRECATED)
func (*SchedulingHandler) ListScheduledSessions ¶
func (h *SchedulingHandler) ListScheduledSessions(c *gin.Context)
ListScheduledSessions lists all scheduled sessions for a user
func (*SchedulingHandler) SyncCalendar ¶
func (h *SchedulingHandler) SyncCalendar(c *gin.Context)
SyncCalendar manually triggers calendar sync (DEPRECATED)
func (*SchedulingHandler) UpdateScheduledSession ¶
func (h *SchedulingHandler) UpdateScheduledSession(c *gin.Context)
UpdateScheduledSession updates a scheduled session
type SearchHandler ¶
type SearchHandler struct {
// contains filtered or unexported fields
}
SearchHandler handles advanced search and filtering
func NewSearchHandler ¶
func NewSearchHandler(database *db.Database) *SearchHandler
NewSearchHandler creates a new search handler
func (*SearchHandler) AdvancedSearch ¶
func (h *SearchHandler) AdvancedSearch(c *gin.Context)
AdvancedSearch performs multi-criteria search
func (*SearchHandler) ClearSearchHistory ¶
func (h *SearchHandler) ClearSearchHistory(c *gin.Context)
ClearSearchHistory clears user's search history
func (*SearchHandler) CreateSavedSearch ¶
func (h *SearchHandler) CreateSavedSearch(c *gin.Context)
CreateSavedSearch creates a new saved search
func (*SearchHandler) DeleteSavedSearch ¶
func (h *SearchHandler) DeleteSavedSearch(c *gin.Context)
DeleteSavedSearch deletes a saved search
func (*SearchHandler) ExecuteSavedSearch ¶
func (h *SearchHandler) ExecuteSavedSearch(c *gin.Context)
ExecuteSavedSearch executes a saved search
func (*SearchHandler) GetAppTypes ¶
func (h *SearchHandler) GetAppTypes(c *gin.Context)
GetAppTypes returns all app types
func (*SearchHandler) GetCategories ¶
func (h *SearchHandler) GetCategories(c *gin.Context)
GetCategories returns all template categories
func (*SearchHandler) GetPopularTags ¶
func (h *SearchHandler) GetPopularTags(c *gin.Context)
GetPopularTags returns most popular tags
func (*SearchHandler) GetSavedSearch ¶
func (h *SearchHandler) GetSavedSearch(c *gin.Context)
GetSavedSearch retrieves a specific saved search
func (*SearchHandler) GetSearchHistory ¶
func (h *SearchHandler) GetSearchHistory(c *gin.Context)
GetSearchHistory returns user's recent searches
func (*SearchHandler) ListSavedSearches ¶
func (h *SearchHandler) ListSavedSearches(c *gin.Context)
ListSavedSearches returns user's saved searches
func (*SearchHandler) RegisterRoutes ¶
func (h *SearchHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers search routes
func (*SearchHandler) Search ¶
func (h *SearchHandler) Search(c *gin.Context)
Search performs universal search across all entities
func (*SearchHandler) SearchSessions ¶
func (h *SearchHandler) SearchSessions(c *gin.Context)
SearchSessions searches user sessions
func (*SearchHandler) SearchSuggestions ¶
func (h *SearchHandler) SearchSuggestions(c *gin.Context)
SearchSuggestions provides auto-complete suggestions
func (*SearchHandler) SearchTemplates ¶
func (h *SearchHandler) SearchTemplates(c *gin.Context)
SearchTemplates performs advanced template search
func (*SearchHandler) UpdateSavedSearch ¶
func (h *SearchHandler) UpdateSavedSearch(c *gin.Context)
UpdateSavedSearch updates a saved search
type SearchResult ¶
type SearchResult struct {
Type string `json:"type"` // template, session, user, etc.
ID string `json:"id"`
Name string `json:"name"`
DisplayName string `json:"displayName,omitempty"`
Description string `json:"description,omitempty"`
Category string `json:"category,omitempty"`
Tags []string `json:"tags,omitempty"`
Icon string `json:"icon,omitempty"`
Score float64 `json:"score"` // Relevance score
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
SearchResult represents a search result item
type SecurityHandler ¶
SecurityHandler handles security-related endpoints (MFA, IP whitelisting, etc.)
func NewSecurityHandler ¶
func NewSecurityHandler(database *db.Database) *SecurityHandler
NewSecurityHandler creates a new SecurityHandler instance
func (*SecurityHandler) CheckDevicePosture ¶
func (h *SecurityHandler) CheckDevicePosture(c *gin.Context)
CheckDevicePosture checks device security posture
func (*SecurityHandler) CheckIPAccess ¶
func (h *SecurityHandler) CheckIPAccess(c *gin.Context)
CheckIPAccess checks if an IP is allowed access
func (*SecurityHandler) CreateIPWhitelist ¶
func (h *SecurityHandler) CreateIPWhitelist(c *gin.Context)
CreateIPWhitelist adds an IP to whitelist
func (*SecurityHandler) DeleteIPWhitelist ¶
func (h *SecurityHandler) DeleteIPWhitelist(c *gin.Context)
DeleteIPWhitelist removes an IP whitelist entry.
CRITICAL SECURITY FIX (2025-11-14): Fixed authorization enumeration vulnerability by returning consistent "not found" error for both non-existent entries AND unauthorized access attempts.
Authorization Enumeration Attack: Before fix:
- Try to delete entry 123: "Forbidden" → Entry exists but you can't access it
- Try to delete entry 999: "Not found" → Entry doesn't exist
- Attacker can enumerate which entries exist by trying many IDs
After fix:
- Try to delete entry 123: "Not found" → Could be either case
- Try to delete entry 999: "Not found" → Could be either case
- Attacker cannot determine if entry exists or just lacks permission
Implementation: - Admins: DELETE any entry - Users: DELETE only if (user_id = $userID OR user_id IS NULL) - Check rows affected: 0 = either not found OR unauthorized - Always return 404 when rowsAffected = 0 (no information leakage)
Parameters:
- entryId: IP whitelist entry ID from URL path
- userID: From authentication context
- role: User role ("admin" or "user")
Returns:
- 200 OK: Entry deleted successfully
- 404 Not Found: Entry doesn't exist OR user lacks permission (secure, no information leakage)
- 500 Internal Server Error: Database error
func (*SecurityHandler) DisableMFA ¶
func (h *SecurityHandler) DisableMFA(c *gin.Context)
DisableMFA disables an MFA method
func (*SecurityHandler) GenerateBackupCodes ¶
func (h *SecurityHandler) GenerateBackupCodes(c *gin.Context)
GenerateBackupCodes generates new backup codes
func (*SecurityHandler) GetSecurityAlerts ¶
func (h *SecurityHandler) GetSecurityAlerts(c *gin.Context)
GetSecurityAlerts gets security alerts for a user
func (*SecurityHandler) ListIPWhitelist ¶
func (h *SecurityHandler) ListIPWhitelist(c *gin.Context)
ListIPWhitelist lists IP whitelist entries
func (*SecurityHandler) ListMFAMethods ¶
func (h *SecurityHandler) ListMFAMethods(c *gin.Context)
ListMFAMethods lists all MFA methods for a user
func (*SecurityHandler) SetupMFA ¶
func (h *SecurityHandler) SetupMFA(c *gin.Context)
func (*SecurityHandler) VerifyMFA ¶
func (h *SecurityHandler) VerifyMFA(c *gin.Context)
VerifyMFA verifies MFA code during login (used after username/password authentication).
CRITICAL SECURITY FIX (2025-11-14): Added rate limiting (5 attempts per minute) to prevent brute force attacks on 6-digit TOTP codes.
Why Rate Limiting is Critical: - TOTP codes are only 6 digits (1,000,000 possible values) - Codes are valid for 30-60 seconds (time window allows some drift) - Without rate limiting, attacker could brute force in ~15 minutes - With 5 attempts/minute, brute force takes ~3,850 hours (160 days)
Process: 1. Check rate limit (5 attempts/minute per user) 2. Reject SMS/Email MFA (not implemented) 3. Verify code (TOTP or backup code) 4. If successful, set MFA session flag 5. Optionally trust device (sets long-lived cookie)
Security: - Rate limiting prevents brute force (5 attempts/minute) - Backup codes are single-use and hashed (SHA-256) - TOTP codes expire every 30 seconds - "Trust device" cookie has limited lifetime and device fingerprint
Parameters:
- userID: From authentication context (JWT)
- req.Code: 6-digit TOTP code or 8-character backup code
- req.MethodType: "totp" (default), "sms" (disabled), "email" (disabled), "backup_code"
- req.TrustDevice: If true, set remember-me cookie for this device
Returns:
- 200 OK: MFA verification successful
- 400 Bad Request: Invalid input
- 401 Unauthorized: Invalid code
- 404 Not Found: MFA method not enabled
- 429 Too Many Requests: Rate limit exceeded (>5 attempts/minute)
- 501 Not Implemented: SMS/Email MFA requested
func (*SecurityHandler) VerifyMFASetup ¶
func (h *SecurityHandler) VerifyMFASetup(c *gin.Context)
VerifyMFASetup verifies and enables MFA method (Step 2: Confirm setup)
func (*SecurityHandler) VerifySession ¶
func (h *SecurityHandler) VerifySession(c *gin.Context)
VerifySession performs continuous session verification
type SelkiesProxyHandler ¶
type SelkiesProxyHandler struct {
// contains filtered or unexported fields
}
SelkiesProxyHandler manages HTTP/WebSocket connections to Selkies-based sessions.
It proxies HTTP and WebSocket traffic between UI clients and session Services, enabling remote access to web-based streaming interfaces (Selkies, Kasm, Guacamole).
func NewSelkiesProxyHandler ¶
func NewSelkiesProxyHandler(database *db.Database, agentHub *ws.AgentHub, namespace string) *SelkiesProxyHandler
NewSelkiesProxyHandler creates a new Selkies/HTTP proxy handler.
Example:
handler := NewSelkiesProxyHandler(database, agentHub, "streamspace")
router.Any("/http/:sessionId/*path", handler.HandleHTTPProxy)
func (*SelkiesProxyHandler) HandleHTTPProxy ¶
func (h *SelkiesProxyHandler) HandleHTTPProxy(c *gin.Context)
HandleHTTPProxy handles HTTP/WebSocket proxy connections to Selkies-based sessions.
Endpoint: ANY /api/v1/http/:sessionId/*path
Query Parameters:
- token: JWT authentication token (required)
Flow:
- Authenticate user via JWT
- Verify user has access to session
- Look up session streaming protocol metadata
- Verify session uses HTTP-based streaming (selkies, guacamole, etc.)
- Look up agent hosting the session
- Verify agent is connected
- Proxy HTTP/WebSocket traffic to agent → pod
Example:
http://control-plane/api/v1/http/sess-123/ http://control-plane/api/v1/http/sess-123/websockify
func (*SelkiesProxyHandler) RegisterRoutes ¶
func (h *SelkiesProxyHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers the Selkies/HTTP proxy routes.
Routes:
- ANY /http/:sessionId/*path - HTTP/WebSocket proxy for Selkies-based sessions
Example:
selkiesProxyHandler.RegisterRoutes(router)
type SendCommandRequest ¶
type SendCommandRequest struct {
Action string `json:"action" binding:"required" validate:"required,oneof=start_session stop_session hibernate_session wake_session"`
SessionID string `json:"sessionId,omitempty" validate:"omitempty,min=1,max=100"`
Payload map[string]interface{} `json:"payload,omitempty"`
}
SendCommand godoc @Summary Send a command to an agent @Description Creates and dispatches a command to an agent. The command is queued and sent via WebSocket. @Tags agents @Accept json @Produce json @Param agent_id path string true "Agent ID" @Param request body models.SendCommandRequest true "Command request" @Success 201 {object} models.AgentCommand "Command created and queued" @Failure 400 {object} map[string]interface{} "Invalid request" @Failure 404 {object} map[string]interface{} "Agent not found" @Failure 503 {object} map[string]interface{} "Agent not connected" @Failure 500 {object} map[string]interface{} "Internal server error" @Router /agents/{agent_id}/command [post] SendCommandRequest represents a command to send to an agent
type SessionActivityEvent ¶
type SessionActivityEvent struct {
ID int `json:"id"`
SessionID string `json:"sessionId"`
UserID string `json:"userId,omitempty"`
EventType string `json:"eventType"`
EventCategory string `json:"eventCategory"`
Description string `json:"description,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
IPAddress string `json:"ipAddress,omitempty"`
UserAgent string `json:"userAgent,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
SessionActivityEvent represents a session activity event
type SessionActivityHandler ¶
type SessionActivityHandler struct {
// contains filtered or unexported fields
}
SessionActivityHandler handles session activity logging and queries
func NewSessionActivityHandler ¶
func NewSessionActivityHandler(database *db.Database) *SessionActivityHandler
NewSessionActivityHandler creates a new session activity handler
func (*SessionActivityHandler) GetActivityStats ¶
func (h *SessionActivityHandler) GetActivityStats(c *gin.Context)
GetActivityStats returns activity statistics
func (*SessionActivityHandler) GetSessionActivity ¶
func (h *SessionActivityHandler) GetSessionActivity(c *gin.Context)
GetSessionActivity returns activity log for a specific session
func (*SessionActivityHandler) GetSessionTimeline ¶
func (h *SessionActivityHandler) GetSessionTimeline(c *gin.Context)
GetSessionTimeline returns a timeline view of session activity
func (*SessionActivityHandler) GetUserSessionActivity ¶
func (h *SessionActivityHandler) GetUserSessionActivity(c *gin.Context)
GetUserSessionActivity returns all session activity for a specific user
func (*SessionActivityHandler) LogActivityEvent ¶
func (h *SessionActivityHandler) LogActivityEvent(c *gin.Context)
LogActivityEvent logs a session activity event
type SessionTemplate ¶
type SessionTemplate struct {
ID string `json:"id"`
UserID string `json:"userId"`
TeamID string `json:"teamId,omitempty"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Icon string `json:"icon,omitempty"`
Category string `json:"category,omitempty"`
Tags []string `json:"tags,omitempty"`
Visibility string `json:"visibility"` // private, team, public
BaseTemplate string `json:"baseTemplate"` // Reference to catalog template
Configuration map[string]interface{} `json:"configuration"`
Resources map[string]interface{} `json:"resources"`
Environment map[string]string `json:"environment,omitempty"`
IsDefault bool `json:"isDefault"`
UsageCount int `json:"usageCount"`
Version string `json:"version"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
SessionTemplate represents a user-defined session configuration template
type SessionTemplatesHandler ¶
type SessionTemplatesHandler struct {
// contains filtered or unexported fields
}
SessionTemplatesHandler handles custom session templates and presets
func NewSessionTemplatesHandler ¶
func NewSessionTemplatesHandler(database *db.Database, k8sClient *k8s.Client, publisher *events.Publisher, platform string) *SessionTemplatesHandler
NewSessionTemplatesHandler creates a new session templates handler
func (*SessionTemplatesHandler) CloneSessionTemplate ¶
func (h *SessionTemplatesHandler) CloneSessionTemplate(c *gin.Context)
CloneSessionTemplate creates a copy of a template
func (*SessionTemplatesHandler) CreateSessionTemplate ¶
func (h *SessionTemplatesHandler) CreateSessionTemplate(c *gin.Context)
CreateSessionTemplate creates a new session template
func (*SessionTemplatesHandler) CreateTemplateFromSession ¶
func (h *SessionTemplatesHandler) CreateTemplateFromSession(c *gin.Context)
CreateTemplateFromSession creates a template from an existing session
func (*SessionTemplatesHandler) CreateTemplateVersion ¶
func (h *SessionTemplatesHandler) CreateTemplateVersion(c *gin.Context)
func (*SessionTemplatesHandler) DeleteSessionTemplate ¶
func (h *SessionTemplatesHandler) DeleteSessionTemplate(c *gin.Context)
DeleteSessionTemplate deletes a template
func (*SessionTemplatesHandler) GetDefaultTemplates ¶
func (h *SessionTemplatesHandler) GetDefaultTemplates(c *gin.Context)
GetDefaultTemplates returns user's default templates
func (*SessionTemplatesHandler) GetSessionTemplate ¶
func (h *SessionTemplatesHandler) GetSessionTemplate(c *gin.Context)
GetSessionTemplate retrieves a specific template
func (*SessionTemplatesHandler) ListPublicTemplates ¶
func (h *SessionTemplatesHandler) ListPublicTemplates(c *gin.Context)
ListPublicTemplates returns all public templates
func (*SessionTemplatesHandler) ListSessionTemplates ¶
func (h *SessionTemplatesHandler) ListSessionTemplates(c *gin.Context)
ListSessionTemplates returns user's session templates
func (*SessionTemplatesHandler) ListTeamTemplates ¶
func (h *SessionTemplatesHandler) ListTeamTemplates(c *gin.Context)
ListTeamTemplates returns team templates
func (*SessionTemplatesHandler) ListTemplateShares ¶
func (h *SessionTemplatesHandler) ListTemplateShares(c *gin.Context)
func (*SessionTemplatesHandler) ListTemplateVersions ¶
func (h *SessionTemplatesHandler) ListTemplateVersions(c *gin.Context)
func (*SessionTemplatesHandler) PublishSessionTemplate ¶
func (h *SessionTemplatesHandler) PublishSessionTemplate(c *gin.Context)
PublishSessionTemplate makes a template public
func (*SessionTemplatesHandler) RegisterRoutes ¶
func (h *SessionTemplatesHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers session template routes
func (*SessionTemplatesHandler) RestoreTemplateVersion ¶
func (h *SessionTemplatesHandler) RestoreTemplateVersion(c *gin.Context)
func (*SessionTemplatesHandler) RevokeTemplateShare ¶
func (h *SessionTemplatesHandler) RevokeTemplateShare(c *gin.Context)
func (*SessionTemplatesHandler) SetAsDefaultTemplate ¶
func (h *SessionTemplatesHandler) SetAsDefaultTemplate(c *gin.Context)
SetAsDefaultTemplate sets a template as the user's default
func (*SessionTemplatesHandler) ShareSessionTemplate ¶
func (h *SessionTemplatesHandler) ShareSessionTemplate(c *gin.Context)
func (*SessionTemplatesHandler) UnpublishSessionTemplate ¶
func (h *SessionTemplatesHandler) UnpublishSessionTemplate(c *gin.Context)
UnpublishSessionTemplate makes a template private
func (*SessionTemplatesHandler) UpdateSessionTemplate ¶
func (h *SessionTemplatesHandler) UpdateSessionTemplate(c *gin.Context)
UpdateSessionTemplate updates a template
func (*SessionTemplatesHandler) UseSessionTemplate ¶
func (h *SessionTemplatesHandler) UseSessionTemplate(c *gin.Context)
UseSessionTemplate creates a session from a template
type SessionVerification ¶
type SessionVerification struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
DeviceID string `json:"device_id"`
IPAddress string `json:"ip_address"`
Location string `json:"location,omitempty"`
RiskScore int `json:"risk_score"` // 0-100
RiskLevel string `json:"risk_level"` // "low", "medium", "high", "critical"
Verified bool `json:"verified"`
LastVerifiedAt time.Time `json:"last_verified_at"`
CreatedAt time.Time `json:"created_at"`
}
SessionVerification represents continuous session verification
type SetApplicationEnabledRequest ¶
type SetApplicationEnabledRequest struct {
Enabled bool `json:"enabled"`
}
SetApplicationEnabled godoc @Summary Enable or disable an application @Description Toggle the application's enabled status @Tags applications @Accept json @Produce json @Param id path string true "Application ID" @Param request body object true "Enabled status" @Success 200 {object} map[string]interface{} @Failure 400 {object} ErrorResponse @Router /api/v1/applications/{id}/enabled [put] SetApplicationEnabledRequest is the request to enable/disable an application
type SetDefaultQuotasRequest ¶
type SetDefaultQuotasRequest struct {
User struct {
MaxSessions int `json:"maxSessions" validate:"gte=0,lte=1000"`
MaxCPU int `json:"maxCPU" validate:"gte=0,lte=100000"`
MaxMemory int `json:"maxMemory" validate:"gte=0,lte=1000000"`
MaxStorage int `json:"maxStorage" validate:"gte=0,lte=10000"`
} `json:"user" validate:"required"`
Team struct {
MaxSessions int `json:"maxSessions" validate:"gte=0,lte=10000"`
MaxCPU int `json:"maxCPU" validate:"gte=0,lte=1000000"`
MaxMemory int `json:"maxMemory" validate:"gte=0,lte=10000000"`
MaxStorage int `json:"maxStorage" validate:"gte=0,lte=100000"`
} `json:"team" validate:"required"`
}
SetDefaultQuotasRequest represents a request to set default quotas
type SetQuotaRequest ¶
type SetQuotaRequest struct {
MaxSessions int `json:"maxSessions" validate:"gte=0,lte=10000"`
MaxCPU int `json:"maxCPU" validate:"gte=0,lte=1000000"` // millicores, max 1000 cores
MaxMemory int `json:"maxMemory" validate:"gte=0,lte=10000000"` // MB, max ~10TB
MaxStorage int `json:"maxStorage" validate:"gte=0,lte=100000"` // GB, max 100TB
}
SetQuotaRequest represents a request to set resource quotas
type SetupAdminRequest ¶
type SetupAdminRequest struct {
Password string `json:"password" binding:"required" validate:"required,password"`
PasswordConfirm string `json:"passwordConfirm" binding:"required" validate:"required,eqfield=Password"`
Email string `json:"email" binding:"required,email" validate:"required,email"`
}
SetupAdminRequest is the request body for admin setup
type SetupAdminResponse ¶
type SetupAdminResponse struct {
Message string `json:"message"`
Username string `json:"username"`
Email string `json:"email"`
}
SetupAdminResponse is the response after successful setup
type SetupHandler ¶
SetupHandler handles initial admin setup wizard
func NewSetupHandler ¶
func NewSetupHandler(database *db.Database) *SetupHandler
NewSetupHandler creates a new setup handler
func (*SetupHandler) GetSetupStatus ¶
func (h *SetupHandler) GetSetupStatus(c *gin.Context)
GetSetupStatus checks if the setup wizard should be enabled GET /api/v1/auth/setup/status
Returns:
200 OK: Setup status information 500 Internal Server Error: Database error
Response body:
{
"setupRequired": true/false,
"adminExists": true/false,
"hasPassword": true/false,
"message": "Setup wizard is enabled/disabled"
}
func (*SetupHandler) RegisterRoutes ¶
func (h *SetupHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers setup wizard endpoints These routes are public (no authentication required) as they are needed for initial admin account setup before authentication is possible.
Routes:
GET /setup/status - Check if setup wizard is enabled POST /setup - Configure admin account
func (*SetupHandler) SetupAdmin ¶
func (h *SetupHandler) SetupAdmin(c *gin.Context)
SetupAdmin configures the initial admin password POST /api/v1/auth/setup
This endpoint is only available when the admin account exists but has no password. After successful setup, it automatically disables the setup wizard.
Request body:
{
"password": "secure-password-min-12-chars",
"passwordConfirm": "secure-password-min-12-chars",
"email": "admin@example.com"
}
Returns:
200 OK: Setup completed successfully 400 Bad Request: Invalid input or validation error 403 Forbidden: Setup wizard is disabled (admin already configured) 500 Internal Server Error: Database error
type SetupStatusResponse ¶
type SetupStatusResponse struct {
SetupRequired bool `json:"setupRequired"`
AdminExists bool `json:"adminExists"`
HasPassword bool `json:"hasPassword"`
Message string `json:"message,omitempty"`
}
SetupStatusResponse returns whether the setup wizard should be displayed
type SharingHandler ¶
type SharingHandler struct {
// contains filtered or unexported fields
}
SharingHandler handles session sharing and collaboration
func NewSharingHandler ¶
func NewSharingHandler(database *db.Database) *SharingHandler
NewSharingHandler creates a new sharing handler
func (*SharingHandler) AcceptInvitation ¶
func (h *SharingHandler) AcceptInvitation(c *gin.Context)
AcceptInvitation accepts an invitation and creates a share
func (*SharingHandler) CreateInvitation ¶
func (h *SharingHandler) CreateInvitation(c *gin.Context)
CreateInvitation creates a shareable invitation link
func (*SharingHandler) CreateShare ¶
func (h *SharingHandler) CreateShare(c *gin.Context)
CreateShare creates a direct share with a specific user
func (*SharingHandler) ListCollaborators ¶
func (h *SharingHandler) ListCollaborators(c *gin.Context)
ListCollaborators lists active collaborators for a session
func (*SharingHandler) ListInvitations ¶
func (h *SharingHandler) ListInvitations(c *gin.Context)
ListInvitations lists all invitations for a session
func (*SharingHandler) ListSharedSessions ¶
func (h *SharingHandler) ListSharedSessions(c *gin.Context)
ListSharedSessions lists all sessions shared with the requesting user
func (*SharingHandler) ListShares ¶
func (h *SharingHandler) ListShares(c *gin.Context)
ListShares lists all shares for a session
func (*SharingHandler) RegisterRoutes ¶
func (h *SharingHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers the sharing routes
func (*SharingHandler) RemoveCollaborator ¶
func (h *SharingHandler) RemoveCollaborator(c *gin.Context)
RemoveCollaborator removes a collaborator from a session
func (*SharingHandler) RevokeInvitation ¶
func (h *SharingHandler) RevokeInvitation(c *gin.Context)
RevokeInvitation revokes an invitation
func (*SharingHandler) RevokeShare ¶
func (h *SharingHandler) RevokeShare(c *gin.Context)
RevokeShare revokes a session share
func (*SharingHandler) TransferOwnership ¶
func (h *SharingHandler) TransferOwnership(c *gin.Context)
TransferOwnership transfers session ownership to another user
func (*SharingHandler) UpdateCollaboratorActivity ¶
func (h *SharingHandler) UpdateCollaboratorActivity(c *gin.Context)
UpdateCollaboratorActivity updates collaborator activity timestamp
type SubscriptionFilters ¶
type SubscriptionFilters struct {
SessionIDs []string `json:"sessionIds"`
UserID string `json:"userId"`
TeamID string `json:"teamId"`
EventTypes []string `json:"eventTypes"`
}
SubscriptionFilters defines what updates a client wants to receive
type SuccessResponse ¶
type SuccessResponse struct {
Message string `json:"message"`
}
SuccessResponse represents a success response
type TeamHandler ¶
type TeamHandler struct {
// contains filtered or unexported fields
}
TeamHandler handles team-related API requests with RBAC
func NewTeamHandler ¶
func NewTeamHandler(database *db.Database) *TeamHandler
NewTeamHandler creates a new team handler
func (*TeamHandler) CheckPermission ¶
func (h *TeamHandler) CheckPermission(c *gin.Context)
CheckPermission checks if the authenticated user has a specific permission in a team
func (*TeamHandler) GetMyTeamPermissions ¶
func (h *TeamHandler) GetMyTeamPermissions(c *gin.Context)
GetMyTeamPermissions returns the authenticated user's permissions in a team
func (*TeamHandler) GetMyTeams ¶
func (h *TeamHandler) GetMyTeams(c *gin.Context)
GetMyTeams returns all teams the authenticated user is a member of
func (*TeamHandler) GetTeamPermissions ¶
func (h *TeamHandler) GetTeamPermissions(c *gin.Context)
GetTeamPermissions returns all permissions defined for team roles
func (*TeamHandler) GetTeamRoleInfo ¶
func (h *TeamHandler) GetTeamRoleInfo(c *gin.Context)
GetTeamRoleInfo returns information about available team roles
func (*TeamHandler) ListTeamSessions ¶
func (h *TeamHandler) ListTeamSessions(c *gin.Context)
ListTeamSessions returns all sessions belonging to a team
func (*TeamHandler) RegisterRoutes ¶
func (h *TeamHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers team RBAC routes
type TemplateInheritance ¶
type TemplateInheritance struct {
ChildTemplateID string `json:"child_template_id"`
ParentTemplateID string `json:"parent_template_id"`
OverriddenFields []string `json:"overridden_fields"`
InheritedFields []string `json:"inherited_fields"`
Metadata map[string]interface{} `json:"metadata"`
}
TemplateInheritance represents template inheritance/parent-child relationship
type TemplateSnapshot ¶
type TemplateSnapshot struct {
ID int `json:"id"`
TemplateID string `json:"templateId"`
VersionNumber int `json:"versionNumber"`
TemplateData map[string]interface{} `json:"templateData"`
Description string `json:"description,omitempty"`
CreatedBy string `json:"createdBy"`
CreatedAt time.Time `json:"createdAt"`
Tags []string `json:"tags,omitempty"`
}
TemplateSnapshot represents a version snapshot of a template
type TemplateTest ¶
type TemplateTest struct {
ID int64 `json:"id"`
TemplateID string `json:"template_id"`
VersionID int64 `json:"version_id"`
Version string `json:"version"`
TestType string `json:"test_type"` // "startup", "smoke", "functional", "performance"
Status string `json:"status"` // "pending", "running", "passed", "failed"
Results map[string]interface{} `json:"results"`
Duration int `json:"duration"` // in seconds
ErrorMessage string `json:"error_message,omitempty"`
StartedAt time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
}
TemplateTest represents a test for a template version
type TemplateVersion ¶
type TemplateVersion struct {
ID int64 `json:"id"`
TemplateID string `json:"template_id"`
Version string `json:"version"`
MajorVersion int `json:"major_version"`
MinorVersion int `json:"minor_version"`
PatchVersion int `json:"patch_version"`
DisplayName string `json:"display_name"`
Description string `json:"description"`
Configuration map[string]interface{} `json:"configuration"`
BaseImage string `json:"base_image"`
ParentTemplateID string `json:"parent_template_id,omitempty"`
ParentVersion string `json:"parent_version,omitempty"`
ChangeLog string `json:"changelog"`
Status string `json:"status"` // "draft", "testing", "stable", "deprecated"
IsDefault bool `json:"is_default"`
TestResults map[string]interface{} `json:"test_results,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
PublishedAt *time.Time `json:"published_at,omitempty"`
DeprecatedAt *time.Time `json:"deprecated_at,omitempty"`
}
TemplateVersion represents a version of a template
type TemplateVersioningHandler ¶
TemplateVersioningHandler handles template versioning endpoints
func NewTemplateVersioningHandler ¶
func NewTemplateVersioningHandler(database *db.Database) *TemplateVersioningHandler
NewTemplateVersioningHandler creates a new TemplateVersioningHandler instance
func (*TemplateVersioningHandler) CloneTemplateVersion ¶
func (h *TemplateVersioningHandler) CloneTemplateVersion(c *gin.Context)
CloneTemplateVersion creates a new version based on an existing one
func (*TemplateVersioningHandler) CreateTemplateTest ¶
func (h *TemplateVersioningHandler) CreateTemplateTest(c *gin.Context)
CreateTemplateTest creates a test for a template version
func (*TemplateVersioningHandler) CreateTemplateVersion ¶
func (h *TemplateVersioningHandler) CreateTemplateVersion(c *gin.Context)
CreateTemplateVersion creates a new version of a template
func (*TemplateVersioningHandler) DeprecateTemplateVersion ¶
func (h *TemplateVersioningHandler) DeprecateTemplateVersion(c *gin.Context)
DeprecateTemplateVersion marks a version as deprecated
func (*TemplateVersioningHandler) GetTemplateInheritance ¶
func (h *TemplateVersioningHandler) GetTemplateInheritance(c *gin.Context)
GetTemplateInheritance retrieves the inheritance chain for a template
func (*TemplateVersioningHandler) GetTemplateVersion ¶
func (h *TemplateVersioningHandler) GetTemplateVersion(c *gin.Context)
GetTemplateVersion retrieves a specific template version
func (*TemplateVersioningHandler) ListTemplateTests ¶
func (h *TemplateVersioningHandler) ListTemplateTests(c *gin.Context)
ListTemplateTests lists all tests for a template version
func (*TemplateVersioningHandler) ListTemplateVersions ¶
func (h *TemplateVersioningHandler) ListTemplateVersions(c *gin.Context)
ListTemplateVersions lists all versions of a template
func (*TemplateVersioningHandler) PublishTemplateVersion ¶
func (h *TemplateVersioningHandler) PublishTemplateVersion(c *gin.Context)
PublishTemplateVersion publishes a template version (draft -> stable)
func (*TemplateVersioningHandler) SetDefaultTemplateVersion ¶
func (h *TemplateVersioningHandler) SetDefaultTemplateVersion(c *gin.Context)
SetDefaultTemplateVersion sets a version as the default for a template
func (*TemplateVersioningHandler) UpdateTemplateTestStatus ¶
func (h *TemplateVersioningHandler) UpdateTemplateTestStatus(c *gin.Context)
UpdateTemplateTestStatus updates the status of a test (used by test runners)
type TransferOwnershipRequest ¶
type TransferOwnershipRequest struct {
NewOwnerUserId string `json:"newOwnerUserId" binding:"required" validate:"required,min=1,max=100"`
}
TransferOwnershipRequest represents a request to transfer session ownership
type TrustedDevice ¶
type TrustedDevice struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
DeviceID string `json:"device_id"` // Browser fingerprint
DeviceName string `json:"device_name"`
UserAgent string `json:"user_agent"`
IPAddress string `json:"ip_address"`
TrustedUntil time.Time `json:"trusted_until"`
LastSeenAt time.Time `json:"last_seen_at"`
CreatedAt time.Time `json:"created_at"`
}
TrustedDevice represents a device trusted for MFA bypass
type UpdateConfigurationRequest ¶
type UpdateConfigurationRequest struct {
Value string `json:"value" binding:"required"`
}
UpdateConfigurationRequest represents a request to update a configuration setting
type UpdateLicenseRequest ¶
type UpdateLicenseRequest struct {
LicenseKey string `json:"license_key" binding:"required"`
}
UpdateLicenseRequest represents license update request
type UpdateSessionTemplateRequest ¶
type UpdateSessionTemplateRequest struct {
Name string `json:"name" validate:"omitempty,min=3,max=100"`
Description string `json:"description" validate:"omitempty,max=1000"`
Icon string `json:"icon" validate:"omitempty,max=100"`
Category string `json:"category" validate:"omitempty,min=2,max=50"`
Tags []string `json:"tags" validate:"omitempty,dive,min=2,max=50"`
Configuration map[string]interface{} `json:"configuration"`
Resources map[string]interface{} `json:"resources"`
Environment map[string]string `json:"environment" validate:"omitempty,dive,keys,min=1,max=100,endkeys,min=0,max=10000"`
}
UpdateSessionTemplateRequest is the request body for updating a session template
type UpdateWebhookRequest ¶
type UpdateWebhookRequest struct {
Name string `json:"name" validate:"omitempty,min=1,max=200"`
Description string `json:"description" validate:"omitempty,max=1000"`
URL string `json:"url" validate:"omitempty,url,max=2048"`
Events []string `json:"events" validate:"omitempty,min=1,max=50,dive,min=3,max=100"`
Headers map[string]string `json:"headers" validate:"omitempty,max=50,dive,keys,max=100,endkeys,max=1000"`
Enabled *bool `json:"enabled"`
RetryPolicy *WebhookRetryPolicy `json:"retry_policy"`
Filters *WebhookFilters `json:"filters"`
Metadata map[string]interface{} `json:"metadata"`
}
UpdateWebhookRequest is the request body for updating a webhook
type UserHandler ¶
type UserHandler struct {
// contains filtered or unexported fields
}
UserHandler handles user-related API requests
func NewUserHandler ¶
func NewUserHandler(userDB *db.UserDB, groupDB *db.GroupDB) *UserHandler
NewUserHandler creates a new user handler
func (*UserHandler) CreateUser ¶
func (h *UserHandler) CreateUser(c *gin.Context)
CreateUser godoc @Summary Create a new user @Description Create a new user account @Tags users @Accept json @Produce json @Param user body models.CreateUserRequest true "User creation request" @Success 201 {object} models.User @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/users [post]
func (*UserHandler) DeleteAdminUserQuota ¶
func (h *UserHandler) DeleteAdminUserQuota(c *gin.Context)
DeleteAdminUserQuota godoc @Summary Delete user quota @Description Delete (reset to default) resource quota for a user (admin only) @Tags admin, quotas @Accept json @Produce json @Param username path string true "Username" @Success 200 {object} SuccessResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/quotas/{username} [delete]
func (*UserHandler) DeleteUser ¶
func (h *UserHandler) DeleteUser(c *gin.Context)
DeleteUser godoc @Summary Delete user @Description Delete a user account @Tags users @Accept json @Produce json @Param id path string true "User ID" @Success 200 {object} SuccessResponse @Failure 500 {object} ErrorResponse @Router /api/v1/users/{id} [delete]
func (*UserHandler) GetAdminUserQuota ¶
func (h *UserHandler) GetAdminUserQuota(c *gin.Context)
GetAdminUserQuota godoc @Summary Get user quota by username @Description Get resource quota for a user by username (admin only) @Tags admin, quotas @Accept json @Produce json @Param username path string true "Username" @Success 200 {object} models.UserQuota @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/quotas/{username} [get]
func (*UserHandler) GetCurrentUser ¶
func (h *UserHandler) GetCurrentUser(c *gin.Context)
GetCurrentUser godoc @Summary Get current user @Description Get information about the currently authenticated user @Tags users @Accept json @Produce json @Success 200 {object} models.User @Failure 401 {object} ErrorResponse @Router /api/v1/users/me [get]
func (*UserHandler) GetCurrentUserQuota ¶
func (h *UserHandler) GetCurrentUserQuota(c *gin.Context)
GetCurrentUserQuota godoc @Summary Get current user quota @Description Get quota information for the currently authenticated user @Tags users, quotas @Accept json @Produce json @Success 200 {object} models.UserQuota @Failure 401 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Router /api/v1/users/me/quota [get]
func (*UserHandler) GetUser ¶
func (h *UserHandler) GetUser(c *gin.Context)
GetUser godoc @Summary Get user by ID @Description Get detailed information about a specific user @Tags users @Accept json @Produce json @Param id path string true "User ID" @Success 200 {object} models.User @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/users/{id} [get]
func (*UserHandler) GetUserGroups ¶
func (h *UserHandler) GetUserGroups(c *gin.Context)
GetUserGroups godoc @Summary Get user groups @Description Get all groups a user belongs to @Tags users, groups @Accept json @Produce json @Param id path string true "User ID" @Success 200 {object} gin.H @Failure 500 {object} ErrorResponse @Router /api/v1/users/{id}/groups [get]
func (*UserHandler) GetUserQuota ¶
func (h *UserHandler) GetUserQuota(c *gin.Context)
GetUserQuota godoc @Summary Get user quota @Description Get resource quota for a user @Tags users, quotas @Accept json @Produce json @Param id path string true "User ID" @Success 200 {object} models.UserQuota @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/users/{id}/quota [get]
func (*UserHandler) GetUserSessions ¶
func (h *UserHandler) GetUserSessions(c *gin.Context)
GetUserSessions godoc @Summary Get user sessions @Description Get all sessions for a specific user @Tags users @Accept json @Produce json @Param id path string true "User ID" @Success 200 {object} gin.H @Failure 307 {object} gin.H @Router /api/v1/users/{id}/sessions [get]
func (*UserHandler) ListAllUserQuotas ¶
func (h *UserHandler) ListAllUserQuotas(c *gin.Context)
ListAllUserQuotas godoc @Summary List all user quotas @Description Get resource quotas for all users (admin only) @Tags admin, quotas @Accept json @Produce json @Success 200 {object} gin.H @Failure 500 {object} ErrorResponse @Router /api/v1/admin/quotas [get]
func (*UserHandler) ListUsers ¶
func (h *UserHandler) ListUsers(c *gin.Context)
ListUsers godoc @Summary List all users @Description Get a list of all users with optional filtering @Tags users @Accept json @Produce json @Param role query string false "Filter by role" @Param provider query string false "Filter by auth provider" @Param active query boolean false "Filter active users only" @Success 200 {array} models.User @Failure 500 {object} ErrorResponse @Router /api/v1/users [get]
func (*UserHandler) RegisterRoutes ¶
func (h *UserHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers user management routes
func (*UserHandler) SetAdminUserQuota ¶
func (h *UserHandler) SetAdminUserQuota(c *gin.Context)
SetAdminUserQuota godoc @Summary Set user quota by username @Description Set or update resource quota for a user by username (admin only) @Tags admin, quotas @Accept json @Produce json @Param quota body models.SetQuotaRequest true "Quota settings with username" @Success 200 {object} models.UserQuota @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/admin/quotas [put]
func (*UserHandler) SetUserQuota ¶
func (h *UserHandler) SetUserQuota(c *gin.Context)
SetUserQuota godoc @Summary Set user quota @Description Set or update resource quota for a user @Tags users, quotas @Accept json @Produce json @Param id path string true "User ID" @Param quota body models.SetQuotaRequest true "Quota settings" @Success 200 {object} models.UserQuota @Failure 400 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/users/{id}/quota [put]
func (*UserHandler) UpdateUser ¶
func (h *UserHandler) UpdateUser(c *gin.Context)
UpdateUser godoc @Summary Update user @Description Update user information @Tags users @Accept json @Produce json @Param id path string true "User ID" @Param user body models.UpdateUserRequest true "User update request" @Success 200 {object} models.User @Failure 400 {object} ErrorResponse @Failure 404 {object} ErrorResponse @Failure 500 {object} ErrorResponse @Router /api/v1/users/{id} [patch]
type ValidateLicenseRequest ¶
type ValidateLicenseRequest struct {
LicenseKey string `json:"license_key" binding:"required" validate:"required,min=10,max=256"`
}
ValidateLicenseRequest represents license validation request
type ValidateLicenseResponse ¶
type ValidateLicenseResponse struct {
Valid bool `json:"valid"`
Tier string `json:"tier,omitempty"`
Features map[string]interface{} `json:"features,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Message string `json:"message"`
}
ValidateLicenseResponse represents license validation result
type WebSocketClient ¶
type WebSocketClient struct {
ID string // Unique client identifier (format: "userID-unixnano")
UserID string // User ID for authorization and targeted broadcasts
Conn *websocket.Conn // Underlying WebSocket connection
Send chan WebSocketMessage // Buffered channel for outbound messages (prevents blocking)
Hub *WebSocketHub // Reference to hub for broadcasting
Mu sync.Mutex // Mutex for thread-safe client state operations
}
WebSocketClient represents a single connected WebSocket client.
Each client has: - Unique ID for tracking (format: "userID-timestamp") - UserID for authorization and targeted messaging - WebSocket connection (Conn) - Buffered send channel to prevent blocking - Reference to hub for broadcasting - Mutex for thread-safe operations (currently unused but available for future state)
The Send channel is buffered (256 messages) to handle burst traffic without blocking. If the buffer fills, the client is considered slow/disconnected and removed.
type WebSocketHandler ¶
type WebSocketHandler struct {
// contains filtered or unexported fields
}
WebSocketHandler handles WebSocket connections for real-time platform updates.
The handler implements a centralized hub pattern where all clients connect to a single hub that routes broadcast messages based on subscription filters.
Key responsibilities:
- Upgrade HTTP connections to WebSocket
- Maintain registry of active client connections
- Route broadcast messages to matching clients
- Enforce origin validation and authentication
- Handle client lifecycle (connect, disconnect, cleanup)
Concurrency:
- Hub runs in a single goroutine (actor pattern)
- Each client has two goroutines (read pump, write pump)
- Channel-based synchronization (register, unregister, broadcast)
- Thread-safe session map protected by RWMutex
Memory usage:
- Handler: ~10 KB (hub state)
- Per client: ~100 KB (goroutines + 256-message buffer)
- 1000 clients: ~100 MB total memory
Performance:
- Supports 10,000+ concurrent connections
- <10ms message latency (broadcast to delivery)
- 10,000+ messages/sec throughput
Typical usage:
wsHandler := NewWebSocketHandler(database)
wsHandler.RegisterRoutes(router.Group("/api"))
// Later, broadcast message from API handler
wsHandler.Broadcast(&BroadcastMessage{
Event: "session.created",
Data: sessionData,
})
func NewWebSocketHandler ¶
func NewWebSocketHandler(database *db.Database) *WebSocketHandler
NewWebSocketHandler creates a new WebSocket handler
func (*WebSocketHandler) AlertUpdates ¶
func (h *WebSocketHandler) AlertUpdates(c *gin.Context)
AlertUpdates handles WebSocket connections for alert updates
func (*WebSocketHandler) BroadcastAlertEvent ¶
func (h *WebSocketHandler) BroadcastAlertEvent(event string, data map[string]interface{})
BroadcastAlertEvent broadcasts an alert event
func (*WebSocketHandler) BroadcastNotificationEvent ¶
func (h *WebSocketHandler) BroadcastNotificationEvent(event string, userID string, data map[string]interface{})
BroadcastNotificationEvent broadcasts a notification event
func (*WebSocketHandler) BroadcastSessionEvent ¶
func (h *WebSocketHandler) BroadcastSessionEvent(event string, sessionID string, userID string, data map[string]interface{})
BroadcastSessionEvent broadcasts a session event to all connected clients
func (*WebSocketHandler) DisconnectUser ¶
func (h *WebSocketHandler) DisconnectUser(userID string)
DisconnectUser disconnects all WebSocket sessions for a user
func (*WebSocketHandler) GetClientsByUser ¶
func (h *WebSocketHandler) GetClientsByUser(userID string) []*WebSocketSession
GetClientsByUser returns connected clients for a specific user
func (*WebSocketHandler) GetConnectedClients ¶
func (h *WebSocketHandler) GetConnectedClients() int
GetConnectedClients returns the number of connected WebSocket clients
func (*WebSocketHandler) MetricsUpdates ¶
func (h *WebSocketHandler) MetricsUpdates(c *gin.Context)
MetricsUpdates handles WebSocket connections for metrics updates
func (*WebSocketHandler) NotificationUpdates ¶
func (h *WebSocketHandler) NotificationUpdates(c *gin.Context)
NotificationUpdates handles WebSocket connections for notification updates
func (*WebSocketHandler) RegisterRoutes ¶
func (h *WebSocketHandler) RegisterRoutes(router *gin.RouterGroup)
RegisterRoutes registers WebSocket routes
func (*WebSocketHandler) SessionUpdates ¶
func (h *WebSocketHandler) SessionUpdates(c *gin.Context)
SessionUpdates handles WebSocket connections for session updates
type WebSocketHub ¶
type WebSocketHub struct {
Clients map[string]*WebSocketClient // All connected clients (key: client ID)
Register chan *WebSocketClient // Channel for new client registrations
Unregister chan *WebSocketClient // Channel for client disconnections
Broadcast chan WebSocketMessage // Buffered channel for broadcast messages
Mu sync.RWMutex // Read-write mutex for thread-safe map access
}
WebSocketHub is the central manager for all WebSocket connections.
It uses a hub-and-spoke architecture: - Hub maintains all active clients in a map - Clients register/unregister via channels - Broadcast channel for sending to all clients - RWMutex for safe concurrent access to the clients map
Thread Safety: - Register/Unregister: Processed sequentially in Run() with write lock - Broadcast: Uses read lock for iteration, write lock for cleanup - BroadcastToUser: Uses read lock only (no modifications)
The hub runs in a single goroutine (via Run()) to avoid race conditions when modifying the clients map.
func GetWebSocketHub ¶
func GetWebSocketHub() *WebSocketHub
GetWebSocketHub returns the singleton hub instance using thread-safe lazy initialization.
This function uses sync.Once to ensure the hub is created exactly once, even if called concurrently from multiple goroutines. This is the standard Go singleton pattern.
The hub is initialized with: - Empty clients map - Unbuffered register/unregister channels (sequential processing) - Buffered broadcast channel (256 messages) to handle burst traffic - Background goroutine running hub.Run() for message processing
Thread Safety: sync.Once guarantees Run() is called exactly once
Returns:
- *WebSocketHub: The global hub instance
func (*WebSocketHub) BroadcastToAll ¶
func (h *WebSocketHub) BroadcastToAll(message WebSocketMessage)
BroadcastToAll sends a message to all connected clients (typically for admin-level events).
This function sends the message to the hub's broadcast channel, where it's processed by the Run() goroutine and distributed to all clients.
Use cases: - System-wide notifications (maintenance window, new features, etc.) - Admin-level events (node health changes, scaling events, etc.) - Platform status updates (high load warnings, service degradation, etc.)
IMPORTANT: This sends to ALL users regardless of role. For admin-only messages, the client-side code should filter based on the user's role.
Thread Safety: - Broadcast channel is buffered (256 messages) - Non-blocking as long as buffer isn't full - Safe to call concurrently from multiple goroutines
Parameters:
- message: The WebSocketMessage to broadcast to all clients
func (*WebSocketHub) BroadcastToUser ¶
func (h *WebSocketHub) BroadcastToUser(userID string, message WebSocketMessage)
BroadcastToUser sends a message to all connections belonging to a specific user.
A single user can have multiple WebSocket connections open simultaneously (e.g., multiple browser tabs, mobile app + desktop app). This function sends the message to ALL of that user's connections.
Use cases: - User-specific notifications (session started, MFA required, etc.) - Account security alerts (new login detected, password changed, etc.) - Personal updates (quota warnings, scheduled session reminders, etc.)
Thread Safety: - Uses read lock only (no map modifications) - Non-blocking send via select/default - Safe to call concurrently from multiple goroutines
Parameters:
- userID: The user ID to target (from authentication context)
- message: The WebSocketMessage to send
func (*WebSocketHub) Run ¶
func (h *WebSocketHub) Run()
Run is the main event loop for the WebSocket hub.
This function runs in a dedicated goroutine for the lifetime of the application. It processes three types of events via select statement:
1. Register: Add new client connections 2. Unregister: Remove disconnected clients 3. Broadcast: Send message to all connected clients
CRITICAL RACE CONDITION FIX: The broadcast case uses a two-phase approach to prevent race conditions:
Phase 1: Read lock - Iterate clients and collect slow/disconnected ones Phase 2: Write lock - Remove collected clients from map
This prevents: - Concurrent map read/write errors - Deadlocks from holding write lock during iteration - Message loss from blocking sends
Why not hold write lock during broadcast? - Broadcasting can be slow (network I/O) - Write lock blocks ALL reads (BroadcastToUser, Register, Unregister) - This would freeze the entire system during broadcasts
Thread Safety: - All map modifications use write lock (h.Mu.Lock) - Map iteration uses read lock (h.Mu.RLock) - Locks are held for minimum time necessary
type WebSocketMessage ¶
type WebSocketMessage struct {
Type string `json:"type"` // Message type/category for client-side routing
Timestamp time.Time `json:"timestamp"` // Server timestamp for accurate event ordering
Data map[string]interface{} `json:"data"` // Flexible payload containing event-specific data
}
WebSocketMessage represents a real-time update message sent to clients.
Type field determines the message category (e.g., "webhook.delivery", "security.alert"). Timestamp is set server-side to ensure accurate event timing. Data contains the message payload as a flexible map.
Example message:
{
"type": "security.alert",
"timestamp": "2025-11-15T10:30:00Z",
"data": {
"alert_type": "mfa_failed",
"severity": "high",
"message": "Multiple failed MFA attempts detected"
}
}
type WebSocketSession ¶
type WebSocketSession struct {
ID string
UserID string
Conn *websocket.Conn
Send chan []byte
Filters *SubscriptionFilters
// contains filtered or unexported fields
}
WebSocketSession represents a client WebSocket connection
type Webhook ¶
type Webhook struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
Secret string `json:"-"` // SECURITY: Never expose secret in API responses
Events []string `json:"events"`
Headers map[string]string `json:"headers,omitempty"`
Enabled bool `json:"enabled"`
RetryPolicy WebhookRetryPolicy `json:"retry_policy"`
Filters WebhookFilters `json:"filters,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Webhook represents a webhook configuration
type WebhookDelivery ¶
type WebhookDelivery struct {
ID int64 `json:"id"`
WebhookID int64 `json:"webhook_id"`
Event string `json:"event"`
Payload map[string]interface{} `json:"payload"`
Status string `json:"status"` // "pending", "success", "failed"
StatusCode int `json:"status_code,omitempty"`
ResponseBody string `json:"response_body,omitempty"`
ErrorMessage string `json:"error_message,omitempty"`
Attempts int `json:"attempts"`
NextRetryAt *time.Time `json:"next_retry_at,omitempty"`
DeliveredAt *time.Time `json:"delivered_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
WebhookDelivery represents a webhook delivery attempt
type WebhookEvent ¶
type WebhookEvent struct {
Event string `json:"event"`
Timestamp time.Time `json:"timestamp"`
Data map[string]interface{} `json:"data"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
WebhookEvent represents an event that can trigger webhooks
type WebhookFilters ¶
type WebhookFilters struct {
Users []string `json:"users,omitempty"`
Templates []string `json:"templates,omitempty"`
SessionStates []string `json:"session_states,omitempty"`
}
WebhookFilters allows filtering events
type WebhookRetryPolicy ¶
type WebhookRetryPolicy struct {
MaxRetries int `json:"max_retries"`
RetryDelay int `json:"retry_delay_seconds"`
BackoffMultiplier float64 `json:"backoff_multiplier"`
}
WebhookRetryPolicy defines retry behavior
type WebhookWithSecret ¶
WebhookWithSecret is used only for CreateWebhook response to show the secret once
Source Files
¶
- activity.go
- agent_websocket.go
- agents.go
- apikeys.go
- applications.go
- audit.go
- batch.go
- catalog.go
- collaboration.go
- configuration.go
- console.go
- constants.go
- dashboard.go
- docs.go
- groups.go
- integrations.go
- license.go
- loadbalancing.go
- monitoring.go
- nodes.go
- notifications.go
- plugin_marketplace.go
- plugins.go
- preferences.go
- quotas.go
- recordings.go
- scheduling.go
- search.go
- security.go
- selkies_proxy.go
- sessionactivity.go
- sessiontemplates.go
- setup.go
- sharing.go
- teams.go
- template_versioning.go
- types.go
- users.go
- websocket.go
- websocket_enterprise.go