models

package
v0.0.0-...-e5d423c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: MIT Imports: 3 Imported by: 0

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:

  1. Add repository (streamspace-plugins GitHub repo)
  2. Sync repository (clone/pull from Git, parse manifests)
  3. Browse catalog (list available plugins with ratings)
  4. Install plugin (copy to installed_plugins table, enable)
  5. 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

View Source
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

View Source
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

func IsValidOrgRole(role string) bool

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.

func (AgentCapacity) Value

func (a AgentCapacity) Value() (driver.Value, error)

Value implements the driver.Valuer 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:

  1. Created (status: pending)
  2. Sent to agent over WebSocket (status: sent, sent_at timestamp)
  3. Agent acknowledges receipt (status: ack, acknowledged_at timestamp)
  4. Agent completes execution (status: completed, completed_at timestamp)
  5. 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.

func (AgentMetadata) Value

func (a AgentMetadata) Value() (driver.Value, error)

Value implements the driver.Valuer 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:

  1. Repository sync discovers new plugins
  2. Manifests are parsed and validated
  3. Plugins appear in catalog API/UI
  4. 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.

func (CommandPayload) Value

func (c CommandPayload) Value() (driver.Value, error)

Value implements the driver.Valuer 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:

  1. User selects plugin from catalog
  2. Plugin files are copied/downloaded
  3. Default configuration is applied
  4. 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

func (PluginManifest) Value

func (m PluginManifest) Value() (driver.Value, error)

Value implements driver.Valuer 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:

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"
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL