--- id: flex-auth-2026-08-29-layer-model-alignment type: history title: "Layer model v0.7 alignment: INTENT, SCOPE, and the gap between them" domain: infotech repo: flex-auth owner: flex-auth created: "2026-08-29" standard: net-kingdom/canon/standards/security-layer-model_v0.7.md records: decisions/decisions.md FLEX-DEC-2026-001, FLEX-DEC-2026-002, FLEX-DEC-2026-003 workplan: workplans/FLEX-WP-0019-layer-model-conformance.md --- # Layer model v0.7 alignment review The NetKingdom Security Layer Model was accepted at **v0.7** on 2026-08-29. `INTENT.md` and `SCOPE.md` were aligned to it in the same session. This document records what changed, then asks the question the alignment exists to answer: **where does the stated scope now outrun the implementation, and what has to be built to close it.** ## 1. How flex-auth arrived at v0.7 flex-auth reviewed three versions and holds three records. Four of its findings became text in the accepted standard: | Finding | Adopted as | | --- | --- | | §9.3 collapsed two failures with different owners | §9.3 rewritten: input degradation is the engine's, engine-unreachability is necessarily the consumer's | | §6.4.2 forbade the session-bound allow §9.7.1 permits | §6.4.2 scoped to the decision's own binding and lifetime, with flex-auth's canonical request digest as the mechanical test, and negative caching ruled permitted where the refusal is recorded | | A PDP's visibility deadline is per input class, not one number | §9.7.2 split by role | | The decision-record schema is the PDP's output, not Taxonomy's | §17 moves it to `access-engine` | The last of those was argued **against flex-auth's own interest** — it takes work on rather than off — and the standard says so, because that is what makes the §2 ownership rule credible when flex-auth also uses it to decline work. Two of flex-auth's positions were recorded rather than adopted: containment surface ownership stays **proposed** (§13, pending under §9.2), and authentication/assurance evidence is recorded as **declined**. ## 2. What changed in INTENT.md 1. **A machine-readable layer declaration** in frontmatter — `layer: Engine`, `role: PDP` — which §11 requires and flex-auth did not have. `audit-core` named this precisely: flex-auth's declaration was "legible as one only by following its decision trail." Prose cannot distinguish a declaration from a transcribed review. 2. **The PDP role stated with its failure semantics**: flex-auth's outage is consumer residue, not input degradation. Fail-open is not expressible by a PDP at all. 3. **Four obligations added to what flex-auth owns**: the decision-record schema as its own contract, the canonical request digest as the published replay test, a lifetime on every allow, and revocation visibility deadlines per input class. 4. **A `Layer Conformance` section** stating the conformance state honestly: conforming with one declared gap, no Tooling client, not PEP-shaped. 5. **A vocabulary correction.** Earlier versions dropped "control plane" as Staff vocabulary. That reason was wrong on the standard's own terms — §8 binds control plane to the **Engine layer**, which is why kings-guard was asked to release it. The term is flex-auth's to use. This file prefers "decision engine" as a matter of precision, not boundary. ## 3. What changed in SCOPE.md The one-liner now states the layer and role. In Scope gained the four v0.7 obligations. Out of Scope gained five boundaries flex-auth had established in review but never written down: fail-open, enforcement, the approval object, authentication evidence, and doctrine authoring. Three capability blocks were still marked `planned` for workplans completed in May and are now `current`, and two capability blocks were added. A superseded citation of ops-warden `ADR-0006` was corrected to `ADR-0009`, which retires the global flag outright rather than deferring it. ## 4. Scope versus implementation — the gap This is the operative section. Each row is checked against the code, not against the documents. | # | Obligation | Standard | Implementation today | Gap | | --- | --- | --- | --- | --- | | G1 | Machine-readable layer declaration | §11 | `INTENT.md` frontmatter, added in this session | **closed**, needs a conformance test | | G2 | Registry-snapshot digest in decision provenance | §6.1, §9.7.2, §13 | `DecisionProvenance` carries evaluator, mode, policy package, policy version, directory ETag, decision time — **no snapshot digest** | **open — conformance prerequisite** | | G3 | Every allow carries an explicit lifetime | §9.7.1 | `DecisionEnvelope` has **no lifetime field**. `ActionAuthorizationValidity` has `not_before`/`expires_at`, but that is the durable approval object, not the decision | **open** | | G4 | Revocation visibility deadline per input class | §9.7.2 | Not stated anywhere — no document, no field | **open** | | G5 | Decision-record schema published as flex-auth's contract | §17 | `schemas/decision_envelope.schema.json` exists and describes `binding` and `provenance` via `$defs`. It carries no lifetime, no policy-package **digest** (name and version only), and no input-claim digests | **partial** | | G6 | Canonical request digest as the §6.4.2 replay test | §6.4.2 | `NewDecisionBinding` computes it over normalized subject, action, resource, context; it is in every binding and regression-tested | **closed in code, unpublished as consumer guidance** | | G7 | Doctrine reaches the decision as claim or versioned rule | §6.2 | Context claims and versioned policy packages both exist | **closed** | | G8 | Approvals consumed as input claims, never mutated | §9.4 | flex-auth mutates no approval. `FLEX-WP-0017` T03/T05 wait on `approval-engine` | **closed on flex-auth's side; blocked externally** | ### Why G2 is the one that matters most G2 and G4 are the same gap seen from two sides, and the standard now says so in flex-auth's own words. A stated visibility deadline for a fact carried by a registry snapshot is **unfalsifiable** while provenance holds no snapshot digest, because nobody can determine afterwards which snapshot a decision read. Publishing G4 without closing G2 would be publishing a number nobody can check. G2 is also cheap. `registry.Snapshot` is already a deterministic, JSON-serializable struct with a test asserting that determinism (`TestStoreLoadsAndSavesDeterministicSnapshot`), and `pkg/api/canonical.go` already carries the canonical-JSON-plus-SHA-256 pattern that `NewDecisionBinding` uses. The work is to reuse that pattern over the snapshot and thread the result into `DecisionProvenance`, including through the delegated adapters, which already share the canonical binding constructor. ### Why G3 is larger than it looks Adding a lifetime field is trivial. Deciding **what the lifetime is** is not: a TTL, a session binding, or an obligation binding, per §9.7.1. flex-auth has no session concept, so the honest first step is a policy-package-declared TTL with an explicit default, and a deny for any allow that would otherwise have no stated end. That is a policy-surface change and needs fixtures, not just a struct field. ### A capability flex-auth claimed and cannot yet exercise flex-auth told gate-house it is the repository positioned to notice when the aggregate of consumer stances diverges from what the policy packages say. §13.1 now exists as the register, and it has **one row** — `ops-warden`, with `ops-mason` catalogued PEP-shaped and unpublished. The claim is sound and the data is not there yet. This is not a flex-auth gap to close alone, but flex-auth should be able to read the register once it is populated, and should say so rather than let the claim sit unexercised. ## 5. What this does not change flex-auth's boundaries are unchanged by v0.7. It still does not author doctrine, own approvals, own enforcement, or own authentication evidence. The rename to `access-engine` remains a separate governed migration under the two conditions in `FLEX-DEC-2026-001`, and nothing in the alignment starts it. ## 6. Outcome `FLEX-WP-0019` carries G1's test, G2, G3, G4, G5, and G6. G7 needs nothing. G8 stays with `FLEX-WP-0017`, blocked on `approval-engine`.