server

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: AGPL-3.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewRouter

func NewRouter(services interfaces.Services, logger *apilogger.Logger, proxyHandler *handlers.ProxyHandler, config ...RouterConfig) *gin.Engine

NewRouter creates a new Gin router with all routes configured. proxyHandler may be nil — proxy routes are not registered in that case.

Types

type RouterConfig

type RouterConfig struct {
	// Debug enables debug mode
	Debug bool

	// TrustedProxies is the list of trusted proxy IP ranges/CIDRs.
	// If nil, trusts nobody (X-Forwarded-For is ignored). This
	// prevents IP-spoofing attacks on lockout and rate-limiting (#757).
	TrustedProxies []string

	// LoggingConfig is the configuration for the logging middleware
	LoggingConfig middleware.LoggingConfig

	// RateLimitConfig is the configuration for the rate limiting middleware
	RateLimitConfig middleware.RateLimitConfig

	// PerRouteRateLimitConfig is the configuration for stricter per-route
	// rate limits applied on top of the global RateLimitConfig. Covers
	// G41 (/secrets/:id/reveal) — endpoints
	// that take credentials as direct input and therefore warrant a
	// tighter cap than the global 100/min/IP. Defaults to enabled with
	// sensible limits; operators can disable by setting Enabled=false.
	PerRouteRateLimitConfig middleware.PerRouteRateLimitConfig

	// SecurityConfig is the configuration for the security middleware
	SecurityConfig middleware.SecurityConfig

	// TracingConfig is the configuration for the tracing middleware
	TracingConfig middleware.TracingConfig

	// SettingsHandler is the optional settings handler for admin/user settings routes
	SettingsHandler *handlers.SettingsHandler

	// InstanceSettings provides access to instance settings for feature flags
	InstanceSettings *settings.InstanceService

	// SecretsHandler is the handler for secret management endpoints (optional)
	SecretsHandler *handlers.SecretsHandler

	// ModelsHandler handles model listing and selection (optional).
	// Extracted from SecretsHandler (US-29.5).
	ModelsHandler *handlers.ModelsHandler

	// WorkspaceEnvHandler is the handler for workspace env-var endpoints (optional).
	// Extracted from SecretsHandler (US-29.4).
	WorkspaceEnvHandler *handlers.WorkspaceEnvHandler

	// AdminProviderCredentialsHandler handles admin credential CRUD (optional)
	AdminProviderCredentialsHandler *handlers.AdminProviderCredentialsHandler

	// UserProviderCredentialsHandler handles user credential CRUD (optional)
	UserProviderCredentialsHandler *handlers.UserProviderCredentialsHandler

	// ImageFactoryHandler serves the consumer-facing image-factory endpoints
	// (catalog, configs). Optional; nil when image-factory is disabled.
	ImageFactoryHandler *handlers.ImageFactoryHandler
	// ImageFactoryAdminHandler serves the platform-owner admin endpoints.
	ImageFactoryAdminHandler *handlers.ImageFactoryAdminHandler

	// UnlockDEKHandler is the soft-unlock endpoint for re-deriving the
	// DEK without forcing logout (Epic 56). Optional — when nil the
	// /auth/unlock-dek route is not registered, which is appropriate
	// for tests that don't exercise key material.
	UnlockDEKHandler *handlers.UnlockDEKHandler

	// OrgsHandler handles org CRUD routes (optional)
	OrgsHandler *handlers.OrgsHandler

	// OrgCredentialsHandler handles org credential routes (optional)
	OrgCredentialsHandler *handlers.OrgCredentialsHandler

	// TerminalHandler is the handler for WebSocket terminal proxy (optional)
	TerminalHandler *handlers.TerminalHandler

	// DevPreviewHandler is the handler for the authenticated HTTP/WS tunnel
	// to in-workspace dev servers (Epic 66, optional). nil when disabled.
	DevPreviewHandler *handlers.DevPreviewHandler

	// PreviewOriginHandler serves <uuid>-preview.<baseDomain> hosts
	// (Epic 66 Phase 1, optional). nil when preview origins are disabled —
	// in that case NO engine middleware is registered and the API behaves
	// exactly as before. When non-nil, its middleware runs BEFORE the API
	// middleware chain: preview hosts bypass API CORS/rate policy and can
	// never match /api/* routes (T5).
	PreviewOriginHandler *handlers.PreviewOriginHandler

	// AgentReloadHandler handles POST /api/v1/workspaces/:id/agent/reload (optional)
	AgentReloadHandler *handlers.AgentReloadHandler
	// DiskRecoverHandler handles POST /api/v1/workspaces/:id/disk-recover
	// (#1601 mechanical disk recovery; optional wiring like reload).
	DiskRecoverHandler *handlers.DiskRecoverHandler

	// BulkReloadHandler handles POST /api/v1/users/me/agents/reload (optional)
	BulkReloadHandler *handlers.BulkReloadHandler

	UsageHandler         *handlers.UsageHandler
	WebhookHandler       *handlers.StripeWebhookHandler
	InvitationsHandler   *handlers.InvitationsHandler
	EmailHandler         *handlers.EmailHandler
	EmailVerifyHandler   *handlers.EmailVerifyHandler
	PasswordResetHandler *handlers.PasswordResetHandler
	PolicyHandler        *handlers.PolicyHandler
	PromptHandler        *handlers.PromptHandler
	AgentRoleHandler     *handlers.AgentRoleHandler
	AuditHandler         *handlers.AuditHandler

	// RelayAdminHandler handles relay admin setup + status endpoints (optional)
	RelayAdminHandler *handlers.RelayAdminHandler

	// PlatformInfoHandler serves the admin "Versions" display — running
	// component versions read from deployed Deployment image tags. Optional.
	PlatformInfoHandler *handlers.PlatformInfoHandler

	// AuthorityFlipHandler serves the flip gate's operator endpoints
	// (US-69.13): park/unpark with mode_transition + the ledger in-flight
	// drain signal (optional).
	AuthorityFlipHandler *handlers.AuthorityFlipHandler
	// AdminSessionHandler handles admin-only session recovery endpoints (optional).
	// US-44.11: force-abort a workspace session stuck in activeSess after the
	// workspace pod was deleted/unreachable.
	AdminSessionHandler *handlers.AdminSessionHandler

	// PlatformAdminHandler handles platform-admin org/user suspension
	// endpoints (US-43.19, D19/D20). Mounted behind AuthMiddleware + AdminGuard.
	PlatformAdminHandler *handlers.PlatformAdminHandler

	// InternalOrgStatusHandler, when non-nil, registers the cluster-internal
	// GET /api/v1/internal/orgs/:orgID/status endpoint that the controller
	// polls to drive org-suspension of workspaces (D20). It is intentionally
	// NOT behind AuthMiddleware; access is gated by a mandatory X-Internal-Token
	// shared-secret header (see InternalOrgStatusHandler — the endpoint FAILS
	// CLOSED with 403 when LLMSAFESPACES_INTERNAL_TOKEN is unset). An optional
	// API NetworkPolicy (chart value networkPolicy.apiIngressRestricted) adds
	// L3/L4 defense-in-depth; the token is the load-bearing control.
	InternalOrgStatusHandler *handlers.InternalOrgStatusHandler

	// InternalLLMProvidersHandler, when non-nil, registers the
	// cluster-internal GET
	// /api/v1/internal/workspaces/:workspaceID/llm-providers endpoint the
	// controller's relay staging polls (US-72.3, design 0058 §4.1 hop 1) to
	// obtain decrypted BYO provider credentials for sealing. Same auth
	// contract as InternalOrgStatusHandler (mandatory X-Internal-Token,
	// fail-closed 403 when unset) — but it returns credential material, so
	// it MUST never be ingress-exposed; every reveal is audited
	// server-side.
	InternalLLMProvidersHandler *handlers.InternalLLMProvidersHandler

	// PodBootstrapHandler, when non-nil, registers POST /internal/v1/pod-bootstrap
	// — the secretless credential injection endpoint (Epic 35). The workspace
	// init container presents a projected SA token; the handler validates it via
	// TokenReview and returns decrypted secrets. NOT behind AuthMiddleware (the
	// init container has no user identity); auth is the TokenReview itself.
	PodBootstrapHandler *handlers.PodBootstrapHandler

	// PodWorkspaceRenameHandler, when non-nil, registers
	// /internal/v1/workspace-rename — the pod-identity path the agentd
	// rename_workspace MCP tool calls. Same TokenReview auth contract as
	// PodBootstrapHandler: the SA must be workspace-<id> in the expected
	// namespace, so a pod can only rename its own workspace.
	PodWorkspaceRenameHandler *handlers.PodWorkspaceRenameHandler

	// PodAutomationHandler, when non-nil, registers the pod-identity
	// trigger + workflow CRUD surface the agentd automation MCP tools
	// call — TokenReview-gated like the rename endpoint, delegating to
	// the existing user handlers under the pod's resolved owner.
	PodAutomationHandler *handlers.PodAutomationHandler

	// PodSessionArchiveHandler, when non-nil, registers the pod-identity
	// session archive/delete surface the agentd #1627 MCP tools call —
	// TokenReview-gated like the rename endpoint.
	PodSessionArchiveHandler *handlers.PodSessionArchiveHandler

	// MCPServersHandler handles external MCP server CRUD for all three
	// scopes (platform/org/user). Optional — when nil, no MCP routes are
	// registered (Epic 53).
	AdminMCPServersHandler *handlers.MCPServersHandler
	OrgMCPServersHandler   *handlers.MCPServersHandler
	UserMCPServersHandler  *handlers.MCPServersHandler
	UserPromptsHandler     *handlers.UserPromptsHandler

	CookieName string

	// CookieDomain (Epic 54, US-54.3): when non-empty, set as the Domain
	// attribute on the lsp_session cookie so the session survives root→subdomain
	// redirects under wildcard subdomain routing. When empty (default), the
	// cookie is host-only — current behavior, single-host deploys.
	CookieDomain string

	// OrgSubdomainBaseDomain (design 0064, #1669): auth.orgSubdomainRouting.
	// baseDomain. When non-empty, GET /auth/config derives an optional
	// orgContext {slug, name} from a <slug>.<base> request Host for
	// SSO-configured orgs — display-only, fail-soft (omitted on every miss).
	OrgSubdomainBaseDomain string

	// SSOHandler handles org-admin SSO config CRUD + the public OIDC login flow
	// (start/callback) and claimed-domain discovery (US-43.10, D17).
	SSOHandler *handlers.SSOHandler

	// LoginDiscoveryHandler handles POST /api/v1/auth/lookup — the email-led
	// login discovery endpoint (Epic 54, US-54.1). Returns a single redirectUrl
	// pointing the browser at the user's org subdomain (or direct SSO start URL
	// when subdomain routing is disabled). Enumeration-safe: uniform 200 +
	// uniform body shape across all non-validation branches; DB errors masked.
	LoginDiscoveryHandler *handlers.LoginDiscoveryHandler

	// PasskeyHandler handles WebAuthn passkey registration + login ceremonies
	// (Epic 59). Public routes (no auth middleware) — the ceremony itself is
	// the authentication. Nil when passkey support is not configured (no RPID).
	PasskeyHandler *handlers.PasskeyHandler
	// PasskeyDefaultSignup, when true, tells the frontend to default to passkey
	// enrollment at registration with "use password" as the explicit opt-in.
	PasskeyDefaultSignup bool

	// Turnstile, when Enabled is true, gates POST /auth/register with a
	// Cloudflare Turnstile CAPTCHA middleware. The middleware fails
	// closed: any of {missing token, verify request fails, verify
	// response says not-success} → 401. When Enabled is false, the
	// route runs without the middleware.
	//
	// SecretKey must be non-empty when Enabled is true (config.Load
	// enforces this at startup, fail-closed). VerifyURL defaults to
	// Cloudflare's production siteverify endpoint if empty.
	Turnstile TurnstileRouterConfig

	// Epic 64: Workflow + trigger handlers (optional — nil when not wired).
	UserWorkflowsHandler   *handlers.WorkflowsHandler
	OrgWorkflowsHandler    *handlers.WorkflowsHandler
	UserTriggersHandler    *handlers.TriggersHandler
	OrgTriggersHandler     *handlers.TriggersHandler
	WebhookReceiverHandler *handlers.WebhookReceiverHandler

	// FaultInjectionRules, when non-empty, installs the deterministic
	// fault-injection middleware (Epic 70 US-70.0). Populated at app
	// wire-up from LLMSAFESPACES_FAULT_INJECTION — a malformed value fails
	// startup there. Empty means the feature is absent: no middleware is
	// registered and the chain is byte-identical to before.
	FaultInjectionRules []middleware.FaultInjectionRule
}

RouterConfig defines configuration for the router

func DefaultRouterConfig

func DefaultRouterConfig() RouterConfig

DefaultRouterConfig returns the default router configuration

type TurnstileRouterConfig added in v0.2.0

type TurnstileRouterConfig struct {
	Enabled   bool
	SecretKey string
	VerifyURL string
}

TurnstileRouterConfig is the routing-side view of Cloudflare Turnstile CAPTCHA configuration used by the /register handler. Only the three fields the router needs at wire-up time; registerAuthRoutes constructs the fuller middleware.TurnstileConfig from this by dropping in a production HTTP client and logger.

This is kept separate from middleware.TurnstileConfig (rather than re-using that type here) because middleware.TurnstileConfig contains an *http.Client field that's only meaningful for tests. Exposing that on RouterConfig — and therefore on every app.go call site that builds a router — would invite confusion about whether operators are meant to plug an httptrace-instrumented client, a custom timeout, etc. The separation costs us one mapping step (app.go:911-914); the alternative would cost us a "please just leave this nil unless you're writing a test" caveat at every call site.

When Enabled is true, SecretKey must be non-empty (config.Load enforces this at startup, fail-closed). VerifyURL defaults to Cloudflare's production siteverify endpoint if empty.

Jump to

Keyboard shortcuts

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