The standard was accepted at v0.7 on 2026-08-29. Four of flex-auth's review findings are in the accepted text: 9.3's two-owner split, 6.4.2 scoped to the decision's own binding with our canonical request digest as its mechanical test, 9.7.2 split by role, and 17 moving the decision-record schema to access-engine. INTENT.md - Machine-readable layer declaration in frontmatter (layer: Engine, role: PDP), which section 11 requires and we did not have. audit-core noted our declaration was legible only by following the decision trail. - PDP failure semantics stated: our outage is consumer residue, not input degradation; fail-open is not expressible by a PDP at all. - Four owned obligations added: the decision-record schema as our contract, the request digest as the published replay test, a lifetime on every allow, and visibility deadlines per input class. - A Layer Conformance section stating the state honestly: conforming with one declared gap, no Tooling client, not PEP-shaped. - Vocabulary correction: earlier text dropped "control plane" as Staff vocabulary. Section 8 binds it to the Engine layer, which is why kings-guard was asked to release it. The term is ours; we prefer "decision engine" for precision, not boundary. SCOPE.md - Layer and role in the one-liner; the four obligations In Scope; five boundaries established in review but never written down Out of Scope. - Three capability blocks marked planned for workplans completed in May are now current; two blocks added. - Superseded ADR-0006 citation corrected to ADR-0009, which retires the global flag outright rather than deferring it. history/2026-08-29-layer-model-v0.7-alignment-review.md checks each obligation against the code and finds six gaps. FLEX-WP-0019 closes them, with T02 before T04 because a visibility deadline for registry-borne facts is unfalsifiable until provenance can identify the snapshot a decision read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sgN4GH5ZYT8pJVkCR6dcP Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014348@bnt-lap001 Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
136 lines
8.1 KiB
Markdown
136 lines
8.1 KiB
Markdown
---
|
|
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`.
|