Documentation
¶
Overview ¶
Package models defines the core data structures for the StreamSpace API.
This file contains models for the v2.0 multi-platform agent architecture:
- Agent: Platform-specific execution agents (Kubernetes, Docker, etc.)
- AgentCommand: Commands dispatched from Control Plane to Agents
These models support the Control Plane + Agent refactor where:
- Control Plane (this API) manages sessions centrally
- Agents connect via WebSocket and execute platform-specific operations
- VNC traffic is tunneled through the Control Plane
Package models defines WebSocket protocol messages for agent communication.
This file defines the message types and structures used for bidirectional communication between the Control Plane and platform-specific agents over WebSocket.
Message Flow:
Control Plane → Agent:
- command: Execute a session command (start_session, stop_session, etc.)
- ping: Keep-alive ping to check connection health
- shutdown: Request graceful agent shutdown
Agent → Control Plane:
- heartbeat: Regular status update (every 10 seconds)
- ack: Acknowledge command receipt
- complete: Report command completion with results
- failed: Report command failure with error details
- status: Report session state changes
Protocol Design:
- All messages are JSON-encoded
- Each message has a type field for routing
- Timestamps are included for tracking
- Command lifecycle: pending → sent → ack → completed/failed
Example Message (Control Plane → Agent):
{
"type": "command",
"timestamp": "2025-11-21T10:30:00Z",
"payload": {
"commandId": "cmd-abc123",
"action": "start_session",
"payload": {
"sessionId": "sess-456",
"user": "alice",
"template": "firefox-browser"
}
}
}
Example Message (Agent → Control Plane):
{
"type": "complete",
"timestamp": "2025-11-21T10:30:05Z",
"payload": {
"commandId": "cmd-abc123",
"result": {
"sessionId": "sess-456",
"vncPort": 5900,
"podName": "sess-456-abc123"
}
}
}
Package models defines the core data structures for the StreamSpace API.
This file contains models for installed applications and access control.
Features:
- Installed application representation
- Group access control models
- Request/response types for application API
Package models defines the core data structures for the StreamSpace API. This file implements Organization models for multi-tenancy support.
SECURITY: Organizations provide tenant isolation - all resources MUST be scoped to an organization to prevent cross-tenant data access.
Package models defines plugin-related data structures for the StreamSpace plugin system.
The plugin system enables extending StreamSpace with:
- Templates from external repositories
- Plugins for additional functionality
- Catalog discovery and ratings
- Automatic synchronization from Git repositories
Architecture:
- Repositories: External Git repos containing plugins and templates
- CatalogPlugin: Plugins available for installation from repositories
- InstalledPlugin: Plugins currently installed and running
- PluginManifest: Metadata and configuration schema for plugins
Example workflow:
- Add repository (streamspace-plugins GitHub repo)
- Sync repository (clone/pull from Git, parse manifests)
- Browse catalog (list available plugins with ratings)
- Install plugin (copy to installed_plugins table, enable)
- Configure plugin (set config via UI or API)
Package models defines the core data structures for the StreamSpace API.
This package contains:
- User and authentication models
- Group and team membership models
- Resource quota models
- Request/response types for API handlers
These models are used for:
- Database persistence (via sqlx struct tags)
- JSON serialization (via json struct tags)
- API request validation (via binding tags)
Database tags use the snake_case convention:
type User struct {
FullName string `json:"fullName" db:"full_name"`
}
Index ¶
- Constants
- func IsValidOrgRole(role string) bool
- type AckMessage
- type AddGroupAccessRequest
- type AddGroupMemberRequest
- type Agent
- type AgentCapacity
- type AgentCommand
- type AgentHeartbeatRequest
- type AgentMessage
- type AgentMetadata
- type AgentRegistrationRequest
- type AgentStatusUpdate
- type ApplicationGroupAccess
- type ApplicationListResponse
- type ApplicationWithGroups
- type CatalogPlugin
- type CommandMessage
- type CommandPayload
- type CompleteMessage
- type CreateGroupRequest
- type CreateOrganizationRequest
- type CreateSessionCommand
- type CreateUserRequest
- type FailedMessage
- type Group
- type GroupMembership
- type GroupQuota
- type HeartbeatMessage
- type InstallApplicationRequest
- type InstallPluginRequest
- type InstalledApplication
- type InstalledPlugin
- type LoginRequest
- type OrgRole
- type Organization
- type PingMessage
- type PluginEntrypoints
- type PluginManifest
- type PluginRating
- type PluginRequirements
- type PluginStats
- type PluginVersion
- type PongMessage
- type RatePluginRequest
- type Repository
- type SetQuotaRequest
- type ShutdownMessage
- type StatusMessage
- type UpdateApplicationRequest
- type UpdateGroupAccessRequest
- type UpdateGroupRequest
- type UpdateOrganizationRequest
- type UpdatePluginRequest
- type UpdateUserRequest
- type User
- type UserQuota
Constants ¶
const ( // MessageTypeCommand instructs agent to execute a command (start_session, stop_session, etc.) MessageTypeCommand = "command" // MessageTypePing is a keep-alive ping to verify connection health MessageTypePing = "ping" // MessageTypeShutdown requests graceful agent shutdown MessageTypeShutdown = "shutdown" )
Message types sent from Control Plane → Agent
const ( // MessageTypeHeartbeat is a regular status update from agent (every 10 seconds) MessageTypeHeartbeat = "heartbeat" // MessageTypeAck acknowledges command receipt MessageTypeAck = "ack" // MessageTypeComplete reports successful command completion MessageTypeComplete = "complete" // MessageTypeFailed reports command failure MessageTypeFailed = "failed" // MessageTypeStatus reports session state changes MessageTypeStatus = "status" )
Message types sent from Agent → Control Plane
Variables ¶
This section is empty.
Functions ¶
func IsValidOrgRole ¶
IsValidOrgRole checks if the given role is valid.
Types ¶
type AckMessage ¶
type AckMessage struct {
// CommandID identifies which command is being acknowledged
CommandID string `json:"commandId"`
}
AckMessage acknowledges command receipt.
Sent immediately when agent receives a command, before execution begins.
Example:
{
"commandId": "cmd-abc123"
}
type AddGroupAccessRequest ¶
type AddGroupAccessRequest struct {
// GroupID is the group to grant access.
GroupID string `json:"groupId" binding:"required" validate:"required,min=1,max=100"`
// AccessLevel is the permission level.
// Valid values: "view", "launch", "admin"
// Default: "launch"
AccessLevel string `json:"accessLevel" validate:"omitempty,oneof=view launch admin"`
}
AddGroupAccessRequest is the request to grant group access to an application.
type AddGroupMemberRequest ¶
type AddGroupMemberRequest struct {
UserID string `json:"userId" binding:"required" validate:"required,min=1,max=100"`
Role string `json:"role" validate:"omitempty,oneof=member admin owner"`
}
AddGroupMemberRequest represents a request to add a user to a group.
Example:
{
"userId": "user-alice",
"role": "member"
}
type Agent ¶
type Agent struct {
// ID is the auto-generated UUID for this agent (database primary key).
ID string `json:"id" db:"id"`
// AgentID is a unique identifier for this agent (user-defined).
// This is what the agent uses to identify itself when connecting.
//
// Examples: "k8s-prod-us-east-1", "docker-dev-host-1", "vm-agent-london-2"
AgentID string `json:"agentId" db:"agent_id"`
// Platform identifies the execution platform this agent manages.
//
// Valid values:
// - "kubernetes": Kubernetes cluster
// - "docker": Docker host
// - "vm": Virtual machines
// - "cloud": Cloud provider (AWS, Azure, GCP)
Platform string `json:"platform" db:"platform"`
// Region is the geographical or logical region where this agent operates.
// Used for geo-aware session placement.
//
// Examples: "us-east-1", "eu-west-1", "on-prem-dc1"
Region string `json:"region,omitempty" db:"region"`
// Status indicates the current health status of the agent.
//
// Valid values:
// - "online": Agent is connected and healthy
// - "offline": Agent is disconnected
// - "draining": Agent is not accepting new sessions
Status string `json:"status" db:"status"`
// Capacity describes the resource limits of this agent.
// Stored as JSONB in the database.
Capacity *AgentCapacity `json:"capacity,omitempty" db:"capacity"`
// LastHeartbeat is the timestamp of the last heartbeat received from this agent.
// Agents send heartbeats every 10 seconds.
LastHeartbeat *time.Time `json:"lastHeartbeat,omitempty" db:"last_heartbeat"`
// WebSocketID is the internal identifier for the active WebSocket connection.
// Used by the Control Plane to route commands to the correct connection.
// Can be nil if the agent is not currently connected.
WebSocketID *string `json:"websocketId,omitempty" db:"websocket_id"`
// Metadata contains arbitrary platform-specific or deployment-specific data.
// Stored as JSONB in the database.
Metadata *AgentMetadata `json:"metadata,omitempty" db:"metadata"`
// APIKeyHash is the bcrypt hash of the agent's API key.
// SECURITY: Never expose this field in JSON responses (json:"-")
// Used for authenticating agent registration and WebSocket connections.
APIKeyHash *string `json:"-" db:"api_key_hash"`
// APIKeyCreatedAt is when the API key was generated.
// Used for key rotation policies and security auditing.
APIKeyCreatedAt *time.Time `json:"-" db:"api_key_created_at"`
// APIKeyLastUsedAt is when the API key was last used successfully.
// Used for anomaly detection and security auditing.
APIKeyLastUsedAt *time.Time `json:"-" db:"api_key_last_used_at"`
// ApprovalStatus indicates the approval state of the agent (Issue #234).
//
// Valid values:
// - "pending": Agent awaiting administrator approval
// - "approved": Agent approved and operational
// - "rejected": Agent rejected by administrator
ApprovalStatus string `json:"approvalStatus" db:"approval_status"`
// ApprovedAt is when this agent was approved (or rejected).
ApprovedAt *time.Time `json:"approvedAt,omitempty" db:"approved_at"`
// ApprovedBy is the user ID of the administrator who approved/rejected the agent.
ApprovedBy *string `json:"approvedBy,omitempty" db:"approved_by"`
// CreatedAt is when this agent was first registered.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is when this agent record was last modified.
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
}
Agent represents a platform-specific execution agent connected to the Control Plane.
Agents are responsible for:
- Connecting to Control Plane via WebSocket (outbound connection)
- Receiving commands to start/stop/hibernate sessions
- Translating generic session specs to platform-specific resources
- Tunneling VNC traffic back to Control Plane
- Reporting session status and health
Supported platforms:
- kubernetes: Kubernetes cluster agent
- docker: Docker host agent
- vm: Virtual machine agent (future)
- cloud: Cloud provider agent (future)
Example:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"agentId": "k8s-prod-us-east-1",
"platform": "kubernetes",
"region": "us-east-1",
"status": "online",
"capacity": {
"maxSessions": 100,
"cpu": "64 cores",
"memory": "256Gi"
},
"lastHeartbeat": "2025-11-21T10:30:00Z"
}
type AgentCapacity ¶
type AgentCapacity struct {
MaxSessions int `json:"maxSessions"`
CPU string `json:"cpu"`
Memory string `json:"memory"`
Storage string `json:"storage,omitempty"`
}
AgentCapacity represents the resource capacity of an agent.
This is stored as JSONB in the database and contains information about how many sessions the agent can handle and its resource limits.
Example:
{
"maxSessions": 100,
"cpu": "64 cores",
"memory": "256Gi",
"storage": "1Ti"
}
func (*AgentCapacity) Scan ¶
func (a *AgentCapacity) Scan(value interface{}) error
Scan implements the sql.Scanner interface for AgentCapacity.
type AgentCommand ¶
type AgentCommand struct {
// ID is the auto-generated UUID for this command (database primary key).
ID string `json:"id" db:"id"`
// CommandID is a unique identifier for this command.
// Used to track the command through its lifecycle.
CommandID string `json:"commandId" db:"command_id"`
// AgentID identifies which agent should execute this command.
AgentID string `json:"agentId" db:"agent_id"`
// SessionID is the session this command affects (if applicable).
// Uses pointer type to handle NULL values for commands without sessions.
SessionID *string `json:"sessionId,omitempty" db:"session_id"`
// Action is the operation to perform.
//
// Valid values:
// - "start_session": Create a new session
// - "stop_session": Terminate a session
// - "hibernate_session": Hibernate a running session
// - "wake_session": Wake a hibernated session
Action string `json:"action" db:"action"`
// Payload contains the command-specific data (e.g., session spec for start_session).
// Stored as JSONB in the database.
Payload *CommandPayload `json:"payload,omitempty" db:"payload"`
// Status tracks the command lifecycle.
//
// Valid values:
// - "pending": Command queued, not yet sent
// - "sent": Sent to agent over WebSocket
// - "ack": Agent acknowledged receipt
// - "completed": Agent completed execution successfully
// - "failed": Agent failed to execute
Status string `json:"status" db:"status"`
// ErrorMessage contains the error details if status is "failed".
// Uses pointer type to handle NULL values for pending/successful commands.
ErrorMessage *string `json:"errorMessage,omitempty" db:"error_message"`
// CreatedAt is when this command was created in the database.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// SentAt is when this command was sent to the agent over WebSocket.
SentAt *time.Time `json:"sentAt,omitempty" db:"sent_at"`
// AcknowledgedAt is when the agent acknowledged receipt of this command.
AcknowledgedAt *time.Time `json:"acknowledgedAt,omitempty" db:"acknowledged_at"`
// CompletedAt is when the agent completed execution of this command.
CompletedAt *time.Time `json:"completedAt,omitempty" db:"completed_at"`
}
AgentCommand represents a command dispatched from the Control Plane to an Agent.
Commands are queued in the database and sent to agents over WebSocket. The lifecycle of a command is:
- Created (status: pending)
- Sent to agent over WebSocket (status: sent, sent_at timestamp)
- Agent acknowledges receipt (status: ack, acknowledged_at timestamp)
- Agent completes execution (status: completed, completed_at timestamp)
- Or agent fails (status: failed, error_message populated)
Supported actions:
- start_session: Create a new session
- stop_session: Terminate a session
- hibernate_session: Hibernate a running session
- wake_session: Wake a hibernated session
Example:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"commandId": "cmd-abc123",
"agentId": "k8s-prod-us-east-1",
"sessionId": "sess-456",
"action": "start_session",
"payload": {
"user": "alice",
"template": "firefox-browser"
},
"status": "completed",
"createdAt": "2025-11-21T10:30:00Z",
"completedAt": "2025-11-21T10:30:05Z"
}
type AgentHeartbeatRequest ¶
type AgentHeartbeatRequest struct {
Status string `json:"status" binding:"required,oneof=online draining" validate:"required,oneof=online draining"`
ActiveSessions int `json:"activeSessions" validate:"gte=0"`
Capacity *AgentCapacity `json:"capacity,omitempty"`
}
AgentHeartbeatRequest represents a heartbeat sent by an agent.
Agents send heartbeats every 10 seconds to indicate they are still alive.
Example:
{
"status": "online",
"activeSessions": 15,
"capacity": {
"maxSessions": 100,
"cpu": "64 cores",
"memory": "256Gi"
}
}
type AgentMessage ¶
type AgentMessage struct {
// Type identifies the message type (command, ping, heartbeat, ack, etc.)
Type string `json:"type"`
// Timestamp when the message was created
Timestamp time.Time `json:"timestamp"`
// Payload contains the message-specific data as raw JSON
// Parse this based on the Type field
Payload json.RawMessage `json:"payload"`
}
AgentMessage is the top-level message structure for all agent communication.
Every message sent between Control Plane and Agent follows this structure. The Type field determines how to parse the Payload.
type AgentMetadata ¶
type AgentMetadata map[string]interface{}
AgentMetadata represents arbitrary metadata about an agent.
This is stored as JSONB in the database and can contain platform-specific information, deployment details, or other custom data.
Example:
{
"version": "2.0.0",
"clusterName": "prod-us-east-1",
"kubernetesVersion": "1.28",
"nodeSelector": {"role": "streamspace"}
}
func (*AgentMetadata) Scan ¶
func (a *AgentMetadata) Scan(value interface{}) error
Scan implements the sql.Scanner interface for AgentMetadata.
type AgentRegistrationRequest ¶
type AgentRegistrationRequest struct {
AgentID string `json:"agentId" binding:"required" validate:"required,min=3,max=100"`
Platform string `json:"platform" binding:"required,oneof=kubernetes docker vm cloud" validate:"required,oneof=kubernetes docker vm cloud"`
Region string `json:"region,omitempty" validate:"omitempty,min=2,max=50"`
Capacity *AgentCapacity `json:"capacity,omitempty"`
Metadata *AgentMetadata `json:"metadata,omitempty"`
}
AgentRegistrationRequest represents the request to register a new agent.
This is sent by the agent when it first connects to the Control Plane.
Example:
{
"agentId": "k8s-prod-us-east-1",
"platform": "kubernetes",
"region": "us-east-1",
"capacity": {
"maxSessions": 100,
"cpu": "64 cores",
"memory": "256Gi"
},
"metadata": {
"kubernetesVersion": "1.28",
"nodeSelector": {"role": "streamspace"}
}
}
type AgentStatusUpdate ¶
type AgentStatusUpdate struct {
SessionID string `json:"sessionId" binding:"required"`
State string `json:"state" binding:"required"`
StreamingReady bool `json:"streamingReady"`
StreamingPort int `json:"streamingPort,omitempty"`
PlatformMetadata map[string]interface{} `json:"platformMetadata,omitempty"`
}
AgentStatusUpdate represents a status update from an agent about a session.
Sent by the agent when a session changes state.
Example:
{
"sessionId": "sess-456",
"state": "running",
"streamingReady": true,
"streamingPort": 8080,
"platformMetadata": {
"podName": "sess-456-abc123",
"nodeName": "worker-1"
}
}
type ApplicationGroupAccess ¶
type ApplicationGroupAccess struct {
// ID is a unique identifier for this access record.
ID string `json:"id" db:"id"`
// ApplicationID is the installed application.
ApplicationID string `json:"applicationId" db:"application_id"`
// GroupID is the group with access.
GroupID string `json:"groupId" db:"group_id"`
// AccessLevel is the permission level.
// Valid values: "view", "launch", "admin"
AccessLevel string `json:"accessLevel" db:"access_level"`
// CreatedAt is when access was granted.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// Group information (populated from JOIN)
GroupName string `json:"groupName,omitempty"`
GroupDisplayName string `json:"groupDisplayName,omitempty"`
}
ApplicationGroupAccess represents a group's access to an application.
Access levels:
- "view": Can see the application in the catalog
- "launch": Can launch sessions with this application
- "admin": Can modify application settings
type ApplicationListResponse ¶
type ApplicationListResponse struct {
Applications []*InstalledApplication `json:"applications"`
Total int `json:"total"`
}
ApplicationListResponse is the response for listing applications.
type ApplicationWithGroups ¶
type ApplicationWithGroups struct {
*InstalledApplication
Groups []*ApplicationGroupAccess `json:"groups"`
}
ApplicationWithGroups is an application with its group access list.
type CatalogPlugin ¶
type CatalogPlugin struct {
// ID is a unique database identifier for this catalog entry.
ID int `json:"id"`
// RepositoryID links this plugin to its source repository.
RepositoryID int `json:"repositoryId"`
// Name is the machine-readable plugin identifier (must match manifest).
// Format: lowercase, hyphens, no spaces
// Example: "streamspace-analytics-advanced", "streamspace-billing"
Name string `json:"name"`
// Version is the semantic version from the manifest.
// Format: MAJOR.MINOR.PATCH (e.g., "1.2.0", "2.0.0-beta.1")
Version string `json:"version"`
// DisplayName is the human-readable plugin name shown in UI.
DisplayName string `json:"displayName"`
// Description explains what this plugin does.
Description string `json:"description"`
// Category organizes plugins in the catalog.
// Examples: "Analytics", "Security", "Integrations", "UI Enhancements"
Category string `json:"category"`
// PluginType indicates the plugin's architecture.
// Valid values:
// - "extension": General-purpose extension (most common)
// - "webhook": Responds to webhook events
// - "api": Adds new API endpoints
// - "ui": Adds UI components or pages
// - "theme": Visual theme customization
PluginType string `json:"pluginType"`
// IconURL is the URL to the plugin's icon image.
IconURL string `json:"iconUrl"`
// Manifest contains the full plugin metadata and configuration schema.
Manifest PluginManifest `json:"manifest"`
// Tags are keywords for search and filtering.
Tags []string `json:"tags"`
// InstallCount is how many times this plugin has been installed.
InstallCount int `json:"installCount"`
// AvgRating is the average user rating (1-5 stars).
AvgRating float64 `json:"avgRating"`
// RatingCount is the number of ratings submitted.
RatingCount int `json:"ratingCount"`
// Repository contains the source repository information.
// Embedded via JOIN query for convenience.
Repository Repository `json:"repository"`
// CreatedAt is when this plugin first appeared in the catalog.
CreatedAt time.Time `json:"createdAt"`
// UpdatedAt is when the plugin manifest or metadata was last updated.
UpdatedAt time.Time `json:"updatedAt"`
}
CatalogPlugin represents a plugin available for installation from a repository.
Catalog plugins are:
- Discovered during repository sync
- Parsed from plugin.json manifest files
- Indexed with ratings and install statistics
- Searchable by name, tags, category
Lifecycle:
- Repository sync discovers new plugins
- Manifests are parsed and validated
- Plugins appear in catalog API/UI
- Users can browse, rate, and install
Example:
{
"id": 42,
"name": "streamspace-analytics-advanced",
"displayName": "Advanced Analytics",
"description": "Comprehensive analytics and reporting for sessions",
"category": "Analytics",
"pluginType": "api",
"version": "1.2.0",
"installCount": 127,
"avgRating": 4.5,
"tags": ["analytics", "reporting", "metrics"]
}
type CommandMessage ¶
type CommandMessage struct {
// CommandID uniquely identifies this command
CommandID string `json:"commandId"`
// Action specifies the operation to perform
Action string `json:"action"`
// Payload contains action-specific data
Payload map[string]interface{} `json:"payload"`
}
CommandMessage is sent from Control Plane to Agent to execute a command.
The Action field determines what operation to perform:
- start_session: Create a new session
- stop_session: Terminate a session
- hibernate_session: Hibernate a running session
- wake_session: Wake a hibernated session
Example:
{
"commandId": "cmd-abc123",
"action": "start_session",
"payload": {
"sessionId": "sess-456",
"user": "alice",
"template": "firefox-browser",
"resources": {"memory": "2Gi", "cpu": "1000m"}
}
}
type CommandPayload ¶
type CommandPayload map[string]interface{}
CommandPayload represents the payload of a command sent to an agent.
This is stored as JSONB and contains the session spec or other command data.
Example (start_session):
{
"sessionId": "sess-123",
"user": "alice",
"template": "firefox-browser",
"resources": {
"memory": "2Gi",
"cpu": "1000m"
}
}
func (*CommandPayload) Scan ¶
func (c *CommandPayload) Scan(value interface{}) error
Scan implements the sql.Scanner interface for CommandPayload.
type CompleteMessage ¶
type CompleteMessage struct {
// CommandID identifies which command completed
CommandID string `json:"commandId"`
// Result contains command-specific result data (optional)
Result map[string]interface{} `json:"result,omitempty"`
}
CompleteMessage reports successful command completion.
Sent when agent successfully completes a command.
Example:
{
"commandId": "cmd-abc123",
"result": {
"sessionId": "sess-456",
"vncPort": 5900,
"podName": "sess-456-abc123"
}
}
type CreateGroupRequest ¶
type CreateGroupRequest struct {
Name string `json:"name" binding:"required" validate:"required,min=3,max=50,lowercase,alphanum|contains=-"`
DisplayName string `json:"displayName" binding:"required" validate:"required,min=3,max=100"`
Description string `json:"description" validate:"omitempty,max=500"`
Type string `json:"type" binding:"required" validate:"required,oneof=team department project"`
ParentID *string `json:"parentId,omitempty" validate:"omitempty,uuid"`
}
CreateGroupRequest represents a request to create a new group.
Validation rules:
- Name: required, lowercase, alphanumeric + hyphens
- DisplayName: required
- Type: required (team, department, project)
- ParentID: optional (for hierarchical groups)
Example:
{
"name": "engineering",
"displayName": "Engineering Department",
"description": "Software engineering team",
"type": "department",
"parentID": null
}
type CreateOrganizationRequest ¶
type CreateOrganizationRequest struct {
Name string `json:"name" binding:"required" validate:"required,min=3,max=50,lowercase,alphanum|contains=-"`
DisplayName string `json:"displayName" binding:"required" validate:"required,min=3,max=100"`
Description string `json:"description" validate:"omitempty,max=500"`
K8sNamespace string `json:"k8sNamespace" validate:"omitempty,min=3,max=63,lowercase"`
}
CreateOrganizationRequest represents a request to create a new organization.
Validation rules:
- Name: required, lowercase, alphanumeric + hyphens
- DisplayName: required
Example:
{
"name": "acme",
"displayName": "ACME Corporation",
"description": "ACME Corp StreamSpace tenant"
}
type CreateSessionCommand ¶
type CreateSessionCommand struct {
SessionID string `json:"sessionId"`
User string `json:"user"`
Template string `json:"template"`
Resources map[string]string `json:"resources,omitempty"`
PersistentHome bool `json:"persistentHome"`
Environment map[string]string `json:"environment,omitempty"`
}
CreateSessionCommand represents the payload for a "start_session" command.
This is sent from the Control Plane to an agent to create a new session.
Example:
{
"sessionId": "sess-456",
"user": "alice",
"template": "firefox-browser",
"resources": {
"memory": "2Gi",
"cpu": "1000m"
},
"persistentHome": true
}
type CreateUserRequest ¶
type CreateUserRequest struct {
Username string `json:"username" binding:"required" validate:"required,username"`
Email string `json:"email" binding:"required,email" validate:"required,email"`
FullName string `json:"fullName" binding:"required" validate:"required,min=1,max=200"`
Password string `json:"password" validate:"omitempty,password"` // Required for local auth, validated in handler
Role string `json:"role" validate:"omitempty,oneof=user admin operator"` // user, admin, operator
Provider string `json:"provider" validate:"omitempty,oneof=local saml oidc"` // local, saml, oidc
}
CreateUserRequest represents a request to create a new user.
Validation rules:
- Username: required, 3-32 chars, alphanumeric + hyphens/underscores
- Email: required, valid email format
- FullName: required
- Password: required for local auth, min 8 chars
- Role: optional, defaults to "user"
- Provider: optional, defaults to "local"
Example:
{
"username": "alice",
"email": "alice@example.com",
"fullName": "Alice Smith",
"password": "securepassword123",
"role": "user",
"provider": "local"
}
type FailedMessage ¶
type FailedMessage struct {
// CommandID identifies which command failed
CommandID string `json:"commandId"`
// Error describes why the command failed
Error string `json:"error"`
}
FailedMessage reports command failure.
Sent when agent fails to execute a command.
Example:
{
"commandId": "cmd-abc123",
"error": "Failed to create pod: insufficient resources"
}
type Group ¶
type Group struct {
// ID is a unique identifier for this group.
// Format: "grp-{name}" or UUID
ID string `json:"id" db:"id"`
// Name is a unique machine-readable identifier.
// Requirements: lowercase, alphanumeric, hyphens only
// Example: "engineering", "sales-west", "research-ai"
Name string `json:"name" db:"name"`
// DisplayName is the human-readable group name.
// Example: "Engineering Department", "West Coast Sales"
DisplayName string `json:"displayName" db:"display_name"`
// Description explains the purpose or scope of this group.
Description string `json:"description" db:"description"`
// Type categorizes the group's organizational level.
//
// Valid types:
// - "team": Small working group
// - "department": Organizational department
// - "project": Project-based team
//
// Default: "team"
Type string `json:"type" db:"type"`
// ParentID creates a hierarchical structure.
// Example: "sales-west" could be a child of "sales"
// Nil for top-level groups.
ParentID *string `json:"parentId,omitempty" db:"parent_id"`
// CreatedAt is when this group was created.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is when this group was last modified.
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
// MemberCount is the number of users in this group.
// Computed from the group_memberships table.
MemberCount int `json:"memberCount" db:"member_count"`
// Quota contains resource limits shared across all group members.
// When set, individual users' quotas are aggregated against this limit.
Quota *GroupQuota `json:"quota,omitempty"`
}
Group represents a user group/team for organizing users and applying shared quotas.
Groups enable:
- Team-based organization
- Shared resource quotas
- Hierarchical structures (departments → teams → projects)
- Bulk permission management
Example use cases:
- Engineering department with multiple project teams
- Sales team with regional sub-teams
- Research groups with shared compute quotas
Example:
{
"id": "grp-engineering",
"name": "engineering",
"displayName": "Engineering Department",
"description": "Software engineering team",
"type": "department",
"memberCount": 25,
"quota": {
"maxSessions": 100,
"maxCpu": "100000m",
"maxMemory": "200Gi"
}
}
type GroupMembership ¶
type GroupMembership struct {
// ID is a unique identifier for this membership.
ID string `json:"id" db:"id"`
// UserID is the ID of the user who belongs to the group.
UserID string `json:"userId" db:"user_id"`
// GroupID is the ID of the group the user belongs to.
GroupID string `json:"groupId" db:"group_id"`
// Role defines the user's permissions within the group.
//
// Valid roles:
// - "member": Standard group member (no special permissions)
// - "admin": Can add/remove members, modify group settings
// - "owner": Full control including delete group
//
// Default: "member"
Role string `json:"role" db:"role"`
// CreatedAt is when this membership was created (when user joined the group).
CreatedAt time.Time `json:"createdAt" db:"created_at"`
}
GroupMembership represents a user's membership in a group.
Each membership defines:
- Which user belongs to which group
- The user's role within that group
- When the membership was created
Example:
{
"id": "mem-123",
"userId": "user-alice",
"groupId": "grp-engineering",
"role": "member",
"createdAt": "2025-01-01T00:00:00Z"
}
type GroupQuota ¶
type GroupQuota struct {
// GroupID links this quota to a specific group.
GroupID string `json:"groupId" db:"group_id"`
// MaxSessions is the total sessions allowed across all group members.
MaxSessions int `json:"maxSessions" db:"max_sessions"`
// MaxCPU is the total CPU allocation for the entire group.
MaxCPU string `json:"maxCpu" db:"max_cpu"`
// MaxMemory is the total memory allocation for the entire group.
MaxMemory string `json:"maxMemory" db:"max_memory"`
// MaxStorage is the total storage allocation for the entire group.
MaxStorage string `json:"maxStorage" db:"max_storage"`
// UsedSessions is the sum of all members' active sessions.
UsedSessions int `json:"usedSessions" db:"used_sessions"`
// UsedCPU is the sum of all members' CPU allocations.
UsedCPU string `json:"usedCpu" db:"used_cpu"`
// UsedMemory is the sum of all members' memory allocations.
UsedMemory string `json:"usedMemory" db:"used_memory"`
// UsedStorage is the sum of all members' storage usage.
UsedStorage string `json:"usedStorage" db:"used_storage"`
// CreatedAt is when this quota was first set.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is when this quota was last modified.
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
}
GroupQuota represents shared resource quotas for a group.
Group quotas work differently from user quotas:
- Limits apply to the sum of all members' usage
- Prevents one group from consuming all platform resources
- Can be combined with individual user quotas (most restrictive wins)
Example scenario:
- Engineering group has quota: 100 sessions, 200Gi RAM
- Individual users each have quota: 10 sessions, 16Gi RAM
- When group reaches 100 total sessions, no member can create more
- Even if individual user only has 5 sessions
Example:
{
"groupId": "grp-engineering",
"maxSessions": 100,
"maxCpu": "100000m", // 100 CPU cores shared
"maxMemory": "200Gi", // 200 GiB shared
"usedSessions": 45,
"usedCpu": "42000m",
"usedMemory": "87Gi"
}
type HeartbeatMessage ¶
type HeartbeatMessage struct {
// Status is the current agent status (online, draining)
Status string `json:"status"`
// ActiveSessions is the number of sessions currently running on this agent
ActiveSessions int `json:"activeSessions"`
// Capacity describes the agent's resource limits (optional)
Capacity *AgentCapacity `json:"capacity,omitempty"`
}
HeartbeatMessage is sent from Agent to Control Plane every 10 seconds.
Heartbeats keep the connection alive and provide status updates.
Example:
{
"status": "online",
"activeSessions": 15,
"capacity": {
"maxSessions": 100,
"cpu": "64 cores",
"memory": "256Gi"
}
}
type InstallApplicationRequest ¶
type InstallApplicationRequest struct {
// CatalogTemplateID is the source template to install from.
CatalogTemplateID int `json:"catalogTemplateId" binding:"required" validate:"required,gt=0"`
// DisplayName is the custom name for this installation (optional).
// If not provided, uses the template's default display name.
DisplayName string `json:"displayName" validate:"omitempty,min=1,max=200"`
// Platform specifies which platform to install on (optional).
// Valid values: kubernetes, docker, hyperv, vcenter
// If not provided, defaults to the template's platform or 'kubernetes'.
Platform string `json:"platform" validate:"omitempty,oneof=kubernetes docker hyperv vcenter"`
// Configuration is the initial application settings (optional).
Configuration map[string]interface{} `json:"configuration"`
// GroupIDs is the list of groups to grant access (optional).
// If not provided, no groups will have access initially.
GroupIDs []string `json:"groupIds" validate:"omitempty,dive,min=1,max=100"`
}
InstallApplicationRequest is the request to install a new application.
type InstallPluginRequest ¶
type InstallPluginRequest struct {
PluginID int `json:"pluginId" validate:"required,gt=0"` // From catalog
Config json.RawMessage `json:"config,omitempty"`
}
InstallPluginRequest represents a request to install a plugin
type InstalledApplication ¶
type InstalledApplication struct {
// ID is a unique identifier for this installed application (UUID v4).
ID string `json:"id" db:"id"`
// CatalogTemplateID is the ID of the source catalog template.
CatalogTemplateID int `json:"catalogTemplateId" db:"catalog_template_id"`
// Name is the internal name with GUID suffix for uniqueness.
// Example: "firefox-abc12345"
Name string `json:"name" db:"name"`
// DisplayName is the custom name shown on user dashboards.
// Can be changed by admins to customize the user experience.
// Example: "Firefox Browser", "Development Firefox"
DisplayName string `json:"displayName" db:"display_name"`
// FolderPath is the path to the application configuration folder.
// Example: "apps/firefox-abc12345"
FolderPath string `json:"folderPath" db:"folder_path"`
// Enabled indicates whether the application is active.
// Disabled applications are not shown to users.
Enabled bool `json:"enabled" db:"enabled"`
// Configuration contains application-specific settings as JSONB.
// Schema depends on the template's configurable options.
Configuration map[string]interface{} `json:"configuration,omitempty"`
// CreatedBy is the user ID who installed the application.
CreatedBy string `json:"createdBy" db:"created_by"`
// CreatedAt is when the application was installed.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is when the application was last modified.
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
// Template information (stored in installed_applications for persistence)
TemplateName string `json:"templateName,omitempty"`
TemplateDisplayName string `json:"templateDisplayName,omitempty"`
Description string `json:"description,omitempty" db:"description"`
Category string `json:"category,omitempty" db:"category"`
AppType string `json:"appType,omitempty"`
IconURL string `json:"icon,omitempty" db:"icon_url"`
IconData []byte `json:"-" db:"icon_data"` // Binary icon data (not sent in JSON)
IconMediaType string `json:"-" db:"icon_media_type"` // MIME type of icon
Manifest string `json:"manifest,omitempty" db:"manifest"`
// InstallStatus tracks the installation state (pending, creating, installed, failed)
InstallStatus string `json:"installStatus,omitempty" db:"install_status"`
// InstallMessage provides additional context about the installation status
InstallMessage string `json:"installMessage,omitempty" db:"install_message"`
// Groups with access to this application (populated separately)
Groups []*ApplicationGroupAccess `json:"groups,omitempty"`
}
InstalledApplication represents an installed application instance.
Applications are installed from catalog templates and can be:
- Customized with display names
- Configured with application-specific settings
- Enabled/disabled
- Granted to specific groups
Example:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"catalogTemplateId": 1,
"name": "firefox-abc12345",
"displayName": "Firefox Browser",
"folderPath": "apps/firefox-abc12345",
"enabled": true,
"configuration": {"homepage": "https://example.com"}
}
type InstalledPlugin ¶
type InstalledPlugin struct {
// ID is a unique database identifier for this installation.
ID int `json:"id"`
// CatalogPluginID links to the catalog entry this was installed from.
// Nil for manually installed plugins (uploaded directly).
CatalogPluginID *int `json:"catalogPluginId,omitempty"`
// Name is the plugin identifier (must match manifest).
Name string `json:"name"`
// Version is the installed version.
Version string `json:"version"`
// Enabled determines whether this plugin is currently running.
// When false:
// - Plugin code is not loaded
// - API endpoints are not registered
// - Webhooks are not processed
// - Can be re-enabled without reinstalling
Enabled bool `json:"enabled"`
// Config is the JSON configuration for this plugin.
// Schema is defined in the plugin's manifest (configSchema field).
Config json.RawMessage `json:"config,omitempty"`
// InstalledBy is the username who installed this plugin.
InstalledBy string `json:"installedBy"`
// InstalledAt is when this plugin was first installed.
InstalledAt time.Time `json:"installedAt"`
// UpdatedAt is when configuration or version was last changed.
UpdatedAt time.Time `json:"updatedAt"`
// DisplayName is the human-readable plugin name.
DisplayName string `json:"displayName,omitempty"`
// Description explains what this plugin does.
Description string `json:"description,omitempty"`
// PluginType indicates the plugin architecture.
PluginType string `json:"pluginType,omitempty"`
// IconURL is the plugin's icon image.
IconURL string `json:"iconUrl,omitempty"`
// Manifest contains the full plugin metadata.
Manifest *PluginManifest `json:"manifest,omitempty"`
}
InstalledPlugin represents a plugin that is currently installed and potentially running.
Installation process:
- User selects plugin from catalog
- Plugin files are copied/downloaded
- Default configuration is applied
- Plugin is enabled (starts running)
Installed plugins can be:
- Enabled/disabled without uninstalling
- Configured via JSON config
- Updated to newer versions
- Uninstalled (removes from this table)
Example:
{
"id": 7,
"catalogPluginId": 42,
"name": "streamspace-analytics-advanced",
"version": "1.2.0",
"enabled": true,
"config": {"retentionDays": 90, "exportFormat": "json"},
"installedBy": "admin",
"installedAt": "2025-01-01T00:00:00Z"
}
type LoginRequest ¶
type LoginRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
LoginRequest represents a user login request.
type OrgRole ¶
type OrgRole string
OrgRole defines the user's role within an organization. This is separate from the system-wide role (admin/operator/user).
const ( // OrgRoleAdmin can manage users/roles, templates, org settings, webhooks. // Full access within the organization. OrgRoleAdmin OrgRole = "org_admin" // OrgRoleMaintainer can manage templates, start/stop/hibernate sessions. // No user/role administration. OrgRoleMaintainer OrgRole = "maintainer" // OrgRoleUser can manage own sessions and list org templates. // Standard user access. OrgRoleUser OrgRole = "user" // OrgRoleViewer has read-only access to lists/metrics. // No session lifecycle permissions. OrgRoleViewer OrgRole = "viewer" )
func ValidOrgRoles ¶
func ValidOrgRoles() []OrgRole
ValidOrgRoles returns all valid organization roles.
type Organization ¶
type Organization struct {
// ID is a unique identifier for this organization (UUID or slug).
// Format: "org-{name}" or UUID
ID string `json:"id" db:"id"`
// Name is a unique machine-readable identifier.
// Requirements: lowercase, alphanumeric, hyphens only
// Example: "acme", "engineering-team", "research-lab"
Name string `json:"name" db:"name"`
// DisplayName is the human-readable organization name.
// Example: "ACME Corporation", "Engineering Team"
DisplayName string `json:"displayName" db:"display_name"`
// Description explains the purpose of this organization.
Description string `json:"description" db:"description"`
// K8sNamespace is the Kubernetes namespace for this org's resources.
// Sessions and pods are created in this namespace.
// Default: "streamspace" (single-tenant) or "streamspace-{orgName}" (multi-tenant)
K8sNamespace string `json:"k8sNamespace" db:"k8s_namespace"`
// Status indicates the organization's state.
//
// Valid statuses:
// - "active": Normal operation
// - "suspended": Temporarily disabled (billing, policy)
// - "deleted": Soft-deleted, pending cleanup
//
// Default: "active"
Status string `json:"status" db:"status"`
// CreatedAt is when this organization was created.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is when this organization was last modified.
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
}
Organization represents a tenant in StreamSpace.
Organizations enable multi-tenancy by providing:
- Isolation: All resources are scoped to an org_id
- Namespace mapping: Each org maps to a K8s namespace
- RBAC: Org-level roles (OrgAdmin, Maintainer, User, Viewer)
- Quotas: Org-wide resource limits
SECURITY: All API handlers MUST filter queries by org_id from the authenticated user's JWT claims to prevent cross-tenant access.
Example:
{
"id": "org-acme",
"name": "acme",
"displayName": "ACME Corporation",
"description": "ACME Corp StreamSpace tenant",
"k8sNamespace": "streamspace-acme",
"status": "active"
}
type PingMessage ¶
type PingMessage struct {
// Timestamp when the ping was sent
Timestamp time.Time `json:"timestamp"`
}
PingMessage is a keep-alive ping from Control Plane to Agent.
Example:
{
"timestamp": "2025-11-21T10:30:00Z"
}
type PluginEntrypoints ¶
type PluginEntrypoints struct {
Main string `json:"main,omitempty"` // Main entry point
UI string `json:"ui,omitempty"` // UI component entry point
API string `json:"api,omitempty"` // API routes entry point
Webhook string `json:"webhook,omitempty"` // Webhook handler
CLI string `json:"cli,omitempty"` // CLI command entry point
}
PluginEntrypoints defines plugin entry points
type PluginManifest ¶
type PluginManifest struct {
// Name is the unique plugin identifier (lowercase, hyphens).
Name string `json:"name"`
// Version is the semantic version (MAJOR.MINOR.PATCH).
Version string `json:"version"`
// DisplayName is the human-readable plugin name.
DisplayName string `json:"displayName"`
// Description explains the plugin's purpose and features.
Description string `json:"description"`
// Author is the plugin developer/organization.
Author string `json:"author"`
// Homepage is a URL to the plugin's website or documentation.
Homepage string `json:"homepage,omitempty"`
// Repository is the source code repository URL.
Repository string `json:"repository,omitempty"`
// License is the SPDX license identifier (e.g., "MIT", "Apache-2.0").
License string `json:"license,omitempty"`
// Type is the plugin architecture type.
// Valid values: "extension", "webhook", "api", "ui", "theme"
Type string `json:"type"`
// Category organizes plugins in the catalog.
Category string `json:"category,omitempty"`
// Tags are keywords for search and filtering.
Tags []string `json:"tags,omitempty"`
// Icon is a relative path to the icon file in the plugin directory.
Icon string `json:"icon,omitempty"`
// Requirements specifies platform version and dependency requirements.
Requirements PluginRequirements `json:"requirements,omitempty"`
// Entrypoints define where to load plugin code.
Entrypoints PluginEntrypoints `json:"entrypoints,omitempty"`
// ConfigSchema is a JSON Schema defining valid configuration.
// Used to generate UI forms and validate config on save.
ConfigSchema map[string]interface{} `json:"configSchema,omitempty"`
// DefaultConfig provides default values for configuration.
DefaultConfig map[string]interface{} `json:"defaultConfig,omitempty"`
// Permissions lists required API permissions.
// Examples: "sessions:read", "sessions:write", "analytics:write"
Permissions []string `json:"permissions,omitempty"`
// Dependencies lists other required plugins with version constraints.
// Format: {"plugin-name": ">=1.0.0", "other-plugin": "^2.0.0"}
Dependencies map[string]string `json:"dependencies,omitempty"`
}
PluginManifest contains complete metadata and configuration schema for a plugin.
The manifest defines:
- Basic metadata (name, version, author, license)
- System requirements and dependencies
- Configuration schema (what settings the plugin accepts)
- Entry points (where to load plugin code)
- Required permissions
Manifest files are:
- Located at {plugin-dir}/plugin.json in repositories
- Validated during sync
- Stored in database as JSONB
- Used to generate UI forms for configuration
Example manifest:
{
"name": "streamspace-analytics-advanced",
"version": "1.2.0",
"displayName": "Advanced Analytics",
"description": "Comprehensive analytics and reporting",
"author": "StreamSpace Team",
"license": "MIT",
"type": "api",
"category": "Analytics",
"configSchema": {
"retentionDays": {"type": "number", "default": 90},
"exportFormat": {"type": "string", "enum": ["json", "csv"]}
},
"permissions": ["sessions:read", "analytics:write"]
}
func (*PluginManifest) Scan ¶
func (m *PluginManifest) Scan(value interface{}) error
Scan implements sql.Scanner for PluginManifest
type PluginRating ¶
type PluginRating struct {
ID int `json:"id"`
PluginID int `json:"pluginId"`
UserID string `json:"userId"`
Rating int `json:"rating"` // 1-5
Review string `json:"review,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
PluginRating represents a user's rating for a plugin
type PluginRequirements ¶
type PluginRequirements struct {
StreamSpaceVersion string `json:"streamspaceVersion,omitempty"` // e.g., ">=0.2.0"
MinimumVersion string `json:"minimumVersion,omitempty"`
MaximumVersion string `json:"maximumVersion,omitempty"`
Plugins []string `json:"plugins,omitempty"` // Required plugins
}
PluginRequirements specifies plugin requirements
type PluginStats ¶
type PluginStats struct {
PluginID int `json:"pluginId"`
ViewCount int `json:"viewCount"`
InstallCount int `json:"installCount"`
LastViewedAt *time.Time `json:"lastViewedAt,omitempty"`
LastInstalledAt *time.Time `json:"lastInstalledAt,omitempty"`
UpdatedAt time.Time `json:"updatedAt"`
}
PluginStats represents usage statistics for a plugin
type PluginVersion ¶
type PluginVersion struct {
ID int `json:"id"`
PluginID int `json:"pluginId"`
Version string `json:"version"`
Changelog string `json:"changelog,omitempty"`
Manifest PluginManifest `json:"manifest"`
CreatedAt time.Time `json:"createdAt"`
}
PluginVersion represents a version of a plugin
type PongMessage ¶
type PongMessage struct {
// Timestamp when the pong was sent
Timestamp time.Time `json:"timestamp"`
}
PongMessage is the agent's response to a ping.
Example:
{
"timestamp": "2025-11-21T10:30:00Z"
}
type RatePluginRequest ¶
type RatePluginRequest struct {
Rating int `json:"rating" validate:"required,min=1,max=5"` // 1-5
Review string `json:"review,omitempty" validate:"omitempty,max=2000"`
}
RatePluginRequest represents a request to rate a plugin
type Repository ¶
type Repository struct {
// ID is a unique database identifier for this repository.
ID int `json:"id"`
// Name is a human-readable name for this repository.
// Example: "Official Plugins", "Community Templates", "Enterprise Add-ons"
Name string `json:"name"`
// URL is the Git repository URL or HTTP endpoint.
// Supported formats:
// - HTTPS Git: https://github.com/user/repo
// - SSH Git: git@github.com:user/repo.git
// - HTTP archive: https://example.com/plugins.zip (future)
URL string `json:"url"`
// Type indicates the repository source type.
// Valid values:
// - "git": Git repository (GitHub, GitLab, Bitbucket, etc.)
// - "http": HTTP archive download (future)
//
// Default: "git"
Type string `json:"type"`
// Description provides information about this repository's contents.
Description string `json:"description,omitempty"`
// Enabled determines whether this repository should be synced.
// When false:
// - Repository is not synced during scheduled sync
// - Plugins from this repo remain installed but won't update
// - Can be re-enabled without losing configuration
Enabled bool `json:"enabled"`
// CreatedAt is when this repository was added.
CreatedAt time.Time `json:"createdAt"`
// UpdatedAt is when repository metadata was last modified (not last sync).
UpdatedAt time.Time `json:"updatedAt"`
}
Repository represents an external Git repository containing plugins or templates.
Repositories are:
- Added by platform administrators
- Synchronized periodically (default: every 1 hour)
- Can be enabled/disabled without deletion
- Support authentication for private repos
Example repositories:
- https://github.com/JoshuaAFerguson/streamspace-plugins (official plugins)
- https://github.com/JoshuaAFerguson/streamspace-templates (official templates)
Example:
{
"id": 1,
"name": "Official Plugins",
"url": "https://github.com/JoshuaAFerguson/streamspace-plugins",
"type": "git",
"description": "Official StreamSpace plugin repository",
"enabled": true
}
type SetQuotaRequest ¶
type SetQuotaRequest struct {
Username string `json:"username,omitempty"` // For admin endpoints only
MaxSessions *int `json:"maxSessions,omitempty"`
MaxCPU *string `json:"maxCpu,omitempty"`
MaxMemory *string `json:"maxMemory,omitempty"`
MaxStorage *string `json:"maxStorage,omitempty"`
}
SetQuotaRequest represents a request to set or update user/group quotas.
All fields are optional (pointer types) - only provided fields are updated.
Example (set max sessions and memory):
{
"maxSessions": 10,
"maxMemory": "16Gi"
}
type ShutdownMessage ¶
type ShutdownMessage struct {
// Reason for the shutdown request
Reason string `json:"reason,omitempty"`
}
ShutdownMessage requests graceful agent shutdown.
Example:
{
"reason": "maintenance"
}
type StatusMessage ¶
type StatusMessage struct {
// SessionID identifies which session this update is for
SessionID string `json:"sessionId"`
// State is the session state (pending, running, hibernated, terminated)
State string `json:"state"`
// StreamingReady indicates if the Selkies streaming endpoint is ready.
StreamingReady bool `json:"streamingReady"`
// StreamingPort is the streaming endpoint's port on the session pod
// (typically 8080 for Selkies-GStreamer).
StreamingPort int `json:"streamingPort,omitempty"`
// PlatformMetadata contains platform-specific information
PlatformMetadata map[string]interface{} `json:"platformMetadata,omitempty"`
}
StatusMessage reports session state changes.
Sent when a session changes state on the agent.
Example:
{
"sessionId": "sess-456",
"state": "running",
"streamingReady": true,
"streamingPort": 8080,
"platformMetadata": {
"podName": "sess-456-abc123",
"nodeName": "worker-1"
}
}
type UpdateApplicationRequest ¶
type UpdateApplicationRequest struct {
// DisplayName updates the custom display name.
DisplayName *string `json:"displayName,omitempty" validate:"omitempty,min=1,max=200"`
// Enabled updates the active status.
Enabled *bool `json:"enabled,omitempty"`
// Configuration updates the application settings.
Configuration map[string]interface{} `json:"configuration,omitempty"`
}
UpdateApplicationRequest is the request to update an installed application.
type UpdateGroupAccessRequest ¶
type UpdateGroupAccessRequest struct {
// AccessLevel is the new permission level.
// Valid values: "view", "launch", "admin"
AccessLevel string `json:"accessLevel" binding:"required" validate:"required,oneof=view launch admin"`
}
UpdateGroupAccessRequest is the request to update a group's access level.
type UpdateGroupRequest ¶
type UpdateGroupRequest struct {
DisplayName *string `json:"displayName,omitempty" validate:"omitempty,min=3,max=100"`
Description *string `json:"description,omitempty" validate:"omitempty,max=500"`
Type *string `json:"type,omitempty" validate:"omitempty,oneof=team department project"`
}
UpdateGroupRequest represents a request to update an existing group.
All fields are optional (pointer types) - only provided fields are updated.
type UpdateOrganizationRequest ¶
type UpdateOrganizationRequest struct {
DisplayName *string `json:"displayName,omitempty" validate:"omitempty,min=3,max=100"`
Description *string `json:"description,omitempty" validate:"omitempty,max=500"`
K8sNamespace *string `json:"k8sNamespace,omitempty" validate:"omitempty,min=3,max=63,lowercase"`
Status *string `json:"status,omitempty" validate:"omitempty,oneof=active suspended deleted"`
}
UpdateOrganizationRequest represents a request to update an organization.
All fields are optional (pointer types) - only provided fields are updated.
type UpdatePluginRequest ¶
type UpdatePluginRequest struct {
Enabled *bool `json:"enabled,omitempty"`
Config json.RawMessage `json:"config,omitempty"`
}
UpdatePluginRequest represents a request to update a plugin
type UpdateUserRequest ¶
type UpdateUserRequest struct {
Email *string `json:"email,omitempty" validate:"omitempty,email"`
FullName *string `json:"fullName,omitempty" validate:"omitempty,min=1,max=200"`
Role *string `json:"role,omitempty" validate:"omitempty,oneof=user admin operator"`
Active *bool `json:"active,omitempty"`
}
UpdateUserRequest represents a request to update an existing user.
All fields are optional (pointer types) - only provided fields are updated.
Example (update email and role):
{
"email": "newemail@example.com",
"role": "admin"
}
type User ¶
type User struct {
// ID is a unique identifier for this user (UUID v4).
// Generated automatically when the user is created.
ID string `json:"id" db:"id"`
// OrgID is the organization this user belongs to.
// SECURITY: This field is critical for multi-tenancy isolation.
// All queries MUST filter by org_id to prevent cross-tenant access.
OrgID string `json:"orgId" db:"org_id"`
// Username is a unique identifier used for authentication and display.
// Requirements:
// - Must be unique across all users
// - 3-32 characters
// - Alphanumeric, hyphens, underscores only
//
// Example: "alice", "bob-smith", "user_123"
Username string `json:"username" db:"username"`
// Email is the user's email address.
// Requirements:
// - Must be a valid email format
// - Must be unique across all users
// - Used for notifications and password resets
//
// Example: "alice@example.com"
Email string `json:"email" db:"email"`
// FullName is the user's display name (can include spaces).
// Example: "Alice Smith", "Bob Jones"
FullName string `json:"fullName" db:"full_name"`
// Role defines the user's system-wide permission level.
//
// Valid roles:
// - "user": Standard user (can manage own sessions)
// - "operator": Platform operator (can view all sessions, manage quotas)
// - "admin": Administrator (full platform access)
//
// Default: "user"
Role string `json:"role" db:"role"`
// OrgRole defines the user's role within their organization.
//
// Valid org roles:
// - "org_admin": Manage users/roles, templates, org settings
// - "maintainer": Manage templates, sessions (no user admin)
// - "user": Manage own sessions, list org templates
// - "viewer": Read-only access to lists/metrics
//
// Default: "user"
OrgRole string `json:"orgRole,omitempty" db:"org_role"`
// Provider indicates how this user authenticates.
//
// Valid providers:
// - "local": Username + password authentication
// - "saml": SAML 2.0 SSO (Authentik, Keycloak, Okta, etc.)
// - "oidc": OIDC OAuth2 (Google, GitHub, Azure AD, etc.)
//
// Default: "local"
Provider string `json:"provider" db:"provider"`
// Active indicates whether the user account is enabled.
//
// When false:
// - User cannot log in
// - Existing sessions are terminated
// - API keys are deactivated
//
// Used for account suspension or deactivation.
Active bool `json:"active" db:"active"`
// CreatedAt is the timestamp when this user was created.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is the timestamp of the last user update.
// Updated on any change to user fields (except lastLogin).
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
// LastLogin is the timestamp of the user's most recent authentication.
// Nil if the user has never logged in.
LastLogin *time.Time `json:"lastLogin,omitempty" db:"last_login"`
// PasswordHash stores the bcrypt hash of the user's password.
// Only used for local authentication (provider="local").
//
// Security:
// - Never exposed in JSON responses (json:"-")
// - Stored using bcrypt with cost factor 10
// - Minimum password length enforced at 8 characters
PasswordHash string `json:"-" db:"password_hash"`
// Quota contains the user's resource limits and current usage.
// Populated from the user_quotas table via a JOIN query.
// Nil if no quota has been explicitly set (platform defaults apply).
Quota *UserQuota `json:"quota,omitempty"`
// Groups is a list of group IDs this user belongs to.
// Populated from the group_memberships table.
// Used for team-based resource quotas and access control.
Groups []string `json:"groups,omitempty"`
}
User represents a StreamSpace user with authentication and quota information.
Users can be created via:
- Local authentication (username + password)
- SAML 2.0 SSO (external identity providers)
- OIDC OAuth2 (Google, GitHub, etc.)
Each user has:
- A unique ID (UUID)
- An organization membership (org_id for multi-tenancy)
- Authentication credentials (provider-specific)
- Resource quotas (sessions, CPU, memory, storage)
- Group memberships (for team-based access control)
SECURITY: All API handlers MUST filter queries by org_id from the authenticated user's JWT claims to prevent cross-tenant data access.
Example:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"orgId": "org-acme",
"username": "alice",
"email": "alice@example.com",
"fullName": "Alice Smith",
"role": "user",
"orgRole": "user",
"provider": "local",
"active": true,
"quota": {
"maxSessions": 5,
"maxCpu": "4000m",
"maxMemory": "8Gi",
"usedSessions": 2
}
}
type UserQuota ¶
type UserQuota struct {
// UserID links this quota to a specific user.
UserID string `json:"userId" db:"user_id"`
// Username is included for convenience in API responses.
Username string `json:"username" db:"username"`
// MaxSessions is the maximum number of concurrent sessions allowed.
// Default: 5 (free tier), unlimited for admins
MaxSessions int `json:"maxSessions" db:"max_sessions"`
// MaxCPU is the total CPU allocation across all sessions.
// Format: Kubernetes quantity (e.g., "4000m" = 4 cores)
// Default: "4000m"
MaxCPU string `json:"maxCpu" db:"max_cpu"`
// MaxMemory is the total memory allocation across all sessions.
// Format: Kubernetes quantity (e.g., "8Gi" = 8 gibibytes)
// Default: "8Gi"
MaxMemory string `json:"maxMemory" db:"max_memory"`
// MaxStorage is the persistent storage size for the user's home directory.
// Format: Kubernetes quantity (e.g., "50Gi")
// Default: "50Gi"
MaxStorage string `json:"maxStorage" db:"max_storage"`
// UsedSessions is the current number of active (non-hibernated) sessions.
// Computed from the sessions table.
UsedSessions int `json:"usedSessions" db:"used_sessions"`
// UsedCPU is the total CPU currently allocated to active sessions.
// Computed from Kubernetes pod resource requests.
UsedCPU string `json:"usedCpu" db:"used_cpu"`
// UsedMemory is the total memory currently allocated to active sessions.
// Computed from Kubernetes pod resource requests.
UsedMemory string `json:"usedMemory" db:"used_memory"`
// UsedStorage is the actual storage consumed in the user's PVC.
// Computed from Kubernetes PVC usage metrics.
UsedStorage string `json:"usedStorage" db:"used_storage"`
// CreatedAt is when this quota was first set.
CreatedAt time.Time `json:"createdAt" db:"created_at"`
// UpdatedAt is when this quota was last modified.
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
}
UserQuota represents resource quotas and current usage for a user.
Quotas enforce limits on:
- Maximum concurrent sessions
- Total CPU allocation across all sessions
- Total memory allocation across all sessions
- Persistent storage size
Quotas can be set:
- Per-user (user_quotas table)
- Per-group (group_quotas table)
- Platform-wide defaults (in code)
The most restrictive quota applies when a user belongs to multiple groups.
Example:
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"maxSessions": 5,
"maxCpu": "4000m", // 4 CPU cores total
"maxMemory": "8Gi", // 8 GiB total
"maxStorage": "50Gi", // 50 GiB persistent storage
"usedSessions": 2,
"usedCpu": "1500m",
"usedMemory": "3Gi"
}