Documentation
¶
Overview ¶
Package config is the thin root composite read by every cmd/aura subcommand. Per CONTEXT.md D-row "Composition": per-subsystem configs (db, knowledge, llm) live in their owning packages; this file only wires the top-level fields and composes credentials from POSTGRES_* primitives.
Slice 0.5 form: DB only. Slice 0.7 added `Neo4j knowledge.Config`; Phase 3 (Slice 1) adds `LLM llm.Config` + the AURA_OTEL_* tracing knobs. No new fields land here without an owning slice plan.
config_env.go holds the env-var parsing helpers split out of config.go (refactor-on-touch, CLAUDE.md ≤600 LOC NO GOD CLASS): the typed envDefault / envIntDefault / envBoolDefault / envSliceDefault accessors loadBase composes the Config from. Each absorbs a malformed/unset value to its fallback rather than booting fatal — a typo in an ad-hoc env tweak should never block startup (the REQUIRED secrets are fail-fast in Validate / llm.Load instead).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GuardWebBind ¶ added in v1.0.0
GuardWebBind is the WEB-02 fail-fast boot policy for the cockpit listener (D-05). A loopback bind always boots with no credential, exactly as before; a non-loopback bind boots ONLY when EITHER AURA_WEB_AUTH_SECRET is set (the in-binary login is active) OR trustProxy is true (the operator vouches a reverse proxy terminates auth). A non-loopback bind with neither credential returns an actionable error so the daemon refuses to silently expose an unauthenticated surface. It is a pure function — total (no panic path) and table-test-friendly — mirroring Validate's "config: …" posture.
Wildcards (0.0.0.0, ::, [::]) are NOT special-cased: net.ParseIP(...).IsLoopback() returns false for them, so they fall through to the gated branch, which is correct.
Types ¶
type Config ¶
type Config struct {
DB db.Config
Neo4j knowledge.Config // Slice 0.7 — graph + vector + embed sidecar wiring
LLM llm.Config // Slice 1 — OpenAI-compat client + load-order chain (D-22)
MCPServers map[string]mcp.ServerConfig
MCPPolicies map[string]mcp.ManagedServer
MCPServersErr error
RunDir string
ToolPreviewCap int
OtelExporter string // AURA_OTEL_EXPORTER ∈ {stdout,otlp,none} (D-06)
OtelEndpoint string // AURA_OTEL_ENDPOINT — OTLP/gRPC target (D-06)
// Phase 4 (Slice 1.8) conversation + context-management tuning knobs.
// Non-fatal envIntDefault fallbacks (an ad-hoc tweak typo falls back, not boots-fatal).
ConversationTurnCapBytes int // AURA_CONVERSATION_TURN_CAP_BYTES — content > this spills to a sidecar file
ContextToolEvictAfterTurns int // AURA_CONTEXT_TOOL_EVICT_AFTER_TURNS — L1 microcompact eviction age
HistoryHardCapTurns int // AURA_HISTORY_HARD_CAP_TURNS — L2.5 picobot hard rolling buffer cap
RunDirWarnThresholdBytes int // AURA_RUN_DIR_WARN_THRESHOLD_BYTES — boot du WARN threshold (audit-only)
RunDirSweepIntervalSec int // AURA_RUN_DIR_SWEEP_INTERVAL_SEC — periodic sidecar-sweep cadence in `serve` (M-06); <=0 disables the worker (boot sweep still runs)
// Phase 7 (Slice 5) web_search/web_fetch knobs. SearxngURL is the upstream-
// canonical name (NO AURA_ prefix); an empty value is NOT boot-fatal — it is
// surfaced as web_search_unavailable{searxng_not_configured} at call time
// (D-05/D-06) so `aura db migrate` and every non-web subcommand keep working.
// No allowlist/loopback escape hatch lands here (D-30).
SearxngURL string // SEARXNG_URL — local SearXNG /search endpoint; empty default, fail-closed at call time
WebDNSPinTTLSec int // AURA_WEB_DNS_PIN_TTL_SEC — per-conversation DNS pin TTL (D-25)
WebFetchMaxBodyBytes int // AURA_WEB_FETCH_MAX_BODY_BYTES — raw HTTP response body download ceiling (DoS guard); the LLM-facing markdown preview/spillover is governed by the agent tool-result preview cap (tools.NewResult), NOT this field
WebCachePersistent bool // AURA_WEB_CACHE_PERSISTENT — opt-in disk cache; default false = in-memory (D-32)
WebSearchTimeoutSec int // AURA_WEB_SEARCH_TIMEOUT_SEC — search wall-clock deadline (D-14)
WebFetchTimeoutSec int // AURA_WEB_FETCH_TIMEOUT_SEC — fetch wall-clock deadline (D-23)
WebUserAgent string // AURA_WEB_USER_AGENT — Aura-specific UA, no browser spoof (D-34/D-35)
// Phase 9 (Slice 3) swarm knobs (D-11/D-12/D-13). All non-fatal
// envIntDefault fallbacks — a typo falls back rather than booting fatal.
MaxSwarmGoals int // AURA_SWARM_MAX_GOALS — hard cap on goals per swarm_spawn call (D-13)
SwarmChildTimeoutSec int // AURA_SWARM_CHILD_TIMEOUT_SEC — per-child wall-clock deadline (D-11)
MaxSwarmConcurrent int // AURA_SWARM_MAX_CONCURRENT — wave width; goals beyond this run in sequential waves (D-12)
// Scheduler agent_job wall-clock (#53/D-42). The 120s swarm-child analog starved
// real artifact jobs (a North-Star-class xlsx run measures 150-360s live); the
// serve composition root passes this into AgentDeps.MaxDuration.
AgentJobMaxDurationSec int // AURA_AGENT_JOB_MAX_DURATION_SEC — agent_job end-to-end wall-clock deadline
// SchedulerPreferOriginChannel is the default-on kill-switch (Phase 20 R5/D-03):
// when on, a scheduled notification with an owning identity prefers the origin
// channel (a Telegram reminder lands back in that DM) over the per-task route. The
// composition root injects it as cron.DispatchDeps.PreferOriginChannel; false →
// byte-identical legacy route-only behavior. Unset/malformed → on.
SchedulerPreferOriginChannel bool // AURA_SCHEDULER_PREFER_ORIGIN_CHANNEL — prefer the origin channel over the route (default true)
// Phase 11 (Slice 7) skills knobs (D-34). SkillsDir is the active skill root the
// loader scans + builtins materialize into; ExportDir is the ro `/skills` mount
// source. Cap knobs bound the per-skill body and the model-visible manifest.
SkillsDir string // AURA_SKILLS_DIR — active skill root (loader scan + builtin materialization)
SkillBodyCapBytes int // AURA_SKILL_BODY_CAP_BYTES — per-skill body size cap at load (DoS guard, D-34)
SkillManifestCapBytes int // AURA_SKILL_MANIFEST_CAP_BYTES — manifest-in-Description byte budget; overflow → BM25 list (D-09/D-34)
SkillExportDir string // AURA_SKILL_EXPORT_DIR — activation→host export dir (the ro /skills mount source, D-17)
SkillSnippetTTLDays int // AURA_SKILL_SNIPPET_TTL_DAYS — TTL sweep archives snippets unused this long (D-16/D-34)
// Write-boundary injection blocklist (D-27/D-34). The NFKC-normalize-then-
// match literal sequence list the skills validator enforces at write time
// (model-authored create/update/install), NEVER on load (D-28). Defaults to
// the prd.md §Slice 7 builtin list; a comma-separated AURA_SKILL_INJECTION_BLOCKLIST
// replaces it wholesale.
SkillInjectionBlocklist []string // AURA_SKILL_INJECTION_BLOCKLIST — prompt-injection literal blocklist (D-27/D-34)
// Phase 12 (Slice 8) AG-UI gateway knobs. AGUIBind is the cockpit HTTP bind: it
// defaults to loopback but may be ANY address — WEB-02/D-06 lifted the historical
// hardcoded-loopback restriction (amendment #35) and replaced it with the boot-time
// GuardWebBind policy (loopback always boots; a non-loopback bind requires a web-auth
// credential). AGUICORSPermissive gates the `Access-Control-Allow-Origin: *` header
// (default restrictive, dev-only). AGUIBufferCap caps the per-connection SSE pump
// channel (drop-on-full, never blocks the Loop). All non-fatal envDefault fallbacks.
AGUIBind string // AURA_AGUI_BIND — cockpit HTTP bind (any address; non-loopback gated by GuardWebBind)
AGUICORSPermissive bool // AURA_AGUI_CORS_PERMISSIVE — dev-only permissive CORS (default restrictive)
AGUIBufferCap int // AURA_AGUI_BUFFER_CAP — SSE/fanout subscriber buffer cap (default 64)
// Industrial asset object-store foundation. The backend is selected by the
// later asset service; config is intentionally non-fatal so DB/migration paths
// do not depend on Garage being reachable.
ObjectStoreBackend string // AURA_OBJECTSTORE_BACKEND — garage|filesystem-dev|fake
ObjectStoreEndpoint string // AURA_OBJECTSTORE_ENDPOINT — S3-compatible internal endpoint
ObjectStorePublicEndpoint string // AURA_OBJECTSTORE_PUBLIC_ENDPOINT — optional presign URL host rewrite
ObjectStoreRegion string // AURA_OBJECTSTORE_REGION — Garage/S3 region
ObjectStoreBucket string // AURA_OBJECTSTORE_BUCKET — asset bucket
ObjectStoreAccessKey string // AURA_OBJECTSTORE_ACCESS_KEY — S3 access key
ObjectStoreSecretKey string // AURA_OBJECTSTORE_SECRET_KEY — S3 secret key
ObjectStorePathStyle bool // AURA_OBJECTSTORE_PATH_STYLE — Garage requires path-style by default
AssetMaxDocumentBytes int // AURA_ASSET_MAX_DOCUMENT_BYTES — document upload ceiling
AssetMaxImageBytes int // AURA_ASSET_MAX_IMAGE_BYTES — image upload ceiling
AssetMaxAudioBytes int // AURA_ASSET_MAX_AUDIO_BYTES — audio upload ceiling
AssetPresignTTLSec int // AURA_ASSET_PRESIGN_TTL_SEC — upload URL lifetime
AssetProcessingConcurrent int // AURA_ASSET_PROCESSING_CONCURRENCY — future asset worker width
TelegramAPIBaseURL string // TELEGRAM_API_BASE_URL — optional local Bot API base
TelegramFileBaseURL string // TELEGRAM_FILE_BASE_URL — optional local Bot API file base
TelegramLocalBotAPI bool // AURA_TELEGRAM_LOCAL_BOT_API — local Bot API toggle
// Phase 24 (WEB-02/WEB-03) web-auth knobs. Neither is boot-fatal on its own —
// GuardWebBind decides at boot whether a non-loopback AGUIBind may start. A loopback
// bind boots with both unset (dev parity, exactly as before).
WebAuthSecret string // AURA_WEB_AUTH_SECRET — operator login passphrase + HMAC cookie-key source; empty default, NOT boot-fatal (GuardWebBind decides)
WebTrustProxy bool // AURA_WEB_TRUST_PROXY — operator vouches a reverse proxy terminates auth (D-05)
// Authula web-auth provider knobs (docs/cockpit-overhaul/05-authula-auth-SPEC.md).
// WebAuthProvider is the migration feature flag: "passphrase" (default — the existing
// stdlib HMAC login is untouched) or "authula" (the embedded Authula framework
// validates the session cookie). The flag is read once at boot; flipping it back to
// passphrase is the M2 rollback safety net (env + one restart). The other three are
// inert while the flag is passphrase.
WebAuthProvider string // AURA_WEB_AUTH_PROVIDER ∈ {passphrase, authula} (default passphrase)
AuthulaDatabaseURL string // AURA_AUTHULA_DATABASE_URL — Postgres DSN for the authula schema; empty default → derived from AURA_DB_URL with ?search_path=authula
AuthulaSecret string // AURA_AUTHULA_SECRET — 32-byte hex secret Authula derives its HMAC/token keys from (required when provider=authula)
AuthulaOperatorIdentity string // AURA_AUTHULA_OPERATOR_IDENTITY — Aura identity name the Authula operator user binds to (default "local")
// ServeShutdownGraceSec bounds the in-flight turn drain on a SIGTERM/SIGINT
// (audit O-06 / AP-17): on the signal the daemon stops accepting new work, then
// gives in-flight turns up to this window to reach a terminal frame before the
// work ctx is hard-cancelled as the final backstop. Default 25s — a real turn
// rarely exceeds it; a misconfigured non-positive value degrades to immediate
// hard-cancel (no wedge).
ServeShutdownGraceSec int // AURA_SERVE_SHUTDOWN_GRACE_SEC — bounded in-flight turn drain window on shutdown (default 25)
// Phase 13 (Slice 9) channels + setup-wizard + multimodal knobs. Aura-native
// knobs use the AURA_<DOMAIN>_<UNIT> convention; third-party sidecars keep
// upstream naming (MULTIMODAL_*/STT_*/TTS_*) per the CLAUDE.md exception. All
// non-fatal silent-fallback loads — a typo falls back, never boots fatal.
//
// SetupBind is a loopback default on a port DISTINCT from the AG-UI :9080
// (T-13-04-SetupExposure: the loopback bind IS the compensating control; the
// override exists only for a deliberate remote-QR scan, token gate is plan
// 13-07). SetupToken empty default → a random UUIDv4 is generated and printed
// to stdout on first boot (plan 13-07), never read from disk here.
SetupBind string // AURA_SETUP_BIND — loopback setup-wizard HTTP bind, distinct from :9080
SetupToken string // AURA_SETUP_TOKEN — setup-API gate; empty → generated at boot (13-07)
// VisionCloud routes image understanding: false (default) → local aura-ocr-vl
// sidecar; true → OpenRouter/minimax-m3 cloud (no GPU). One env branch, zero
// code dup (#60 / Pitfall 6).
VisionCloud bool // AURA_VISION_CLOUD — false=local GLM-OCR sidecar, true=cloud vision
// Multimodal sidecar URLs/models (upstream naming, CLAUDE.md third-party
// exception). MultimodalFallbackModel is the cloud vision model used when
// VisionCloud is true and the primary model lacks SupportsVision.
MultimodalBaseURL string // MULTIMODAL_BASE_URL — aura-ocr-vl OpenAI-compat base
MultimodalModel string // MULTIMODAL_MODEL — local vision model id
MultimodalFallbackModel string // MULTIMODAL_FALLBACK_MODEL — cloud vision fallback (default minimax/minimax-m3)
STTBaseURL string // STT_BASE_URL — aura-stt OpenAI-compat base
STTModel string // STT_MODEL — speech-to-text model id
STTLanguage string // STT_LANGUAGE — transcription language hint (default "it"; "" = whisper auto-detect, unreliable on short clips — spike-027)
TTSBaseURL string // TTS_BASE_URL — aura-tts OpenAI-compat base
TTSVoice string // TTS_VOICE — Kokoro voice id (default if_sara)
TTSFormat string // TTS_FORMAT — voice-note audio format (default opus)
DocumentsBaseURL string // DOCUMENTS_BASE_URL — markitdown /convert base (UX-04 documents leg)
MultimodalTimeoutSec int // MULTIMODAL_TIMEOUT_SEC — per-request sidecar ceiling (default 120s; CPU OCR on a downscaled photo is well under, but vision needs more headroom than STT/TTS)
// Phase 14 (Slice 10) Agent.md profile knobs.
ProfileDir string // AURA_PROFILE_DIR — per-identity Agent.md root, default ~/.aura/agents
ProfileCertaintyN int // AURA_PROFILE_CERTAINTY_N — observation threshold for auto-add, default 3
}
Config is the root composite. Subsystem configs live in their packages.
func Load ¶
Load reads .env (best-effort) then populates a Config from environment variables. A missing .env file is not an error — production deployments rely on real environment variables, not on the .env shim.
Postgres DSN composition: AURA_DB_URL / AURA_DB_MIGRATE_URL overrides take precedence (production managed Postgres). Otherwise URLs are composed from POSTGRES_* primitives + AURA_DB_*_ROLE role names. Single POSTGRES_PASSWORD fans out to both runtime + DDL roles for local-dev ergonomics.
func LoadDB ¶
func LoadDB() *Config
LoadDB loads the non-LLM configuration only. DB-admin commands (aura db migrate/ping/status/reset) must NOT require an LLM API key — migration is a pure DB operation, and Load's fail-fast empty-key (D-22) would otherwise block `aura db migrate` wherever OPENROUTER_API_KEY is unset (notably CI's migrate step). LLM is left zero-value; DB commands never read it.
func LoadServe ¶
LoadServe reads the full daemon config but permits an empty LLM API key so the setup wizard and channels can boot. LLM turns still fail closed at call time.
func (*Config) Validate ¶
Validate fails fast on an empty REQUIRED infrastructure secret so a misconfigured deploy errors at boot with a named cause instead of a late, cryptic DB auth failure or a silently degraded graph (O-04). The LLM API key has its own fail-fast in llm.Load (D-22); this covers the composed DB DSN and the Neo4j password. The daemon/REPL boot wires it in; the DB-only commands (LoadDB) skip it.