feat(authz): bind decisions to exact actions
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02e47-6aac-7ee1-914d-0584c75d3c81
This commit is contained in:
parent
7323dd1a60
commit
c473f1971d
28 changed files with 644 additions and 12 deletions
|
|
@ -195,7 +195,8 @@ verify expected decisions before activation.
|
|||
|
||||
flex-auth must provide `check(subject, action, resource, context)` returning a
|
||||
decision envelope with effect, reason, policy version, matched rule,
|
||||
obligations, diagnostics, and provenance.
|
||||
obligations, diagnostics, provenance, and a structured binding to the exact
|
||||
normalized subject/action/resource/context request that was evaluated.
|
||||
|
||||
### FR7. Batch Authorization Checks
|
||||
|
||||
|
|
|
|||
103
docs/action-bound-authorization-contract.md
Normal file
103
docs/action-bound-authorization-contract.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Action-bound authorization contract
|
||||
|
||||
Status: implemented for execute-time request binding; durable approval storage
|
||||
requires State Hub support.
|
||||
|
||||
Date: 2026-08-23
|
||||
|
||||
## Ownership and endpoints
|
||||
|
||||
flex-auth owns authorization evaluation and the canonical request/decision
|
||||
vocabulary. A protected system obtains a current decision from:
|
||||
|
||||
```text
|
||||
POST /v1/check
|
||||
```
|
||||
|
||||
The response now includes `binding`, the exact normalized subject, action,
|
||||
resource, context, and full SHA-256 request digest evaluated by the policy.
|
||||
Consumers must compare structured fields; `reason`, `diagnostics`, titles, and
|
||||
other prose are never an authorization contract.
|
||||
|
||||
State Hub owns durable organizational-decision identity, resolution,
|
||||
supersession, and availability. Its current endpoint is:
|
||||
|
||||
```text
|
||||
GET /decisions/{uuid}
|
||||
```
|
||||
|
||||
That object is not yet sufficient for privileged action execution. As of
|
||||
2026-08-23 it has lifecycle fields and `superseded_by`, but action details live
|
||||
only in prose and it records only one free-form `decided_by` value. Production
|
||||
consumers must not infer action binding or dual control from it.
|
||||
|
||||
## Durable object
|
||||
|
||||
[`../schemas/action_authorization.schema.json`](../schemas/action_authorization.schema.json)
|
||||
defines the proposed `ActionAuthorization` storage and transport object. It
|
||||
combines:
|
||||
|
||||
- a canonical UUID and explicit lifecycle status;
|
||||
- one complete `CheckRequest` containing the actor, action, resource, exact
|
||||
target attributes, stage, purpose, and other policy inputs;
|
||||
- a bounded validity window;
|
||||
- approval count and individual approval evidence;
|
||||
- the flex-auth `DecisionEnvelope` whose structured binding and digest match
|
||||
that request.
|
||||
|
||||
The schema is generic. For secrets-engine, use this profile:
|
||||
|
||||
| Requirement | Canonical field |
|
||||
| --- | --- |
|
||||
| catalog id | `request.resource.id` |
|
||||
| stage | `request.resource.attributes.stage` |
|
||||
| lifecycle operation | `request.action` |
|
||||
| exact secret fields | `request.resource.attributes.fields` |
|
||||
| policy/auth targets | `request.resource.attributes.policy_targets` / `auth_targets` |
|
||||
| requesting actor | `request.subject` |
|
||||
| purpose | `request.context.purpose` |
|
||||
| execution window | `validity.not_before` / `validity.expires_at` |
|
||||
| dual control | `approvals.required_count` and distinct `entries[].subject_id` |
|
||||
|
||||
Array values that express exact targets are sets: producers sort and de-duplicate
|
||||
them before evaluation; consumers require exact set equality. Wildcards are
|
||||
policy inputs and should be denied for destructive production actions.
|
||||
|
||||
## Required verification
|
||||
|
||||
A production consumer may execute only when all of the following hold:
|
||||
|
||||
1. The durable object resolves from its canonical authority; an outage fails
|
||||
the action closed.
|
||||
2. `status` is `approved`, `superseded_by` is absent, and the current time is
|
||||
inside the validity window.
|
||||
3. The caller's proposed action exactly matches `request`, including resource
|
||||
id, system, stage, target sets, actor, and purpose.
|
||||
4. `decision.effect` is `allow`; `decision.binding` matches the request and its
|
||||
digest; the policy package/version are accepted for the deployment.
|
||||
5. Approval entries contain at least `required_count` distinct authenticated
|
||||
subjects. Repeated entries from one subject count once.
|
||||
|
||||
Local fixtures, CCR labels, workplan ids, prose, and a caller-supplied flex-auth
|
||||
decision id are provenance only. They cannot unlock a production action.
|
||||
|
||||
## Outage and supersession semantics
|
||||
|
||||
- State Hub or future authorization-object store unreachable: privileged live
|
||||
action denied; read-only inspection and dry-run may continue with a clear
|
||||
non-authoritative status.
|
||||
- flex-auth unavailable when a fresh decision is required: privileged live
|
||||
action denied. A previously stored decision is usable only inside its bounded
|
||||
validity window and only if the authoritative lifecycle object can still be
|
||||
checked for supersession or revocation.
|
||||
- `superseded`, `expired`, `revoked`, `denied`, or unknown status: deny.
|
||||
- `superseded_by` present regardless of status: deny and resolve the replacement
|
||||
explicitly; never follow it silently during execution.
|
||||
|
||||
## Remaining external work
|
||||
|
||||
State Hub needs a structured object/endpoint capable of storing this schema or
|
||||
equivalent fields, authenticated approval entries, and atomic supersession.
|
||||
Until that lands, secrets-engine is correct to keep live destructive actions
|
||||
disabled. The standalone evaluator and the Topaz, relationship, rule, and
|
||||
Keycloak delegated adapter boundaries now all populate the same binding.
|
||||
Loading…
Add table
Add a link
Reference in a new issue