Documentation
¶
Overview ¶
Package agent defines the Agent domain entity for scanner/collector/agent management.
Package agent defines domain errors for agent-related operations.
Index ¶
- Variables
- func CollectorScopes() []string
- func DefaultAgentScopes() []string
- func IsAgentNotFound(err error) bool
- func IsAllPlatformAgentsOverloaded(err error) bool
- func IsAuthTokenError(err error) bool
- func IsBootstrapTokenError(err error) bool
- func IsNoPlatformAgentAvailable(err error) bool
- func IsPlatformAgentNotFound(err error) bool
- func IsPlatformLimitReached(err error) bool
- func RunnerScopes() []string
- func SensorScopes() []string
- func WorkerScopes() []string
- type APIKey
- func (k *APIKey) HasAnyScope(scopes ...APIKeyScope) bool
- func (k *APIKey) HasScope(scope APIKeyScope) bool
- func (k *APIKey) IsExpired() bool
- func (k *APIKey) IsValid() bool
- func (k *APIKey) RecordUsage(ip string)
- func (k *APIKey) Revoke(reason string)
- func (k *APIKey) SetExpiration(expiresAt time.Time)
- func (k *APIKey) SetKeyHash(hash, prefix string)
- type APIKeyFilter
- type APIKeyRepository
- type APIKeyScope
- type Agent
- func (a *Agent) Activate()
- func (a *Agent) AvailableSlots() int
- func (a *Agent) CanExecutePlatformJob(capabilities []string, tool, preferredRegion string) bool
- func (a *Agent) ComputeLoadScore() float64
- func (a *Agent) ComputeLoadScoreWithWeights(weights LoadBalancingWeights) float64
- func (a *Agent) Disable(reason string)
- func (a *Agent) HasCapability(cap string) bool
- func (a *Agent) HasCapacity() bool
- func (a *Agent) HasTool(tool string) bool
- func (a *Agent) IncrementFindings(count int64)
- func (a *Agent) IncrementScans()
- func (a *Agent) IsAvailable() bool
- func (a *Agent) IsDaemon() bool
- func (a *Agent) IsOneShot() bool
- func (a *Agent) LoadFactor() float64
- func (a *Agent) MatchesRequirements(capabilities []string, tool string) bool
- func (a *Agent) RecordError(message string)
- func (a *Agent) Revoke(reason string)
- func (a *Agent) ScoreForJob(capabilities []string, tool, preferredRegion string) int
- func (a *Agent) SetAPIKey(hash, prefix string)
- func (a *Agent) SetMaxConcurrentJobs(max int)
- func (a *Agent) SetPlatformAgent(isPlatform bool)
- func (a *Agent) SetStatus(status AgentStatus, message string)
- func (a *Agent) UpdateExtendedMetrics(metrics ExtendedMetrics)
- func (a *Agent) UpdateLastSeen()
- func (a *Agent) UpdateMetrics(cpuPercent, memoryPercent float64, activeJobs int, region string)
- func (a *Agent) UpdateRuntimeInfo(version, hostname string, ip net.IP)
- type AgentHealth
- type AgentStatus
- type AgentType
- type Capability
- type ExecutionMode
- type ExtendedMetrics
- type Filter
- type LoadBalancingWeights
- type RegistrationToken
- func (t *RegistrationToken) CanRegister() error
- func (t *RegistrationToken) Deactivate()
- func (t *RegistrationToken) IncrementUsage()
- func (t *RegistrationToken) IsExhausted() bool
- func (t *RegistrationToken) IsExpired() bool
- func (t *RegistrationToken) IsValid() bool
- func (t *RegistrationToken) SetCreatedBy(userID shared.ID)
- func (t *RegistrationToken) SetDefaults(scopes, capabilities, tools []string, labels map[string]any)
- func (t *RegistrationToken) SetTokenHash(hash, prefix string)
- type RegistrationTokenFilter
- type RegistrationTokenRepository
- type Repository
Constants ¶
This section is empty.
Variables ¶
var ( // ErrAgentNotFound is returned when an agent is not found. ErrAgentNotFound = fmt.Errorf("%w: agent not found", shared.ErrNotFound) // ErrAgentAlreadyExists is returned when an agent with the same name exists. ErrAgentAlreadyExists = fmt.Errorf("%w: agent already exists", shared.ErrAlreadyExists) // ErrAgentDisabled is returned when trying to use a disabled agent. ErrAgentDisabled = fmt.Errorf("%w: agent is disabled", shared.ErrForbidden) // ErrAgentRevoked is returned when trying to use a revoked agent. ErrAgentRevoked = fmt.Errorf("%w: agent access has been revoked", shared.ErrForbidden) // ErrAgentLimitReached is returned when the agent limit for a tenant is reached. ErrAgentLimitReached = fmt.Errorf("%w: agent limit reached for this plan", shared.ErrForbidden) // ErrAgentNoCapacity is returned when an agent has no capacity for more jobs. ErrAgentNoCapacity = fmt.Errorf("%w: agent has no capacity for more jobs", shared.ErrConflict) // ErrInvalidAPIKey is returned when an API key is invalid. ErrInvalidAPIKey = fmt.Errorf("%w: invalid API key", shared.ErrUnauthorized) )
var ( // ErrPlatformAgentNotFound is returned when a platform agent is not found. ErrPlatformAgentNotFound = fmt.Errorf("%w: platform agent not found", shared.ErrNotFound) // ErrNoPlatformAgentAvailable is returned when no platform agent is available. ErrNoPlatformAgentAvailable = fmt.Errorf("%w: no platform agent available", shared.ErrConflict) // ErrAllPlatformAgentsOverloaded is returned when agents exist but all are at capacity. ErrAllPlatformAgentsOverloaded = fmt.Errorf("%w: all platform agents are at capacity", shared.ErrConflict) // ErrPlatformAgentAccessDenied is returned when tenant doesn't have platform agent access. ErrPlatformAgentAccessDenied = fmt.Errorf("%w: platform agent access not included in plan", shared.ErrForbidden) // ErrPlatformConcurrentLimitReached is returned when concurrent platform job limit is reached. ErrPlatformConcurrentLimitReached = fmt.Errorf("%w: concurrent platform job limit reached", shared.ErrConflict) // ErrPlatformQueueLimitReached is returned when queue limit is reached. ErrPlatformQueueLimitReached = fmt.Errorf("%w: platform job queue limit reached", shared.ErrConflict) // ErrPlatformJobNotFound is returned when a platform job is not found. ErrPlatformJobNotFound = fmt.Errorf("%w: platform job not found", shared.ErrNotFound) // ErrInvalidAuthToken is returned when the command auth token is invalid. ErrInvalidAuthToken = fmt.Errorf("%w: invalid command auth token", shared.ErrUnauthorized) // ErrAuthTokenExpired is returned when the command auth token has expired. ErrAuthTokenExpired = fmt.Errorf("%w: command auth token has expired", shared.ErrUnauthorized) // ErrAgentMismatch is returned when agent ID doesn't match the command's assigned agent. ErrAgentMismatch = fmt.Errorf("%w: agent not authorized for this command", shared.ErrForbidden) )
var ( // ErrBootstrapTokenNotFound is returned when a bootstrap token is not found. ErrBootstrapTokenNotFound = fmt.Errorf("%w: bootstrap token not found", shared.ErrNotFound) // ErrBootstrapTokenExpired is returned when a bootstrap token has expired. ErrBootstrapTokenExpired = fmt.Errorf("%w: bootstrap token has expired", shared.ErrForbidden) // ErrBootstrapTokenRevoked is returned when a bootstrap token has been revoked. ErrBootstrapTokenRevoked = fmt.Errorf("%w: bootstrap token has been revoked", shared.ErrForbidden) // ErrBootstrapTokenExhausted is returned when a bootstrap token has reached its usage limit. ErrBootstrapTokenExhausted = fmt.Errorf("%w: bootstrap token usage limit reached", shared.ErrForbidden) // ErrBootstrapTokenInvalid is returned when a bootstrap token is invalid. ErrBootstrapTokenInvalid = fmt.Errorf("%w: invalid bootstrap token", shared.ErrUnauthorized) // ErrAgentConstraintViolation is returned when agent doesn't meet token constraints. ErrAgentConstraintViolation = fmt.Errorf("%w: agent does not meet token constraints", shared.ErrValidation) )
Functions ¶
func CollectorScopes ¶
func CollectorScopes() []string
CollectorScopes returns scopes for a collector.
func DefaultAgentScopes ¶
func DefaultAgentScopes() []string
DefaultAgentScopes returns default scopes for an agent.
func IsAgentNotFound ¶
IsAgentNotFound checks if the error is an agent not found error.
func IsAllPlatformAgentsOverloaded ¶
IsAllPlatformAgentsOverloaded checks if all platform agents are at capacity.
func IsAuthTokenError ¶
IsAuthTokenError checks if the error is an auth token error.
func IsBootstrapTokenError ¶
IsBootstrapTokenError checks if the error is a bootstrap token error.
func IsNoPlatformAgentAvailable ¶
IsNoPlatformAgentAvailable checks if the error indicates no platform agent is available.
func IsPlatformAgentNotFound ¶
IsPlatformAgentNotFound checks if the error is a platform agent not found error.
func IsPlatformLimitReached ¶
IsPlatformLimitReached checks if the error is a platform limit error.
Types ¶
type APIKey ¶
type APIKey struct {
ID shared.ID
AgentID shared.ID
Name string
KeyHash string
KeyPrefix string
Scopes []string
// Lifecycle
ExpiresAt *time.Time
LastUsedAt *time.Time
LastUsedIP string
UseCount int64
// Status
IsActive bool
RevokedAt *time.Time
RevokedReason string
// Timestamps
CreatedAt time.Time
}
APIKey represents an API key for an agent.
func (*APIKey) HasAnyScope ¶
func (k *APIKey) HasAnyScope(scopes ...APIKeyScope) bool
HasAnyScope checks if the key has any of the specified scopes.
func (*APIKey) HasScope ¶
func (k *APIKey) HasScope(scope APIKeyScope) bool
HasScope checks if the key has a specific scope.
func (*APIKey) RecordUsage ¶
RecordUsage records a usage of the API key.
func (*APIKey) SetExpiration ¶
SetExpiration sets the expiration time.
func (*APIKey) SetKeyHash ¶
SetKeyHash sets the key hash and prefix.
type APIKeyFilter ¶
APIKeyFilter represents filter options for listing API keys.
type APIKeyRepository ¶
type APIKeyRepository interface {
// Create creates a new API key.
Create(ctx context.Context, key *APIKey) error
// GetByID retrieves an API key by ID.
GetByID(ctx context.Context, id shared.ID) (*APIKey, error)
// GetByHash retrieves an API key by hash.
GetByHash(ctx context.Context, hash string) (*APIKey, error)
// GetByAgentID retrieves all API keys for an agent.
GetByAgentID(ctx context.Context, agentID shared.ID) ([]*APIKey, error)
// List lists API keys with filters.
List(ctx context.Context, filter APIKeyFilter) ([]*APIKey, error)
// Update updates an API key.
Update(ctx context.Context, key *APIKey) error
// Delete deletes an API key.
Delete(ctx context.Context, id shared.ID) error
// RecordUsage records API key usage.
RecordUsage(ctx context.Context, id shared.ID, ip string) error
// Revoke revokes an API key.
Revoke(ctx context.Context, id shared.ID, reason string) error
// CountActiveByAgentID counts active keys for an agent.
CountActiveByAgentID(ctx context.Context, agentID shared.ID) (int, error)
}
APIKeyRepository defines the interface for API key persistence.
type APIKeyScope ¶
type APIKeyScope string
APIKeyScope represents a permission scope for API keys.
const ( ScopeIngestWrite APIKeyScope = "ingest:write" // Push findings and assets ScopeIngestRead APIKeyScope = "ingest:read" // Read ingested data ScopeCommandsRead APIKeyScope = "commands:read" // Poll for pending commands ScopeCommandsExec APIKeyScope = "commands:execute" // Execute commands and report results ScopeCommandsWrite APIKeyScope = "commands:write" // Create commands (admin only) ScopeAgentHeartbeat APIKeyScope = "agent:heartbeat" // Send heartbeat/status updates ScopeAgentRead APIKeyScope = "agent:read" // Read own agent config ScopeAgentWrite APIKeyScope = "agent:write" // Update own agent config ScopeAdminAgents APIKeyScope = "admin:agents" // Manage other agents ScopeAdminKeys APIKeyScope = "admin:keys" // Manage API keys ScopeAdminTokens APIKeyScope = "admin:tokens" // Manage registration tokens )
type Agent ¶
type Agent struct {
ID shared.ID
TenantID *shared.ID // nil for platform agents (is_platform_agent = true)
Name string
Type AgentType
Description string
Capabilities []string
Tools []string // Specific tools: semgrep, trivy, nuclei, nmap, etc.
ExecutionMode ExecutionMode
Status AgentStatus // Admin-controlled: active, disabled, revoked
Health AgentHealth // Automatic heartbeat: unknown, online, offline, error
StatusMessage string
// Platform agent flag (SaaS model)
// Platform agents are managed by OpenCTEM and don't count towards tenant's agent limit.
// Tenants can use platform agents for their scans without provisioning their own.
IsPlatformAgent bool
// API key for authentication
APIKeyHash string
APIKeyPrefix string
// Metadata and configuration
Labels map[string]interface{}
Config map[string]interface{}
Metadata map[string]interface{}
// Runtime info
Version string
Hostname string
IPAddress net.IP
// System metrics (from heartbeat)
CPUPercent float64
MemoryPercent float64
DiskReadMBPS float64 // Disk read throughput in MB/s
DiskWriteMBPS float64 // Disk write throughput in MB/s
NetworkRxMBPS float64 // Network receive throughput in MB/s
NetworkTxMBPS float64 // Network transmit throughput in MB/s
LoadScore float64 // Computed weighted load score (lower is better)
MetricsUpdatedAt *time.Time
ActiveJobs int
CurrentJobs int
MaxConcurrentJobs int
Region string
// Statistics
LastSeenAt *time.Time // Last heartbeat timestamp - effectively "last online time"
LastOfflineAt *time.Time // When agent went offline (heartbeat timeout)
LastErrorAt *time.Time
TotalFindings int64
TotalScans int64
ErrorCount int64
// Timestamps
CreatedAt time.Time
UpdatedAt time.Time
}
Agent represents a registered agent (runner, worker, collector, or sensor).
func NewAgent ¶
func NewAgent( tenantID shared.ID, name string, agentType AgentType, description string, capabilities []string, tools []string, executionMode ExecutionMode, ) (*Agent, error)
NewAgent creates a new tenant-owned Agent entity.
func (*Agent) AvailableSlots ¶
AvailableSlots returns the number of available job slots.
func (*Agent) CanExecutePlatformJob ¶
CanExecutePlatformJob checks if this platform agent can execute a job with the given requirements.
func (*Agent) ComputeLoadScore ¶
ComputeLoadScore calculates the weighted load score for agent selection. Lower score = better candidate for receiving new jobs. Formula: score = (w1 * job_load) + (w2 * cpu) + (w3 * memory) + (w4 * io_score) + (w5 * net_score)
func (*Agent) ComputeLoadScoreWithWeights ¶
func (a *Agent) ComputeLoadScoreWithWeights(weights LoadBalancingWeights) float64
ComputeLoadScoreWithWeights calculates load score with custom weights.
func (*Agent) HasCapability ¶
HasCapability checks if the agent has a specific capability.
func (*Agent) HasCapacity ¶
HasCapacity checks if the agent has capacity for more jobs.
func (*Agent) IncrementFindings ¶
IncrementFindings increments the total findings counter.
func (*Agent) IncrementScans ¶
func (a *Agent) IncrementScans()
IncrementScans increments the total scans counter.
func (*Agent) IsAvailable ¶
IsAvailable checks if the agent is available for work.
func (*Agent) LoadFactor ¶
LoadFactor returns the current load factor (0.0 to 1.0).
func (*Agent) MatchesRequirements ¶
MatchesRequirements checks if the agent matches the given requirements.
func (*Agent) RecordError ¶
RecordError records an error and updates error timestamp.
func (*Agent) ScoreForJob ¶
ScoreForJob calculates a score for job matching (higher is better). Used for selecting the best platform agent for a job.
func (*Agent) SetMaxConcurrentJobs ¶
SetMaxConcurrentJobs sets the maximum number of concurrent jobs.
func (*Agent) SetPlatformAgent ¶
SetPlatformAgent marks this agent as a platform-managed agent. Platform agents don't count towards tenant's agent limit.
func (*Agent) SetStatus ¶
func (a *Agent) SetStatus(status AgentStatus, message string)
SetStatus sets the agent status.
func (*Agent) UpdateExtendedMetrics ¶
func (a *Agent) UpdateExtendedMetrics(metrics ExtendedMetrics)
UpdateExtendedMetrics updates all system metrics from heartbeat including disk I/O and network.
func (*Agent) UpdateLastSeen ¶
func (a *Agent) UpdateLastSeen()
UpdateLastSeen updates the last seen timestamp and sets health to online.
func (*Agent) UpdateMetrics ¶
UpdateMetrics updates system metrics from heartbeat.
type AgentHealth ¶
type AgentHealth string
AgentHealth represents the AUTOMATIC health state based on heartbeat. This is for monitoring only, does NOT affect authentication.
const ( AgentHealthUnknown AgentHealth = "unknown" // Never seen (just registered) AgentHealthOnline AgentHealth = "online" // Recently sent heartbeat AgentHealthOffline AgentHealth = "offline" // No recent heartbeat AgentHealthError AgentHealth = "error" // Last operation had errors )
func (AgentHealth) IsValid ¶
func (h AgentHealth) IsValid() bool
IsValid checks if the agent health is valid.
type AgentStatus ¶
type AgentStatus string
AgentStatus represents the ADMIN-CONTROLLED status of an agent. This determines whether the agent is ALLOWED to authenticate.
const ( AgentStatusActive AgentStatus = "active" // Agent is enabled (can authenticate) AgentStatusDisabled AgentStatus = "disabled" // Admin disabled (cannot authenticate) AgentStatusRevoked AgentStatus = "revoked" // Access permanently revoked )
func (AgentStatus) CanAuthenticate ¶
func (s AgentStatus) CanAuthenticate() bool
CanAuthenticate checks if the status allows authentication.
func (AgentStatus) IsValid ¶
func (s AgentStatus) IsValid() bool
IsValid checks if the agent status is valid.
type AgentType ¶
type AgentType string
AgentType represents the type of agent. The platform supports 4 main component types:
- runner: CI/CD one-shot scans (execution_mode: standalone)
- worker: Server-controlled daemon (execution_mode: daemon)
- collector: Data collection agent (execution_mode: daemon)
- sensor: External Attack Surface Monitoring (EASM)
func (AgentType) DefaultExecutionMode ¶
func (t AgentType) DefaultExecutionMode() ExecutionMode
DefaultExecutionMode returns the default execution mode for this agent type.
func (AgentType) IsCollector ¶
IsCollector checks if this is a collector type.
type Capability ¶
type Capability string
Capability represents an agent's capability.
const ( CapabilitySAST Capability = "sast" // Static Application Security Testing CapabilitySCA Capability = "sca" // Software Composition Analysis CapabilitySecrets Capability = "secrets" // Secret Detection CapabilityIAC Capability = "iac" // Infrastructure as Code CapabilityDAST Capability = "dast" // Dynamic Application Security Testing CapabilityInfra Capability = "infra" // Infrastructure Scanning CapabilityContainer Capability = "container" // Container Scanning CapabilityWeb3 Capability = "web3" // Web3/Blockchain Security CapabilityCollector Capability = "collector" // Data Collection CapabilityAPI Capability = "api" // API Security Testing )
type ExecutionMode ¶
type ExecutionMode string
ExecutionMode represents how the agent executes tasks.
const ( ExecutionModeStandalone ExecutionMode = "standalone" // Triggered externally (CI/CD, cron, webhook) ExecutionModeDaemon ExecutionMode = "daemon" // Long-running, polls for commands )
func (ExecutionMode) IsValid ¶
func (m ExecutionMode) IsValid() bool
IsValid checks if the execution mode is valid.
type ExtendedMetrics ¶
type ExtendedMetrics struct {
CPUPercent float64 `json:"cpu_percent"`
MemoryPercent float64 `json:"memory_percent"`
DiskReadMBPS float64 `json:"disk_read_mbps"`
DiskWriteMBPS float64 `json:"disk_write_mbps"`
NetworkRxMBPS float64 `json:"network_rx_mbps"`
NetworkTxMBPS float64 `json:"network_tx_mbps"`
ActiveJobs int `json:"active_jobs"`
Region string `json:"region,omitempty"`
}
ExtendedMetrics represents all system metrics for load balancing.
type Filter ¶
type Filter struct {
TenantID *shared.ID
Type *AgentType
Status *AgentStatus // Admin-controlled: active, disabled, revoked
Health *AgentHealth // Automatic: unknown, online, offline, error
ExecutionMode *ExecutionMode
Capabilities []string
Tools []string
Labels map[string]string
Search string
HasCapacity *bool // Filter by agents that have job capacity
}
Filter represents filter options for listing agents.
type LoadBalancingWeights ¶
type LoadBalancingWeights struct {
JobLoad float64 // Weight for job load factor (default: 0.30)
CPU float64 // Weight for CPU usage (default: 0.40)
Memory float64 // Weight for memory usage (default: 0.15)
DiskIO float64 // Weight for disk I/O (default: 0.10)
Network float64 // Weight for network I/O (default: 0.05)
}
LoadBalancingWeights defines the weights for load score computation. These weights can be configured via environment variables.
func DefaultLoadBalancingWeights ¶
func DefaultLoadBalancingWeights() LoadBalancingWeights
DefaultLoadBalancingWeights returns the default weights for load score computation.
type RegistrationToken ¶
type RegistrationToken struct {
ID shared.ID
TenantID shared.ID
Name string
// Token identification
TokenHash string
TokenPrefix string
// Pre-configuration for registered agents
AgentType AgentType
AgentNamePrefix string
DefaultScopes []string
DefaultCapabilities []string
DefaultTools []string
DefaultLabels map[string]any
// Usage limits
MaxUses *int // nil = unlimited
UsesCount int
// Lifecycle
ExpiresAt *time.Time
IsActive bool
// Audit
CreatedBy *shared.ID
CreatedAt time.Time
}
RegistrationToken represents a token for agent auto-registration.
func NewRegistrationToken ¶
func NewRegistrationToken( tenantID shared.ID, name string, agentType AgentType, maxUses *int, expiresAt *time.Time, ) (*RegistrationToken, error)
NewRegistrationToken creates a new registration token.
func (*RegistrationToken) CanRegister ¶
func (t *RegistrationToken) CanRegister() error
CanRegister checks if the token can be used and returns an error if not.
func (*RegistrationToken) Deactivate ¶
func (t *RegistrationToken) Deactivate()
Deactivate deactivates the token.
func (*RegistrationToken) IncrementUsage ¶
func (t *RegistrationToken) IncrementUsage()
IncrementUsage increments the usage counter.
func (*RegistrationToken) IsExhausted ¶
func (t *RegistrationToken) IsExhausted() bool
IsExhausted checks if the token has reached its usage limit.
func (*RegistrationToken) IsExpired ¶
func (t *RegistrationToken) IsExpired() bool
IsExpired checks if the token is expired.
func (*RegistrationToken) IsValid ¶
func (t *RegistrationToken) IsValid() bool
IsValid checks if the token can be used for registration.
func (*RegistrationToken) SetCreatedBy ¶
func (t *RegistrationToken) SetCreatedBy(userID shared.ID)
SetCreatedBy sets the user who created the token.
func (*RegistrationToken) SetDefaults ¶
func (t *RegistrationToken) SetDefaults(scopes, capabilities, tools []string, labels map[string]any)
SetDefaults sets default configuration for registered agents.
func (*RegistrationToken) SetTokenHash ¶
func (t *RegistrationToken) SetTokenHash(hash, prefix string)
SetTokenHash sets the token hash and prefix.
type RegistrationTokenFilter ¶
RegistrationTokenFilter represents filter options for listing tokens.
type RegistrationTokenRepository ¶
type RegistrationTokenRepository interface {
// Create creates a new registration token.
Create(ctx context.Context, token *RegistrationToken) error
// GetByID retrieves a token by ID.
GetByID(ctx context.Context, id shared.ID) (*RegistrationToken, error)
// GetByTenantAndID retrieves a token by tenant and ID.
GetByTenantAndID(ctx context.Context, tenantID, id shared.ID) (*RegistrationToken, error)
// GetByHash retrieves a token by hash.
GetByHash(ctx context.Context, hash string) (*RegistrationToken, error)
// List lists tokens with filters and pagination.
List(ctx context.Context, filter RegistrationTokenFilter, page pagination.Pagination) (pagination.Result[*RegistrationToken], error)
// Update updates a token.
Update(ctx context.Context, token *RegistrationToken) error
// Delete deletes a token.
Delete(ctx context.Context, id shared.ID) error
// IncrementUsage increments the usage counter.
IncrementUsage(ctx context.Context, id shared.ID) error
// Deactivate deactivates a token.
Deactivate(ctx context.Context, id shared.ID) error
}
RegistrationTokenRepository defines the interface for registration token persistence.
type Repository ¶
type Repository interface {
// Create creates a new agent.
Create(ctx context.Context, agent *Agent) error
// CountByTenant counts the number of agents for a tenant.
// Used for enforcing agent limits per plan.
CountByTenant(ctx context.Context, tenantID shared.ID) (int, error)
// GetByID retrieves an agent by ID.
GetByID(ctx context.Context, id shared.ID) (*Agent, error)
// GetByTenantAndID retrieves an agent by tenant and ID.
GetByTenantAndID(ctx context.Context, tenantID, id shared.ID) (*Agent, error)
// GetByAPIKeyHash retrieves an agent by API key hash.
GetByAPIKeyHash(ctx context.Context, hash string) (*Agent, error)
// List lists agents with filters and pagination.
List(ctx context.Context, filter Filter, page pagination.Pagination) (pagination.Result[*Agent], error)
// Update updates an agent.
Update(ctx context.Context, agent *Agent) error
// Delete deletes an agent.
Delete(ctx context.Context, id shared.ID) error
// UpdateLastSeen updates the last seen timestamp for an agent.
UpdateLastSeen(ctx context.Context, id shared.ID) error
// IncrementStats increments agent statistics.
IncrementStats(ctx context.Context, id shared.ID, findings, scans, errors int64) error
// FindByCapabilities finds agents with the given capabilities.
FindByCapabilities(ctx context.Context, tenantID shared.ID, capabilities []string, tool string) ([]*Agent, error)
// FindAvailable finds available agents for a step.
FindAvailable(ctx context.Context, tenantID shared.ID, capabilities []string, tool string) ([]*Agent, error)
// FindAvailableWithTool finds the best available agent for a tool.
// Returns the least-loaded agent that has the required tool.
FindAvailableWithTool(ctx context.Context, tenantID shared.ID, tool string) (*Agent, error)
// MarkStaleAsOffline marks agents as offline (health) if they haven't sent heartbeat within the timeout.
// Note: This updates Health (automatic), not Status (admin-controlled).
// Agents can still authenticate if their Status is 'active', regardless of Health.
// Returns the number of agents marked as offline.
MarkStaleAsOffline(ctx context.Context, timeout time.Duration) (int64, error)
// FindAvailableWithCapacity finds agents that have capacity for new jobs.
FindAvailableWithCapacity(ctx context.Context, tenantID shared.ID, capabilities []string, tool string) ([]*Agent, error)
// ClaimJob atomically claims a job slot for an agent.
ClaimJob(ctx context.Context, agentID shared.ID) error
// ReleaseJob releases a job slot for an agent.
ReleaseJob(ctx context.Context, agentID shared.ID) error
// UpdateOfflineTimestamp marks an agent as offline with the current timestamp.
// Called when a health monitor detects heartbeat timeout.
UpdateOfflineTimestamp(ctx context.Context, id shared.ID) error
// MarkStaleAgentsOffline finds agents that haven't sent heartbeat within timeout and marks them offline.
// Returns the list of agent IDs that were marked offline (for audit logging).
MarkStaleAgentsOffline(ctx context.Context, timeout time.Duration) ([]shared.ID, error)
// GetAgentsOfflineSince returns agents that went offline after the given timestamp.
// Used for historical queries like "which agents went offline in the last hour?"
GetAgentsOfflineSince(ctx context.Context, since time.Time) ([]*Agent, error)
// GetAvailableToolsForTenant returns all unique tool names that have at least one available agent.
// Used to determine which tools can actually be executed.
GetAvailableToolsForTenant(ctx context.Context, tenantID shared.ID) ([]string, error)
// HasAgentForTool checks if there's at least one agent that supports the given tool.
HasAgentForTool(ctx context.Context, tenantID shared.ID, tool string) (bool, error)
// GetAvailableCapabilitiesForTenant returns all unique capability names from all agents accessible to the tenant.
// Used to determine what capabilities a tenant can use based on their available agents.
GetAvailableCapabilitiesForTenant(ctx context.Context, tenantID shared.ID) ([]string, error)
// HasAgentForCapability checks if there's at least one agent that supports the given capability.
HasAgentForCapability(ctx context.Context, tenantID shared.ID, capability string) (bool, error)
}
Repository defines the interface for agent persistence.