config

package
v0.3.0 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	DefaultJWTIssuer   = "llmsafespaces"
	DefaultJWTAudience = "llmsafespaces"
)

DefaultJWTIssuer / DefaultJWTAudience are the iss/aud claims minted on every JWT and validated on every parse, when the operator hasn't set them explicitly. Defaults keep out-of-the-box deploys working; operators running multiple LLMSafeSpaces instances that should not accept each other's tokens set their own values via Helm or env.

Variables

This section is empty.

Functions

This section is empty.

Types

type AWSKMSConfig added in v0.3.0

type AWSKMSConfig struct {
	Region          string            `mapstructure:"region"`
	CredentialsFile string            `mapstructure:"credentialsFile"`
	KeyArns         map[string]string `mapstructure:"keyArns"`
}

AWSKMSConfig holds AWS KMS-specific provider configuration. CredentialsFile is the path to an AWS shared-credentials file mounted from a K8s Secret (D2: file-mount, not IRSA — narrower trust surface). Region is the AWS region of the configured keys. KeyArns maps purpose strings to KMS key ARNs; exactly three purposes are expected (D4): "providerCredentials", "orgCredentials", "masterKek".

type Config

type Config struct {
	Server struct {
		Host            string        `mapstructure:"host"`
		Port            int           `mapstructure:"port"`
		ShutdownTimeout time.Duration `mapstructure:"shutdownTimeout"`
		// InferenceRelayURL is the CF Worker URL for free-tier inference relay (Epic 26).
		// When set, ListModels remaps free-tier opencode models to providerID=opencode-relay.
		InferenceRelayURL string `mapstructure:"inferenceRelayURL"`
	} `mapstructure:"server"`

	// Use the shared Kubernetes config
	Kubernetes k8sconfig.KubernetesConfig `mapstructure:"kubernetes"`

	Database struct {
		Host            string        `mapstructure:"host"`
		Port            int           `mapstructure:"port"`
		User            string        `mapstructure:"user"`
		Password        string        `mapstructure:"password"`
		Database        string        `mapstructure:"database"`
		SSLMode         string        `mapstructure:"sslMode"`
		MaxOpenConns    int           `mapstructure:"maxOpenConns"`
		MaxIdleConns    int           `mapstructure:"maxIdleConns"`
		ConnMaxLifetime time.Duration `mapstructure:"connMaxLifetime"`
	} `mapstructure:"database"`

	Redis struct {
		Host     string `mapstructure:"host"`
		Port     int    `mapstructure:"port"`
		Password string `mapstructure:"password"`
		DB       int    `mapstructure:"db"`
		PoolSize int    `mapstructure:"poolSize"`
	} `mapstructure:"redis"`

	Auth struct {
		JWTSecret string `mapstructure:"jwtSecret"`
		// JWTPreviousSecrets is the list of previous JWT signing keys
		// retained for VALIDATION ONLY. Tokens signed with any entry
		// here are still accepted; new tokens are always signed with
		// JWTSecret. Operators rotate by:
		//   1. Move current JWTSecret to head of JWTPreviousSecrets.
		//   2. Set JWTSecret to a fresh random string.
		//   3. Restart API; old sessions stay valid until they
		//      expire (TokenDuration), at which point the entry can
		//      be removed.
		// Closes F1.7.5 (Epic 17). Set via env
		// LLMSAFESPACES_AUTH_JWTPREVIOUSSECRETS as a comma-separated
		// list, OR via the YAML key `jwtPreviousSecrets: [...]`.
		JWTPreviousSecrets []string `mapstructure:"jwtPreviousSecrets"`
		// JWTIssuer is the iss claim minted on every token and validated
		// on every parse. Default "llmsafespaces". Set when deploying
		// multiple LLMSafeSpaces instances that should not accept each
		// other's tokens. Set via env LLMSAFESPACES_AUTH_JWTISSUER.
		JWTIssuer string `mapstructure:"jwtIssuer"`
		// JWTAudience is the aud claim minted on every token and validated
		// on every parse. Default "llmsafespaces". Same deployment-shape
		// rationale as JWTIssuer. Set via env
		// LLMSAFESPACES_AUTH_JWTAUDIENCE.
		JWTAudience         string        `mapstructure:"jwtAudience"`
		TokenDuration       time.Duration `mapstructure:"tokenDuration"`
		APIKeyPrefix        string        `mapstructure:"apiKeyPrefix"`
		CookieName          string        `mapstructure:"cookieName"`
		RememberMeDuration  time.Duration `mapstructure:"rememberMeDuration"`
		RegistrationEnabled bool          `mapstructure:"registrationEnabled"`
		LockoutEnabled      bool          `mapstructure:"lockoutEnabled"`
		LockoutAttempts     int           `mapstructure:"lockoutAttempts"`
		LockoutDuration     time.Duration `mapstructure:"lockoutDuration"`
		APIKeyDEKTTL        time.Duration `mapstructure:"apiKeyDEKTTL"`
	} `mapstructure:"auth"`

	Security struct {
		AllowedOrigins       []string `mapstructure:"allowedOrigins"`
		AllowCredentials     bool     `mapstructure:"allowCredentials"`
		RootKeyProvider      string   `mapstructure:"rootKeyProvider"`
		SealedKeyPath        string   `mapstructure:"sealedKeyPath"`
		PassphrasePath       string   `mapstructure:"passphrasePath"`
		SkipMasterKeyWarning bool     `mapstructure:"skipMasterKeyWarning"`
		// KMS holds cloud KMS provider configuration (Epic 57 US-57.1).
		// When RootKeyProvider is "aws-kms", KMS.AWS.KeyArns must contain
		// ARNs for each purpose (providerCredentials, orgCredentials,
		// masterKek). See design/stories/epic-57-rce-resistance-hardening/
		// README.md D4 for the three-key model.
		KMS KMSConfig `mapstructure:"kms"`
	} `mapstructure:"security"`

	Logging struct {
		Level       string `mapstructure:"level"`
		Development bool   `mapstructure:"development"`
		Encoding    string `mapstructure:"encoding"`
	} `mapstructure:"logging"`

	RateLimiting struct {
		Enabled       bool          `mapstructure:"enabled"`
		DefaultLimit  int           `mapstructure:"defaultLimit"`
		DefaultWindow time.Duration `mapstructure:"defaultWindow"`
		BurstSize     int           `mapstructure:"burstSize"`
		Strategy      string        `mapstructure:"strategy"`
	} `mapstructure:"rateLimiting"`

	Proxy struct {
		RequestBufferSizePerWorkspace int `mapstructure:"requestBufferSizePerWorkspace"`
		RequestBufferTimeoutSeconds   int `mapstructure:"requestBufferTimeoutSeconds"`
	} `mapstructure:"proxy"`

	// Billing holds Stripe configuration for org subscriptions (Epic 43).
	// When SecretKey is empty, a NoopCheckoutProvider is used and the webhook
	// endpoint rejects all deliveries — development/test mode.
	Billing struct {
		SecretKey          string            `mapstructure:"secretKey"`
		WebhookSecret      string            `mapstructure:"webhookSecret"`
		CheckoutSuccessURL string            `mapstructure:"checkoutSuccessUrl"`
		CheckoutCancelURL  string            `mapstructure:"checkoutCancelUrl"`
		PortalReturnURL    string            `mapstructure:"portalReturnUrl"`
		PlanPrices         map[string]string `mapstructure:"planPrices"`
		Meters             map[string]string `mapstructure:"meters"`
	} `mapstructure:"billing"`

	// Email holds outbound email configuration (US-43.2 invitations). When
	// Provider is empty or "noop", NoopProvider logs to stderr — no AWS
	// dependency. "ses" requires AWS credentials via IRSA or env.
	Email struct {
		Provider    string `mapstructure:"provider"`
		SESRegion   string `mapstructure:"sesRegion"`
		FromAddress string `mapstructure:"fromAddress"`
		BaseURL     string `mapstructure:"baseUrl"`
	} `mapstructure:"email"`

	// OIDC holds SSO login wiring (US-43.10, D17). RedirectBaseURL is the
	// origin the IdP redirects back to after authentication; the full callback
	// is {RedirectBaseURL}/api/v1/auth/sso/:orgSlug/callback. When empty the
	// start endpoint derives it from the incoming request. FrontendRedirectURL
	// is where the browser lands after a successful or failed SSO callback.
	OIDC struct {
		RedirectBaseURL     string `mapstructure:"redirectBaseUrl"`
		FrontendRedirectURL string `mapstructure:"frontendRedirectUrl"`
		// StateCookieName is the signed PKCE/state cookie name.
		StateCookieName string `mapstructure:"stateCookieName"`
	} `mapstructure:"oidc"`

	// OrgSubdomainRouting holds Epic 54 (US-54.1) email-led login discovery
	// config. When BaseDomain is non-empty, POST /auth/lookup redirects found
	// users to https://<orgSlug>.<baseDomain>. When empty (subdomain routing
	// disabled — the default), the lookup falls back to the direct SSO start
	// URL (/api/v1/auth/sso/<slug>/start), which works regardless of chart
	// config. CookieDomain is the value set on the lsp_session cookie's
	// Domain attribute so the session survives root→subdomain redirects; it
	// is consumed by the auth cookie setter (US-54.3 wires it through Helm).
	OrgSubdomainRouting struct {
		BaseDomain   string `mapstructure:"baseDomain"`
		CookieDomain string `mapstructure:"cookieDomain"`
	} `mapstructure:"orgSubdomainRouting"`

	// Turnstile is Cloudflare's CAPTCHA. When Enabled, the /register
	// middleware validates the client-supplied cf-turnstile-response
	// token against SecretKey using VerifyURL. When Enabled but SecretKey
	// is empty, /register 500s at startup — fail-closed, don't run in
	// a state where the operator thinks Turnstile is on but it isn't.
	//
	// When Enabled is false, the middleware is a no-op and /register
	// accepts requests without a token. All chart-side wiring flows
	// through Enabled+SecretKey+SiteKey; there's no partial-config state.
	//
	// Wired via ops-prod cluster-config → chart values → env:
	//   LLMSAFESPACES_TURNSTILE_ENABLED     ("true" | unset)
	//   LLMSAFESPACES_TURNSTILE_SECRETKEY   (secretKeyRef; never in ConfigMap)
	//   LLMSAFESPACES_TURNSTILE_VERIFYURL   (defaults to Cloudflare production)
	Turnstile struct {
		Enabled   bool   `mapstructure:"enabled"`
		SecretKey string `mapstructure:"secretKey"`
		VerifyURL string `mapstructure:"verifyURL"`
	} `mapstructure:"turnstile"`

	// Workspace holds Helm-managed workspace defaults. Currently only
	// DefaultStorageClass is exposed here: when non-empty the API pins the
	// `workspace.defaultStorageClass` instance setting via SetHelmOverrides
	// so admins cannot override it via the settings UI (Tier 1). When
	// empty, the setting stays admin-mutable (Tier 2) with its DB-backed
	// value (which itself defaults to "" — meaning "use cluster default SC").
	//
	// This pathway exists so operators running LLMSafeSpaces on clusters
	// with dedicated low-durability StorageClasses (e.g. Longhorn 2-replica
	// pools) can declare that choice in the Helm chart rather than having
	// to remember to set it in the admin UI after every install/re-install.
	//
	// Wired via: values.yaml `workspace.defaultStorageClass` → API
	// ConfigMap `workspace.defaultStorageClass` → this field → app.go
	// SetHelmOverrides → workspace service Create path.
	Workspace struct {
		DefaultStorageClass string `mapstructure:"defaultStorageClass"`
	} `mapstructure:"workspace"`

	// Terminal holds the WebSocket terminal proxy's security config.
	//
	// AllowedOrigins governs the gorilla/websocket Upgrader's CheckOrigin:
	//   - Empty (default): same-origin only. Browser requests whose Origin
	//     does not match the API's own Host are rejected at upgrade.
	//     Non-browser clients (no Origin) are accepted; they authenticate
	//     via the single-use ticket, not cookies.
	//   - Contains "*": all origins accepted (the historical behavior).
	//     Operators who really want this must opt in explicitly.
	//   - Otherwise: same-origin requests plus anything in the list.
	//
	// Wired via: values.yaml `terminal.allowedOrigins` → API ConfigMap
	// `terminal.allowedOrigins` → this field → app.go → NewTerminalHandler.
	// Default empty so an out-of-the-box install is fail-closed against
	// cross-site WebSocket hijacking (G35).
	Terminal struct {
		AllowedOrigins []string `mapstructure:"allowedOrigins"`
	} `mapstructure:"terminal"`
}

Config represents the application configuration

func Load

func Load(path string) (*Config, error)

Load loads configuration from file and environment variables

type KMSConfig added in v0.3.0

type KMSConfig struct {
	AWS AWSKMSConfig `mapstructure:"aws"`
}

KMSConfig holds cloud KMS provider configuration for the master KEK (Epic 57 US-57.1). When Security.RootKeyProvider is "aws-kms", KMS.AWS must be fully configured. When "gcp-kms" (future US-57.3), KMS.GCP. Otherwise this struct is ignored.

Jump to

Keyboard shortcuts

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