Make the layer declaration a boundary, and review the boundaries it implies.

INTENT.md pinned standard_version: "0.7" in the frontmatter §11 requires. That
conflated two things the standard separates itself: assent "records assent to a
BOUNDARY, given at the version named. It is not assent to the current text."
flex-auth is Engine/PDP at v0.6, v0.7, v0.8 and after; the role does not change
when the text is amended. The field was also decorative — parsed into
Declaration.StandardVersion and never validated — so the version was load-bearing
only via a test asserting it equalled 0.7.

That test is inverted rather than deleted: internal/layer now rejects a version
pin in the declaration and requires conformance_record to name a file that
exists. Version-scoped state moves to docs/conformance/security-layer-conformance.md,
a derived artifact carrying what it derives from and the version derived at, as
§11 requires of derived artifacts.

SCOPE.md: gap assessment replaces "conforming with one declared gap" with three
gaps, each with an owner and a route. G2 is new — flex-auth declares no emission
guarantee where §11 requires one of every §4 source of evidence. It is recorded
as a gap rather than as conformance because the flattering reading, that
audit-core is the source and flex-auth merely produces, has been asserted by
nobody but flex-auth. Also corrects the stance register from two rows to five.

Fixing one line meant reading what the declaration asserts, and a boundary is
only half held here. docs/conformance/boundaries-review.md checks the other
halves across twelve counterparts and finds four security-relevant repositories
with no layer declaration at all — including key-cape, the identity source whose
claims flex-auth consumes as normative input. That boundary is asserted from one
side only. Recorded as unstated, never as agreed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
This commit is contained in:
tegwick 2026-09-21 00:11:56 +02:00
parent 5a2e1959e5
commit c0d0d92e9f
7 changed files with 470 additions and 26 deletions

View file

@ -1,13 +1,22 @@
---
# NetKingdom security layer declaration (security-layer-model_v0.7 §11).
# NetKingdom security layer declaration (security-layer-model §11).
# Machine-readable because §11 requires it: prose cannot distinguish a
# declaration from a transcribed review. Reference form: ops-warden layer.yaml.
#
# This declares a BOUNDARY, and carries no standard version on purpose. The
# standard draws the distinction itself: assent "records assent to a BOUNDARY,
# given at the version named. It is not assent to the current text." flex-auth is
# Engine / PDP at v0.6, v0.7, v0.8 and after; the role does not change when the
# text is amended, so a version here would make every revision read as though it
# invalidated the declaration. Version-scoped conformance state is derived, moves,
# and lives in conformance_record below — which carries the version it was
# derived at, as §11 requires of a derived artifact.
layer: Engine
role: PDP
framework: netkingdom-security-layer-model
standard_version: "0.7"
declared_by: decisions/decisions.md FLEX-DEC-2026-001, FLEX-DEC-2026-002, FLEX-DEC-2026-003
declared_at: "2026-08-29"
conformance_record: docs/conformance/security-layer-conformance.md
pep_stance: null # not PEP-shaped: flex-auth renders decisions, it causes no protected side effect
tooling_contacts: [] # §5 binds Staff; flex-auth holds no Tooling client
---
@ -15,8 +24,8 @@ tooling_contacts: [] # §5 binds Staff; flex-auth holds no Tooling client
# Flex-Auth Intent
> **Layer declaration.** flex-auth is **Engine / PDP** under the NetKingdom
> Security Layer Model (`net-kingdom/canon/standards/security-layer-model_v0.7.md`,
> accepted 2026-08-29). It is **the only policy decision point in NetKingdom**
> Security Layer Model (`net-kingdom/canon/standards/`, the Security
> Layer Model; declared 2026-08-29). It is **the only policy decision point in NetKingdom**
> (§6): no other repository, in any layer, renders or caches an authorization
> decision. The frontmatter above is the machine-readable form §11 requires; this
> paragraph is the declaration in flex-auth's own voice.
@ -38,7 +47,7 @@ tooling_contacts: [] # §5 binds Staff; flex-auth holds no Tooling client
> three records: `FLEX-DEC-2026-001` (Engine framing, the `access-engine` name,
> the authoring/evaluation split), `FLEX-DEC-2026-002` (§9.3 contested and
> upheld), and `FLEX-DEC-2026-003` (v0.6 review; §6.4.2, §9.7.2 and §17 as
> adopted in v0.7).
> adopted into the standard).
>
> *One item remains open: the ruled rename to `access-engine`. It is a separate
> governed migration — it touches `FLEX-WP` prefix ownership, State Hub
@ -62,7 +71,7 @@ enterprise-grade authorization without giving up clear ownership, local
development ergonomics, or inspectable policy decisions.
It is an **Engine**, role **PDP**, in the NetKingdom security layer model
(`net-kingdom/canon/standards/security-layer-model_v0.7.md`): a deterministic
(`net-kingdom/canon/standards/`, the Security Layer Model): a deterministic
API for a modeled concept, where the same authoritative input state yields the
same result.

View file

@ -4,8 +4,8 @@
flex-auth is a policy-as-code authorization registry and decision engine for
NetKingdom-aligned systems. Under the NetKingdom Security Layer Model
(`security-layer-model_v0.7`, accepted 2026-08-29) it is **Engine / PDP** — the
estate's only policy decision point.
(declared 2026-08-29) it is **Engine / PDP** — the estate's only policy decision
point.
## Core Idea
@ -36,7 +36,7 @@ can be coordinated behind a stable flex-auth API.
- Delegated PDP and directory adapter boundaries after the standalone core is
stable.
- The **decision-record schema**, published as flex-auth's own contract
(`security-layer-model_v0.7` §17).
(Security Layer Model §17).
- The **canonical request digest** as the published replay test for consumers
(§6.4.2) — `binding.submitted_request_digest`, over the request as sent.
`request_digest` is over the *enriched* request and is flex-auth's own
@ -152,11 +152,13 @@ certificates the ops-bridge tunnels depend on, one of which carries the policy
call itself. `ADR-0009` retires `policy.enabled` and the global `policy.fail_closed`
outright and replaces them with a total per-zone stance map in the consumer PEP
(`ops-warden/pep-stance.yaml`): open for `z0`-`z2` and `unknown`, closed for
`z3-critical`. That map is the reference shape for `security-layer-model_v0.7`
`z3-critical`. That map is the reference shape for the Security Layer Model's
§6.4 obligation 3. It is no longer the only published one: `secrets-engine`
published `pep-stance.yaml` (total over catalog stage plus `unknown`, runtime-read
and test-pinned), so §13.1's register now has **two rows** rather than the one the
standard recorded as itself the finding. flex-auth reviewed the pair in
and test-pinned), so §13.1's register grew past the single row the standard
recorded as itself the finding. It now carries **five**`ops-warden`,
`user-engine`, `tenant-engine`, `secrets-engine`, and `ops-mason` with no map at
all — two of them marked non-conformant. flex-auth reviewed the pair in
`docs/stance-register-review.md` — the first exercise of the aggregate-divergence
capability it claimed on 2026-08-29 — and found that the two maps take opposite
stances on `unknown` (`fail_open` vs `fail_closed`) and scope on different axes
@ -172,15 +174,52 @@ PDP at all** and stays a consumer-side setting. The enforcing pins stay
enforcing regardless — an enforcing pin with no enforcing consumer still turns
the anonymous path into a 401 rather than a decision.
**Layer position (2026-08-29).** The NetKingdom Security Layer Model was
accepted at v0.7. flex-auth is **Engine / PDP**, declared machine-readably in
`INTENT.md` frontmatter per §11. Four of flex-auth's review findings were adopted
into the standard: §9.3's two-owner split for degraded mode, §6.4.2 scoped to the
decision's own binding with the canonical request digest as its mechanical test
and negative caching ruled explicitly, §9.7.2 split by role, and §17 moving the
decision-record schema to flex-auth. Conformance state is **conforming with one
declared gap** — the registry-snapshot digest in decision provenance, which §9.7.2
promotes to a conformance prerequisite. `FLEX-WP-0019` carries the work.
**Layer position (declared 2026-08-29).** flex-auth is **Engine / PDP** under
the NetKingdom Security Layer Model, declared machine-readably in `INTENT.md`
frontmatter per §11. That declaration deliberately carries **no standard
version**: a layer is a boundary and does not change when the text is amended,
which is the distinction the standard itself draws when it says assent is *"to a
BOUNDARY, given at the version named. It is not assent to the current text."* The
absence is enforced by test in `internal/layer`, and raised to `gate-house` as
`FLEX-WP-0030` B4 in case §11 should say so generally.
Version-scoped state therefore lives in
`docs/conformance/security-layer-conformance.md` — a derived artifact that names
what it derives from and the version it was derived at, as §11 requires. It
carries the assent history (v0.4 `FLEX-DEC-2026-002`, v0.6 `FLEX-DEC-2026-003`,
v0.8 `FLEX-DEC-2026-011`) and the gap table below.
Findings of flex-auth's adopted into the standard: §9.3's two-owner split for
degraded mode, §6.4.2 scoped to the decision's own binding with the canonical
request digest as its mechanical test and negative caching ruled explicitly,
§9.7.2 split by role, §17 moving the decision-record schema to flex-auth, and
four more in the v0.8 round (`FLEX-DEC-2026-011`), of which F1 — that a decision
must be *attributable* to flex-auth and that a digest comparison does not
discharge it — was the finding of the round.
Conformance state is **conforming with three declared gaps**, each with an owner
and a route rather than a sentence:
| # | Gap | Owner | Route |
| --- | --- | --- | --- |
| G1 | Registry-snapshot digest absent from decision provenance (§9.7.2 conformance prerequisite) | `flex-auth` | `FLEX-WP-0019` |
| G2 | No emission guarantee declared, where §11 requires one of every §4 source of evidence | `gate-house` to rule, then `flex-auth` | `FLEX-WP-0030` B3 |
| G3 | Published stance-register review stale — written at two register rows, §13.1 now carries five | `flex-auth` | `FLEX-WP-0029` |
G2 is new and is recorded as a gap rather than as conformance on purpose: whether
flex-auth is a §4 *source of evidence* or only the producer of an artifact
`audit-core` sources has been asserted by nobody but flex-auth, and §11 says a
source declaring no emission guarantee is not conforming. The conservative entry
is the honest one until the boundary is ruled.
**Boundaries review (2026-09-21).** `FLEX-WP-0030` reviews flex-auth's boundary
against every security-relevant counterpart and raises five items: inconsistent
`layer:` casing across the estate against §11's mechanical-checkability claim
(B1); four security-relevant repositories with no layer declaration at all —
`gate-house`, `key-cape`, `ops-mason`, `net-kingdom` — of which `key-cape` is the
identity source whose claims flex-auth consumes as normative input, making that
boundary asserted from one side only (B2); G2 above (B3); B4; and canon naming
`access-engine` while the repository still answers to `flex-auth` (B5).
State Hub integration is present through:
@ -297,12 +336,12 @@ description: Workplan for Topaz evaluation, relationship PDP adapters, rule PDP
type: contract
title: Decision-record contract
status: current
description: Published decision-record schema, the submitted-request digest as the replay test for consumers, request-enrichment precedence, and decision provenance — flex-auth's own contract under security-layer-model v0.7 section 17.
description: Published decision-record schema, the submitted-request digest as the replay test for consumers, request-enrichment precedence, and decision provenance — flex-auth's own contract under the Security Layer Model section 17.
```
```capability
type: orientation
title: Layer declaration
status: current
description: Machine-readable Engine/PDP declaration in INTENT.md frontmatter with conformance state and the one declared gap, per security-layer-model v0.7 section 11.
description: Machine-readable Engine/PDP boundary declaration in INTENT.md frontmatter, carrying no standard version by design, with version-stamped conformance state and three declared gaps in docs/conformance/security-layer-conformance.md, per Security Layer Model section 11.
```

View file

@ -0,0 +1,68 @@
# Boundaries review — flex-auth against its security-relevant counterparts
> **Derived artifact** (§11). Derives from
> `net-kingdom/canon/standards/security-layer-model_v0.8.md`
> (`status: proposed`, `source_revision: gate-house@516ed4e`), from each
> counterpart's `INTENT.md` / `layer.yaml` as of the date below, and from
> flex-auth's own `decisions/decisions.md`.
> Derived at: **2026-09-21**. Reviewer: `flex-auth` (Engine / PDP).
> Carried by `FLEX-WP-0030`.
## Why this exists
`INTENT.md` was carrying a standard version it should not (`FLEX-WP-0030` T01).
Fixing one line meant reading what the declaration actually asserts, and the
declaration asserts a boundary — which is only half of a boundary. The other half
is held by someone else, and flex-auth had never checked whether the other halves
were stated at all.
They are not, in four cases. That is the finding of this review, and it was not
the one being looked for.
## The rule this review holds itself to
§11 is explicit: *"A layer stated **about** a repository by another repository is
not a declaration."* So nothing below grades a peer. flex-auth reports what it can
observe from outside, names the owner, and says which of three states the boundary
is in. **`unstated` is not recorded as `agreed`** — that conflation is the whole
reason the four cases below went unnoticed.
## Boundary status
| Counterpart | Boundary | State |
| --- | --- | --- |
| `gate-house` | owns invariants, authority ceilings, operating modes; flex-auth authors no doctrine and consumes authority context as claims | **agreed in substance, undeclared in form** — no `layer:` key (B2) |
| `key-cape` / NetKingdom SSO | identity source; flex-auth consumes verified claims as normative input and never redefines them | **asserted from one side only** — no `layer:` key (B2) |
| `ops-warden` | consumer / PEP; owns SSH CA, OpenBao signing, actor inventory and its own stance map. flex-auth owns the decision, never the credential | **agreed, and the most exercised boundary in the estate** |
| `secrets-engine` | consumer / PEP; owns credential lifecycle downstream of a decision | **agreed** |
| `approval-engine` | owns the approval object, its storage and lifecycle; flex-auth validates approvals as input claims and never mutates them | **agreed**`GH-DEC-2026-005`, accepted in `FLEX-DEC-2026-006` against flex-auth's own proposal |
| `zone-engine` | zone **membership** compiles into the registry snapshot flex-auth consumes; per-zone **stance** is the consumer's | **held by flex-auth since 2026-08-19; not contested, not confirmed** |
| `user-engine` | PIP; supplies subject facts | **agreed** |
| `tenant-engine` | PIP and consumer. What `CheckRequest.tenant` denotes on the write API — caller, target, or guardrail scope — is **unanswered since 2026-09-15** | **unclear, and live**`FLEX-WP-0022`, re-asked 2026-09-20 |
| `audit-core` | records evidence; flex-auth produces the decision record | **unclear** — which of the two is the §4 *source of evidence* decides whether flex-auth owes an emission guarantee (B3 / G2) |
| `maturity-engine` | PIP; supplies maturity claims. §9.5 forbids ranking blocked-clean below conforming | **agreed** |
| `kings-guard` | Staff; raised the authentication/assurance evidence gap that flex-auth **declined** (§13, `FLEX-DEC-2026-002`) | **agreed, by mutual declining** |
| `ops-mason` | catalogued PEP-shaped in §4 | **undeclared twice over** — no stance map (§13.1 marks it), no `layer:` key (B2) |
## Findings raised for resolution
Full statements in `workplans/FLEX-WP-0030-boundary-declaration-cleanup.md` T04.
| # | Finding | Owner |
| --- | --- | --- |
| B1 | `layer:` casing is inconsistent across ten declarations; §11 calls the check mechanical, and flex-auth's own validator would fail eight of them | `gate-house` |
| B2 | `gate-house`, `key-cape`, `ops-mason`, `net-kingdom` carry no machine-readable layer declaration | each named repository |
| B3 | flex-auth declares no emission guarantee; whether it owes one turns on an unruled boundary with `audit-core` | `gate-house`, `audit-core` |
| B4 | a layer declaration should not pin a standard version; if §11 agrees it should say so generally | `gate-house` |
| B5 | canon names `access-engine`; the repository still answers to `flex-auth` and the rename has not landed | `gate-house` to note |
## What flex-auth is not claiming
- **Not a conformance finding against anyone.** B1 and B2 are observations about
form. A repository may be entirely conformant in substance and simply not have
written the key; `gate-house` is the clearest case.
- **Not a request that any peer change casing.** B1 may equally be resolved by
ruling the vocabulary case-insensitive, which would make flex-auth's validator
the thing that changes.
- **Not a grade.** §9.3's two-owner split is flex-auth's own finding and it cuts
here: the PDP does not get to score the repositories whose facts it consumes.

View file

@ -0,0 +1,72 @@
# Security Layer Model — flex-auth conformance record
> **Derived artifact** (§11). Derives from
> `net-kingdom/canon/standards/security-layer-model_v0.8.md`
> (`status: proposed`, `source_revision: gate-house@516ed4e`).
> Derived at: **2026-09-21**. Maintained by `flex-auth`.
This file exists because `INTENT.md` deliberately does not carry one. The layer
declaration states a **boundary** — flex-auth is Engine / PDP — and a boundary
does not change when the standard text is amended. Conformance state does change,
every revision, and belongs in an artifact that is expected to move and that
carries the version it was derived at.
The split is the standard's own. Its frontmatter: *"`assented_by` records assent
to a BOUNDARY, given at the version named. It is not assent to the current text."*
## Declaration
| Field | Value |
| --- | --- |
| Layer | `Engine` |
| Role | `PDP` — the estate's only policy decision point (§6) |
| Declared at | 2026-08-29 |
| Declared by | `FLEX-DEC-2026-001`, `FLEX-DEC-2026-002`, `FLEX-DEC-2026-003` |
| PEP stance | `null` — not PEP-shaped; flex-auth renders decisions and causes no protected side effect |
| Tooling contacts | none — §5 binds Staff; flex-auth holds no Tooling client |
## Assent history
Assent is to the boundary, recorded at the version where it was given.
| Version | Record | Outcome |
| --- | --- | --- |
| v0.4 | `FLEX-DEC-2026-002` | §9.3 contested and upheld |
| v0.6 | `FLEX-DEC-2026-003` | review; §6.4.2, §9.7.2, §17 adopted into v0.7 |
| v0.7 | — | four flex-auth findings adopted |
| v0.8 (`proposed`) | `FLEX-DEC-2026-011` | assent with four findings, all adopted |
## Conformance state at v0.8
**Conforming, with declared gaps below.** §11's four states: conforming,
blocked-clean, declared gap, undeclared violation. flex-auth claims no
blocked-clean capability and holds no undeclared violation it is aware of.
| # | Gap | Owner | Blocked on | Review |
| --- | --- | --- | --- | --- |
| G1 | Registry-snapshot digest absent from decision provenance. §9.7.2 promotes it to a conformance prerequisite: a decision that turned on registry content must be replayable from its own record. | `flex-auth` | implementation | `FLEX-WP-0019` |
| G2 | **Emission guarantee not declared.** §11 requires every §4 repository catalogued as a source of evidence to declare class, cadence and detection surface in its machine-readable declaration, and says a source declaring none is not conforming. flex-auth declares none. | `gate-house` to rule, then `flex-auth` | whether flex-auth is a §4 *source of evidence* or only the producer of an artifact `audit-core` sources — see `FLEX-WP-0030` B3 | `FLEX-WP-0030-T04` |
| G3 | Published stance-register review is stale: written at two register rows, §13.1 now carries five, and its Finding 1 was ruled by v0.8 §6.4 obligation 3. | `flex-auth` | second edition | `FLEX-WP-0029` |
G2 is recorded as a gap rather than as conformance because the flattering reading
— that `audit-core` is the source and flex-auth merely produces — has not been
confirmed by anyone but flex-auth. §11 says a source that declares no emission
guarantee is not conforming; until the boundary is ruled, the conservative entry
is the honest one.
## Not gaps
- **No standard version in `INTENT.md`.** Deliberate, enforced by test
(`internal/layer`), and raised to `gate-house` as `FLEX-WP-0030` B4 in case §11
should say so generally.
- **Canon says `access-engine`, the repository answers to `flex-auth`.** The
rename is ruled (`FLEX-DEC-2026-013`) and sequenced (`FLEX-WP-0020`); the
coordinate is pending, not broken. Raised as B5.
## How this file is kept true
`internal/layer` asserts that `INTENT.md` carries no `standard_version` and names
a `conformance_record` that exists on disk. That is the same property flex-auth
praised in `ops-warden`'s stance map: the published artifact is asserted equal to
the shipped one by test, rather than merely written down. It does **not** assert
the contents below the declaration — a reviewer still has to read this file.

View file

@ -37,9 +37,15 @@ type Declaration struct {
Layer string `yaml:"layer"`
Role string `yaml:"role"`
Framework string `yaml:"framework"`
StandardVersion string `yaml:"standard_version"`
DeclaredBy string `yaml:"declared_by"`
DeclaredAt string `yaml:"declared_at"`
// ConformanceRecord points at the derived, version-stamped conformance state.
// The declaration itself is a boundary and carries no standard version.
ConformanceRecord string `yaml:"conformance_record"`
// StandardVersion must stay empty: a layer is a boundary, and the standard
// says assent is "to a BOUNDARY, given at the version named. It is not
// assent to the current text."
StandardVersion string `yaml:"standard_version"`
PepStance any `yaml:"pep_stance"`
ToolingContacts []any `yaml:"tooling_contacts"`
}
@ -98,6 +104,12 @@ func ValidateDeclaration(decl Declaration) error {
if decl.PepStance != nil {
return fmt.Errorf("flex-auth is not PEP-shaped; pep_stance must be null")
}
if strings.TrimSpace(decl.StandardVersion) != "" {
return fmt.Errorf("layer declaration must carry no standard_version: a layer is a boundary, not a version-scoped claim; version-stamped state belongs in conformance_record (got %q)", decl.StandardVersion)
}
if strings.TrimSpace(decl.ConformanceRecord) == "" {
return fmt.Errorf("layer declaration must name a conformance_record: §11 requires a derived artifact to carry the version it was derived at")
}
return nil
}

View file

@ -1,6 +1,7 @@
package layer_test
import (
"os"
"path/filepath"
"runtime"
"testing"
@ -27,8 +28,28 @@ func TestLayerDeclarationConforms(t *testing.T) {
if decl.Framework != "netkingdom-security-layer-model" {
t.Fatalf("framework = %q", decl.Framework)
}
if decl.StandardVersion != "0.7" {
t.Fatalf("standard_version = %q; want 0.7", decl.StandardVersion)
// The declaration is a boundary and must NOT pin a standard version: the
// role does not change when the standard text is amended. Version-scoped
// conformance state lives in the derived record named below.
if decl.StandardVersion != "" {
t.Fatalf("standard_version = %q; want empty (boundary, not version-scoped)", decl.StandardVersion)
}
if decl.ConformanceRecord == "" {
t.Fatal("conformance_record is empty; version-stamped state must have a home")
}
if _, err := os.Stat(filepath.Join(repoRoot(t), decl.ConformanceRecord)); err != nil {
t.Fatalf("conformance_record %q does not exist: %v", decl.ConformanceRecord, err)
}
}
func TestVersionPinInDeclarationIsRejected(t *testing.T) {
err := layer.ValidateDeclaration(layer.Declaration{
Layer: "Engine", Role: "PDP",
ConformanceRecord: "docs/conformance/security-layer-conformance.md",
StandardVersion: "0.8",
})
if err == nil {
t.Fatal("a standard_version pin in the boundary declaration was accepted")
}
}

View file

@ -0,0 +1,223 @@
---
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"
---
# 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: todo
priority: high
```
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.
## 2. Update SCOPE.md and assess the gaps
```task
id: FLEX-WP-0030-T02
status: todo
priority: high
```
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.
## 3. Publish the boundaries review
```task
id: FLEX-WP-0030-T03
status: todo
priority: high
```
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".
## 4. Raise the conflicting and unclear boundaries for resolution
```task
id: FLEX-WP-0030-T04
status: todo
priority: high
```
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.
## 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.