feat(authz): bind decisions to exact actions
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 37s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02e47-6aac-7ee1-914d-0584c75d3c81
This commit is contained in:
tegwick 2026-08-23 13:18:26 +02:00
parent 7323dd1a60
commit c473f1971d
28 changed files with 644 additions and 12 deletions

View file

@ -12,6 +12,7 @@ JSON Schema definitions for flex-auth's canonical artefacts:
- `policy_fixture.schema.json`
- `check_request.schema.json`
- `decision_envelope.schema.json`
- `action_authorization.schema.json`
- `audit_event.schema.json`
Schemas are pinned in `FLEX-WP-0002 P2.1` and validated against Go

View file

@ -0,0 +1,66 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://flex-auth.netkingdom/schemas/action_authorization.schema.json",
"title": "ActionAuthorization",
"description": "Durable approval envelope for one exact authorization request. This is a storage/transport contract; live evaluation remains POST /v1/check.",
"type": "object",
"additionalProperties": false,
"required": ["schema_version", "id", "status", "request", "validity", "approvals", "decision"],
"properties": {
"schema_version": {"const": "0.1"},
"id": {"type": "string", "format": "uuid"},
"status": {
"enum": ["pending", "approved", "denied", "superseded", "expired", "revoked"]
},
"superseded_by": {
"type": ["string", "null"],
"format": "uuid"
},
"request": {"$ref": "https://flex-auth.netkingdom/schemas/check_request.schema.json"},
"validity": {"$ref": "#/$defs/validity"},
"approvals": {"$ref": "#/$defs/approvals"},
"decision": {"$ref": "https://flex-auth.netkingdom/schemas/decision_envelope.schema.json"},
"provenance": {"type": "object", "additionalProperties": true}
},
"allOf": [
{
"if": {"properties": {"status": {"const": "superseded"}}},
"then": {"required": ["superseded_by"]}
}
],
"$defs": {
"validity": {
"type": "object",
"additionalProperties": false,
"required": ["expires_at"],
"properties": {
"not_before": {"type": "string", "format": "date-time"},
"expires_at": {"type": "string", "format": "date-time"}
}
},
"approvals": {
"type": "object",
"additionalProperties": false,
"required": ["required_count", "entries"],
"properties": {
"required_count": {"type": "integer", "minimum": 1},
"entries": {
"type": "array",
"uniqueItems": true,
"items": {"$ref": "#/$defs/approval_entry"}
}
}
},
"approval_entry": {
"type": "object",
"additionalProperties": false,
"required": ["subject_id", "approved_at"],
"properties": {
"subject_id": {"type": "string", "minLength": 1},
"approved_at": {"type": "string", "format": "date-time"},
"assurance": {"type": "string", "minLength": 1},
"evidence_ref": {"type": "string", "minLength": 1}
}
}
}
}

View file

@ -14,12 +14,26 @@
"matched_rule": {"type": "string", "minLength": 1},
"resource": {"$ref": "https://flex-auth.netkingdom/schemas/check_request.schema.json#/$defs/resource_ref"},
"subject": {"$ref": "https://flex-auth.netkingdom/schemas/check_request.schema.json#/$defs/subject_ref"},
"binding": {"$ref": "#/$defs/decision_binding"},
"obligations": {"type": "array", "items": {"$ref": "#/$defs/obligation"}},
"diagnostics": {"type": "object", "additionalProperties": true},
"provenance": {"$ref": "#/$defs/provenance"},
"caring": {"$ref": "#/$defs/caring_decision_metadata"}
},
"$defs": {
"decision_binding": {
"type": "object",
"additionalProperties": false,
"required": ["subject", "action", "resource", "request_digest"],
"properties": {
"tenant": {"type": "string", "minLength": 1},
"subject": {"$ref": "https://flex-auth.netkingdom/schemas/check_request.schema.json#/$defs/subject_ref"},
"action": {"type": "string", "minLength": 1},
"resource": {"$ref": "https://flex-auth.netkingdom/schemas/check_request.schema.json#/$defs/resource_ref"},
"context": {"type": "object", "additionalProperties": true},
"request_digest": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}
}
},
"obligation": {
"type": "object",
"additionalProperties": false,