approval-engine filed APPROVAL-IN-0002: secrets-engine built its PEP
validator against our ActionAuthorization schema, pointed it at
GET /v1/approvals/{id}/claim, and it rejects every response. Both
envelopes declare schema_version 0.1, so it fails late and reads like an
approval-engine outage rather than a contract mismatch.
FLEX-DEC-2026-006 accepts the deferral and argues against flex-auth's own
proposal. The composed object had the PIP republish our decision, which
crosses the same layer boundary we invoked to decline authentication
evidence and to win section 17's schema. The claim-plus-DecisionEnvelope
split drops no check; each verification lands on the layer that owns it.
approval-engine asked, before the decision, whether the open G3 finding
argues for ratifying now. It does not: G3 is already closed the other
way. FLEX-WP-0019 added lifetime to the DecisionEnvelope itself, required
on every allow by schema conditional, published 2026-09-02. The trigger
resolved by adding a field rather than by composition, so the decision
stands alone and needs no bundle.
The provenance.authority == state-hub constant is our defect and is
fixed at source. It came from examples/caring/action_authorization.json,
which contradicted the same contract's ownership section. That fixture
now names approval-engine as the approval fact's authority and flex-auth
as the decision's, and its stale secrets-engine.lifecycle pin is
corrected to the reserved coordinate from FLEX-DEC-2026-005.
The contract doc and schema are marked deferred-not-withdrawn so no
other consumer builds a validator against them. The execute-time half is
untouched: /v1/check, binding, the canonical digest, and
flex-auth.decision-record.v1 stay published.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JTbVXpEiXA7mNJVpDnEPcB
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 412054@bnt-lap001
Assistant-Session: 3968fae1-8d59-4209-9bd6-c22594b8ab19
880 lines
45 KiB
Markdown
880 lines
45 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.
|
||
|
||
## FLEX-DEC-2026-003 — Review of security layer model v0.6 and companion v0.1: assent, two answers, five findings
|
||
|
||
```yaml
|
||
id: FLEX-DEC-2026-003
|
||
kind: decision
|
||
title: 'Review of security layer model v0.6 and companion v0.1: assent, two answers,
|
||
five findings'
|
||
status: resolved
|
||
origin: cross-repo
|
||
origin_ref: net-kingdom security-layer-model_v0.6 + companion_v0.1
|
||
standard: net-kingdom/canon/standards/security-layer-model_v0.6.md
|
||
owner: flex-auth
|
||
affects:
|
||
- flex-auth
|
||
- gate-house
|
||
- net-kingdom
|
||
- info-tech-canon
|
||
- ops-warden
|
||
- approval-engine
|
||
requested_dispositions:
|
||
- assent
|
||
- revise
|
||
- reject
|
||
created: '2026-08-29T08:18:39.602701Z'
|
||
updated: '2026-08-29T08:19:41.832549Z'
|
||
rationale: 'Assent to v0.6 and companion v0.1, with two answers and five findings,
|
||
none blocking. Q1: section 6.4.2 is right but collides with 9.7.1''s session-bound
|
||
allow, needs the request digest as its mechanical replay test, and should rule explicitly
|
||
on deny-caching. Q2: the visibility deadline does land on a PDP and harder than
|
||
at a PEP, but must be per input class rather than one number, and it makes flex-auth''s
|
||
registry-provenance gap load-bearing rather than untidy. Findings: 6.4''s stance-map
|
||
register does not exist in section 13 and neither document says where a map is published;
|
||
the companion omits it too, which is the sufficiency gap gate-house asked for; section
|
||
17 puts the decision-record schema in Taxonomy when it is the PDP''s output artifact,
|
||
inverting the section 2 rule flex-auth used to decline authentication evidence;
|
||
sections 17-19 are H1 outside the hierarchy; section 19 grades the document it lives
|
||
in and will age.'
|
||
decided_by: flex-auth (reviewing side)
|
||
decided_at: '2026-08-29T08:19:41.832549Z'
|
||
state_hub_decision_id: "def6a31b-4cd7-4474-8cfa-339b0fc9fcc6"
|
||
```
|
||
|
||
## Context
|
||
|
||
gate-house published v0.5 (answering `FLEX-DEC-2026-002`), then v0.6 with a new
|
||
two-page companion, and asked flex-auth to review two rules specifically. This
|
||
record reviews **v0.6 + companion v0.1** and answers both questions.
|
||
|
||
Every finding in `FLEX-DEC-2026-002` was honored: §9.3 rewritten along the two-
|
||
owner split, §13 given an owner-status column with containment recorded as
|
||
*proposed* and authentication/assurance evidence as *declined* with flex-auth's
|
||
reasoning, all three consistency defects fixed, and both T05 answers folded into
|
||
`approval-engine`'s INTENT and `GH-WP-0002-T06`. gate-house also recorded
|
||
plainly that v0.4 had ruled against shipped assented behavior and that neither
|
||
it nor ops-warden caught it. That is the loop working.
|
||
|
||
## Disposition
|
||
|
||
**Assent to v0.6 and companion v0.1**, with two answers and five findings. None
|
||
blocks adoption.
|
||
|
||
The Engine typing in §3.3 is a real improvement and flex-auth endorses it,
|
||
particularly *"a new engine is a PIP unless this standard is amended"* — that
|
||
sentence is the structural form of §6, and it forecloses the drift §6 was
|
||
written to prevent.
|
||
|
||
### Answer to question 1 — §6.4.2, no local recaching of the verdict
|
||
|
||
**The rule is right and flex-auth supports it.** Caching the answer is deciding
|
||
early at the consumer; caching an input claim under its own freshness rule is
|
||
not. Three refinements, one of which is a genuine collision:
|
||
|
||
**(a) It contradicts §9.7.1 as written.** §9.7.1 permits an allow bound to *"a
|
||
session or obligation that ends."* A session-bound allow is used across later
|
||
requests by construction — that is what binding to a session means. §6.4.2
|
||
forbids replaying a stored verdict *"for a later request."* Taken together, a
|
||
session-bound allow is both permitted and prohibited. The fix is small: scope
|
||
§6.4.2 to requests **outside the decision's own stated binding and lifetime**,
|
||
which preserves the rule and legalizes exactly the case §9.7.1 already intends.
|
||
|
||
**(b) "Later request" needs a mechanical test, and flex-auth already ships one.**
|
||
A PEP retrying an identical action after a transport failure is not a later
|
||
request, but nothing in the standard says how to tell. flex-auth computes a
|
||
canonical request digest over the normalized subject, action, resource, and
|
||
context (`NewDecisionBinding`, `FLEX-WP-0017-T01`), and it is already in every
|
||
decision binding. flex-auth offers it as the normative test: **replay is
|
||
permitted iff the request digest matches and the decision's lifetime holds.**
|
||
That makes §6.4.2 checkable rather than a matter of implementer judgment, and it
|
||
costs the estate nothing new.
|
||
|
||
**(c) Deny-caching is the one real pattern the rule outlaws without naming it.**
|
||
A consumer caching a *deny* under load cannot manufacture authority — §8's
|
||
asymmetry holds, and it protects the PDP from retry storms, which is a real
|
||
operational need. But it does breach §6.4.4: an action refused with no decision
|
||
record naming that request is not reconstructable, and a stale deny is an
|
||
availability failure that will be misdiagnosed as a policy one. flex-auth's
|
||
recommendation is to **rule on it explicitly** rather than leave implementers to
|
||
infer: permit short-lived negative caching only where the refusal is still
|
||
recorded, or forbid it in terms. Either is defensible; silence is not, because
|
||
this is the pattern an implementer under load reaches for first.
|
||
|
||
### Answer to question 2 — §9.7.2, does the visibility deadline land on a PDP
|
||
|
||
**Yes, and it lands harder on the PDP than on the PEP** — but one number is the
|
||
wrong shape for a decision point.
|
||
|
||
A PEP has one boundary and can state one deadline. A PDP's revocation visibility
|
||
is **per input class**, because a decision is a join over sources with unrelated
|
||
refresh behavior: approval-claim freshness from `approval-engine`, registry
|
||
snapshot cadence, policy package activation, and directory ETag. A single
|
||
flex-auth number would be either a fiction or the worst case, and the worst case
|
||
is the registry snapshot — which is the slowest and the least visible. Proposed:
|
||
**§9.7.2 requires a per-input-class deadline at a PDP and a single boundary
|
||
deadline at a PEP.**
|
||
|
||
The consequence for flex-auth is worth stating plainly, because it changes
|
||
flex-auth's own priorities. §9.7.2 makes the self-declared registry-provenance
|
||
gap **load-bearing rather than untidy**. Without a snapshot digest in
|
||
`DecisionProvenance`, nobody can determine after the fact which snapshot a
|
||
decision read, so a stated visibility deadline for registry-borne facts is
|
||
unfalsifiable — the deadline and the digest are the same gap seen from two
|
||
sides. flex-auth accepts that this raises the gap from housekeeping to a
|
||
conformance prerequisite and will plan it as one.
|
||
|
||
### Finding 1 — §6.4's stance-map register does not exist
|
||
|
||
§6.4 requires every PEP-shaped consumer to publish its stance map and requires
|
||
those maps to be *"inventoried — in `maturity-engine` once it exists, in §13
|
||
until then."* **§13 contains no stance rows and does not mention stance maps.**
|
||
Neither document says where a map is published or in what form.
|
||
|
||
This matters for precisely the reason §6.4 gives: without the register,
|
||
*"`z0`–`z2` and unknown fail open"* is the estate's effective policy with nobody
|
||
having compiled it. `ops-warden` `ADR-0009` is cited three times across the two
|
||
documents as the reference shape and appears in no register. flex-auth has a
|
||
direct interest here — the aggregate of consumer stances is the estate's real
|
||
authorization behavior, and flex-auth is the only repository positioned to
|
||
notice when it diverges from what the policy packages say.
|
||
|
||
### Finding 2 — the companion omits it too, which answers the question asked
|
||
|
||
gate-house asked what would show the companion is not sufficient on its own.
|
||
Companion §5.3 says *"publish your unreachable-engine stance"* but never says
|
||
**where**, and omits the inventory obligation entirely. A repository satisfying
|
||
the companion faithfully would publish a stance map into its own repo and
|
||
believe itself conforming, and no register would learn of it. On every other
|
||
point reviewed the companion is faithful to the statute; this is the one gap.
|
||
|
||
### Finding 3 — §17 puts the decision-record schema in the wrong layer
|
||
|
||
The four artifacts are the right four, and Taxonomy is right for three of them.
|
||
The **request-claim schema** is genuinely cross-engine vocabulary and belongs
|
||
there; so do the gap-record and emission-cadence artifacts.
|
||
|
||
The **decision-record schema** does not. A decision record is the PDP's output
|
||
artifact — the one thing in the estate that only `access-engine` produces — and
|
||
§2 keeps what a repository owns in that repository's own `INTENT.md`. flex-auth
|
||
already publishes its shape: the `binding` in `DecisionEnvelope`, the request
|
||
digest, and `schemas/action_authorization.schema.json`. Taxonomy authoring the
|
||
schema for an artifact only flex-auth emits inverts the ownership rule the
|
||
standard applies everywhere else.
|
||
|
||
This is the same §2 argument flex-auth used to decline authentication and
|
||
assurance evidence in `FLEX-DEC-2026-002`, and gate-house accepted it there.
|
||
Symmetry requires flex-auth to apply it against its own interest as well as for
|
||
it: proposed split is **claim / gap-record / emission-cadence to Taxonomy,
|
||
decision-record schema to `access-engine` as a published contract**, with
|
||
Taxonomy holding only the shared field vocabulary the claim schema needs to
|
||
reference. flex-auth will publish that contract; it should not receive it.
|
||
|
||
### Finding 4 — §§17–19 are H1, outside the section hierarchy
|
||
|
||
They use `#` where every other section uses `##`, so they render as siblings of
|
||
the document title rather than sections of it. Mechanical, but the standard asks
|
||
repositories to cite section numbers, and §§17–18 carry normative content.
|
||
|
||
### Finding 5 — §19 grades the document it lives in
|
||
|
||
A *"Verdict on fitness"* inside a standard of record makes the assessment
|
||
normative by adjacency and will age against the text it grades — v0.7 will
|
||
either restate it or leave a stale verdict in force. Suggest it live in the
|
||
2026-08-29 assessment history document and be cited from §16, where the open
|
||
questions already carry the same content as questions rather than as a grade.
|
||
|
||
## Consequences
|
||
|
||
- flex-auth's assent attaches to **v0.6 + companion v0.1**, with §6.4.2 and
|
||
§9.7.2 read as refined above pending gate-house's disposition.
|
||
- The registry-snapshot digest gap is reclassified from housekeeping to a
|
||
conformance prerequisite under §9.7.2, and will be planned as one.
|
||
- flex-auth offers the canonical request digest as the §6.4.2 replay test and
|
||
offers to publish the decision-record schema as its own contract.
|
||
|
||
## FLEX-DEC-2026-004 — Decision lifetime does not reach past issuance: answer to ops-warden WARDEN-WP-0034-T05
|
||
|
||
```yaml
|
||
id: FLEX-DEC-2026-004
|
||
kind: decision
|
||
title: 'Decision lifetime does not reach past issuance: answer to ops-warden WARDEN-WP-0034-T05'
|
||
status: resolved
|
||
origin: cross-repo
|
||
origin_ref: WARDEN-WP-0034-T05
|
||
owner: flex-auth
|
||
affects:
|
||
- flex-auth
|
||
- ops-warden
|
||
requested_dispositions:
|
||
- answer
|
||
- decline
|
||
decided_by: flex-auth (access-engine / PDP)
|
||
rationale: 'Answered, not declined. A decision lifetime shorter than the SSH certificate
|
||
TTL is meaningful, but only as an authority-to-issue window, never as an authority-to-use
|
||
window over an already-issued certificate. flex-auth lifetime.expires_at bounds
|
||
how long that one allow may be relied on to authorise a sign; it cannot bound an
|
||
artifact ops-warden issued under it, and flex-auth does not claim it does. The downstream
|
||
contract that consumes the shorter lifetime is the pre-sign gate itself: no replay
|
||
of an allow past expires_at, and a fresh Check per sign. The lever that actually
|
||
shortens effective access is the requested TTL as a policy input, which is already
|
||
deployed as the ttl_out_of_bounds deny; ops-warden section 9.7.2 window through
|
||
cert TTL is correctly stated and correctly owned by the PEP.'
|
||
created: '2026-09-05T23:08:38.877787Z'
|
||
updated: '2026-09-06T00:00:00.000000Z'
|
||
decided_at: '2026-09-06T00:00:00.000000Z'
|
||
state_hub_decision_id: "f6bfb02a-bbf3-4488-acf9-0e1cb57ce19d"
|
||
```
|
||
|
||
## Context
|
||
|
||
ops-warden now states its §9.7.2 revocation window explicitly: an allow can
|
||
remain effective through an already-issued SSH certificate until TTL expiry
|
||
(`adm` 48h, `agt` 24h, `atm` 8h), because there is no CRL/KRL recall channel.
|
||
It asked flex-auth, as the access engine, whether a decision lifetime shorter
|
||
than the certificate TTL is meaningful under that PEP behaviour, and if so what
|
||
downstream contract should consume the shorter lifetime.
|
||
|
||
## Disposition
|
||
|
||
**Answered, not declined.** The lifetime is meaningful, and the mismatch
|
||
ops-warden noticed is not a defect on either side. It is two different objects
|
||
with two different revocation stories.
|
||
|
||
### A decision lifetime is authority to issue, not authority to use
|
||
|
||
`lifetime.expires_at` (`docs/decision-record-contract.md`, default TTL 15m)
|
||
bounds one thing: how long that particular allow may be relied on as the
|
||
authority for the action it decided. For ops-warden the action is `sign`, and
|
||
the action completes at issuance. Once the certificate exists, the decision has
|
||
been consumed; nothing in the decision record reaches the artifact.
|
||
|
||
flex-auth does not claim otherwise, and a PDP that did would be lying. The
|
||
estate already ruled that fail-open is not expressible by a PDP because there
|
||
is no evaluator in that path; recall of an issued credential is the same shape
|
||
of claim. There is no flex-auth in the path of an SSH session already
|
||
authenticated by a valid certificate.
|
||
|
||
So a 15m decision lifetime against a 48h `adm` certificate is not an
|
||
inconsistency to reconcile. It says the gate's answer goes stale in 15 minutes;
|
||
it says nothing about the certificate, and was never asked to.
|
||
|
||
### The downstream contract is the pre-sign gate itself
|
||
|
||
That is the only consumer of the shorter lifetime, and it consumes it two ways:
|
||
|
||
1. **No replay past `expires_at`.** An allow may not be reused to authorise a
|
||
second `warden sign`, and a cached verdict must not outlive its TTL. This is
|
||
already the published rule (`docs/decision-input-freshness.md`, "How to read
|
||
this as a consumer") and it is the whole of what the lifetime binds.
|
||
2. **Fresh Check per sign.** Because the lifetime is short and claims are not
|
||
cached PDP-side, revocation of a subject, actor, or approval claim is visible
|
||
to the *next* sign immediately — deadline 0 for the claim class. That is the
|
||
real value of the short lifetime: it bounds how long a revoked principal can
|
||
keep obtaining *new* certificates, which is the part flex-auth can bound.
|
||
|
||
### The lever that shortens effective access is already deployed
|
||
|
||
If the goal is to shrink the window in which a revoked principal retains live
|
||
access, the mechanism is not a shorter decision lifetime — it is a shorter
|
||
**certificate** TTL, and the requested TTL is already a policy input. The
|
||
shipped `ops-warden.ssh-certificate.sign` package denies `ttl_out_of_bounds`
|
||
before OpenBao is reached (verified 2026-06-29). Capping the requested TTL per
|
||
actor class or per zone in the policy package is a policy change flex-auth can
|
||
make and explain; asking the decision lifetime to reach past issuance is not.
|
||
|
||
flex-auth is not proposing that change here. Certificate TTLs are ops-warden's
|
||
to set, and this record does not reopen them.
|
||
|
||
## Consequences
|
||
|
||
- ops-warden's §9.7.2 statement — allow effective through certificate TTL,
|
||
bounded by 48h/24h/8h, no recall channel — is **correct as written and
|
||
correctly owned by the PEP**. flex-auth does not want that residue moved to
|
||
the PDP's side of the line.
|
||
- No change to `flex-auth.decision-record.v1`. `lifetime` keeps its published
|
||
meaning; this record states the boundary it already had rather than adding
|
||
one.
|
||
- If ops-warden ever wants a certificate TTL bound to policy rather than to
|
||
actor class, that is a policy-package change under a new workplan, not a
|
||
lifetime semantics change.
|
||
|
||
## FLEX-DEC-2026-005 — secrets-engine policy package is expected but unpublished; /v1/check has no estate-wide endpoint by design
|
||
|
||
```yaml
|
||
id: FLEX-DEC-2026-005
|
||
kind: decision
|
||
title: secrets-engine policy package is expected but unpublished; /v1/check has no
|
||
estate-wide endpoint by design
|
||
status: resolved
|
||
origin: cross-repo
|
||
origin_ref: secrets-engine SECRETS-WP-0009-T03
|
||
owner: flex-auth
|
||
affects:
|
||
- flex-auth
|
||
- secrets-engine
|
||
- approval-engine
|
||
requested_dispositions:
|
||
- answer
|
||
decided_by: flex-auth (access-engine / PDP)
|
||
rationale: 'Two answers. (1) Yes, a real package is expected, and flex-auth authors
|
||
it in this repo as it did for every other consumer; the reserved coordinate is secrets-engine.catalog-lane.lifecycle
|
||
at version v1, and it does not exist yet. Until it is published and pinned, secrets-engine
|
||
keeping SECRETS_ENGINE_AUTHORIZATION_POLICY_PACKAGE and _VERSION as required configuration
|
||
with no fallback is the correct shape and flex-auth endorses it. (2) POST /v1/check
|
||
is deployed, but there is no estate-wide PDP address and there is not meant to be
|
||
one: each consumer gets its own cluster-local pin whose NetworkPolicy default-denies
|
||
ingress except from that one approved workload. The 2026-09-06 probe finding no
|
||
reachable PDP is the design working, not an outage. A reachable endpoint for secrets-engine
|
||
is a per-consumer pin that follows its policy package.'
|
||
created: '2026-09-05T23:08:51.144287Z'
|
||
updated: '2026-09-06T00:00:00.000000Z'
|
||
decided_at: '2026-09-06T00:00:00.000000Z'
|
||
state_hub_decision_id: "f318e4e2-6195-4db8-b8c0-c71eeecad766"
|
||
```
|
||
|
||
## Context
|
||
|
||
secrets-engine applied flex-auth's earlier PDP answers in commit `627810b`
|
||
(`resource.type: secret-catalog-lane`, `resource.system: secrets-engine`,
|
||
catalog id as `request.resource.id`, and a join that validates
|
||
`ActionAuthorization.decision.binding.request_digest` against
|
||
`flex-auth.decision-record.v1`). It then asked two questions, with Glas
|
||
real-key execution (`SECRETS-WP-0009-T03`) waiting on the answers.
|
||
|
||
## Disposition
|
||
|
||
### Answer 1 — yes, a package is expected; it does not exist yet
|
||
|
||
Every shipped consumer's policy package is authored **in this repository**, not
|
||
in the consumer's, and baked into the image: `ops-warden.ssh-certificate.sign`
|
||
(v2), `tenant-engine.write-api.mutate`, `user-engine.portal.authorize`,
|
||
`railiance-platform.credential-grant.issue`, `qonto-assistant.finance-read`.
|
||
secrets-engine follows the same path. The reserved coordinate is:
|
||
|
||
| | |
|
||
| --- | --- |
|
||
| Package | `secrets-engine.catalog-lane.lifecycle` |
|
||
| Version | `v1` |
|
||
|
||
This is a **reservation, not a publication.** No such package exists in
|
||
`examples/` today, and until one is published and pinned, a Check naming it
|
||
evaluates nothing. `FLEX-WP-0021` carries the work.
|
||
|
||
secrets-engine's decision not to default the pin was the right call and
|
||
flex-auth endorses it explicitly: keeping
|
||
`SECRETS_ENGINE_AUTHORIZATION_POLICY_PACKAGE` and `_VERSION` as required
|
||
configuration with no fallback is exactly correct. Defaulting them would have
|
||
pinned production to example vocabulary nobody publishes, and the failure would
|
||
have been a silent evaluation against a package that is not there rather than a
|
||
loud missing-configuration error.
|
||
|
||
### Answer 2 — /v1/check is deployed; there is no estate-wide address, by design
|
||
|
||
The 2026-09-06 probe finding no reachable PDP found the design working.
|
||
|
||
flex-auth runs as **per-consumer cluster-local pins**, not as one shared
|
||
service. Three are live (`flex-auth-ops-warden`, `flex-auth-tenant-engine`,
|
||
`flex-auth-user-engine`). Each is a three-document manifest whose third document
|
||
is a default-deny `NetworkPolicy` admitting ingress from exactly one approved
|
||
consumer workload, and each is pinned to its own image digest so one consumer's
|
||
policy can roll without moving another's (`deploy/README.md`). Caller
|
||
authentication is per-pin: on the ops-warden pin it is `enforce`, so an
|
||
anonymous `/v1/check` is 401 and a token bound to another protected system is
|
||
403 (`FLEX-WP-0016`).
|
||
|
||
There is therefore no address for secrets-engine to reach *because none has been
|
||
created for it*. A reachable endpoint is a per-consumer pin, and a pin follows
|
||
its policy package — so both questions resolve to the same piece of work, in
|
||
that order: publish the package, then pin it.
|
||
|
||
## Consequences
|
||
|
||
- `FLEX-WP-0021` is opened in this repo to publish
|
||
`secrets-engine.catalog-lane.lifecycle` v1 and stand up a
|
||
`flex-auth-secrets-engine` pin. It needs secrets-engine's real action
|
||
vocabulary as input; the example `secrets-engine.lifecycle/v1` vocabulary is
|
||
explicitly not it.
|
||
- secrets-engine should keep the pin required and unset until the package is
|
||
published. Nothing in this record authorises a fallback value.
|
||
- No change to `flex-auth.decision-record.v1`. The digest join secrets-engine
|
||
built against it is correct as described.
|
||
|
||
## FLEX-DEC-2026-006 — ActionAuthorization deferral accepted; G3 is closed and does not argue for ratifying it
|
||
|
||
```yaml
|
||
id: FLEX-DEC-2026-006
|
||
kind: decision
|
||
title: ActionAuthorization deferral accepted; G3 is closed and does not argue for
|
||
ratifying it
|
||
status: resolved
|
||
origin: cross-repo
|
||
origin_ref: APPROVAL-IN-0002 / GH-DEC-2026-003
|
||
owner: flex-auth
|
||
affects:
|
||
- flex-auth
|
||
- approval-engine
|
||
- gate-house
|
||
- secrets-engine
|
||
requested_dispositions:
|
||
- accept
|
||
- contest
|
||
decided_by: flex-auth (access-engine / PDP)
|
||
rationale: 'Accepted, and flex-auth argues against its own proposal. The composed
|
||
ActionAuthorization object was never ratified; the approval-claim plus DecisionEnvelope
|
||
split lands each check on the layer that owns it and drops none. approval-engine
|
||
asked whether the open G3 finding (DecisionEnvelope carries no lifetime) argues
|
||
for ratifying the composed object now. It does not, because G3 is already closed
|
||
the other way: FLEX-WP-0019 added lifetime to the DecisionEnvelope itself, required
|
||
on every allow by schema conditional, published 2026-09-02. The revisit trigger
|
||
is spent, and it resolved by adding a field rather than by composition, so the decision
|
||
now stands alone and needs no bundle. Separately, the provenance.authority == state-hub
|
||
constant is flex-auth defect: it came from examples/caring/action_authorization.json,
|
||
which contradicted our own ownership section. Corrected at source, with the schema
|
||
and contract doc marked deferred-not-withdrawn so no other consumer builds a validator
|
||
against them.'
|
||
created: '2026-09-05T23:29:20.156770Z'
|
||
updated: '2026-09-05T23:29:20.156770Z'
|
||
```
|
||
|
||
## Context
|
||
|
||
`approval-engine` filed `APPROVAL-IN-0002` with gate-house and raised it here
|
||
directly, because the request touches flex-auth's artifact and accepting the
|
||
shelving is flex-auth's call.
|
||
|
||
The trigger was concrete damage: secrets-engine built its PEP validator against
|
||
the `ActionAuthorization` schema in
|
||
`docs/action-bound-authorization-contract.md`, then pointed it at
|
||
`GET /v1/approvals/{id}/claim`. It rejects every response. Both envelopes
|
||
declare `schema_version: 0.1`, so the mismatch surfaces late as a field or
|
||
authority error that reads like an `approval-engine` outage rather than a
|
||
contract mismatch.
|
||
|
||
## Disposition
|
||
|
||
**Accepted.** The approval-claim is the step-1 artifact; `ActionAuthorization`
|
||
is not required on that path; a PEP validates across the claim (approval fact)
|
||
and flex-auth's step-2 `DecisionEnvelope` (exact `CheckRequest` match and policy
|
||
pin).
|
||
|
||
flex-auth argues **against its own proposal** here. The composed object had the
|
||
PIP republish flex-auth's decision, which is the part that was wrong: it moves an
|
||
artifact across a layer boundary that the estate's own §2 rule says it should not
|
||
cross. flex-auth used that rule to decline authentication evidence in
|
||
`FLEX-DEC-2026-002` and to win §17's decision-record schema in
|
||
`FLEX-DEC-2026-003`. It applies the same way when it costs us the object.
|
||
|
||
The split drops no check. Each of the five verifications in the contract's
|
||
"Required verification" section lands on the layer that owns it — status,
|
||
validity window, supersession, and distinct authenticated approvers on the
|
||
approval-claim; effect, binding match, digest, and policy pin on the
|
||
`DecisionEnvelope`.
|
||
|
||
### Answer to the question asked before the decision: G3 does not argue for it
|
||
|
||
`approval-engine` named the open G3 finding — `DecisionEnvelope` carries no
|
||
lifetime — as a revisit trigger, *if* it is settled by composition rather than
|
||
by adding a lifetime field, and asked flex-auth to say so **before** the
|
||
decision if G3 is the strongest case for ratifying now.
|
||
|
||
It is not, and the reason is that **G3 is already closed, the other way.**
|
||
|
||
`FLEX-WP-0019` closed it by adding the field. `schemas/decision_envelope.schema.json`
|
||
now carries a conditional requiring `lifetime` whenever `effect` is `allow`; the
|
||
duration comes from the policy package's `allow_ttl` with a `15m` engine default,
|
||
and a package declaring `allow_ttl: none` produces a deny with reason
|
||
`allow_lifetime_unstated` rather than a standing grant. This was published in
|
||
`docs/decision-record-contract.md` on 2026-09-02.
|
||
|
||
So the trigger is spent, and it resolved on the branch that removes the argument
|
||
rather than the one that supports it. A `DecisionEnvelope` now states its own
|
||
end without borrowing `ActionAuthorizationValidity`. The bundle is not needed to
|
||
give an allow a lifetime, which was the only structural thing it did that the
|
||
split does not.
|
||
|
||
The 2026-08-29 alignment review's table still shows G3 `open`. That file is a
|
||
dated review record and is not rewritten; this record supersedes its status.
|
||
|
||
### The `provenance.authority == "state-hub"` constant is flex-auth's defect
|
||
|
||
Correct on the merits, and correctable regardless of how the deferral landed.
|
||
`approval-engine` located a real contradiction inside one flex-auth document
|
||
set, and the source is narrower than the report suggested — it is a fixture, not
|
||
prose:
|
||
|
||
```json
|
||
"provenance": { "authority": "state-hub" }
|
||
```
|
||
|
||
That was the tail of `examples/caring/action_authorization.json`, directly
|
||
contradicting the same contract's ownership section: *"State Hub decision
|
||
records are coordination and provenance evidence; they are not the runtime
|
||
approval authority."* A consumer reading the example rather than the paragraph
|
||
gets the wrong constant, which is what happened.
|
||
|
||
Corrected at source. The example now names `approval-engine` as the approval
|
||
fact's authority and flex-auth as the decision's, and says State Hub is neither.
|
||
Its stale `secrets-engine.lifecycle` policy pin is also corrected to the
|
||
reserved-but-unpublished coordinate from `FLEX-DEC-2026-005`.
|
||
|
||
## Consequences
|
||
|
||
- `docs/action-bound-authorization-contract.md` status is now **deferred, not
|
||
withdrawn**, with the two-step split stated up front and an explicit "do not
|
||
build a validator against it" warning. The `PROPOSED` material is retained as
|
||
the record of what was proposed.
|
||
- `schemas/action_authorization.schema.json` carries the same deferral in its
|
||
`description`, so a machine reader sees it too. `schema_version` stays `0.1`;
|
||
bumping it would imply a ratified successor that does not exist.
|
||
- The execute-time half is untouched and stays published: `POST /v1/check`,
|
||
`binding`, the canonical request digest, and `flex-auth.decision-record.v1`.
|
||
Nothing secrets-engine built against the digest join is invalidated.
|
||
- No revisit trigger remains open on flex-auth's side. If the composed object is
|
||
ever revisited, it needs a fresh argument, not G3.
|
||
|