Compare commits

...

6 commits

Author SHA1 Message Date
b30c858d46 Review security layer model v0.4 (FLEX-DEC-2026-002), closing FLEX-IN-0002
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
FLEX-IN-0002 asked for review of v0.3; v0.4 supersedes it, so the assessment is
against v0.4 plus the in-place section 11 amendment.

Assent, with one rule contested:

- Section 9.3 conflates two failure cases. Input degradation inside a reachable
  engine is flex-auth's fallback and is accepted. Engine unreachability is not:
  there is no evaluator in the path to express anything, which is why flex-auth
  has held that fail-open is not expressible by a PDP at all. As written 9.3
  also collides with ops-warden ADR-0009 (accepted, superseding ADR-0006),
  which retires the global flag for a total per-zone map in the consumer PEP —
  the correct design, since the alternative makes flex-auth a hard dependency
  of the SSH certificate the tunnel carrying the policy call depends on.
- Section 13 names access-engine as intended owner of two capabilities never
  reviewed here. Containment is plausible and recorded as proposed owner only.
  Authentication/assurance evidence is declined as stated: flex-auth consumes
  assurance claims and never re-defines them.
- Three consistency defects: frontmatter status proposed vs section 14
  "accepted"; "seven of fifteen"/"remaining eight" against sixteen
  estate-authored catalog rows and nine listed; "all three repositories" above
  a table of four.

FLEX-IN-0002's two questions answered: the approval boundary unblocks T03
design, but T05 needs the approval claim bound to the same request digest
NewDecisionBinding computes, and a named owner and ordering for single
consumption. The maturity claim route works as a request claim, not as registry
content, until the self-declared provenance digest gap closes.

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 02:42:28 +02:00
repo-manager
54aae6b6b3 repo.work.close_intake FLEX-IN-0002
correlation_id: 1e832e3c-4e51-4dfd-919d-40593c18b2ab
reason: rmgr CLI
source: repo-manager

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
2026-08-29 02:42:14 +02:00
repo-manager
e18a69900c repo.work.add_intake_note FLEX-IN-0002
correlation_id: bc6af047-9a4d-40de-b915-53fdbbdcf7d5
reason: rmgr CLI
source: repo-manager

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
2026-08-29 02:42:14 +02:00
repo-manager
f5e49182b6 repo.work.resolve_decision FLEX-DEC-2026-002
correlation_id: c08c9fd9-29e5-472f-bf10-26c62d6dd597
reason: rmgr CLI
source: repo-manager

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
2026-08-29 02:42:13 +02:00
repo-manager
30c62bc6be repo.work.create_decision FLEX-DEC-2026-002
correlation_id: 76ede6f9-6bcd-40e2-b4c6-5b59d27ccc60
reason: rmgr CLI
source: repo-manager

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
2026-08-29 02:41:21 +02:00
aafc74bd74 Refresh work-record index
Regenerated by fix-consistency; adds the inbound v0.3 review intake.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2564823@bnt-lap001
Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9
2026-08-28 22:43:06 +02:00
4 changed files with 279 additions and 13 deletions

View file

@ -2,9 +2,9 @@
"schema": "repo_manager.index.v1",
"slug": "flex-auth",
"repo_root": "/home/worsch/flex-auth",
"head_sha": "8f815bb304799f81377b66d92733848dc5521bc9",
"observed_at": "2026-08-28T19:45:14.006414Z",
"source_fingerprint": "fb09ffb68b552d10f3ed4d8d60cade2e57b321d1f3c0567775bfe957ebc82128",
"head_sha": "54aae6b6b365407c102c511e30c392b459423be2",
"observed_at": "2026-08-29T00:42:15.556704Z",
"source_fingerprint": "3cadc015fd19f01f7381a51c7d7b0aa461f875bfe59253be427e9d5d8f373795",
"source_files": [
".repo-classification.yaml",
"INTENT.md",
@ -1030,7 +1030,7 @@
"status": "resolved",
"title": "Assent to GH-DEC-2026-001: Engine framing, access-engine rename, authoring/evaluation split",
"source_path": "decisions/decisions.md",
"uuid": null,
"uuid": "c990e442-77c2-4556-a40b-61f65eded10b",
"parent_id": null,
"extra": {
"record": {
@ -1060,7 +1060,48 @@
"updated": "2026-08-28T19:44:29.505314Z",
"rationale": "Assent to all three items of GH-DEC-2026-001. Item 1: flex-auth is Engine-layer and the sole decision point; the INTENT reframe at fe46122 stands. flex-auth accepts one conformance debt of its own \u2014 DecisionProvenance carries no registry snapshot digest, so a decision turning on registry content is not replayable from its own provenance (standard section 6). Item 2: access-engine is the right name; execution is a separate governed migration, conditioned on renaming repository identity and runtime identity in separate revertible steps (the enforcing ops-warden pin binds tokens to the protected-system name flex-auth, and a single-step rename would 401 every warden sign) and on FLEX-WP prefix ownership staying with the repository. Item 3: the authoring/evaluation split is accepted; gate-house authority ceilings must reach the decision as input claims or as rules in the versioned policy package so their application is reconstructable from the decision record \u2014 the same section 6 test flex-auth applied to zone-engine and now to itself. FLEX-WP-0017-T03/T05 stay wait: the design half is re-routed to gate-house, the durable storage half remains unowned and is raised as an engine gap.",
"decided_by": "flex-auth (reviewing side)",
"decided_at": "2026-08-28T19:44:29.505314Z"
"decided_at": "2026-08-28T19:44:29.505314Z",
"state_hub_decision_id": "c990e442-77c2-4556-a40b-61f65eded10b"
}
}
},
{
"kind": "decision",
"id": "FLEX-DEC-2026-002",
"status": "resolved",
"title": "Review of security layer model v0.4: assent with findings, one rule contested",
"source_path": "decisions/decisions.md",
"uuid": null,
"parent_id": null,
"extra": {
"record": {
"id": "FLEX-DEC-2026-002",
"kind": "decision",
"title": "Review of security layer model v0.4: assent with findings, one rule contested",
"status": "resolved",
"origin": "cross-repo",
"origin_ref": "net-kingdom security-layer-model_v0.4",
"standard": "net-kingdom/canon/standards/security-layer-model_v0.4.md",
"intake_ref": "FLEX-IN-0002",
"owner": "flex-auth",
"affects": [
"flex-auth",
"gate-house",
"net-kingdom",
"ops-warden",
"approval-engine",
"maturity-engine"
],
"requested_dispositions": [
"assent",
"revise",
"reject"
],
"created": "2026-08-29T00:41:21.171665Z",
"updated": "2026-08-29T00:42:13.009799Z",
"rationale": "Assent to security-layer-model v0.4, with one rule contested and two capability assignments not accepted as assented. Section 9.3 conflicts with shipped assented behavior: it rules engine-unreachability fallback into the engine, where it cannot live, and collides with ops-warden ADR-0009's per-zone consumer PEP map. Section 13 names access-engine as intended owner of containment (accept as proposed owner only, pending per 9.2) and of authentication/assurance evidence (declined as stated; the identity layer and audit-core own that). Three consistency defects: frontmatter status proposed contradicts section 14 'accepted'; the adoption count reads seven of fifteen with remaining eight against sixteen estate-authored repositories and nine listed; section 14 says three repositories above a table of four. FLEX-IN-0002 answered: the approval boundary unblocks T03 design, T05 additionally needs the approval claim bound to the NewDecisionBinding request digest and a named owner and ordering for single consumption; the maturity claim route is practical as a request claim but not as registry content until the self-declared provenance digest gap closes.",
"decided_by": "flex-auth (reviewing side)",
"decided_at": "2026-08-29T00:42:13.009799Z"
}
}
},
@ -1070,7 +1111,7 @@
"status": "closed",
"title": "Assent requested: Engine framing, access-engine rename, and the authoring/evaluation split",
"source_path": "intakes/intakes.md",
"uuid": null,
"uuid": "01a049eb-812c-7641-8e46-8dd63b12b2a8",
"parent_id": null,
"extra": {
"record": {
@ -1095,18 +1136,60 @@
}
],
"closed_at": "2026-08-28T19:45:06.001794Z",
"outcome": "assented \u2014 see FLEX-DEC-2026-001"
"outcome": "assented \u2014 see FLEX-DEC-2026-001",
"state_hub_intake_id": "01a049eb-812c-7641-8e46-8dd63b12b2a8"
}
}
},
{
"kind": "intake",
"id": "FLEX-IN-0002",
"status": "closed",
"title": "Review requested: security layer model v0.3 (approval-engine, maturity-engine)",
"source_path": "intakes/intakes.md",
"uuid": null,
"parent_id": null,
"extra": {
"record": {
"id": "FLEX-IN-0002",
"kind": "intake",
"title": "Review requested: security layer model v0.3 (approval-engine, maturity-engine)",
"status": "closed",
"origin": "cross-repo",
"origin_ref": "net-kingdom security-layer-model_v0.3",
"priority": "medium",
"owner": "flex-auth",
"requested_by": "gate-house",
"description": "v0.3 is proposed and changes sections 4, 9 and 13 only; the section 14 assent record from v0.2 stands. Two additions concern flex-auth. (1) Section 9.4 assigns the approval object to a new approval-engine \u2014 the gap FLEX-DEC-2026-001 raised. Your self-dealing objection is upheld: the evaluator does not own what it evaluates. access-engine consumes approvals as input claims under section 6.2 and never mutates them, so the approval identifier stays reconstructable from the decision record. Question for you: do you want the claim shape specified before you plan FLEX-WP-0017 T03/T05 around it, or is the boundary enough to unblock design? (2) Section 9.5 assigns graded progression to a new maturity-engine, carrying the guardrail that a maturity level must never gate a decision directly \u2014 if a level determines an outcome it reaches access-engine as an input claim or a versioned policy rule. That guardrail is section 6.1 applied to a new engine, and it is your rule as much as ours; if the claim route is impractical from where you sit, that is worth knowing before the engine is built rather than after. Assent, revision, or rejection acceptable.",
"created": "2026-08-28T20:40:00.263659Z",
"updated": "2026-08-29T00:42:14.888434Z",
"notes": [
{
"content": "Answered by FLEX-DEC-2026-002, reviewing v0.4 (which supersedes the v0.3 this intake asked about): assent with findings, section 9.3 contested, two section 13 owner rows not accepted as assented, three consistency defects, and both questions answered.",
"author": "flex-auth",
"created": "2026-08-29T00:42:14.005210Z"
}
],
"closed_at": "2026-08-29T00:42:14.888434Z",
"outcome": "assented with findings \u2014 see FLEX-DEC-2026-002"
}
}
}
],
"events": [
{
"type": "repo.reconciled",
"workplan_count": 18,
"task_count": 81,
"type": "repo.command.applied",
"command": "repo.work.close_intake",
"operation": "close",
"correlation_id": "1e832e3c-4e51-4dfd-919d-40593c18b2ab",
"kind": "intake",
"id": "FLEX-IN-0002",
"git_sha": "54aae6b6b365407c102c511e30c392b459423be2",
"files_touched": [
"intakes/intakes.md"
],
"source": "repo-manager",
"emitted_at": "2026-08-28T19:45:14.006530Z"
"emitted_at": "2026-08-29T00:42:15.556791Z"
}
]
}

View file

@ -108,4 +108,5 @@
| task | FLEX-WP-0018-T01 | done | — | workplans/FLEX-WP-0018-inbound-auth-corrections.md |
| task | FLEX-WP-0018-T02 | done | — | workplans/FLEX-WP-0018-inbound-auth-corrections.md |
| intake | FLEX-IN-0001 | closed | — | intakes/intakes.md |
| intake | FLEX-IN-0002 | open | — | intakes/intakes.md |
| decision | FLEX-DEC-2026-001 | resolved | — | decisions/decisions.md |

View file

@ -170,3 +170,176 @@ an engine gap under §5, not solved locally.
- A workplan will carry the registry snapshot digest into `DecisionProvenance`.
- The rename is not started, and must not start before a migration record
exists that satisfies the two conditions above.
## FLEX-DEC-2026-002 — Review of security layer model v0.4: assent with findings, one rule contested
```yaml
id: FLEX-DEC-2026-002
kind: decision
title: 'Review of security layer model v0.4: assent with findings, one rule contested'
status: resolved
origin: cross-repo
origin_ref: net-kingdom security-layer-model_v0.4
standard: net-kingdom/canon/standards/security-layer-model_v0.4.md
intake_ref: FLEX-IN-0002
owner: flex-auth
affects:
- flex-auth
- gate-house
- net-kingdom
- ops-warden
- approval-engine
- maturity-engine
requested_dispositions:
- assent
- revise
- reject
created: '2026-08-29T00:41:21.171665Z'
updated: '2026-08-29T00:42:13.009799Z'
rationale: 'Assent to security-layer-model v0.4, with one rule contested and two capability
assignments not accepted as assented. Section 9.3 conflicts with shipped assented
behavior: it rules engine-unreachability fallback into the engine, where it cannot
live, and collides with ops-warden ADR-0009''s per-zone consumer PEP map. Section
13 names access-engine as intended owner of containment (accept as proposed owner
only, pending per 9.2) and of authentication/assurance evidence (declined as stated;
the identity layer and audit-core own that). Three consistency defects: frontmatter
status proposed contradicts section 14 ''accepted''; the adoption count reads seven
of fifteen with remaining eight against sixteen estate-authored repositories and
nine listed; section 14 says three repositories above a table of four. FLEX-IN-0002
answered: the approval boundary unblocks T03 design, T05 additionally needs the
approval claim bound to the NewDecisionBinding request digest and a named owner
and ordering for single consumption; the maturity claim route is practical as a
request claim but not as registry content until the self-declared provenance digest
gap closes.'
decided_by: flex-auth (reviewing side)
decided_at: '2026-08-29T00:42:13.009799Z'
```
## Context
`FLEX-IN-0002` asked flex-auth to review v0.3. By the time of review the current
text is **v0.4** (plus the in-place §11 amendment at `2aaf46c`), which supersedes
v0.3. This record reviews v0.4 and answers the two questions `FLEX-IN-0002` put.
Three versions have landed since `FLEX-DEC-2026-001`, which answered **v0.1**.
## Disposition
**Assent to v0.4, with one rule contested, two capability assignments not
accepted as assented, and three consistency defects.** Nothing here blocks
adoption; §9.3 needs correction before it is relied on.
### What v0.4 gets right, from flex-auth's side
§6.2 adopts flex-auth's boundary from `FLEX-DEC-2026-001` in substance and binds
gate-house on the same terms. §9.4 upholds the self-dealing objection: the
evaluator does not own the object it evaluates, `access-engine` consumes
approvals as input claims and never mutates them. §13 attributes the
registry-snapshot digest gap to flex-auth as self-declared, which is correct.
§9.5's guardrail — a maturity level MUST NOT gate a decision directly — is §6.1
applied to a new engine, and flex-auth endorses it.
### Contested — §9.3 conflicts with shipped, assented behavior
> *"The deterministic fail to reduced authority default is `access-engine`'s,
> applied when it cannot reach its own inputs."*
Two different failure cases are conflated:
1. **access-engine is reachable but cannot reach its own inputs.** The fallback
is flex-auth's, it is deterministic, and §9.3 is right. flex-auth accepts it.
2. **access-engine is not reachable at all.** The engine applies nothing,
because it is not running. Whatever happens next is the consumer's behavior,
necessarily. flex-auth has held since 2026-08-19 that **fail-open is not
expressible by a PDP at all** — not as a preference, but because there is no
evaluator in the path to express it.
§9.3 as written rules case 2 into the engine, where it cannot live. It also
collides with shipped behavior in a repository that has assented to this
standard: **ops-warden `ADR-0009`** (accepted 2026-08-22, superseding `ADR-0006`)
retires the global `policy.enabled` and `policy.fail_closed` and replaces them
with a **total per-zone map in the consumer PEP** — fails open for
`z0-experimental`, `z1-operational`, `z2-protected`, `z2-continuity` and
`unknown`; fails closed for `z3-critical`. That map is a Staff-layer
degraded-mode fallback, and it is the correct design: the alternative makes
flex-auth a hard dependency of every `warden sign`, including the SSH
certificate the ops-bridge tunnel carrying the policy call depends on.
Proposed correction: §9.3 should rule the **input-degradation** fallback into the
engine and state that **engine-unreachability residue is the consumer's**,
bounded by a requirement that the consumer's stance be declared per zone and
auditable — which `ADR-0009` already satisfies. The sentence *"engine-unavailable
is not grounds for a Staff break-glass path"* is sound and should be kept: a
bypass path around a **reachable** engine is a second decision point. A consumer
choosing its own behavior when there is no engine to ask is not.
### Not accepted as assented — two capability assignments
v0.4's frontmatter lists `flex-auth FLEX-DEC-2026-001` under `assented_by`, and
§14 presents it as adoption of the current text. That record answered v0.1.
Since then §13 names `access-engine` as intended owner of two capabilities
flex-auth has never reviewed:
| Gap row | Position |
| --- | --- |
| Containment surface → `access-engine` + runtime engines | Plausible and consistent with §8's posture asymmetry — rendering reduced authority is what a PDP does. Not yet reviewed, and §9.2 marks it pending anyway. Record it as **proposed owner**, not owner. |
| Authentication / assurance evidence → `user-engine`, `access-engine` | **Declined as stated.** flex-auth consumes assurance claims as input and never re-defines them; `INTENT.md` is explicit that the identity layer owns authentication. Evidence *of authentication* belongs to the identity layer and `audit-core`. flex-auth owns evidence of the **decision**, which it already emits. |
An `intended_owner` in a gap register is a proposal to the named repository, not
an assignment to it — §2 keeps what a repository owns in that repository's own
`INTENT.md`. flex-auth suggests §13 gain a column distinguishing a proposed owner
from an assented one, so the register does not accumulate silent assignments the
way §14's assent row nearly did.
### Consistency defects
1. **Frontmatter `status: proposed` contradicts §14 "Status is accepted."**
Material, because §2 makes this standard the authority for layer assignment.
The change log records v0.2 as accepted and v0.3/v0.4 as proposed, so §14
appears to be a carryover.
2. **§14's adoption count does not add up.** "seven of fifteen" and "the
remaining eight" against a §4 catalog of 17 rows, 16 of them estate-authored
(`OpenBao` excepted by §11's own who-must-declare rule). Seven declared plus
the nine repositories actually listed is sixteen. Should read **seven of
sixteen** and **the remaining nine**.
3. **§14 says "All three repositories whose boundaries moved"** above a table of
four. `audit-core` is the fourth.
## Answers to FLEX-IN-0002
**(1) Is the boundary enough to unblock `FLEX-WP-0017` T03/T05 design?**
Yes for T03. Not quite for T05, which needs two things specified in
`approval-engine`'s contract first:
- **Claim shape must bind to the request digest flex-auth already computes.**
The approval claim should carry the approval id plus the digest of the action
it approves, computed over the same canonical binding as
`NewDecisionBinding` (`FLEX-WP-0017-T01`). Otherwise "approved" and "approved
*for this exact request*" are not distinguishable at decision time, and T05's
wrong-action/lane/stage/targets proofs have nothing to compare against.
- **Single consumption needs an owner and an ordering.** flex-auth never mutates
approvals, so consumption is `approval-engine`'s. But the decision precedes the
action, and the action precedes consumption — so an allow rendered against an
approval that is then never consumed, or consumed twice by a racing caller, is
a gap neither engine closes alone. Naming who marks consumed and at what point
relative to the decision belongs in the contract before T05, not after.
**(2) Is the maturity claim route practical from where flex-auth sits?**
Yes, with one caveat that is flex-auth's own fault rather than
`maturity-engine`'s. A level reaching flex-auth as a **request claim** is
practical today and lands in the decision binding. A level reaching flex-auth as
**registry content** is not reconstructable, because `DecisionProvenance` carries
no registry-snapshot digest — the gap flex-auth self-declared in §13. Until that
closes, maturity levels should arrive as request claims or versioned policy
rules, never compiled into the registry snapshot. This is the same constraint
flex-auth placed on zone stance, for the same reason.
## Consequences
- `FLEX-IN-0002` is closed; the assessment covers v0.4 rather than v0.3.
- flex-auth's assent now attaches to **v0.4** for §§18, §9.19.2, §9.49.6,
and §§1016, and to §9.3 only in its input-degradation half.
- `FLEX-WP-0017` T03/T05 stay `wait` on `approval-engine`, with the two contract
items above raised as prerequisites for T05.
- `SCOPE.md` cites ops-warden `ADR-0006` as current; it is superseded by
`ADR-0009`. Correcting that is flex-auth's own housekeeping.

View file

@ -48,7 +48,7 @@ state_hub_intake_id: "01a049eb-812c-7641-8e46-8dd63b12b2a8"
id: FLEX-IN-0002
kind: intake
title: 'Review requested: security layer model v0.3 (approval-engine, maturity-engine)'
status: open
status: closed
origin: cross-repo
origin_ref: net-kingdom security-layer-model_v0.3
priority: medium
@ -69,5 +69,14 @@ description: 'v0.3 is proposed and changes sections 4, 9 and 13 only; the sectio
as ours; if the claim route is impractical from where you sit, that is worth knowing
before the engine is built rather than after. Assent, revision, or rejection acceptable.'
created: '2026-08-28T20:40:00.263659Z'
updated: '2026-08-28T20:40:00.263659Z'
updated: '2026-08-29T00:42:14.888434Z'
notes:
- content: 'Answered by FLEX-DEC-2026-002, reviewing v0.4 (which supersedes the v0.3
this intake asked about): assent with findings, section 9.3 contested, two section
13 owner rows not accepted as assented, three consistency defects, and both questions
answered.'
author: flex-auth
created: '2026-08-29T00:42:14.005210Z'
closed_at: '2026-08-29T00:42:14.888434Z'
outcome: assented with findings — see FLEX-DEC-2026-002
```