# ADR-0046: v1 security release gate ## Status Accepted in M16 on 2026-08-27. ## Decision Treat the security review as a source of build-enforced properties rather than a point-in-time report. Every conclusion the M16 review reached by hand is encoded as a test: no shell execution, no arbitrary execution primitive, subprocess use allowlisted, no command route, AES-256-GCM from a reviewed library with a fresh nonce per chunk and fail-closed decryption, no privileged mode or Docker socket, no floating dependency specifier, datastores bound to loopback, capabilities dropped, and a console image that serves a build rather than a development server. Publish nothing on a network interface that is not authenticated for it. PostgreSQL, Redis and the operator console default to loopback; the API is published deliberately because every admin route is operator-authenticated. Inventory what shipped, not what was intended: read the Python SBOM from the built images, bind each image to its source commit, and classify every advisory with evidence rather than counting them. ## Consequences The most serious finding of M16 was configuration, not code: the control-plane database was published on every interface behind a development password, exposing provenance, credential hashes and the audit trail to the LAN. A test now fails if that binding returns. Encoding review conclusions as tests means M17 cannot quietly reintroduce them while packaging, and a future reviewer inherits the reasoning rather than having to rediscover it. The cost is friction: adding a subprocess call, a new route segment, or a dependency without a version now requires either a deliberate allowlist change or a failing build. That friction is the point. Some findings are correctly accepted rather than fixed. `pip` carried archive-extraction advisories and never runs at runtime, but leaving a known-vulnerable installer in a release image makes every future scan noisier, so the build upgrades it — a cheap fix is preferred to a standing exception even where the risk is not reachable.