--- id: FLEX-WP-0030 type: workplan title: "The layer declaration pins a version it should not, and four security-relevant peers do not declare at all" domain: infotech repo: flex-auth status: ready flavor: review owner: claude topic_slug: netkingdom planning_priority: P1 planning_order: 300 related_workplans: - FLEX-WP-0019 - FLEX-WP-0029 created: "2026-09-21" updated: "2026-09-21" state_hub_workstream_id: "abe60f5f-79cc-5857-b9e8-a46bed704279" --- # FLEX-WP-0030 — Boundary declaration cleanup and estate boundaries review `INTENT.md` declares `standard_version: "0.7"` in the frontmatter that §11 requires. That conflates two things the standard itself separates. The standard's own frontmatter says it outright: > `assented_by` records assent to a **BOUNDARY**, given at the version named. > It is not assent to the current text. A layer is a boundary. flex-auth is Engine / PDP whether the standard is at v0.6, v0.7, v0.8 or v1.0 — the role does not change when the text is amended. Pinning a version in the boundary declaration makes every standard revision look like it invalidates the declaration, and generates exactly the churn seen this month: v0.8 lands, the file still says `0.7`, and a reader cannot tell whether that is staleness or a deliberate position. **It is also decorative.** `internal/layer/conformance.go:40` parses `standard_version` into `Declaration.StandardVersion` and `ValidateDeclaration` never reads it. The field is enforced by nothing, in a file whose entire purpose is being mechanically checkable. ## 1. Make the declaration version-agnostic ```task id: FLEX-WP-0030-T01 status: done priority: high state_hub_task_id: "016ab184-e814-591b-938b-24ff9ace5ede" ``` Owner: `flex-auth`. - Drop `standard_version` from the `INTENT.md` frontmatter. §11 requires a `layer:` key; it does not require a version, and flex-auth's own validator does not check one. - Replace versioned prose references (`security-layer-model_v0.7.md`) with the unversioned standard path. `INTENT.md` is declared "aspirational and stable" in its own words; a stable file should not carry a number that moves quarterly. - Move version-scoped conformance state out of `INTENT.md` into a conformance record that is *supposed* to move: which version was reviewed, the conformance state, and each declared gap with owner, blocker and review date (§11's four-state table). - That split also satisfies §11's derived-artifact rule, which requires a derived artifact to name what it derives from **and the version it was derived at**. The boundary declaration is not derived; the conformance record is, and it is the artifact that should carry the version. - Keep `internal/layer` green, and decide whether `StandardVersion` stays as a tolerated-but-unused field or is removed. Do not leave a parsed field that nothing validates without saying which it is. Gate: `INTENT.md` names no standard version; conformance state is version-stamped somewhere that is maintained; `go test ./internal/layer/...` passes. 2026-09-21: done. `standard_version` removed; `conformance_record` added. The test that pinned `0.7` was **inverted rather than deleted** — `internal/layer` now rejects a version pin in the declaration and requires `conformance_record` to name a file that exists on disk. `StandardVersion` is kept on the struct deliberately, documented as must-stay-empty, so a reintroduced pin fails loudly instead of being silently ignored. Version-scoped state is in `docs/conformance/security-layer-conformance.md`. Full suite green. ## 2. Update SCOPE.md and assess the gaps ```task id: FLEX-WP-0030-T02 status: done priority: high state_hub_task_id: "224cd214-7226-5286-9794-a8a6d36c25e5" ``` Owner: `flex-auth`. `SCOPE.md`'s Current State is accurate but drifting: it says §13.1's register has **two rows** (it has five — `FLEX-WP-0029` owns that), and it states conformance as "conforming with one declared gap" without naming where the gap list is maintained. Assess and state, per gap: what it is, who owns it, what unblocks it, and when it is next reviewed. Known candidates: | Candidate gap | State | | --- | --- | | Registry-snapshot digest in decision provenance | declared, `FLEX-WP-0019`, §9.7.2 conformance prerequisite | | Emission guarantee not declared (see T04 / B3) | **unassessed** — may be a second declared gap | | Stance-register review stale at five rows | `FLEX-WP-0029` | Gate: every gap in `SCOPE.md` has an owner and a route; no gap is described only as a sentence. 2026-09-21: done. Three gaps, each with owner and route. G2 (emission guarantee) is newly assessed and recorded as a gap rather than as conformance, because the flattering reading has been asserted by nobody but flex-auth. Register corrected from two rows to five. All `v0.7` references removed from `SCOPE.md`. ## 3. Publish the boundaries review ```task id: FLEX-WP-0030-T03 status: done priority: high state_hub_task_id: "7d45a3d6-d4a7-556a-8607-58086f74a998" ``` Owner: `flex-auth`. Review flex-auth's boundary against every security-relevant repository it names or is named by, and publish findings as a derived artifact marked with the version it was derived at. Five findings are already identified in T04; the review is the durable form of them. Cover at minimum: `gate-house` (doctrine), `key-cape` (identity claims in), `ops-warden`, `secrets-engine`, `user-engine`, `tenant-engine`, `zone-engine`, `approval-engine`, `audit-core`, `maturity-engine`, `kings-guard`, `ops-mason`. Gate: the review states, for each counterpart, whether the boundary is agreed, contested, or unstated — and does not record "unstated" as if it were "agreed". 2026-09-21: published at `docs/conformance/boundaries-review.md`, marked derived and version-stamped. Twelve counterparts. Seven agreed, one agreed-in-substance but undeclared (`gate-house`), one asserted from one side only (`key-cape`), one held unilaterally and unconfirmed (`zone-engine`), two unclear (`tenant-engine` on `CheckRequest.tenant`, `audit-core` on evidence source), one undeclared twice over (`ops-mason`). ## 4. Raise the conflicting and unclear boundaries for resolution ```task id: FLEX-WP-0030-T04 status: progress priority: high state_hub_task_id: "70786e6d-02f2-5a90-8640-247ba377d9a4" ``` Owner: `flex-auth` to raise; the named owner resolves each. ### B1 — `layer:` case is inconsistent, and §11 calls the check mechanical | Value written | Repositories | | --- | --- | | `Engine` | `flex-auth`, `maturity-engine` | | `engine` | `secrets-engine`, `approval-engine`, `user-engine`, `tenant-engine`, `zone-engine`, `audit-core` | | `staff` | `ops-warden`, `kings-guard` | flex-auth's own validator rejects anything outside `{Staff, Engine, Tooling}` (`internal/layer/conformance.go:86`), so run across the estate it would fail eight of ten declarations on casing alone. Either the §3 vocabulary is case-insensitive and every checker MUST fold case, or it is not and eight declarations are non-conformant. Today each repository's checker only reads its own file, so the disagreement is invisible by construction. Owner: `gate-house`. This is the §11 mechanical-checkability claim meeting its first cross-repository run. ### B2 — four security-relevant repositories carry no layer declaration `gate-house`, `key-cape`, `ops-mason`, and `net-kingdom` have no `layer:` key in `INTENT.md` and no equivalent declaration file. §11 requires one of every estate-authored repository in §4, and is explicit that a layer stated *about* a repository by another repository is not a declaration. Two matter directly to flex-auth: - **`key-cape`** is the identity source whose verified claims flex-auth consumes as normative input and never redefines. That boundary is load-bearing for every decision flex-auth renders, and it is asserted only from flex-auth's side. - **`gate-house`** authors the obligation. A doctrine owner that has not discharged its own §11 obligation is the standard's §9.1 defect pointed at itself. `ops-mason` is already marked non-conformant in §13.1 for publishing no stance map; a missing layer declaration is the same gap one level up. Owner: each named repository. flex-auth raises, does not grade. ### B3 — flex-auth declares no emission guarantee, and may owe one §11 requires every repository catalogued in §4 **as a source of evidence** to declare its emission guarantee — class, cadence, and detection surface — in its machine-readable layer declaration, and says a source that declares none is not conforming. flex-auth produces the decision record, which §17 moved to flex-auth as its own contract and calls "the one thing in the estate only `access-engine` produces". flex-auth's frontmatter declares no emission guarantee. The unclear boundary is whether flex-auth is a §4 *source of evidence* or merely the producer of an artifact that `audit-core` is the source of. The answer decides whether this is a second declared gap or nothing at all. flex-auth should not answer it alone, and should not assume the flattering reading. Owner: `gate-house` to rule; `audit-core` to confirm which side of the line it holds. ### B4 — the declaration pins a version the standard says is not part of the boundary Raised here as the general form of T01, because if flex-auth is right that a layer declaration should not carry a standard version, the fix belongs in §11 and not only in flex-auth's file. If §11 wants a version, it should say so and say what it means when the standard moves. Owner: `gate-house`. ### B5 — canon names a repository that does not resolve v0.8 refers to the PDP as `access-engine` throughout (§4 catalog row, §13.1, §17), while the repository, runtime, namespace, images, and API vocabulary all remain `flex-auth` per `FLEX-DEC-2026-013`, and the rename has not landed — `access-engine` raw returns 404, verified 2026-09-20 under `FLEX-WP-0020`. Neither side is wrong: the rename is ruled and sequenced, and canon named the end state. But a reader of v0.8 cannot resolve the repository it keeps naming, and `reuse-surface` already probed the 404 independently. Worth one line in the standard recording that the coordinate is pending rather than broken. Owner: `gate-house` to note; `flex-auth` to ping when `FLEX-WP-0020` lands. Gate: every finding above is sent to its named owner with what would resolve it. An unanswered finding stays open and is not closed by silence. 2026-09-21: eleven messages sent. `gate-house` (all five findings), `key-cape` (B2, one-sided identity boundary), `audit-core` (B3, evidence source), `ops-mason` (B2), `net-kingdom` (B5 plus the vendored-vs-authored question), `zone-engine` (membership/stance confirmation), `tenant-engine` (the live unclear boundary, restated with its standing), and B1 as a heads-up to the five affected engine repos — sent as an estate property, not as a finding against any of them, since no repository could have discovered it from inside its own checker. Task stays `progress`: every finding is open until its owner answers. None is closed by silence. ## Out of scope - Bumping flex-auth to declare v0.8. v0.8 is `status: proposed`; T01 removes the version from the declaration entirely, which makes the question moot rather than answering it. - Grading any peer repository's conformance. flex-auth reports what it can observe and names the owner; §9.3's two-owner split cuts here too. - `FLEX-WP-0029`'s stance-register second edition. Adjacent, separately owned.