From 39a0034fcc8ede2395f51e991cee1a2788a89e2f Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 21 Sep 2026 22:57:56 +0200 Subject: [PATCH] Close B2 and finish FLEX-WP-0030; record tenant-engine's and key-cape's answers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit B2: key-cape (Tooling), net-kingdom (Taxonomy) and ops-mason (Staff) now declare in their own files. Verified by the survey rather than taken on report: 14 of 14 counterparts declared, 0 undeclared. ops-mason sent no reply and needed none — under §11 the file is the declaration. Every T04 finding is answered, so FLEX-WP-0030 is finished. B5's residual ping belongs to FLEX-WP-0020. key-cape stated the identity boundary from its side for the first time and cautioned that principal_type must not be read as authentication-derived until GH-DEC-2026-013/-016 §5 is answered. Checked against every published package: only the two informed-decision packages gate on a human subject, and both also require principal_type_source == "authentication-derived", which informed-decision derives from the verified code-flow MFA event rather than from key-cape's claim. No change needed; the assessment and a warning about the legacy "otherwise -> human" fallback are in docs/iam-profile-consumption.md. tenant-engine confirmed FLEX-DEC-2026-016's reading of commitment (b): the fixed-record exclusion is consistent with it. Recorded under point 3; v3 stands. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 28468@bnt-lap001 Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d --- decisions/decisions.md | 9 + docs/conformance/boundaries-review.md | 20 + ...21-layer-declaration-survey-b2-closed.json | 531 ++++++++++++++++++ docs/iam-profile-consumption.md | 20 + ...EX-WP-0030-boundary-declaration-cleanup.md | 29 +- 5 files changed, 607 insertions(+), 2 deletions(-) create mode 100644 docs/evidence/2026-09-21-layer-declaration-survey-b2-closed.json diff --git a/decisions/decisions.md b/decisions/decisions.md index c8ed6fb..aa42175 100644 --- a/decisions/decisions.md +++ b/decisions/decisions.md @@ -1935,6 +1935,15 @@ reviewer can check rather than as an absence: is reported back to tenant-engine because its commitment (b) reads as literally unconditional. + **Confirmed by tenant-engine, 2026-09-21** (message `6fdb0180`). (b) as a + rule is its first sentence — no action is refused on the relationship + between subject and tenant — and the fixed-record exclusion is consistent + with it. The looser test sentence will be reworded to *"varying tenant + across targets that carry no fixed-record rule"* if the decision is + reissued; tenant-engine is not editing the record for this alone. Nothing + needs raising with `net-kingdom` or `user-engine`; tenant-engine takes no + position on the grant itself. No change to v3. + **Fixtures.** Every tenant-engine-subject fixture now carries `tenant` equal to `resource.id`, rotated across four tenants; five cross-tenant allow fixtures (three `flex-auth` guardrail reads, two creates) and two `tenant_not_target` diff --git a/docs/conformance/boundaries-review.md b/docs/conformance/boundaries-review.md index 803ba92..7cdb670 100644 --- a/docs/conformance/boundaries-review.md +++ b/docs/conformance/boundaries-review.md @@ -156,3 +156,23 @@ with one of flex-auth's in a different shape (`audit-core`'s list-shaped `emission_guarantee`) made that peer's `layer.yaml` silently disappear. Peers are now read for `layer` and `role` only. A surveyor's schema is a house rule too. Receipt: `docs/evidence/2026-09-21-layer-declaration-survey-after-ghdec017.json`. + +## Addendum — B2 closed, 2026-09-21 + +The status table above is left as derived. Three rows have since moved, each +verified in the counterpart's own file (receipt +`docs/evidence/2026-09-21-layer-declaration-survey-b2-closed.json`): + +| Counterpart | Was | Now | +| --- | --- | --- | +| `key-cape` | asserted from one side only | **agreed, stated from both sides** — declares `Tooling` (`key-cape@9cb9507`); expects nothing of flex-auth beyond standard token verification | +| `ops-mason` | undeclared twice over | declares `Staff` (`ops-mason@0ff263a`); the §13.1 stance-map mark is gate-house's and unchanged | +| `net-kingdom` | undeclared | declares `Taxonomy` (`net-kingdom@0b10b4b`) | + +`gate-house` declared earlier the same day. Fourteen of fourteen counterparts now +declare. The `tenant-engine` row closed under `FLEX-WP-0022` (`TEN-DEC-2026-002`, +`FLEX-DEC-2026-016`); the `audit-core` row was ruled against flex-auth +(`GH-DEC-2026-018`), and delivery is `FLEX-WP-0031`. + +One boundary remains held by flex-auth alone: `zone-engine` has confirmed the +casing ruling but not the membership/stance boundary it was asked about. diff --git a/docs/evidence/2026-09-21-layer-declaration-survey-b2-closed.json b/docs/evidence/2026-09-21-layer-declaration-survey-b2-closed.json new file mode 100644 index 0000000..2fc58c4 --- /dev/null +++ b/docs/evidence/2026-09-21-layer-declaration-survey-b2-closed.json @@ -0,0 +1,531 @@ +{ + "checks_only": "the closed four-token §3 vocabulary, ASCII case folded per GH-DEC-2026-017 §2; and A12 r2 (GH-DEC-2026-020): no standard or companion version in any key or value of INTENT.md frontmatter or layer.yaml; stance, claims and classification maps not read; no flex-auth house rules applied to peers", + "derived_at": "run time", + "off_vocab": null, + "root": "/home/worsch", + "rows": [ + { + "Repo": "approval-engine", + "Intent": { + "Source": "approval-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "approval-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "audit-core", + "Intent": { + "Source": "audit-core/INTENT.md", + "Layer": "Engine", + "Role": "Evidence", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "audit-core/layer.yaml", + "Layer": "engine", + "Role": "evidence", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "flex-auth", + "Intent": { + "Source": "flex-auth/INTENT.md", + "Layer": "Engine", + "Role": "PDP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "", + "Layer": "", + "Role": "", + "Found": false, + "InVocabulary": false, + "Canonical": "" + }, + "InCatalog": true + }, + { + "Repo": "gate-house", + "Intent": { + "Source": "gate-house/INTENT.md", + "Layer": "Staff", + "Role": "—", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "File": { + "Source": "", + "Layer": "", + "Role": "", + "Found": false, + "InVocabulary": false, + "Canonical": "" + }, + "InCatalog": true + }, + { + "Repo": "key-cape", + "Intent": { + "Source": "key-cape/INTENT.md", + "Layer": "Tooling", + "Role": "—", + "Found": true, + "InVocabulary": true, + "Canonical": "Tooling" + }, + "File": { + "Source": "", + "Layer": "", + "Role": "", + "Found": false, + "InVocabulary": false, + "Canonical": "" + }, + "InCatalog": true + }, + { + "Repo": "kings-guard", + "Intent": { + "Source": "kings-guard/INTENT.md", + "Layer": "Staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "File": { + "Source": "kings-guard/layer.yaml", + "Layer": "staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "InCatalog": true + }, + { + "Repo": "maturity-engine", + "Intent": { + "Source": "maturity-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "maturity-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "net-kingdom", + "Intent": { + "Source": "net-kingdom/INTENT.md", + "Layer": "Taxonomy", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Taxonomy" + }, + "File": { + "Source": "", + "Layer": "", + "Role": "", + "Found": false, + "InVocabulary": false, + "Canonical": "" + }, + "InCatalog": true + }, + { + "Repo": "ops-mason", + "Intent": { + "Source": "ops-mason/INTENT.md", + "Layer": "Staff", + "Role": "pep-shaped", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "File": { + "Source": "", + "Layer": "", + "Role": "", + "Found": false, + "InVocabulary": false, + "Canonical": "" + }, + "InCatalog": true + }, + { + "Repo": "ops-warden", + "Intent": { + "Source": "ops-warden/INTENT.md", + "Layer": "Staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "File": { + "Source": "ops-warden/layer.yaml", + "Layer": "staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "InCatalog": true + }, + { + "Repo": "secrets-engine", + "Intent": { + "Source": "secrets-engine/INTENT.md", + "Layer": "Engine", + "Role": "Lifecycle", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "secrets-engine/layer.yaml", + "Layer": "engine", + "Role": "lifecycle", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "tenant-engine", + "Intent": { + "Source": "tenant-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "tenant-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "user-engine", + "Intent": { + "Source": "user-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "user-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "zone-engine", + "Intent": { + "Source": "zone-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "zone-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + } + ], + "scope": { + "Name": "estate-wide", + "Statement": "every repository surveyed, catalogued or not. Repositories outside §4 are reported as declared voluntarily, outside catalog scope — never as §11 non-conformances.", + "Repos": [ + "approval-engine", + "audit-core", + "flex-auth", + "gate-house", + "key-cape", + "kings-guard", + "maturity-engine", + "net-kingdom", + "ops-mason", + "ops-warden", + "secrets-engine", + "tenant-engine", + "user-engine", + "zone-engine" + ] + }, + "self_disagreeing": [ + { + "Repo": "approval-engine", + "Intent": { + "Source": "approval-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "approval-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "audit-core", + "Intent": { + "Source": "audit-core/INTENT.md", + "Layer": "Engine", + "Role": "Evidence", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "audit-core/layer.yaml", + "Layer": "engine", + "Role": "evidence", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "kings-guard", + "Intent": { + "Source": "kings-guard/INTENT.md", + "Layer": "Staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "File": { + "Source": "kings-guard/layer.yaml", + "Layer": "staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "InCatalog": true + }, + { + "Repo": "maturity-engine", + "Intent": { + "Source": "maturity-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "maturity-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "ops-warden", + "Intent": { + "Source": "ops-warden/INTENT.md", + "Layer": "Staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "File": { + "Source": "ops-warden/layer.yaml", + "Layer": "staff", + "Role": "", + "Found": true, + "InVocabulary": true, + "Canonical": "Staff" + }, + "InCatalog": true + }, + { + "Repo": "secrets-engine", + "Intent": { + "Source": "secrets-engine/INTENT.md", + "Layer": "Engine", + "Role": "Lifecycle", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "secrets-engine/layer.yaml", + "Layer": "engine", + "Role": "lifecycle", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "tenant-engine", + "Intent": { + "Source": "tenant-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "tenant-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "user-engine", + "Intent": { + "Source": "user-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "user-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + }, + { + "Repo": "zone-engine", + "Intent": { + "Source": "zone-engine/INTENT.md", + "Layer": "Engine", + "Role": "PIP", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "File": { + "Source": "zone-engine/layer.yaml", + "Layer": "engine", + "Role": "pip", + "Found": true, + "InVocabulary": true, + "Canonical": "Engine" + }, + "InCatalog": true + } + ], + "spellings": { + "Engine": [ + "approval-engine/INTENT.md", + "audit-core/INTENT.md", + "flex-auth/INTENT.md", + "maturity-engine/INTENT.md", + "secrets-engine/INTENT.md", + "tenant-engine/INTENT.md", + "user-engine/INTENT.md", + "zone-engine/INTENT.md" + ], + "Staff": [ + "gate-house/INTENT.md", + "kings-guard/INTENT.md", + "ops-mason/INTENT.md", + "ops-warden/INTENT.md" + ], + "Taxonomy": [ + "net-kingdom/INTENT.md" + ], + "Tooling": [ + "key-cape/INTENT.md" + ], + "engine": [ + "approval-engine/layer.yaml", + "audit-core/layer.yaml", + "maturity-engine/layer.yaml", + "secrets-engine/layer.yaml", + "tenant-engine/layer.yaml", + "user-engine/layer.yaml", + "zone-engine/layer.yaml" + ], + "staff": [ + "kings-guard/layer.yaml", + "ops-warden/layer.yaml" + ] + }, + "undeclared": null, + "validated_against": "net-kingdom/canon/standards/security-layer-model_v0.7.md (net-kingdom@66dc491) as amended by GH-DEC-2026-017, GH-DEC-2026-020, GH-DEC-2026-021 (gate-house@39d9287)", + "version_pinned": null, + "volunteers": null +} diff --git a/docs/iam-profile-consumption.md b/docs/iam-profile-consumption.md index f1e81fe..08c9a30 100644 --- a/docs/iam-profile-consumption.md +++ b/docs/iam-profile-consumption.md @@ -126,6 +126,26 @@ This matches Markitect's `NetKingdomIdentityClaimsAdapter._principal_type` as a compatibility path. New claim envelopes should not force flex-auth to infer principal type. +**`principal_type` carries no route (key-cape, 2026-09-21).** Whether key-cape +distinguishes a registration-asserted `principal_type` from an +authentication-derived one is open (`GH-DEC-2026-013` / `-016` §5). Until it is +answered, key-cape's own instruction is: **do not read `principal_type` as +authentication-derived.** flex-auth may classify with it; no rule may discharge +a human-in-the-loop control on it alone. + +Checked against every published package on that date. Only +`informed-decision-t03` and `informed-decision-sitting` gate on a human subject, +and both also require `principal_type_source == "authentication-derived"`. That +value is not key-cape's `principal_type`: informed-decision derives it from the +verified code-flow MFA event itself (`informed_decision/oidc.py`, refused unless +`aal2`, `pwd`+`otp`, source `key-cape`, fresh `at`). So neither package rests on +the claim key-cape cautioned against, and no change was needed. + +The legacy fallback above ends in *"Otherwise → human"*, which defaults to the +strongest reading. It is a compatibility path for classification only; a rule +that needs humanness must require a routed source, as the two packages above do, +and never this default. + ## Group Overage and Freshness Microsoft Entra and Keycloak both clip the `groups` claim once a diff --git a/workplans/FLEX-WP-0030-boundary-declaration-cleanup.md b/workplans/FLEX-WP-0030-boundary-declaration-cleanup.md index 5cce861..826d867 100644 --- a/workplans/FLEX-WP-0030-boundary-declaration-cleanup.md +++ b/workplans/FLEX-WP-0030-boundary-declaration-cleanup.md @@ -4,7 +4,7 @@ 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: active +status: finished flavor: review owner: claude topic_slug: netkingdom @@ -146,7 +146,7 @@ over (`ops-mason`). ```task id: FLEX-WP-0030-T04 -status: progress +status: done priority: high state_hub_task_id: "70786e6d-02f2-5a90-8640-247ba377d9a4" ``` @@ -286,6 +286,31 @@ survey (`docs/evidence/2026-09-21-layer-declaration-survey-after-ghdec017.json`) `maturity-engine`, `zone-engine`, `secrets-engine` and `railiance-master` also confirmed the ruling applied. None of these bears on B2. +2026-09-21 (B2 closed): all three outstanding repositories now declare in their +own files, verified by the survey rather than taken on report — receipt +`docs/evidence/2026-09-21-layer-declaration-survey-b2-closed.json`, 14 of 14 +declared, 0 undeclared. + +| Repository | Declares | Commit | Reply | +| --- | --- | --- | --- | +| `key-cape` | `Tooling` | `key-cape@9cb9507` | `c9bd902b` — boundary read the same way from its side | +| `net-kingdom` | `Taxonomy` | `net-kingdom@0b10b4b` | `897ef3b6` | +| `ops-mason` | `Staff` | `ops-mason@0ff263a` | none — the file is the declaration (§11), a reply is not needed | + +`key-cape` also stated the boundary from its side for the first time: it +expects nothing of flex-auth beyond standard token verification, and there is no +assurance property flex-auth should re-derive. Its caveat — do not read +`principal_type` as authentication-derived until `GH-DEC-2026-013`/`-016` §5 is +answered — was checked against every published package and needs no change; the +assessment is in `docs/iam-profile-consumption.md`. + +B5: `net-kingdom` approved A13, the "pending, not broken" note. It lands with the +rest of gate-house's amendment set after the v0.8 hold closes, not before. The +remaining obligation — ping when `access-engine` resolves — is `FLEX-WP-0020`'s, +already owed to `reuse-surface` on the same trigger. + +Every finding is answered. T04 is done. + ## Out of scope - Bumping flex-auth to declare v0.8. v0.8 is `status: proposed`; T01 removes the