flex-auth/examples/caring/action_authorization.json

125 lines
3.6 KiB
JSON
Raw Normal View History

{
"schema_version": "0.1",
"id": "8bfc20be-47a4-4fb0-97a2-bf0a920afad8",
"status": "approved",
"request": {
"id": "check:secrets-engine-destroy-example",
"subject": {
"id": "user:alice",
"type": "Human"
},
"action": "destroy",
"resource": {
"id": "catalog:example-build-test-token",
"type": "secret-catalog-lane",
"system": "secrets-engine",
"attributes": {
"stage": "build",
Accept ActionAuthorization deferral; fix the state-hub authority constant 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
2026-09-06 01:30:04 +02:00
"fields": [
"token"
],
"policy_targets": [],
"auth_targets": []
}
},
"context": {
"purpose": "contract-test"
}
},
"validity": {
"not_before": "2026-08-23T10:00:00Z",
"expires_at": "2026-08-23T10:15:00Z"
},
"approvals": {
"required_count": 2,
"entries": [
{
"subject_id": "user:alice",
"approved_at": "2026-08-23T10:01:00Z",
"assurance": "mfa",
"evidence_ref": "approval:alice"
},
{
"subject_id": "user:bob",
"approved_at": "2026-08-23T10:02:00Z",
"assurance": "mfa",
"evidence_ref": "approval:bob"
}
]
},
"decision": {
"id": "decision:contract-example",
"contract_version": "flex-auth.decision-record.v1",
"request_id": "check:secrets-engine-destroy-example",
"effect": "allow",
"reason": "destruction_approved",
"matched_policy_version": "v1",
"matched_rule": "allow_destroy",
"resource": {
"id": "catalog:example-build-test-token",
"type": "secret-catalog-lane",
"system": "secrets-engine",
"attributes": {
"stage": "build",
Accept ActionAuthorization deferral; fix the state-hub authority constant 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
2026-09-06 01:30:04 +02:00
"fields": [
"token"
],
"policy_targets": [],
"auth_targets": []
}
},
"subject": {
"id": "user:alice",
"type": "Human"
},
"binding": {
"subject": {
"id": "user:alice",
"type": "Human"
},
"action": "destroy",
"resource": {
"id": "catalog:example-build-test-token",
"type": "secret-catalog-lane",
"system": "secrets-engine",
"attributes": {
"stage": "build",
Accept ActionAuthorization deferral; fix the state-hub authority constant 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
2026-09-06 01:30:04 +02:00
"fields": [
"token"
],
"policy_targets": [],
"auth_targets": []
}
},
"context": {
"purpose": "contract-test"
},
"request_digest": "sha256:eb9d856a060813aebe039f19b82d4be1c4589fa6c0429cf20e15fb115db3ef9a"
},
"lifetime": {
"kind": "ttl",
"ttl": "15m",
"not_before": "2026-08-23T10:00:30Z",
"expires_at": "2026-08-23T10:15:30Z"
},
"provenance": {
"evaluator": "flex-auth/local",
"mode": "standalone",
Accept ActionAuthorization deferral; fix the state-hub authority constant 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
2026-09-06 01:30:04 +02:00
"policy_package": "secrets-engine.catalog-lane.lifecycle",
"policy_version": "v1",
Fix the destroy rule: it was written against an invented claim shape approval-engine flagged the class one message earlier -- a contract whose examples contradict its prose gets implemented as its examples -- and yesterday's package was a fresh instance of it, committed while flagging it. The published rule required context.approval.status == "approved" and counted context.approval.approvals[].subject_id. Neither field exists. approval-engine's approval_claim.schema.json has `state` (whose operative value is `valid`, not `approved`) and carries no approver list at all. The rule was unsatisfiable: every live destroy would have denied dual_control_required no matter how good the approval was. It failed closed, so it was never a hole, but it was policy written against a shape of our own devising rather than a published one. The rule now consumes valid_now from the real claim, guarded on kind and issuer. valid_now is the summary predicate that already folds in the distinct-approver threshold, with reason_code insufficient_approvers for a claim that failed it -- so this is also the correct layering, not just the correct shape. Counting approvers here is exactly the duplication GH-DEC-2026-005 removes; the compensating property is reconstructability at the issuer under 9.6, which is approval-engine's. Recorded as a correction section in the package and the vocabulary doc rather than quietly rewritten. 25 Rego tests and 29 fixtures pass, covering insufficient_approvers, consumed, revoked, approved-but-not-yet- valid, foreign issuer, and wrong kind. Two things the package deliberately does not do, both now written down: it does not compare binding.pdp_digest, because the request digest is computed after policy evaluation and a Rego rule cannot see it; and it makes no cross-check that the claim was approved for this action and target, because the claim's binding uses approval-engine's vocabulary and no mapping between the two is published. Inventing one would silently accept a claim approved for something else. Both belong to the PEP until a mapping exists, and that is worth closing before SECRETS-WP-0007-T04 makes destroy reachable. Also swept the other published fixtures on approval-engine's reasoning. One more instance: the inner decision in examples/caring/action_authorization.json declared contract_version flex-auth.decision-record.v1 while its provenance omitted policy_package_digest, registry_snapshot_digest, and input_claim_digests -- all published contract fields since 2026-09-02. Completed. The remaining example context vocabularies are consumer-owned and match their integrations. 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
2026-09-06 08:11:14 +02:00
"policy_package_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"registry_snapshot_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"input_claim_digests": {
"context": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
},
Accept ActionAuthorization deferral; fix the state-hub authority constant 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
2026-09-06 01:30:04 +02:00
"decision_time": "2026-08-23T10:00:30Z",
"policy_package_note": "Reserved coordinate, not yet published (FLEX-DEC-2026-005). Illustrative only."
}
},
"provenance": {
Accept ActionAuthorization deferral; fix the state-hub authority constant 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
2026-09-06 01:30:04 +02:00
"note": "DEFERRED EXAMPLE (FLEX-DEC-2026-006). Not a contract. The approval fact's authority is approval-engine; the decision's authority is flex-auth. State Hub is never the authority for either -- do not derive a provenance.authority constant from this file.",
"approval_authority": "approval-engine",
"decision_authority": "flex-auth"
}
}