ADR 0023: Complete policy approval statements and authorization-state verification
- Status: Accepted
- Date: 2026-09-24
Context
The initial shared approval-library draft passed its unit tests but did not establish the intended approval contract: it expected raw ES256 signatures, left envelope-receipt metadata unsigned, relied on updated trust bundles for successor keys, and hashed export metadata instead of resolved runtime state.
The corrected library must support independent approval verification under ADR 0022’s trusted-gateway boundary. It must not imply that approval signatures prove execution.
Decision
- Use WebAuthn-standard DER ES256 assertions. Require exact origin/RP/purpose binding and reject cross-origin approval ceremonies. Retain zero-counter support.
- Version approval receipts and customer checkpoints as v2, rejecting the unshipped v1 draft. Every assertion binds the complete receipt body, including envelope digest/version, sequence, predecessor, epoch and pre-activation authority digest. Existing Ed25519 signed-file formats remain unchanged.
- Include a versioned, typed
EffectiveStateprojection covering ordered exact component identities, configs/grants, expanded operation routes, resource limits, adapter identity, and concrete immutable destination bindings. Export name/version references and download checksums alone are insufficient. - Effective-state schema v2 represents destinations as tagged concrete HTTPS targets or a managed weighted-rendezvous topology with sorted, uniquely identified physical backends, placement/authority version and non-secret credential-version evidence. Presigned approval binds a declared origin and bucket, never a signature query. The v1 single-destination draft cannot authorize an enforced workspace; there are no deployed v1 approvals to migrate. ReceiptBody stays v2 and signs the entire v2 state; digest vectors change with that state rather than silently reinterpreting old bytes.
- Verify full history from independently pinned genesis authority, deriving each successor only from an authorized transition. The old authorized key signs the complete replacement credential/public key and retired credential identity; the replacement key countersigns the same statement and current effective state. An authorized backup may retire a lost credential. No updated server bundle is accepted as transition evidence.
- Carry post-head authorization state, envelope high-water mark, effective-state digest, and root binding in independently retained checkpoints. Suffix verification resumes that state machine, including revocation and epoch checks.
- Keep one serialized source of truth for credential keys. Verification must not use a cached key that can diverge from the bundle’s fingerprint.
The concrete contract and tests are described in the corrected Slice 1 protocol.
Slice 4 status (2026-10-12)
The verification contract is now customer-executable. verify_artifact in
maskura-pipeline-config implements the fail-closed pipeline as one entry
point — container/schema gate, canonical-CBOR digest re-derivation, the
receipt-body invariants above, chain-link checks, approval-proof verification
against the COSE key of a customer-pinned trust root (unpinned verification is
refused), signer transitions with trust resets rendered as discontinuities
(“discontinuity: new root not accepted” unless explicitly accepted),
checkpoint extension/freshness against customer-retained checkpoints
(extended-ok / gap / rollback-suspect / first-run), and validity at an
evaluated instant (--at, default now with the ±60 s skew convention). The
report is stable and versioned (verdict, findings[], completeness,
witness: "not-witness-verified") and enforces completeness honesty: with no
prior checkpoint it says UNVERIFIED (no prior checkpoint) and never claims a
complete history. The maskura policy CLI wraps this for customers with a
portable trust store whose pins are written only from customer-controlled
input — a server-fetched trust bundle can never establish a pin. Golden
vectors accompany the crate for third-party interoperability. Witness
verification remains a gated program and is never claimed. See
docs/policy-verification.md.
Consequences
- These shared-library corrections are implemented locally without enabling hosted MFA, publication enforcement, recovery, or runtime gating. Those integrations still require their database, browser and request-path acceptance tests.
- Revoked credentials cannot append by claiming an old epoch. Previously approved artifacts remain verifiable at their historical chain positions.
- A lost-all-keys recovery is a new independently accepted root, not cryptographic continuity; login recovery codes cannot authorize it on their own.
- Customers must retain trust material independently. A valid prefix/extension does not establish latest history or completeness, and a downloaded checkpoint is not automatically a trust anchor.
- Runtime adapters must populate and compare the resolved projection rather than silently treating existing portable exports as exact-state approvals. Missing operation/format/storage coverage must fail closed at enforcement activation.
- This decision adds no hardware attestation, computation proofs, external witness service, or additional S3-client onboarding requirement.