Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014348@bnt-lap001 Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
346 lines
18 KiB
Markdown
346 lines
18 KiB
Markdown
# Decision records
|
||
|
||
## FLEX-DEC-2026-001 — Assent to GH-DEC-2026-001: Engine framing, access-engine rename, authoring/evaluation split
|
||
|
||
```yaml
|
||
id: FLEX-DEC-2026-001
|
||
kind: decision
|
||
title: 'Assent to GH-DEC-2026-001: Engine framing, access-engine rename, authoring/evaluation
|
||
split'
|
||
status: resolved
|
||
origin: cross-repo
|
||
origin_ref: gate-house GH-DEC-2026-001
|
||
standard: net-kingdom/canon/standards/security-layer-model_v0.1.md
|
||
intake_ref: FLEX-IN-0001
|
||
owner: flex-auth
|
||
affects:
|
||
- flex-auth
|
||
- gate-house
|
||
- net-kingdom
|
||
- ops-warden
|
||
- secrets-engine
|
||
- zone-engine
|
||
requested_dispositions:
|
||
- assent
|
||
- revise
|
||
- reject
|
||
created: '2026-08-28T19:43:38.443788Z'
|
||
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 — 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 — 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'
|
||
state_hub_decision_id: "c990e442-77c2-4556-a40b-61f65eded10b"
|
||
```
|
||
|
||
## Context
|
||
|
||
`gate-house` asked flex-auth, via `FLEX-IN-0001`, to assent to the three items
|
||
ratified in `GH-DEC-2026-001`. The request follows the estate precedent that a
|
||
boundary is drawn on review by the other side rather than asserted — the
|
||
precedent flex-auth itself set when it reviewed a `zone-engine` draft and ruled
|
||
that flex-auth is the policy decision point and stays the only one.
|
||
|
||
This record is flex-auth's answer. It is written from the reviewing side: the
|
||
questions asked were not "is this flattering to flex-auth" but "does this hold
|
||
against what flex-auth actually is, and does flex-auth actually conform".
|
||
|
||
## Disposition
|
||
|
||
**Assent to all three items, with one accepted conformance debt and two
|
||
conditions on the rename.** Nothing here revises or rejects any part of
|
||
`GH-DEC-2026-001`.
|
||
|
||
### Item 1 — Engine framing and the sole decision point: assent
|
||
|
||
flex-auth is Engine-layer under §3.3 and §4 of the standard. The defining
|
||
property holds: the same authoritative input state yields the same result. The
|
||
INTENT reframe is applied at `fe46122` and is correct as written — "control
|
||
plane" is dropped as Staff vocabulary, and the exclusive decision-point role of
|
||
§6 is stated.
|
||
|
||
The generalization in §6 is the ruling flex-auth drew against `zone-engine`,
|
||
applied to the estate. flex-auth cannot consistently hold that boundary against
|
||
another repository and decline it as a general rule.
|
||
|
||
**Accepted conformance debt — registry provenance.** §6 states that compiled
|
||
data determining an outcome is still deciding, and that provenance must remain
|
||
reconstructable from the engine's decision. flex-auth does not fully satisfy
|
||
this today. `DecisionProvenance` (`pkg/api/canonical.go`) carries the evaluator,
|
||
mode, policy package, policy version, and a directory ETag — but no digest of
|
||
the registry snapshot that supplied resource, subject, and relationship facts.
|
||
A decision that turned on registry content therefore cannot be replayed from
|
||
its own provenance.
|
||
|
||
flex-auth accepts this as its own gap rather than claiming conformance it does
|
||
not have. It is the same argument flex-auth made to `zone-engine` — zone
|
||
*membership* compiles into the registry snapshot, per-zone *stance* belongs in
|
||
the versioned policy package, precisely because registry content is absent from
|
||
decision provenance. The clean fix is to make registry content provenanced, and
|
||
a workplan will carry it. Until it lands, the flex-auth position that
|
||
outcome-determining content belongs in the versioned policy package stands
|
||
unchanged, and stands for gate-house's inputs on the same terms (item 3).
|
||
|
||
### Item 2 — The `flex-auth` → `access-engine` rename: assent to the name, not yet to execution
|
||
|
||
`access-engine` is the right name. The rejection of `auth-engine` is correct —
|
||
`key-cape` owns authentication, and `auth-` preserves exactly the ambiguity the
|
||
rename exists to remove. The §8 lane/rule demarcation is an acceptable cost and
|
||
flex-auth adopts it: `ops-warden` and `ops-mason` own access lanes, flex-auth
|
||
owns access rules.
|
||
|
||
flex-auth agrees the rename is a separate governed migration and does not treat
|
||
`GH-DEC-2026-001` as authorizing it. Two conditions, from the consumer side
|
||
rather than the documentary side:
|
||
|
||
1. **Repository identity and runtime identity must be renamed in separate,
|
||
independently revertible steps, repository first.** The name `flex-auth` is
|
||
not only a repo slug: it is a deployed service, an in-cluster DNS name, a
|
||
chart and image name, and — since `FLEX-WP-0016` moved the ops-warden pin to
|
||
`callerAuth.mode: enforce` — a protected-system identifier that inbound
|
||
tokens are bound to. A single-step rename would make every `warden sign` a
|
||
401, including the certificate the `ops-bridge` tunnels depend on. This is
|
||
the same dependency shape that caused `ops-warden`'s `ADR-0006` to defer
|
||
`policy.enabled` permanently.
|
||
2. **`FLEX-WP` prefix ownership stays with the repository across the rename.**
|
||
Existing `FLEX-WP-0001..0018` identifiers are referenced by State Hub
|
||
records, by consumer repositories, and by decision provenance in shipped
|
||
audit records. They are not renamed retroactively; whether new work takes a
|
||
new prefix is a question for the migration record, not for this assent.
|
||
|
||
The migration also touches State Hub identifiers, `ops-warden`'s routing
|
||
tables, `zone-engine`'s boundary text, and `secrets-engine` integrations, as
|
||
`GH-DEC-2026-001` states. flex-auth will not begin any of it under this record.
|
||
|
||
### Item 3 — The authoring/evaluation split: assent, with the §6 test applied symmetrically
|
||
|
||
The split is correct and flex-auth gives up the authoring half willingly:
|
||
gate-house owns the doctrine, the invariants, the authority ceilings, the
|
||
operating modes, and the authority context; flex-auth owns evaluation
|
||
exclusively plus the policy-as-code mechanism; policy *content* stays with the
|
||
protected system's owner.
|
||
|
||
flex-auth draws one boundary back, which is the §6 test applied to gate-house's
|
||
inputs on the same terms flex-auth applies it to `zone-engine` and to itself:
|
||
|
||
> An authority ceiling that determines an outcome must reach the decision as
|
||
> either an input claim on the request or a rule in the versioned policy
|
||
> package — and its application must be reconstructable from the decision
|
||
> record. A ceiling that resolves an outcome before evaluation runs has decided
|
||
> early, and gate-house is Staff, where §6 forbids a decision point.
|
||
|
||
Concretely: gate-house authors the ceiling; flex-auth renders it. The principal
|
||
/actor/runtime triple, the mandate, and the operating mode arrive as input
|
||
claims and appear in the decision binding. Where a ceiling constrains an
|
||
outcome, it is expressed in the versioned policy package so that the policy
|
||
version in provenance identifies the ceiling that applied. This is not a
|
||
restriction on gate-house's authorship; it is what keeps the authorship
|
||
auditable at decision time.
|
||
|
||
**Effect on `FLEX-WP-0017`.** The split resolves the overlap and re-routes the
|
||
design half of the blocked work: gate-house designs the approval contract,
|
||
flex-auth validates approvals at decision time. It does not unblock
|
||
`FLEX-WP-0017-T03` — the durable approval object, authenticated approval
|
||
entries, and atomic supersession still need an owner for *storage and
|
||
lifecycle*, which is neither gate-house's (Staff holds no state another layer
|
||
depends on at runtime, §3.4) nor flex-auth's (flex-auth does not own the
|
||
organizational approval lifecycle). T03 and T05 stay `wait`, with the design
|
||
half now addressed to gate-house. That unowned half is flagged to gate-house as
|
||
an engine gap under §5, not solved locally.
|
||
|
||
## Consequences
|
||
|
||
- The standard's §11 blocker "flex-auth reframed as an Engine … not yet
|
||
assented" is answered for flex-auth. `kings-guard` and `ops-warden` assent
|
||
remains outstanding and is not flex-auth's to give.
|
||
- `INTENT.md` records the assent and the registry-provenance debt.
|
||
- 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'
|
||
state_hub_decision_id: "2e96321d-c7bf-4127-9c30-f3def32e5bee"
|
||
```
|
||
|
||
## 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 §§1–8, §9.1–9.2, §9.4–9.6,
|
||
and §§10–16, 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.
|