Help us shape the future of Go! Take the 2026 Go Developer Survey

apiserver

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 52 Imported by: 0

Documentation

Overview

Package apiserver provides the operator's internal HTTP API (localhost:8082). This API is called exclusively by the tool executor running inside agent pods:

POST /agentrun/{namespace}          — create a child AgentRun
GET  /agentrun/{namespace}/{name}   — get AgentRun status

The server is NOT exposed outside the cluster. It binds to 0.0.0.0:8082 so that agent pods in the same namespace can reach it via the operator Service. All requests must carry a valid Kubernetes SA token in the Authorization header; the server validates it with a TokenReview before processing.

Index

Constants

View Source
const (
	// ExternalAPITokenAudience is the audience for K8s SA tokens on the external API.
	ExternalAPITokenAudience = "agentorca/external-api"
)

Variables

View Source
var Version = "dev"

Version is the operator build version. Set at link time via:

go build -ldflags "-X github.com/heddles/agent-orca/internal/apiserver.Version=<v>"

or left as "dev" for local builds.

Functions

func AdminFromContext

func AdminFromContext(ctx context.Context) (adminIdentity, bool)

AdminFromContext returns the authenticated admin SA identity, if any.

Types

type ACPAgentManifest

type ACPAgentManifest struct {
	Name               string            `json:"name"`
	Namespace          string            `json:"namespace,omitempty"`
	Description        string            `json:"description"`
	InputContentTypes  []string          `json:"input_content_types"`
	OutputContentTypes []string          `json:"output_content_types"`
	Metadata           *ACPAgentMetadata `json:"metadata,omitempty"`
	Status             *ACPAgentStatus   `json:"status,omitempty"`

	// InputSchema is a JSON Schema describing the expected input format
	// (derived from the agent's configured tools + built-in tools).
	InputSchema map[string]any `json:"input_schema,omitempty"`

	// OutputSchema is a JSON Schema describing the expected output format.
	OutputSchema map[string]any `json:"output_schema,omitempty"`

	// AllowedTools lists the tools available to this agent with descriptions.
	AllowedTools []ACPToolInfo `json:"allowed_tools,omitempty"`

	// KnowledgeBases lists the KnowledgeBase names available to this agent.
	KnowledgeBases []string `json:"knowledge_bases,omitempty"`

	// GuardrailPolicy is the name of the GuardrailPolicy applied to this agent, if any.
	GuardrailPolicy string `json:"guardrail_policy,omitempty"`

	// ClarifyAvailable indicates whether the _clarify built-in tool is available
	// (i.e. human-in-the-loop is possible). False when DisableClarify is true.
	ClarifyAvailable bool `json:"clarify_available"`

	// Filesystem declares the agent's ACP fs/* relay policy (issue #34). nil
	// means the agent has no filesystem tools; the bridge's aoctl-side flags
	// layer on top of this (they can only narrow, never widen, this policy).
	Filesystem *ACPFilesystemPolicy `json:"filesystem,omitempty"`
}

ACPAgentManifest is the response body for GET /agents/{name}.

type ACPAgentMetadata

type ACPAgentMetadata struct {
	Annotations         map[string]any `json:"annotations,omitempty"`
	Documentation       string         `json:"documentation,omitempty"`
	License             string         `json:"license,omitempty"`
	ProgrammingLanguage string         `json:"programming_language,omitempty"`
	NaturalLanguages    []string       `json:"natural_languages,omitempty"`
	Framework           string         `json:"framework,omitempty"`
}

ACPAgentMetadata represents agent metadata per spec.

type ACPAgentRunRequest

type ACPAgentRunRequest struct {
	Input     []ACPMessage `json:"input"`
	SessionID string       `json:"session_id,omitempty"`
}

ACPAgentRunRequest is the body for POST /agents/{name}/run.

type ACPAgentStatus

type ACPAgentStatus struct {
	AvgRunTokens      *float64 `json:"avg_run_tokens,omitempty"`
	AvgRunTimeSeconds *float64 `json:"avg_run_time_seconds,omitempty"`
	SuccessRate       *float64 `json:"success_rate,omitempty"`
}

ACPAgentStatus represents agent status metrics per spec.

type ACPAgentsListResponse

type ACPAgentsListResponse struct {
	Agents []ACPAgentManifest `json:"agents"`
}

ACPAgentsListResponse is the response body for GET /agents.

type ACPAwaitRequest

type ACPAwaitRequest struct {
	// Question is the human-readable clarifying question the agent asked,
	// copied from the AgentRun's ClarifyQuestion status field.
	Question string `json:"question,omitempty"`
}

ACPAwaitRequest describes what the client should provide next when a run is awaiting human input (e.g. the answer to a _clarify question).

type ACPErr

type ACPErr struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

ACPErr represents an error response.

type ACPErrEvent

type ACPErrEvent struct {
	Type  string `json:"type"`
	Error ACPErr `json:"error"`
}

ACPErrEvent is emitted on errors.

type ACPEvent

type ACPEvent struct {
	Type string `json:"type"`
}

ACPEvent is the base event type.

type ACPFilesystemPolicy added in v0.7.0

type ACPFilesystemPolicy struct {
	// Mode is "readOnly" or "readWrite".
	Mode string `json:"mode"`
	// WriteApproval asks the bridge to elicit explicit user approval per write.
	WriteApproval bool `json:"writeApproval,omitempty"`
	// RememberApproval, when false, forbids the bridge from remembering an
	// approval for the rest of the session (approve every write). nil means
	// the agent does not constrain it (issue #41).
	RememberApproval *bool `json:"rememberApproval,omitempty"`
}

ACPFilesystemPolicy mirrors Agent.spec.filesystem for bridge-side policy enforcement (mode gating and write approval elicitation).

type ACPGenericEvent

type ACPGenericEvent struct {
	Type    string `json:"type"`
	Generic any    `json:"generic"`
}

ACPGenericEvent is for generic events.

type ACPMessage

type ACPMessage struct {
	Role        string           `json:"role"`
	Parts       []ACPMessagePart `json:"parts"`
	CreatedAt   string           `json:"created_at,omitempty"`
	CompletedAt string           `json:"completed_at,omitempty"`
}

ACPMessage represents a message with parts per ACP spec.

type ACPMessageCompletedEvent

type ACPMessageCompletedEvent struct {
	Type    string     `json:"type"`
	Message ACPMessage `json:"message"`
}

ACPMessageCompletedEvent is emitted when a message is complete.

type ACPMessageCreatedEvent

type ACPMessageCreatedEvent struct {
	Type    string     `json:"type"`
	Message ACPMessage `json:"message"`
}

ACPMessageCreatedEvent is emitted when a new message is created.

type ACPMessageMetadata

type ACPMessageMetadata struct {
	Kind string `json:"kind"` // "citation" or "trajectory"
	// Citation fields
	StartIndex  *int   `json:"start_index,omitempty"`
	EndIndex    *int   `json:"end_index,omitempty"`
	URL         string `json:"url,omitempty"`
	Title       string `json:"title,omitempty"`
	Description string `json:"description,omitempty"`
	// Trajectory fields
	Message    string `json:"message,omitempty"`
	ToolName   string `json:"tool_name,omitempty"`
	ToolInput  any    `json:"tool_input,omitempty"`
	ToolOutput any    `json:"tool_output,omitempty"`
}

ACPMessageMetadata represents citation or trajectory metadata.

type ACPMessagePart

type ACPMessagePart struct {
	Name            string              `json:"name,omitempty"`
	ContentType     string              `json:"content_type"`
	Content         string              `json:"content,omitempty"`
	ContentEncoding string              `json:"content_encoding,omitempty"`
	ContentURL      string              `json:"content_url,omitempty"`
	Metadata        *ACPMessageMetadata `json:"metadata,omitempty"`
}

ACPMessagePart represents a part of a message per ACP spec.

type ACPMessagePartEvent

type ACPMessagePartEvent struct {
	Type string         `json:"type"`
	Part ACPMessagePart `json:"part"`
}

ACPMessagePartEvent is emitted when a message part is streamed.

type ACPRun

type ACPRun struct {
	AgentName    string           `json:"agent_name"`
	SessionID    string           `json:"session_id,omitempty"`
	RunID        string           `json:"run_id"`
	Status       ACPRunStatus     `json:"status"`
	AwaitRequest *ACPAwaitRequest `json:"await_request,omitempty"`
	Output       []ACPMessage     `json:"output,omitempty"`
	Error        *ACPErr          `json:"error,omitempty"`
	CreatedAt    string           `json:"created_at"`
	FinishedAt   string           `json:"finished_at,omitempty"`
	// ContinuationRunRef is the name of a follow-up AgentRun created when a
	// waiting run is resumed with a clarify answer (see resumeACPRun). Clients
	// should poll this run instead of the original.
	ContinuationRunRef string `json:"continuationRunRef,omitempty"`
}

ACPRun is the response body for run operations.

type ACPRunAwaitingEvent

type ACPRunAwaitingEvent struct {
	Type string `json:"type"`
	Run  ACPRun `json:"run"`
}

ACPRunAwaitingEvent is emitted when a run is waiting for input.

type ACPRunCancelledEvent

type ACPRunCancelledEvent struct {
	Type string `json:"type"`
	Run  ACPRun `json:"run"`
}

ACPRunCancelledEvent is emitted when a run is cancelled.

type ACPRunCompletedEvent

type ACPRunCompletedEvent struct {
	Type string `json:"type"`
	Run  ACPRun `json:"run"`
}

ACPRunCompletedEvent is emitted when a run completes.

type ACPRunCreateRequest

type ACPRunCreateRequest struct {
	AgentName string       `json:"agent_name"`
	Input     []ACPMessage `json:"input"`
	SessionID string       `json:"session_id,omitempty"`
	Session   *ACPSession  `json:"session,omitempty"`
	Mode      ACPRunMode   `json:"mode,omitempty"`
}

ACPRunCreateRequest is the request body for POST /runs.

type ACPRunCreatedEvent

type ACPRunCreatedEvent struct {
	Type string `json:"type"`
	Run  ACPRun `json:"run"`
}

ACPRunCreatedEvent is emitted when a run is created.

type ACPRunFailedEvent

type ACPRunFailedEvent struct {
	Type string `json:"type"`
	Run  ACPRun `json:"run"`
}

ACPRunFailedEvent is emitted when a run fails.

type ACPRunInProgressEvent

type ACPRunInProgressEvent struct {
	Type string `json:"type"`
	Run  ACPRun `json:"run"`
}

ACPRunInProgressEvent is emitted when a run starts processing.

type ACPRunMode

type ACPRunMode string

ACPRunMode matches ACP RunMode enum.

const (
	ACPRunModeSync   ACPRunMode = "sync"
	ACPRunModeAsync  ACPRunMode = "async"
	ACPRunModeStream ACPRunMode = "stream"
)

type ACPRunStatus

type ACPRunStatus string

ACPRunStatus matches ACP RunStatus enum.

const (
	ACPRunCreated    ACPRunStatus = "created"
	ACPRunInProgress ACPRunStatus = "in-progress"
	ACPRunAwaiting   ACPRunStatus = "awaiting"
	ACPRunCancelling ACPRunStatus = "cancelling"
	ACPRunCancelled  ACPRunStatus = "cancelled"
	ACPRunCompleted  ACPRunStatus = "completed"
	ACPRunFailed     ACPRunStatus = "failed"
)

type ACPServer

type ACPServer struct {
	// contains filtered or unexported fields
}

func NewACPServer

func NewACPServer(k8s kubernetes.Interface, crdClient client.Client, auth *ExternalAuth, store state.Store) *ACPServer

NewACPServer creates a new ACP server.

func (*ACPServer) Handler

func (s *ACPServer) Handler() http.Handler

Handler returns an http.Handler for the ACP API.

func (*ACPServer) SetFilesystemRelay added in v0.7.0

func (s *ACPServer) SetFilesystemRelay(relay acpfs.Relay)

SetFilesystemRelay wires the fs/* relay. Call with nil to disable filesystem access (fs endpoints then return 501).

type ACPSession

type ACPSession struct {
	ID      string   `json:"id"`
	History []string `json:"history"`
	State   string   `json:"state,omitempty"`
}

ACPSession represents a session per ACP spec.

type ACPToolInfo

type ACPToolInfo struct {
	Name        string         `json:"name"`
	Description string         `json:"description,omitempty"`
	InputSchema map[string]any `json:"input_schema,omitempty"`
}

ACPToolInfo describes a tool available to an agent.

type AdminRateLimit

type AdminRateLimit struct {
	RequestsPerMinute int `json:"requestsPerMinute,omitempty"`
	ConcurrentRuns    int `json:"concurrentRuns,omitempty"`
}

AdminRateLimit mirrors TenantRateLimit for the create request.

type AdminTenantCreateRequest

type AdminTenantCreateRequest struct {
	Name              string          `json:"name"`
	AllowedNamespaces []string        `json:"allowedNamespaces"`
	ClientID          string          `json:"clientID"`
	ClientSecret      string          `json:"clientSecret,omitempty"`
	AllowedAgents     []string        `json:"allowedAgents,omitempty"`
	RateLimit         *AdminRateLimit `json:"rateLimit,omitempty"`
	BudgetPerDayUSD   string          `json:"budgetPerDayUSD,omitempty"`
}

AdminTenantCreateRequest is the body for POST /admin/tenants.

type AdminTenantResponse

type AdminTenantResponse struct {
	Name              string          `json:"name"`
	Namespace         string          `json:"namespace"`
	ClientID          string          `json:"clientID"`
	ClientSecret      string          `json:"clientSecret,omitempty"`
	AllowedNamespaces []string        `json:"allowedNamespaces"`
	AllowedAgents     []string        `json:"allowedAgents,omitempty"`
	RateLimit         *AdminRateLimit `json:"rateLimit,omitempty"`
	BudgetPerDayUSD   string          `json:"budgetPerDayUSD,omitempty"`
}

AdminTenantResponse is the tenant representation returned to callers. ClientSecret is included ONLY at create time (one-time disclosure).

type Alert

type Alert struct {
	// ID is a stable identifier for the alert (e.g. "redis-down").
	ID string `json:"id"`
	// SubSystem is the subsystem the alert pertains to (e.g. "redis", "kubernetes-api").
	SubSystem string `json:"subsystem"`
	// State is "firing" or "resolved".
	State AlertState `json:"state"`
	// Message is a human-readable description of the current condition.
	Message string `json:"message"`
	// FirstSeen is when the alert first entered the firing state.
	FirstSeen time.Time `json:"firstSeen"`
	// LastSeen is when the alert was last evaluated.
	LastSeen time.Time `json:"lastSeen"`
	// ResolvedAt is set when the alert transitions to resolved.
	ResolvedAt *time.Time `json:"resolvedAt,omitempty"`
}

Alert represents the current state of a subsystem alert.

type AlertManager

type AlertManager struct {
	// contains filtered or unexported fields
}

AlertManager evaluates subsystem health checks and fires webhooks on state transitions (up→down or down→up). Alert state is persisted in Redis so it survives operator restarts.

func NewAlertManager

func NewAlertManager(store state.Store, webhooks []AlertWebhook) *AlertManager

NewAlertManager creates an AlertManager backed by the given Redis store. webhooks configures webhook delivery on alert transitions. May be empty to disable webhook delivery (state is still tracked for the status endpoint).

func (*AlertManager) Evaluate

func (am *AlertManager) Evaluate(ctx context.Context, name, detail string, up bool) *Alert

Evaluate checks a subsystem's health and records any state transition. It returns the current Alert (always non-nil) so the caller can include it in the system status response. If the subsystem transitioned state, appropriate webhooks are fired.

func (*AlertManager) ListAlerts

func (am *AlertManager) ListAlerts(ctx context.Context) []*Alert

ListAlerts returns all active (non-resolved) alerts from the store. Used by GET /api/system/alerts.

type AlertState

type AlertState string

AlertState describes whether an alert is actively firing or has been resolved.

const (
	AlertFiring   AlertState = "firing"
	AlertResolved AlertState = "resolved"
)

type AlertWebhook

type AlertWebhook struct {
	URL     string `json:"url"`
	HMACKey []byte `json:"-"` // raw HMAC key (resolved from K8s Secret by caller)
}

AlertWebhook configures webhook delivery for alert state transitions. The webhook receives a JSON payload signed with HMAC-SHA256 using HMACKey.

type ApprovalNotifier added in v0.9.0

type ApprovalNotifier interface {
	NotifyApproval(ctx context.Context, a postgresql.Approval) error
}

ApprovalNotifier tells approvers about a new pending approval.

type ExternalAPIServer

type ExternalAPIServer struct {
	// contains filtered or unexported fields
}

ExternalAPIServer handles the external-facing REST API for enterprise integrations. Port 8084, authenticated via ExternalAuth middleware.

func NewExternalAPIServer

func NewExternalAPIServer(k8s kubernetes.Interface, crdClient client.Client, auth *ExternalAuth, hasStore bool, store state.Store) *ExternalAPIServer

NewExternalAPIServer creates a new external API server.

func (*ExternalAPIServer) Handler

func (s *ExternalAPIServer) Handler() http.Handler

Handler returns an http.Handler for the external API.

type ExternalAuth

type ExternalAuth struct {
	// contains filtered or unexported fields
}

ExternalAuth handles authentication for the external API. It supports three modes checked in order:

  1. agent-orca-issued JWTs (for authMode: issued tenants)
  2. Federated OIDC JWTs (for authMode: federated tenants)
  3. Kubernetes ServiceAccount tokens (for in-cluster callers)

func NewExternalAuth

func NewExternalAuth(k8s kubernetes.Interface, crdClient client.Client) (*ExternalAuth, error)

NewExternalAuth creates a new ExternalAuth middleware. The signing key is loaded from a Kubernetes Secret if it exists, otherwise a new key is generated and persisted so that issued tokens survive operator restarts.

func (*ExternalAuth) FederatedLoginTenants

func (a *ExternalAuth) FederatedLoginTenants() []*agentorcav1alpha1.TenantConfig

FederatedLoginTenants returns federated TenantConfigs configured for the interactive (authorization-code) login flow — i.e. whose FederatedAuthConfig carries a ClientSecretRef or RedirectURI. Used to render the /oauth/login picker.

func (*ExternalAuth) HandleTokenRequest

func (a *ExternalAuth) HandleTokenRequest(w http.ResponseWriter, r *http.Request)

HandleTokenRequest handles POST /oauth/token for client_credentials grant.

func (*ExternalAuth) Middleware

func (a *ExternalAuth) Middleware(next http.Handler) http.Handler

Middleware returns an http.Handler that authenticates requests and injects TenantIdentity.

func (*ExternalAuth) MintSessionForIdentity

func (a *ExternalAuth) MintSessionForIdentity(ident *TenantIdentity) (string, error)

MintSessionForIdentity mints an agent-orca-issued session JWT for an authenticated principal (e.g. the result of an OIDC login). The token is accepted by validateIssuedToken and carries the per-user identity claims (userid/groups/roles) needed by the future RBAC layer.

func (*ExternalAuth) MintSessionJWT

func (a *ExternalAuth) MintSessionJWT(claims jwt.MapClaims) (string, error)

MintSessionJWT signs a JWT with the operator's signing key. It is shared by the client_credentials token exchange (HandleTokenRequest) and the OIDC login callback so that an OIDC-logged-in user receives an agent-orca-issued session JWT that the existing validateIssuedToken middleware already accepts. Identity claims such as "userid"/"groups"/"roles" are carried through so a future RBAC layer can consume them (see TenantIdentity).

func (*ExternalAuth) NewProviderForTenant

func (a *ExternalAuth) NewProviderForTenant(ctx context.Context, tc *agentorcav1alpha1.TenantConfig) (*oidc.Provider, error)

NewProviderForTenant builds an OIDC provider from a federated tenant's config, reading its OAuth2 client_secret from the tenant's first allowed namespace (spec.allowedNamespaces[0], or ClientSecretRef.Namespace when set). PKCE is enabled for the browser flow. The login handler only calls this for login-capable tenants (see isLoginCapable).

func (*ExternalAuth) RefreshTenants

func (a *ExternalAuth) RefreshTenants(ctx context.Context) error

RefreshTenants reloads all TenantConfig CRs into the cache. Called by the TenantConfig controller on reconcile.

func (*ExternalAuth) ResolveFederatedTenant

func (a *ExternalAuth) ResolveFederatedTenant(issuer string, claims map[string]any) (*agentorcav1alpha1.TenantConfig, error)

ResolveFederatedTenant resolves the federated tenant for an already-verified OIDC token (e.g. one minted by the login callback). Unlike validateFederatedToken it does NOT re-verify the signature — the caller is responsible for that — and so it is the bridge from the browser auth-code flow into the existing tenant cache.

func (*ExternalAuth) ValidateToken

func (a *ExternalAuth) ValidateToken(ctx context.Context, token string) (*TenantIdentity, error)

ValidateToken attempts to validate a bearer token against all three supported auth modes and returns the resolved TenantIdentity. This is the single-token variant of Middleware, used by the UI API server as a fallback after K8s SA token validation fails (enabling OIDC tenant JWT login from the browser).

type MetricSample

type MetricSample struct {
	Time            int64   `json:"time"`
	RequestCount    int     `json:"requestCount"`
	EgressPublished int     `json:"egressPublished"`
	EgressFailed    int     `json:"egressFailed"`
	P50LatencyMs    float64 `json:"p50LatencyMs"`
	P95LatencyMs    float64 `json:"p95LatencyMs"`
	P99LatencyMs    float64 `json:"p99LatencyMs"`
	TokenThroughput float64 `json:"tokenThroughput"`
}

type OIDCLoginHandler

type OIDCLoginHandler struct {
	// contains filtered or unexported fields
}

OIDCLoginHandler implements the tenant-aware OIDC authorization-code login flow. Each federated TenantConfig that carries a clientSecretRef/redirectURI is a selectable login provider; the browser picks one at /oauth/login and the callback uses that tenant's IdP + client_secret to exchange the code. On success an agent-orca-issued session JWT is set as an HttpOnly cookie; requireAuth is cookie-only when this handler is wired, so the UI is never shown without a successful login.

func NewOIDCLoginHandler

func NewOIDCLoginHandler(auth *ExternalAuth, opts ...OIDCLoginOption) *OIDCLoginHandler

NewOIDCLoginHandler builds a handler. auth supplies the tenant cache, signing key, and K8s client (for reading per-tenant client secrets).

func (*OIDCLoginHandler) Register

func (h *OIDCLoginHandler) Register(mux *http.ServeMux)

Register mounts the login routes on the given mux.

type OIDCLoginOption

type OIDCLoginOption func(*OIDCLoginHandler)

OIDCLoginOption configures an OIDCLoginHandler.

func WithOIDCCookieSecure

func WithOIDCCookieSecure(b bool) OIDCLoginOption

WithOIDCCookieSecure sets the Secure attribute on session cookies (true behind TLS; false for plain-HTTP local dev).

func WithOIDCLogoResolver

func WithOIDCLogoResolver(r logoResolver) OIDCLoginOption

WithOIDCLogoResolver injects a logo resolver used when rendering the /oauth/login picker (test seam). Production callers can omit it and defaultLogoResolver is used, which safely resolves each issuer's logo from its OIDC discovery document and falls back to the issuer origin favicon.

func WithOIDCProviderFactory

func WithOIDCProviderFactory(f providerFactory) OIDCLoginOption

WithOIDCProviderFactory injects a provider builder (for tests).

func WithOIDCRedirectURI

func WithOIDCRedirectURI(u string) OIDCLoginOption

WithOIDCRedirectURI overrides the post-login/logout redirect target (default "/").

type ProviderHealth

type ProviderHealth struct {
	Name      string `json:"name"`
	Namespace string `json:"namespace"`
	Ready     bool   `json:"ready"`
	LatencyMs int    `json:"latencyMs,omitempty"`
	Message   string `json:"message,omitempty"`
}

type QuotaError

type QuotaError struct {
	Code       int
	Message    string
	RetryAfter time.Duration // >0 only for 429
}

QuotaError is returned by enforceQuotas and maps directly to an HTTP response so callers can translate it without inspecting strings.

func (*QuotaError) Error

func (e *QuotaError) Error() string

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter is a simple, single-process token bucket scoped per tenant. It is sufficient for a single-replica operator; in a multi-replica deployment each instance enforces independently (documented limitation — a Redis-backed limiter can replace the backend without changing call sites).

func NewRateLimiter

func NewRateLimiter() *RateLimiter

NewRateLimiter creates a rate limiter with no buckets (lazy population).

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(tenant string, requestsPerMinute int) (time.Duration, bool)

Allow returns (retryAfter, ok). ok=false means the request is rejected; retryAfter is the duration the caller should wait before retrying.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server handles the operator's internal API for agent-to-agent communication.

func New

func New(k8s kubernetes.Interface, crdClient client.Client) *Server

New creates a new API server.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns an http.Handler for the internal API.

func (*Server) SetFilesystemRelay added in v0.7.0

func (s *Server) SetFilesystemRelay(relay acpfs.Relay)

SetFilesystemRelay wires the fs/* relay. Call with nil to disable filesystem access (fs requests then fail fast with 501).

func (*Server) WithApprovals added in v0.9.0

func (s *Server) WithApprovals(store ToolApprovalStore, notifier ApprovalNotifier) *Server

WithApprovals gives the server the approval store (nil leaves tool approvals off) and an optional notifier. It returns s for chaining.

type SystemMetrics

type SystemMetrics struct {
	RequestCount24h int            `json:"requestCount24h"`
	P50LatencyMs    float64        `json:"p50LatencyMs"`
	P95LatencyMs    float64        `json:"p95LatencyMs"`
	P99LatencyMs    float64        `json:"p99LatencyMs"`
	TokenThroughput float64        `json:"tokenThroughput"`
	EgressPublished int            `json:"egressPublished"`
	EgressFailed    int            `json:"egressFailed"`
	Samples         []MetricSample `json:"samples,omitempty"`
}

type SystemStatusResponse

type SystemStatusResponse struct {
	StateConfigured      bool                    `json:"stateConfigured"`
	Version              string                  `json:"version"`
	SubSystems           []SystemSubSystemStatus `json:"subsystems"`
	ModelProviders       []ProviderHealth        `json:"modelProviders,omitempty"`
	Metrics              *SystemMetrics          `json:"metrics,omitempty"`
	RunHistoryConfigured bool                    `json:"runHistoryConfigured"`
}

type SystemSubSystemStatus

type SystemSubSystemStatus struct {
	Name      string `json:"name"`
	Status    string `json:"status"`
	Message   string `json:"message,omitempty"`
	LatencyMs int    `json:"latencyMs,omitempty"`
}

type TaskCallback

type TaskCallback struct {
	URL string `json:"url"`
	// SecretRef is the name of a Kubernetes Secret in the tenant namespace.
	// When set, the controller reads its `hmac-key` value and signs each
	// delivery with an `X-Agentorc-Signature: sha256=<hex>` header (HMAC-SHA256
	// over the raw JSON body) plus an `X-Agentorc-Timestamp`. Receivers verify
	// the signature with the same shared key. When absent, the callback is
	// delivered unsigned (backward compatible).
	SecretRef string `json:"secretRef,omitempty"`
}

TaskCallback configures webhook delivery on task completion.

type TaskLinks struct {
	Self   string `json:"self"`
	Stream string `json:"stream,omitempty"`
}

TaskLinks provides HATEOAS-style links for task navigation.

type TaskResponse

type TaskResponse struct {
	ID          string            `json:"id"`
	Agent       string            `json:"agent"`
	Status      string            `json:"status"`
	Output      string            `json:"output,omitempty"`
	SpendUSD    string            `json:"spendUSD,omitempty"`
	CreatedAt   string            `json:"createdAt,omitempty"`
	CompletedAt string            `json:"completedAt,omitempty"`
	Metadata    map[string]string `json:"metadata,omitempty"`
	Links       *TaskLinks        `json:"links,omitempty"`
}

TaskResponse is the response body for task operations.

type TaskSubmission

type TaskSubmission struct {
	Agent    string            `json:"agent"`
	Input    string            `json:"input"`
	Timeout  string            `json:"timeout,omitempty"`
	Callback *TaskCallback     `json:"callback,omitempty"`
	Metadata map[string]string `json:"metadata,omitempty"`
	// Egress configures durable result delivery to an external message bus.
	// +optional
	Egress *agentorcav1alpha1.EgressConfig `json:"egress,omitempty"`
}

TaskSubmission is the request body for POST /v1/tasks.

type TenantIdentity

type TenantIdentity struct {
	// TenantName is the TenantConfig CR name.
	TenantName string
	// Namespace is the tenant's primary (first) authorized namespace. Kept as a
	// single string for backward compatibility with the "namespace" bearer/session
	// JWT claim and single-namespace consumers; the full authorized set is in
	// Namespaces below.
	Namespace string
	// Namespaces is the full set of Kubernetes namespaces this tenant is
	// authorized to access (spec.allowedNamespaces). Agent/run lookups resolve to
	// the resource's own namespace within this set; lists span the whole set.
	Namespaces []string
	// AllowedAgents is the list of agents this tenant may invoke. Nil means all.
	AllowedAgents []string

	// UserID is the authenticated user's stable identifier (e.g. the IdP sub or
	// email claim). Populated from the bearer/session token's "userid" claim.
	// Empty for client_credentials and K8s SA callers (tenant-level, not user-level).
	// +optional
	UserID string
	// Groups are the user's group memberships (e.g. from an IdP "groups" claim),
	// carried through the identity so a future RBAC layer can map group -> role.
	// Intentionally NOT used for authorization yet.
	// +optional
	Groups []string
	// Roles are resolved from Groups by a future role-mapper; empty until that
	// layer exists. Present so the identity shape is stable for RBAC.
	// +optional
	Roles []string

	// Quota fields below are populated from the tenant's TenantConfig (if any) and
	// are only set for issued/federated tenants — never for in-cluster K8s SA callers,
	// which assert their own namespace identity and are not rate/budget limited here.
	//
	// RateLimitRPM is RequestsPerMinute from TenantConfig.spec.rateLimit.
	RateLimitRPM int
	// ConcurrentRuns is spec.rateLimit.concurrentRuns.
	ConcurrentRuns int
	// BudgetPerDayUSD is spec.budgetPerDayUSD.
	BudgetPerDayUSD string
}

TenantIdentity is the resolved identity of an authenticated external API caller.

func TenantFromContext

func TenantFromContext(ctx context.Context) (*TenantIdentity, bool)

TenantFromContext retrieves the TenantIdentity from the request context.

type ToolApprovalStore added in v0.9.0

type ToolApprovalStore interface {
	RequestApproval(ctx context.Context, a postgresql.Approval) (postgresql.Approval, error)
	GetApproval(ctx context.Context, id string) (postgresql.Approval, error)
	DecideApproval(ctx context.Context, id, status, by, reason string) (postgresql.Approval, error)
}

ToolApprovalStore is the part of the approval engine this API uses (postgresql.Store).

type UIServer

type UIServer struct {
	// contains filtered or unexported fields
}

UIServer serves the REST API consumed by the React UI.

When authEnabled is true every request must carry a valid Kubernetes SA token with audience "agentorca/ui", validated via TokenReview. In production the UIProxy pod holds such a token (projected volume) and injects it on every proxied request. Browsers never send the token directly.

When externalAuth is non-nil, OIDC tenant JWTs (validated by the external auth middleware) are also accepted as an alternative to the K8s SA token. The resolved TenantIdentity scopes list operations to the tenant's namespaces, enabling per-tenant run history filtering and resource access control.

Set --ui-auth-enabled=false for local development where the proxy is not running.

func NewUIServer

func NewUIServer(
	k8s kubernetes.Interface,
	crdClient client.Client,
	stateConfigured bool,
	store state.Store,
	authEnabled bool,
	externalAuth *ExternalAuth,
	pgStore *postgresql.Store,
	alertManager *AlertManager,
) *UIServer

NewUIServer creates a UIServer.

func (*UIServer) Handler

func (s *UIServer) Handler() http.Handler

func (*UIServer) SetOIDCLogin

func (s *UIServer) SetOIDCLogin(h *OIDCLoginHandler)

Jump to

Keyboard shortcuts

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