flex-auth/history/2026-08-29-layer-model-v0.7-alignment-review.md
tegwick 0e2efa8fcf
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Align INTENT and SCOPE to security layer model v0.7; plan conformance work
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
2026-08-29 14:43:49 +02:00

8.1 KiB

id type title domain repo owner created standard records workplan
flex-auth-2026-08-29-layer-model-alignment history Layer model v0.7 alignment: INTENT, SCOPE, and the gap between them infotech flex-auth flex-auth 2026-08-29 net-kingdom/canon/standards/security-layer-model_v0.7.md decisions/decisions.md FLEX-DEC-2026-001, FLEX-DEC-2026-002, FLEX-DEC-2026-003 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 rowops-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.