# ADR-009: regulatory_posture as a fail-closed Policy Decision Point (PDP)

**Status:** accepted (2026-07-03; wording revised 2026-07-18).

**Context.** The oracle spans surfaces with different regulatory sensitivity, from surfaces that would be squarely regulated anywhere (custody) through surfaces this project treats with precaution (scored queries, a named-rail results table, routing evaluation outputs) to ones that carry no score, rank, or intent parameter (the Tier-2 lookup, the methodology form). What is live versus built-but-inert must be enforced in code, not asserted in prose or hidden behind a UI flag.

**Decision.** Build the full capability; gate live emission. Every surface that could emit a gated output routes through one fail-closed canEmit(mechanic, context) PDP driven by a regulatory_posture config keyed by gate: G_AUTH (authorisation), G_QF (self-deploy), G_S21 (financial promotion), G_CUSTODY (custody). A mechanic emits iff all its required gates are open AND its emission invariants hold (ADR-007's intent-free contract among them). Default deny; an unknown gate is treated as closed. Flipping a gate is one config value plus a redeploy (not a migration, not an unhide); each flip carries an audit record tying it to its trigger (for example a change in the applicable legal position). Invariants are enforced as CI property tests against the live-posture config, not asserted in prose. One codebase, two posture configs (testnet and live): the gated path is proven to work under testnet posture and proven inert under live posture, so build-to-the-invariant-now and build-for-after-the-flip are one build. The financial-promotion gate (G_S21, the named-rail table) and the gates the scored query consults (G_AUTH / G_QF) never share a flag: they answer different questions.

**Rationale.** The gate is deliberately classification-agnostic: this project builds precautionary guardrails around any regulation-adjacent surface as standard practice, whatever a surface's ultimate classification, and the gate's existence concedes nothing about any classification. A single fail-closed decision point with a default-deny posture is auditable and testable; hidden-but-present is neither. A guardrail you cannot inspect is an assertion; a guardrail in public code, with public config and public tests, is evidence of diligence. Keying by gate lets each surface cross to live on its own trigger without coupling to the others.

**Options considered.** (a) Hide gated surfaces behind a feature flag or unpublished route: rejected; hidden is not enforced and not demonstrable. (b) Separate codebases for testnet and live: rejected; divergence risk and double maintenance. (c) One shared flag for all gates: rejected; it conflates independent triggers (financial promotion versus authorisation).

**Consequences.** All gated emission passes canEmit. The oracle owns the shared regulatory_posture config (config/regulatory_posture.testnet.json and config/regulatory_posture.live.json). Gate flips are config-plus-redeploy with an audit record.

**Related:** ADR-007 (the intent-free invariant this PDP enforces); the tiered-schema design.
