Close the remaining PDP obligations: mechanical layer declaration check, registry-snapshot digest in provenance, explicit allow TTL, per-input-class freshness deadlines, and the published decision-record contract. Document the canonical request digest as the §6.4.2 replay test. Assistant: grok Assistant-Session: 01a06256-fb71-7102-b3a9-27e6734257d0
57 lines
2.5 KiB
Markdown
57 lines
2.5 KiB
Markdown
# Decision-record contract
|
|
|
|
Status: published
|
|
Contract: `flex-auth.decision-record.v1`
|
|
Schema: [`../schemas/decision_envelope.schema.json`](../schemas/decision_envelope.schema.json)
|
|
Date: 2026-09-02
|
|
|
|
This is flex-auth's output artifact under the NetKingdom Security Layer Model
|
|
v0.7 §17. Taxonomy holds only the shared field vocabulary. Consumers may rely
|
|
on this schema.
|
|
|
|
A decision record is a `DecisionEnvelope` returned by `POST /v1/check` and the
|
|
CLI `check` / `batch-check` / `list-allowed` commands. Standalone evaluation
|
|
and every delegated adapter (Topaz, relationship, rule, Keycloak) emit the
|
|
same shape.
|
|
|
|
## Required fields
|
|
|
|
| Field | Meaning |
|
|
| --- | --- |
|
|
| `id` | Deterministic decision identifier |
|
|
| `effect` | `allow`, `deny`, `redact`, `audit_only`, or `not_applicable` |
|
|
| `subject` / `resource` | Normalized refs the evaluator used |
|
|
| `provenance` | Who evaluated, over which policy and facts |
|
|
|
|
## Contract fields consumers may rely on
|
|
|
|
| Field | Meaning |
|
|
| --- | --- |
|
|
| `contract_version` | `flex-auth.decision-record.v1` |
|
|
| `binding` | Structured subject, action, resource, context, and `request_digest` |
|
|
| `lifetime` | **Required on every allow.** A TTL with `not_before` and `expires_at` |
|
|
| `provenance.policy_package` / `policy_version` | Named package pin |
|
|
| `provenance.policy_package_digest` | SHA-256 of package metadata plus compiled Rego |
|
|
| `provenance.registry_snapshot_digest` | SHA-256 of the canonical registry snapshot |
|
|
| `provenance.directory_etag` | Directory consistency token when a delegated directory was joined |
|
|
| `provenance.input_claim_digests` | SHA-256 per request-time claim class (`context`, `caring_context`) |
|
|
| `provenance.decision_time` | UTC timestamp used to compute `lifetime` |
|
|
|
|
`reason`, `diagnostics`, and CARING prose are not an authorization contract.
|
|
|
|
## Allow lifetime
|
|
|
|
Every allow carries `lifetime.kind = ttl`. The duration comes from the policy
|
|
package `allow_ttl` field, or from the engine default of `15m` when the package
|
|
omits it. A package that declares `allow_ttl: none` (or `0s`) produces a deny
|
|
with reason `allow_lifetime_unstated` instead of a standing grant.
|
|
|
|
Replay is permitted only while `lifetime.expires_at` is still in the future.
|
|
See [`canonical-request-digest.md`](canonical-request-digest.md) and
|
|
[`decision-input-freshness.md`](decision-input-freshness.md).
|
|
|
|
## Versioning
|
|
|
|
This is contract version 1. Additive optional fields may appear. Removing or
|
|
redefining a required field requires a new `contract_version` value and a new
|
|
schema id.
|