approval-engine/docs/gate-house-decision-request-claim-envelope.md
tegwick 48ffc34993 chore(consistency): record decision id for GH-DEC-2026-005
fix-consistency C-32 registered the outcome block in the request doc as
hub decision b606e8ce and wrote the id back. Resolved it in the hub with
decided_by gate-house, since gate-house decided it on 2026-09-06 and a
record left open misrepresents live state in estate-wide open-decision
queries. The rationale records that this hub row was created from
approval-engine's repo and that gate-house's decisions.md remains the
source of truth for GH-prefixed decisions.

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
2026-09-06 08:05:00 +02:00

7.5 KiB

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:

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 lifetimeSPENT, 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.

Record as resolved

Adopted by gate-house as GH-DEC-2026-005; this block reflects the outcome, not the original request.

id: GH-DEC-2026-005
kind: decision
title: The approval-claim is the step-1 artifact on the PEP consumption path
status: resolved
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
disposition: approved
affects:
- gate-house
- approval-engine
- flex-auth
- secrets-engine
- ops-warden
state_hub_decision_id: "b606e8ce-f1fa-4b39-bfe9-c11e88a3cde6"