flex-auth/workplans/FLEX-WP-0017-action-bound-authorization-contract.md
tegwick cde77f0097
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assent to GH-DEC-2026-001 (FLEX-DEC-2026-001), closing FLEX-IN-0001
flex-auth answers gate-house's assent request on the three items ratified in
GH-DEC-2026-001, following the estate precedent that a boundary is drawn on
review by the other side.

Assent to all three, with one conformance debt flex-auth accepts as its own and
two conditions on the rename:

- Engine framing and sole decision point: assent. flex-auth cannot hold this
  boundary against zone-engine and decline it as a general rule. But standard
  section 6 also binds flex-auth: DecisionProvenance carries no registry
  snapshot digest, so a decision that turned on registry content cannot be
  replayed from its own provenance. Recorded as a known non-conformance rather
  than claimed as conformance.
- access-engine rename: assent to the name, not to execution. Repository
  identity and runtime identity must rename in separate revertible steps —
  since FLEX-WP-0016 the enforcing ops-warden pin binds tokens to the
  protected-system name, so a single-step rename 401s every warden sign,
  including the certificate the ops-bridge tunnels depend on. FLEX-WP prefix
  ownership stays with the repository.
- Authoring/evaluation split: assent, with the section 6 test applied
  symmetrically — a gate-house authority ceiling that determines an outcome
  reaches the decision as an input claim or as a rule in the versioned policy
  package, so its application stays reconstructable from the decision record.

FLEX-WP-0017-T03 stays wait: the design half re-routes to gate-house, the
durable storage half remains unowned and is raised as an engine gap under
section 5.

Decision id follows the canon scheme {PREFIX}-DEC-YYYY-NNN.

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-28 21:47:06 +02:00

3.7 KiB

id type title domain repo status owner topic_slug planning_priority planning_order created updated state_hub_workstream_id
FLEX-WP-0017 workplan Action-bound authorization and durable approval contract infotech flex-auth active codex netkingdom P1 117 2026-08-23 2026-08-23 d75b7256-8b3d-5797-911c-96c3199b8baa

FLEX-WP-0017 - Action-bound authorization and durable approval contract

secrets-engine needs production authorization that binds an approval to an exact action, catalog lane, stage, targets, actor, purpose, validity window, and distinct approvers. The existing flex-auth decision response and State Hub decision object each provide only part of that contract.

Bind execute-time decisions to the evaluated request

id: FLEX-WP-0017-T01
status: done
priority: high
state_hub_task_id: "e7b47e1d-58e8-503c-be89-e8f2050215b1"

Add a structured binding to standalone DecisionEnvelope responses with the normalized subject, action, resource, context, and full SHA-256 request digest. Add schema and regression coverage. Prose remains diagnostic only.

Define the durable authorization object and semantics

id: FLEX-WP-0017-T02
status: done
priority: high
state_hub_task_id: "df7984fb-c31f-5b26-bf42-193e4c3cbb9f"

Publish schemas/action_authorization.schema.json and docs/action-bound-authorization-contract.md, including exact target mapping, validity, distinct approvals, supersession, and fail-closed outage semantics.

Corrective verification 2026-08-23: secrets-engine detected that the example's stored request digest predated its final request shape. The fixture now carries the digest produced by NewDecisionBinding, and the API test compares the full published binding to a freshly generated canonical binding so future fixture drift fails the suite.

Add durable storage and authenticated approval evidence

id: FLEX-WP-0017-T03
status: wait
priority: high
state_hub_task_id: "82d39961-8140-5a7f-9bd8-5164dd1742e5"

State Hub must add a structured endpoint/object equivalent to the published contract, authenticated approval entries, and atomic supersession. Its current /decisions/{uuid} shape has only prose plus a single free-form decided_by. No flex-auth-local substitute is acceptable because flex-auth does not own the organizational approval lifecycle.

Re-routed 2026-08-28 by FLEX-DEC-2026-001 (assent to gate-house GH-DEC-2026-001): under the authoring/evaluation split, gate-house designs the approval contract and flex-auth validates approvals at decision time. The design half of this task is therefore addressed to gate-house. The storage and lifecycle half — durable object, authenticated approval entries, atomic supersession — remains unowned: it is not gate-house's, because Staff holds no state another layer depends on at runtime (standard §3.4), and not flex-auth's, for the reason above. Raised to gate-house as an engine gap under §5. Task stays wait.

Propagate bindings through delegated evaluators

id: FLEX-WP-0017-T04
status: done
priority: medium
state_hub_task_id: "d85089ee-ad8c-502b-ba1b-be4ad23aec46"

Populate the same binding in Topaz, relationship, rule, and Keycloak adapter success and fail-closed responses using the shared canonical constructor.

Consumer handoff and live destructive-action proof

id: FLEX-WP-0017-T05
status: wait
priority: high
state_hub_task_id: "8c3fc0a2-0855-5ac9-afa5-d03b8b1f0bf9"

After T03, secrets-engine validates the canonical object before every privileged production action and proves wrong action/lane/stage/targets, expiry, supersession, outage, insufficient approvals, and duplicate approvers all fail before any OpenBao call. Live destroy stays disabled until that proof.