Documentation
¶
Overview ¶
Package config defines wowapi's typed configuration contracts: the framework-owned Framework struct, the Secret type with structural redaction, and the ModuleView through which modules receive their namespaced configuration.
Ownership model, precedence, and loader behavior are specified in docs/blueprint/12-configuration-and-deployment.md. Phase 0 ships the core types and validation; the layered loader (files → overlay → env vars → secret resolution) lands in Phase 1.
Product applications compose rather than fork: they define their own Config type embedding Framework in an internal/appcfg package (scaffolded by `wowapi init`).
Index ¶
- Constants
- func Schema[T any]() ([]byte, error)
- type CSRF
- type CapacityMode
- type CapacityProblem
- type Concurrency
- type CookieDefaults
- type DB
- type Env
- type Fingerprint
- type Framework
- type HTTP
- type Layer
- type Loaded
- type Log
- type MapView
- type ModuleView
- type Namespaces
- type Options
- type Overload
- type Pool
- type Privileged
- type PrivilegedGrant
- type Provenance
- type RateLimit
- type Secret
- func (s Secret) Format(f fmt.State, verb rune)
- func (s Secret) GoString() string
- func (s Secret) IsZero() bool
- func (s Secret) LogValue() slog.Value
- func (s Secret) MarshalJSON() ([]byte, error)
- func (s Secret) MarshalText() ([]byte, error)
- func (s Secret) Ref() string
- func (s Secret) Reveal() string
- func (s Secret) String() string
- func (s *Secret) UnmarshalText(b []byte) error
- type Security
- type SecurityProfile
- type SharedSection
- type Telemetry
- type Webhook
- type WebhookOutbound
Constants ¶
const SchemaVersion = 1
SchemaVersion is the current config file format version. Loaders reject files declaring a newer version (config written for a newer wowapi) and files older than the supported floor.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type CSRF ¶ added in v1.1.0
type CSRF struct {
CookieName string `conf:"cookie_name" default:"csrf_token" json:"cookie_name" doc:"name of the CSRF token cookie set for browser clients"`
HeaderName string `conf:"header_name" default:"X-CSRF-Token" json:"header_name" doc:"request header the client must echo the CSRF token in"`
FieldName string `` /* 142-byte string literal not displayed */
}
CSRF names the cookie/header/form-field pair used by the double-submit- cookie CSRF defense (kernel/httpx.CSRFProtect). Both names must be non-empty when Profile is browser.
type CapacityMode ¶ added in v1.1.0
type CapacityMode string
CapacityMode selects whether an oversubscribed deployment shape fails boot or only warns.
const ( // CapacityModeAdvisory warns (CheckCapacity) without failing Validate. // This is the default so shipping this feature cannot break an existing // deployment that hasn't sized its shape knobs yet. CapacityModeAdvisory CapacityMode = "advisory" // CapacityModeEnforced fails Validate on an oversubscribed shape. Opt-in. CapacityModeEnforced CapacityMode = "enforced" )
type CapacityProblem ¶ added in v1.1.0
type CapacityProblem struct {
Replicas int
RuntimePoolMax int
PlatformPoolMax int
MigratePoolMax int
ReservedAdmin int
Demand int
DBMaxConns int
}
CapacityProblem describes a failed capacity-budget check: the computed demand exceeded the database's max_conns.
func CheckCapacity ¶ added in v1.1.0
func CheckCapacity(f Framework) *CapacityProblem
CheckCapacity evaluates the deployment-shape formula from benchmark §Concurrency:
replicas*(runtime_pool_max+platform_pool_max) + migrate_pool_max + reserved_admin <= db_max_connections
It returns nil when Replicas is 0 (shape not configured — the check is a deliberate no-op so an unconfigured product never gets a spurious result) or when the shape fits; otherwise it returns a *CapacityProblem describing the oversubscription. Callers decide what to do with a non-nil result: Validate() (via checkCapacityEnforced) turns it into a hard failure only in CapacityModeEnforced; the CLI (`wowapi config capacity`) and boot-time logging always print it regardless of mode.
func (*CapacityProblem) Error ¶ added in v1.1.0
func (p *CapacityProblem) Error() string
type Concurrency ¶ added in v1.1.0
type Concurrency struct {
// HTTPMaxInFlight bounds concurrent in-flight HTTP requests via a bounded
// semaphore in kernel/httpx's backpressure middleware. 0 disables the
// limiter (pass-through) — the safe default for existing deployments.
HTTPMaxInFlight int `` /* 146-byte string literal not displayed */
// WorkerMaxJobs mirrors kernel/jobs' runner pool size for capacity
// bookkeeping; it does not itself change runner behavior (products still
// configure the runner via jobs.WithPoolSize). 0 means "not tracked" here.
WorkerMaxJobs int `` /* 134-byte string literal not displayed */
// PlatformMaxInFlight bounds concurrent in-flight requests specifically
// against the platform (cross-tenant) pool, e.g. API-key verification.
// 0 means "not tracked" — no separate platform limiter is installed.
PlatformMaxInFlight int `` /* 139-byte string literal not displayed */
// Replicas is the number of process replicas of THIS deployment (api or
// worker) sharing the same database. 0 means "not configured" and the
// entire capacity-budget check (CheckCapacity) is skipped — the formula is
// undefined without a declared shape, so leaving this unset must never
// produce a spurious pass or fail.
Replicas int `` /* 139-byte string literal not displayed */
// RuntimePoolMax is the runtime (app_rt) pool's max_conns as budgeted per
// replica. Distinct from db.max_conns (a single pool's own cap): this is
// the value the deployment-shape formula multiplies by Replicas. Typically
// equal to db.max_conns for a single-pool-per-process deployment.
RuntimePoolMax int `` /* 133-byte string literal not displayed */
// PlatformPoolMax is the platform (app_platform) pool's max_conns per
// replica.
PlatformPoolMax int `` /* 136-byte string literal not displayed */
// MigratePoolMax is the one-shot migrate process's pool max_conns (not
// multiplied by Replicas: migrations run as a single job, not per-replica).
MigratePoolMax int `` /* 128-byte string literal not displayed */
// ReservedAdmin is connections held back for admin/operator access
// (psql, pgAdmin, an emergency migration) that must always fit under
// db_max_connections alongside the application's own budget.
ReservedAdmin int `` /* 148-byte string literal not displayed */
// CapacityMode gates whether an oversubscribed shape fails boot
// ("enforced") or only warns ("advisory", the default — see rollout
// guidance on the Concurrency type doc).
CapacityMode CapacityMode `` /* 168-byte string literal not displayed */
Overload Overload `conf:"overload" json:"overload"`
}
Concurrency is the framework's capacity-budget model (backlog B6, benchmark §Concurrency: "Capacity Budget Instead Of Independent Knobs"). Today's knobs — HTTP body/timeout limits, the per-client rate limiter, DB pool size, job runner pool size — are each independently bounded but nothing reasons about them TOGETHER across a deployment shape. Concurrency adds:
An in-flight HTTP request cap (HTTPMaxInFlight) enforced by a backpressure middleware (kernel/httpx) that rejects with a configured overload status BEFORE the DB pool is exhausted.
Deployment-shape knobs (Replicas, RuntimePoolMax, PlatformPoolMax, MigratePoolMax, ReservedAdmin) that feed the capacity-budget formula:
replicas*(runtime_pool_max+platform_pool_max) + migrate_pool_max + reserved_admin <= db.max_conns
checked by CheckCapacity / enforced by Validate per CapacityMode.
A worker pool cap (WorkerMaxJobs) mirroring kernel/jobs' poolSize knob, carried here so the same capacity budget can account for worker concurrency alongside HTTP (kernel/jobs itself is unaffected — this is advisory bookkeeping, not a new enforcement point in the runner).
ROLLOUT (backlog B6 risk: "default budget too tight breaks existing deploys — ship advisory-then-enforced"):
- CapacityMode defaults to "advisory": an oversubscribed shape is reported (CheckCapacity returns a non-nil warning; the boot path and `wowapi config capacity` print it) but Validate() does NOT fail. Existing deployments that haven't set Replicas/pool-max knobs are entirely unaffected — CheckCapacity is a no-op while Replicas == 0 (unconfigured).
- CapacityMode: "enforced" flips Validate() to fail closed on the same oversubscribed shape. A product opts in only after using `wowapi config capacity` (or the advisory boot warning) to size its deployment shape correctly.
- HTTPMaxInFlight defaults to 0, which the backpressure middleware treats as "disabled" (pass-through, no limiter installed) — a bounded semaphore is only sized and wired once a product sets a cap explicitly. No current deployment starts returning the overload status unexpectedly.
func ConcurrencyDefaults ¶ added in v1.1.0
func ConcurrencyDefaults() Concurrency
ConcurrencyDefaults returns the safe, zero-impact defaults: no in-flight limiter installed (HTTPMaxInFlight=0), no deployment shape declared (Replicas=0, so CheckCapacity is a no-op), advisory capacity mode, and a 503+2s overload response for when a product DOES opt in.
type CookieDefaults ¶ added in v1.1.0
type CookieDefaults struct {
// SameSite is one of "strict", "lax", or "none" (case-insensitive on
// input; canonicalized to lowercase). "lax" is the safe, commonly-usable
// default recommended by OWASP for session-adjacent cookies.
SameSite string `conf:"same_site" default:"lax" json:"same_site" doc:"cookie SameSite attribute: strict|lax|none"`
// Secure marks cookies HTTPS-only. Required (validated) when SameSite is
// "none", since browsers reject SameSite=None without Secure.
Secure bool `conf:"secure" default:"true" json:"secure" doc:"set the Secure attribute on cookies (required when same_site=none)"`
}
CookieDefaults configures the SameSite/Secure attributes applied to cookies the browser profile sets. This is CSRF-token issuance policy only — the framework does not build or own a session store (backlog B7 scope: token issuance/validation, not session management).
type DB ¶
type DB struct {
DSN Secret `conf:"dsn" json:"dsn" doc:"runtime database DSN (app_rt role) as a secretref:// reference"`
MigrateDSN Secret `` /* 142-byte string literal not displayed */
PlatformDSN Secret `` /* 444-byte string literal not displayed */
Pool // embedded: pool knobs stay flat under db.* and flow to every process view wholesale
}
DB configures the Postgres pools. DSNs are optional at load time and validated at process-view narrowing instead: api/worker require DSN, migrate requires MigrateDSN (D-0021) — the framework repo's config tooling and DB-less tests must stay loadable.
type Env ¶
type Env string
Env is the deployment environment. It gates dev-only behavior: anything marked unsafe refuses to run when the environment is Prod.
type Fingerprint ¶
Fingerprint identifies an effective configuration: the SHA-256 of its canonical *redacted* JSON rendering. Secret values never enter the hash (Secret marshals as its redaction marker), so the fingerprint is safe to log, expose as a metric label, and include in /readyz output — and two processes sharing config sections can be compared for drift (12 §7).
Note the redaction consequence: rotating a secret's VALUE (same ref) does not change the fingerprint; changing the reference does.
func FingerprintOf ¶
func FingerprintOf(v any) (Fingerprint, error)
FingerprintOf hashes the canonical redacted JSON rendering of v. v is normally a bound config struct; json.Marshal is deterministic for structs (field order) and maps (sorted keys), making the hash canonical.
func Load ¶
func Load[T any](opts Options) (T, Fingerprint, error)
Load computes the effective configuration exactly once, at boot: compiled defaults ← base file ← env overlay ← env vars ← flags, then secret resolution, then validation. It fails with ALL problems joined, never just the first (blueprint 12 §3–4).
func (Fingerprint) Short ¶
func (f Fingerprint) Short() string
Short returns the first 12 hex chars — enough for log correlation.
func (Fingerprint) String ¶
func (f Fingerprint) String() string
String returns the full lowercase hex digest.
type Framework ¶
type Framework struct {
// Environment carries NO default tag: it is fail-closed (D-0010/SEC-1) —
// the loader errors when it is absent from every layer. The compiled
// `local` value exists only through Defaults() for tests/local tooling.
Environment Env `` /* 135-byte string literal not displayed */
SchemaVersion int `conf:"schema_version" default:"1" json:"schema_version" doc:"config file format version"`
HTTP HTTP `conf:"http" json:"http"`
Log Log `conf:"log" json:"log"`
DB DB `conf:"db" json:"db"`
Telemetry Telemetry `conf:"telemetry" json:"telemetry"`
Webhook Webhook `conf:"webhook" json:"webhook"`
Privileged Privileged `conf:"privileged" json:"privileged"`
Security Security `conf:"security" json:"security"`
Concurrency Concurrency `conf:"concurrency" json:"concurrency"`
}
Framework is the framework-owned configuration. It is loaded and validated once at boot and is immutable afterwards; hot paths read precomputed values, never stores. Fields grow phase by phase with the components that consume them (DB in Phase 2, Auth in Phase 4, …).
func Defaults ¶
func Defaults() Framework
Defaults returns the compiled framework defaults — the always-present, always-safe bottom layer of the precedence chain.
func (Framework) CheckSharedDrift ¶
CheckSharedDrift reports an error when this process's shared-config fingerprint differs from expected (the hex fingerprint the deployment pins, e.g. via an env var stamped at release). An empty expected disables the check. Wire it as a startup gate or a /readyz check so a mis-deployed process fails loudly rather than silently diverging.
func (Framework) SharedFingerprint ¶
func (f Framework) SharedFingerprint() (Fingerprint, error)
SharedFingerprint is the fingerprint of the shared section only — the value api/worker/migrate compare to detect drift. Like Fingerprint it is redacted (secret VALUES never enter it), so it is safe to log and expose.
func (Framework) SharedSection ¶
func (f Framework) SharedSection() SharedSection
SharedSection extracts the cross-process-shared configuration.
type HTTP ¶
type HTTP struct {
Addr string `conf:"addr" default:":8080" json:"addr" doc:"HTTP listen address"`
ReadHeaderTimeout time.Duration `conf:"read_header_timeout" default:"5s" json:"read_header_timeout" doc:"maximum time to read request headers"`
RequestTimeout time.Duration `conf:"request_timeout" default:"30s" json:"request_timeout" doc:"per-request handler timeout"`
MaxBodyBytes int64 `conf:"max_body_bytes" default:"1048576" json:"max_body_bytes" doc:"maximum request body size in bytes"`
// CORSAllowedOrigins is the exact-match CORS allowlist (deny-by-default when
// empty). Set per environment, e.g. modules-free base leaves it empty and the
// prod overlay lists the product's web origins.
CORSAllowedOrigins []string `` /* 127-byte string literal not displayed */
RateLimit RateLimit `conf:"rate_limit" json:"rate_limit"`
}
HTTP holds server guardrails. Zero values are replaced by Defaults.
type Layer ¶
type Layer string
Layer identifies which precedence layer supplied a config value (blueprint 12 §3; surfaced by `wowapi config doctor`).
const ( LayerDefault Layer = "default" // compiled default tag LayerBaseFile Layer = "base-file" // configs/base.yaml LayerEnvFile Layer = "env-file" // configs/<env>.yaml overlay LayerEnvVar Layer = "env" // PREFIX__SECTION__FIELD environment variable LayerFlag Layer = "flag" // local-only CLI flag LayerSecret Layer = "secret" // value resolved through the secret provider )
type Loaded ¶
type Loaded[T any] struct { Config T Fingerprint Fingerprint Provenance Provenance // Warnings carries non-fatal findings (e.g. unsafe knobs enabled in stage). Warnings []string }
Loaded is the full result of LoadDetailed.
type Log ¶
type Log struct {
Level string `conf:"level" default:"info" json:"level" doc:"log level: debug|info|warn|error"`
Format string `conf:"format" default:"json" json:"format" doc:"log output format: json|text (prod requires json)"`
}
Log configures structured logging.
type MapView ¶
MapView is a ModuleView backed by an in-memory map. The loader produces these from the `modules.<name>` subtree; tests construct them directly.
type ModuleView ¶
type ModuleView interface {
// Decode strict-decodes the module's namespace into the module-owned
// typed struct. Unknown keys in the namespace are an error (typo
// defense); the module's own validation runs after decoding. Errors here
// fail application boot.
Decode(out any) error
}
ModuleView is the ONLY configuration surface a module receives (via module.Context.Config()). It exposes exactly the module's own `modules.<name>.*` namespace: there is deliberately no Get(key), no parent traversal, and no way to read framework or sibling-module configuration.
type Namespaces ¶
Namespaces is the raw `modules.*` subtree of a product configuration: one isolated MapView per module name. The binder captures the subtree opaquely (module keys are validated by each module's own strict Decode, not by the framework binder), and the app hands each module exactly its own view — there is no API to traverse from a view back to framework, product, or sibling configuration.
type Options ¶
type Options struct {
// BaseFile is the committed product config file (configs/base.yaml).
BaseFile string
// EnvFile is the environment overlay (configs/<env>.yaml).
EnvFile string
// EnvPrefix enables the environment-variable layer:
// "ACME__" maps ACME__DB__MAX_CONNS=32 onto db.max_conns. Empty = no env layer.
EnvPrefix string
// Environ supplies the environment ("KEY=VALUE" pairs); nil = os.Environ().
Environ []string
// Secrets resolves secretref:// values at boot. Required if any Secret
// field is set; resolution failures fail the load.
Secrets secrets.Provider
// Flags holds local-tooling overrides by dotted key ("http.addr" → value).
// The loader refuses to start when flags are set and environment=prod.
Flags map[string]string
}
Options configures a Load call. Zero-value fields skip their layer.
type Overload ¶ added in v1.1.0
type Overload struct {
// Status is the HTTP status code written on overload. Defaults to 503
// (Service Unavailable) per benchmark §Concurrency; some deployments may
// prefer 429 (Too Many Requests) to align with rate-limit semantics —
// either is accepted, anything else is rejected by Validate.
Status int `conf:"api_status" default:"503" json:"api_status" doc:"HTTP status returned on overload (503 or 429)"`
// RetryAfter is the Retry-After hint (seconds, rounded up) sent with the
// overload response.
RetryAfter time.Duration `conf:"retry_after" default:"2s" json:"retry_after" doc:"Retry-After hint sent with the overload response"`
}
Overload configures the response the backpressure middleware sends when HTTPMaxInFlight is exceeded.
type Pool ¶
type Pool struct {
MaxConns int `conf:"max_conns" default:"16" json:"max_conns" doc:"maximum pool connections"`
QueryTimeout time.Duration `conf:"query_timeout" default:"5s" json:"query_timeout" doc:"per-query context deadline"`
}
Pool holds the connection-pool knobs shared by every process view. New pool fields belong HERE, never directly on DB: the app views embed Pool, so additions propagate to api/worker/migrate narrowing automatically instead of silently dropping out of a hand-copied field list (ARCH-17).
type Privileged ¶ added in v1.1.0
type Privileged map[string]PrivilegedGrant
Privileged is the product config section that widens a module's kernel/privileged ownership beyond its own name-prefixed keys (backlog B10; evidence app/context.go — module.Context.Privileged() used to construct privileged.New with an always-empty privileged.Config, so a product could only reach a cross-namespace or kernel-owned relationship type / rule key by building its own privileged.Services outside the standard module.Context path). It maps a module name to the extra relationship types / rule keys that module is allowed to manage via mc.Privileged().
SECURITY (fail closed): every entry must be a concrete, fully-spelled relationship-type or rule-key string. Wildcards, glob syntax, and empty entries are REJECTED at boot by Validate — see the doc comment there for the exact rule. There is no "allow everything" escape hatch; each grant must be enumerated explicitly, one string per key, reviewable in a diff.
The zero value (nil map, or a module absent from it) changes NOTHING: that module keeps exactly today's prefix-only ownership.
func (Privileged) Validate ¶ added in v1.1.0
func (p Privileged) Validate() error
Validate enforces the explicit-enumeration rule (fail closed): every AllowRelTypes/AllowRuleKeys entry, for every module, must be a non-empty, whitespace-free, glob-free concrete string, and every module name (map key) must be non-empty. Like Framework.Validate, it collects ALL problems and joins them rather than stopping at the first.
type PrivilegedGrant ¶ added in v1.1.0
type PrivilegedGrant struct {
// AllowRelTypes lists relationship-type keys (relationship_types.key) this
// module may Grant/Revoke beyond its own "<module>." prefix, e.g. a kernel
// "core.owner_of" type a product module is sanctioned to grant.
AllowRelTypes []string `` /* 142-byte string literal not displayed */
// AllowRuleKeys lists rule keys (rule_definitions.key) this module may
// activate tenant versions of, beyond its own "<module>." prefix.
AllowRuleKeys []string `` /* 131-byte string literal not displayed */
}
PrivilegedGrant is one module's allow-list. Both fields feed directly into privileged.Config{AllowRelTypes, AllowRuleKeys} (kernel/privileged) — see app/context.go's moduleContext.Privileged().
type Provenance ¶
Provenance maps dotted config keys to the layer that supplied their value.
type RateLimit ¶
type RateLimit struct {
Disabled bool `conf:"disabled" json:"disabled" doc:"set true to remove the default per-client rate limiter from the chain"`
RequestsPerSecond float64 `conf:"requests_per_second" default:"20" json:"requests_per_second" doc:"sustained requests/sec per client key (per replica)"`
Burst int `conf:"burst" default:"40" json:"burst" doc:"burst capacity per client key"`
}
RateLimit configures the in-process per-client rate limiter that the generated api installs in its default middleware chain (roadmap S2/CA-2). It is OPT-OUT: enabled unless Disabled is set, so a scaffolded product is protected against resource-exhaustion by default. Limits are guardrails, not billing.
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret holds a resolved secret value with structural redaction: every standard rendering path (fmt verbs, JSON/text marshaling, slog) emits a redaction marker, never the value. The raw value is reachable only via Reveal, whose call sites are restricted by boundary lint to adapters and the app composition root.
The zero Secret is empty and renders as "[redacted]".
func (Secret) Format ¶
Format implements fmt.Formatter so every fmt verb (%v, %+v, %s, %q, %x, …) renders the redaction marker.
func (Secret) MarshalJSON ¶
MarshalJSON redacts. Secrets are never serialized as values.
func (Secret) MarshalText ¶
MarshalText redacts (covers yaml/text encoders that honor TextMarshaler).
func (Secret) Ref ¶
Ref returns the secret reference this value was resolved from ("" if none). Safe to log.
func (Secret) Reveal ¶
Reveal returns the raw secret value. Do not log it. Boundary lint flags Reveal calls outside adapters/, app/, and _test.go files.
func (*Secret) UnmarshalText ¶
UnmarshalText accepts only a secret *reference*; the value is resolved later, at boot, by the app composition root via a secrets.Provider. A raw (non-reference) value is rejected so plaintext secrets cannot enter through config files or environment variables.
type Security ¶ added in v1.1.0
type Security struct {
// Profile selects the security posture. Empty resolves to
// SecurityProfileAPI via DefaultSecurity()/Defaults() — see the fail-safe
// note on Validate().
Profile SecurityProfile `` /* 152-byte string literal not displayed */
// CSRF configures the double-submit-cookie token names. Only consulted
// when Profile is browser.
CSRF CSRF `conf:"csrf" json:"csrf"`
// Cookie configures SameSite/Secure defaults for any cookie the browser
// profile sets (the CSRF cookie today; a product's own session cookie
// should follow the same defaults). Only consulted when Profile is
// browser.
Cookie CookieDefaults `conf:"cookie" json:"cookie"`
// CSP overrides the Content-Security-Policy value applied by the browser
// profile's header chain. Empty uses a conservative built-in default
// (kernel/httpx.SecurityChain's browserCSPDefault). Only applied when
// Profile is browser — the API profile keeps httpx.SecureHeaders'
// existing "frame-ancestors 'none'" default untouched.
CSP string `conf:"csp" json:"csp" doc:"Content-Security-Policy value for the browser profile; empty uses the built-in HTML-safe default"`
}
Security is the framework-owned security-profile configuration (Framework field, loaded/validated once at boot like every other Framework section). CSRF and Cookie are only enforced/consulted when Profile is SecurityProfileBrowser; under SecurityProfileAPI they are inert (and may be left at their zero value).
func DefaultSecurity ¶ added in v1.1.0
func DefaultSecurity() Security
DefaultSecurity returns the compiled default: the API profile, exactly reproducing today's framework behavior. Framework-level Defaults() embeds this so a Framework zero value plus Defaults() always validates.
func (Security) Validate ¶ added in v1.1.0
Validate checks the security section. Like Framework.Validate it returns ALL problems joined. Under SecurityProfileAPI, CSRF/Cookie are not enforced — they may be zero-valued (the API profile ignores them by contract) — so a plain `Security{Profile: SecurityProfileAPI}` (as a hand-written config file might produce before defaults are applied) validates cleanly. Under SecurityProfileBrowser every field the CSRF middleware depends on must be coherent, since an incoherent browser profile would silently disable the CSRF defense (config validate must reject that, not boot into it).
type SecurityProfile ¶ added in v1.1.0
type SecurityProfile string
SecurityProfile selects the framework's security posture for a deployment.
const ( // SecurityProfileAPI is the DEFAULT profile: bearer/API-key auth, no // cookies, CSRF disabled by contract (there is no cookie-based session to // forge), strict JSON decoding, CORS allowlist, RLS guard. This is // exactly what wowapi does today — selecting it (or leaving Security // unset) changes NOTHING. SecurityProfileAPI SecurityProfile = "api" // SecurityProfileBrowser is the OPT-IN profile for products that serve a // browser/cookie-session client: it additionally wires CSRF token // enforcement on state-changing requests, SameSite cookie defaults, and a // CSP header suitable for HTML. No product gains this behavior by // selecting anything other than this profile. SecurityProfileBrowser SecurityProfile = "browser" )
func (SecurityProfile) Valid ¶ added in v1.1.0
func (p SecurityProfile) Valid() bool
Valid reports whether p is a known security profile.
type SharedSection ¶
type SharedSection struct {
}
SharedSection is the config subset that must match across every process of one deployment.
type Telemetry ¶
type Telemetry struct {
TraceSampleRatio float64 `` /* 176-byte string literal not displayed */
}
Telemetry configures distributed tracing (roadmap O1). Tracing is OFF by default (zero-cost NoOp tracer) and becomes active only when the sample ratio is > 0 — the composition root then wires the OTel adapter with this ratio, exporting to the OTLP endpoint named by the standard OTEL_EXPORTER_OTLP_ENDPOINT environment variable (e.g. http://jaeger:4318 in the compose stack). This is the real config key that replaces the previously-documented-but-nonexistent cfg.TraceSampleRatio (roadmap CA-2/CA-7).
type Webhook ¶ added in v1.1.0
type Webhook struct {
Outbound WebhookOutbound `conf:"outbound" json:"outbound"`
}
Webhook configures the webhook framework (kernel/webhook).
type WebhookOutbound ¶ added in v1.1.0
type WebhookOutbound struct {
SSRFProtectionDisabled bool `` /* 197-byte string literal not displayed */
AllowedHosts []string `` /* 150-byte string literal not displayed */
AllowedCIDRs []string `` /* 131-byte string literal not displayed */
}
WebhookOutbound configures outbound webhook delivery's SSRF protection (backlog B2). Outbound delivery targets are USER-CONFIGURABLE URLs (tenants register their own webhook endpoints), so by default every dial is guarded by kernel/httpclient: loopback, link-local (incl. the 169.254.169.254 cloud metadata address), RFC1918/ULA private ranges, and unspecified addresses are all refused. AllowedHosts/AllowedCIDRs are the escape hatch for intentional internal targets (e.g. a tenant's own internal relay); SSRFProtectionDisabled exists only for local/dev convenience against a hand-rolled test receiver. It is tagged `unsafe:"true"` — the framework's standard dev-only-knob gate (kernel/config/bind.go enforceUnsafe) refuses it at Load() time in prod and WARNS in stage; Validate() below additionally refuses it in prod as defense-in-depth for callers that build/validate a Framework value directly without going through Load() (e.g. tests).