Gate House confirmed all three requested dispositions as GH-DEC-2026-005 (GH-IN-0002, closed); flex-auth accepted as FLEX-DEC-2026-006. The approval-claim is the step-1 artifact, ActionAuthorization is not required and MUST NOT be served from the claim endpoint, and a PEP validates across the claim and the step-2 DecisionEnvelope. Gate House recorded the split as doctrine rather than convenience -- a PIP must not republish the PDP's decision -- and struck the provenance.authority == state-hub requirement explicitly. This engine's claim schema is unchanged. Correct the deferred option D trigger list. The G3 trigger was written conditional on G3 being settled by composition; flex-auth reports FLEX-WP-0019 closed it by adding a lifetime field to DecisionEnvelope on 2026-09-02, so a decision now states its own end without borrowing ActionAuthorizationValidity. That was the one structural thing the bundle did that the split does not, so the trigger is not merely spent -- it resolved against ratification. Struck with reasons; a future revisit needs a fresh argument. The trigger came from a stale row in a dated 2026-08-29 review record that flex-auth does not rewrite. Also record the root cause of the bad authority constant: it came from a flex-auth fixture, not prose. A contract whose examples contradict its prose will be implemented as its examples. Close APPROVAL-IN-0002. Docs only; 84 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvyJPAaVCGsVheVhcCwNND Assistant: claude-code Assistant-Model: opus Assistant-Process: 411227@bnt-lap001 Assistant-Session: d566f6d3-bcaf-43c3-bc5e-3ddd0f64b535
158 lines
7.3 KiB
Markdown
158 lines
7.3 KiB
Markdown
# Decision request to gate-house — the claim envelope on the PEP path
|
|
|
|
**Status:** RESOLVED 2026-09-06 — confirmed in full as `GH-DEC-2026-005`
|
|
(gate-house commit `1a920a5`; recorded there as `GH-IN-0002`, closed) and
|
|
accepted as `FLEX-DEC-2026-006` (flex-auth commit `74bfb3b`). All three
|
|
requested dispositions granted. Retained as the reasoning record.
|
|
**Requested by:** approval-engine
|
|
**Date:** 2026-09-06
|
|
**Governs:** `GH-DEC-2026-003` (approval consumption ordering)
|
|
**Blocks:** first live consume for `SECRETS-WP-0007-T04`; recorded on
|
|
`APPROVAL-WP-0002-T05`
|
|
**Does not block:** `APPROVAL-WP-0002-T03` (see "Scope" below)
|
|
|
|
This is a drafted request, not a decision. gate-house owns the outcome.
|
|
|
|
## The question
|
|
|
|
secrets-engine's PEP validator (`validate_action_authorization`) expects an
|
|
`ActionAuthorization` envelope, but calls
|
|
`GET /v1/approvals/{id}/claim`, which serves approval-engine's approval-claim.
|
|
The two are different objects. Which one is the step-1 artifact on the governed
|
|
PEP path?
|
|
|
|
## Why this is a confirmation, not a redesign
|
|
|
|
`GH-DEC-2026-003` already names step 1 by endpoint and by field:
|
|
|
|
```text
|
|
1. PIP GET /v1/approvals/{id}/claim → valid_now (a fact, not permission)
|
|
```
|
|
|
|
`valid_now` is an approval-claim field. `ActionAuthorization` has no `valid_now`.
|
|
|
|
`ActionAuthorization` is not a governed object. It appears zero times in
|
|
gate-house and zero times in state-hub. It originates in flex-auth's
|
|
`docs/action-bound-authorization-contract.md` (2026-08-23), whose own status
|
|
line calls it *"the **proposed** `ActionAuthorization` storage and transport
|
|
object"* — a proposed shape for the durable approval object, which the same
|
|
document assigns to approval-engine. It was never ratified, and
|
|
`GH-DEC-2026-003` was issued six days later without it.
|
|
|
|
One further conflict worth recording: the validator hard-requires
|
|
`provenance.authority == "state-hub"`, while flex-auth's own contract states
|
|
that State Hub decision records *"are not the runtime approval authority."*
|
|
The constant contradicts the document it came from.
|
|
|
|
**Root cause, established after this request was filed:** the constant came
|
|
from a *fixture*, not from prose — `flex-auth/examples/caring/action_authorization.json`
|
|
ended with `"provenance": {"authority": "state-hub"}`. A consumer reading the
|
|
example rather than the paragraph gets the wrong constant, which is what
|
|
happened. flex-auth has corrected the fixture and marked both the contract and
|
|
`action_authorization.schema.json` as deferred with a do-not-build-a-validator
|
|
warning. Worth generalizing: a contract whose examples contradict its prose
|
|
will be implemented as its examples.
|
|
|
|
## Requested disposition — confirm the claim (option A)
|
|
|
|
Confirm that:
|
|
|
|
1. The approval-claim (`approval-engine/docs/approval-claim.md`) is the step-1
|
|
artifact on the `GH-DEC-2026-003` path.
|
|
2. `ActionAuthorization` is **not** required on the claim path, and
|
|
approval-engine is not expected to serve it there.
|
|
3. A PEP validates across the two artifacts it already fetches: the claim for
|
|
approval fact (binding digest, validity window, consumption state,
|
|
freshness, issuer), and the flex-auth `DecisionEnvelope` from step 2 for
|
|
exact `CheckRequest` match and policy package/version pin.
|
|
|
|
No safety property is dropped by (3). `ActionAuthorization` is a *bundle* of
|
|
approval fact plus decision envelope; splitting validation returns each check
|
|
to the layer that owns the data, rather than having the PIP republish the PDP's
|
|
decision.
|
|
|
|
### What changes if approved
|
|
|
|
| Repo | Change |
|
|
| --- | --- |
|
|
| approval-engine | none — the claim schema stands as published |
|
|
| secrets-engine | split `validate_action_authorization` into a claim check and a decision check; drop the `authority == "state-hub"` requirement |
|
|
| flex-auth | acknowledge the proposed `ActionAuthorization` is shelved on this path (see "Deferred option" — it is not withdrawn) |
|
|
| gate-house | record the confirmation against `GH-DEC-2026-003` |
|
|
|
|
## Deferred option D — a ratified post-decision `ActionAuthorization`
|
|
|
|
Recorded so it is not rediscovered. **Not** requested now.
|
|
|
|
A single composed post-decision artifact — canonical UUID, lifecycle status,
|
|
one complete `CheckRequest`, bounded validity, approval evidence, and the
|
|
matching `DecisionEnvelope` — remains a coherent design. flex-auth's schema and
|
|
its secrets-engine profile already exist as a starting point.
|
|
|
|
**Why not now:** it needs a named issuer and lifecycle owner (nobody holds
|
|
that today), and `GH-DEC-2026-003` already settles the sequence without it. The
|
|
cost is months; the present problem is resolved by a confirmation.
|
|
|
|
**Revisit if any of these appear:**
|
|
|
|
- a third or fourth PEP-shaped consumer, where per-consumer two-artifact
|
|
validation starts duplicating logic worth centralizing;
|
|
- a requirement for a single signed, forwardable authorization artifact
|
|
(offline verification, or an audit that must replay one object rather than a
|
|
join);
|
|
- ~~resolution of flex-auth's open G3 finding — `DecisionEnvelope` carries no
|
|
lifetime~~ — **SPENT, and it resolved against ratification.** `FLEX-WP-0019`
|
|
closed G3 by *adding the field*, not by composition: as of 2026-09-02
|
|
`decision_envelope.schema.json` requires `lifetime` whenever `effect` is
|
|
`allow`, sourced from the policy package's `allow_ttl` (15m engine default),
|
|
and `allow_ttl: none` yields a deny with reason `allow_lifetime_unstated`
|
|
rather than a standing grant. A `DecisionEnvelope` now states its own end
|
|
without borrowing `ActionAuthorizationValidity` — the one structural thing the
|
|
bundle did that the split does not. This trigger is closed and must not be
|
|
re-cited; a future revisit needs a fresh argument (`FLEX-DEC-2026-006`);
|
|
- assent of the statute §17 Taxonomy request-claim schema (`APPROVAL-IN-0001`),
|
|
which the approval-claim already declares it yields to. If Taxonomy lands
|
|
first, converge there and **do not** revive this separately.
|
|
|
|
**Constraint on any future adoption:** such an object is post-decision by
|
|
construction. It cannot be served from the step-1 claim call, because a step-1
|
|
response cannot contain a step-2 decision. It would be a new artifact at a new
|
|
endpoint, not a change to the claim.
|
|
|
|
## Also considered and rejected
|
|
|
|
- **approval-engine serves `ActionAuthorization` at the claim endpoint.**
|
|
Structurally impossible for step 1, per the constraint above, and it would
|
|
require asserting a `state-hub` authority that this engine does not hold.
|
|
- **Additively extend the claim** with `approvals.required_count` / `entries`.
|
|
Publishing approver identities to consumers is a deliberate least-disclosure
|
|
non-goal, and it still would not satisfy `id`, `authority`, or `request`, so
|
|
the consumer's validator changes regardless.
|
|
|
|
## Scope
|
|
|
|
This does not gate `APPROVAL-WP-0002-T03`. secrets-engine is fail-closed until
|
|
T03 and its own T04 both land; deploying publishes a URL and commits no one to
|
|
an envelope. The question gates the first live consume, not the deployment.
|
|
|
|
## Proposed record
|
|
|
|
```yaml
|
|
kind: decision
|
|
title: The approval-claim is the step-1 artifact on the PEP consumption path
|
|
status: proposed
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|
source_note: docs/contracts/approval-consumption.md
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- approval-engine
|
|
- flex-auth
|
|
- secrets-engine
|
|
- ops-warden
|
|
```
|