flex-auth/workplans/FLEX-WP-0019-layer-model-conformance.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

5.4 KiB

id type title domain repo status owner topic_slug planning_priority planning_order created updated
FLEX-WP-0019 workplan Layer model v0.7 conformance: provenance, lifetimes, deadlines, and the decision contract infotech flex-auth ready codex netkingdom P1 119 2026-08-29 2026-08-29

FLEX-WP-0019 - Layer model v0.7 conformance

The NetKingdom Security Layer Model was accepted at v0.7 on 2026-08-29 and INTENT.md/SCOPE.md were aligned to it. The alignment review (history/2026-08-29-layer-model-v0.7-alignment-review.md) identified six gaps between what flex-auth now states and what it implements. This workplan closes them.

Two are conformance obligations rather than features: the registry-snapshot digest (§9.7.2 promotes it from housekeeping to a prerequisite, on flex-auth's own argument) and the per-input-class visibility deadlines that depend on it.

Ordering is load-bearing. T02 precedes T04 — publishing a visibility deadline for registry-borne facts before provenance can identify the snapshot would publish a number nobody can check.

Assert the layer declaration mechanically

id: FLEX-WP-0019-T01
status: todo
priority: medium

INTENT.md frontmatter carries layer: Engine, role: PDP per §11. Add a conformance check and test asserting the declaration parses, states a layer in the §3 vocabulary, states a role because the layer is Engine, and that no Tooling client exists in the tree — the Engine-side analogue of ops-warden's scripts/check_layer_conformance.py, which is offered estate-wide as a reference form.

Closes G1's remaining half. Wire it into make test.

Add the registry-snapshot digest to decision provenance

id: FLEX-WP-0019-T02
status: todo
priority: high

DecisionProvenance carries no digest of the registry snapshot that supplied resource, subject, and relationship facts, so a decision that turned on registry content cannot be replayed from its own record (§6.1). This is flex-auth's one declared gap in §13 and a conformance prerequisite under §9.7.2.

Reuse the canonical-JSON plus SHA-256 pattern already in pkg/api/canonical.go over registry.Snapshot, which is already deterministic and has a test asserting it (TestStoreLoadsAndSavesDeterministicSnapshot). Thread the digest into DecisionProvenance, through the standalone engine and through every delegated adapter that shares the canonical constructor, and into schemas/decision_envelope.schema.json. Add regression coverage that a changed snapshot changes the digest and that two decisions over the same snapshot agree.

Give every allow an explicit lifetime

id: FLEX-WP-0019-T03
status: todo
priority: high

§9.7.1 requires every allow to carry an explicit lifetime — a TTL, or a binding to a session or obligation that ends. DecisionEnvelope has no lifetime field; ActionAuthorizationValidity has one but belongs to the durable approval object, not the decision.

The struct field is trivial; the semantics are not. flex-auth has no session concept, so the first honest shape 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: it needs package schema support, fixtures covering declared TTL, defaulted TTL, and the no-stated-end deny, and it must appear in the decision record and the published schema.

State revocation visibility deadlines per input class

id: FLEX-WP-0019-T04
status: todo
priority: high

§9.7.2 requires a PDP to state a deadline per input class, because a decision is a join over sources with unrelated refresh behaviour. Enumerate the classes flex-auth actually joins — approval-claim freshness, registry snapshot cadence, policy package activation, directory ETag — and state a deadline for each, with the mechanism that bounds it rather than an aspiration.

Depends on T02: the registry deadline is unfalsifiable until provenance can identify the snapshot a decision read. Publish as docs/decision-input-freshness.md and reference it from INTENT.md.

Publish the decision-record schema as flex-auth's contract

id: FLEX-WP-0019-T05
status: todo
priority: medium

§17 moves the decision-record schema from Taxonomy to access-engine, on flex-auth's own argument that a decision record is the PDP's output artifact. schemas/decision_envelope.schema.json exists and describes binding and provenance, but carries no lifetime (T03), no snapshot digest (T02), no policy-package digest — name and version only — and no input-claim digests.

Complete it, version it as a published contract rather than an internal shape, and document it in docs/ as the artifact consumers may rely on. Taxonomy holds only the shared field vocabulary the claim schema references; this schema is flex-auth's.

Publish the request digest as the replay test

id: FLEX-WP-0019-T06
status: todo
priority: medium

§6.4.2 makes replay permitted iff the canonical request digest matches and the decision's lifetime holds, and names flex-auth's digest as the mechanical test. The digest is computed and regression-tested but is documented nowhere a consumer would look.

Publish what it is computed over, what normalization applies, its stability guarantees across versions, and worked examples of a permitted retry and a refused replay. Consumers cannot honour §6.4.2 against an undocumented digest, and negative caching under §6.4.2 needs the same guidance.