2026-10-03 12:56:22 +02:00
|
|
|
# Custody Record Validator
|
|
|
|
|
|
|
|
|
|
Validates the non-secret platform-root custody record defined by
|
|
|
|
|
`canon/schemas/custody-record_v0.1.schema.json` (NK-ADR-0017, status
|
2026-10-03 19:01:13 +02:00
|
|
|
accepted; NK-WP-0045-T02/T03). Offline and read-only.
|
2026-10-03 12:56:22 +02:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run tools/custody-record/validate.py tools/custody-record/fixtures/valid/*.json
|
|
|
|
|
uv run pytest tools/custody-record/tests
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Beyond the schema it checks: one active grant per exact `(issuer, subject)`,
|
|
|
|
|
revision ordering and supersession links inside a record, append-only
|
|
|
|
|
successors across reads (`successor_errors`: an older revision is a stale read,
|
|
|
|
|
a removed entry is not a revocation), and secret-looking values.
|
|
|
|
|
`observe_root_grant` is the consumer rule from ADR-0017 section 3: a grant only
|
|
|
|
|
for tenant `platform`, from a valid record read at most 15 minutes ago,
|
|
|
|
|
otherwise no grant (fail closed).
|
2026-10-03 19:27:16 +02:00
|
|
|
Observations include `expires_at`, derived from the actual read time and the
|
|
|
|
|
record's cache bound, so downstream consumers can honor bounds below 900 seconds.
|
2026-10-03 12:56:22 +02:00
|
|
|
|
2026-10-03 18:40:41 +02:00
|
|
|
Pass the last trusted document as `previous_record` to `observe_root_grant`
|
|
|
|
|
to reject rollback or same-revision mutation. New custody actions cannot be
|
|
|
|
|
inserted into already observed revisions. Read/check times must be timezone
|
|
|
|
|
aware; future document/grant timestamps yield no grant. The CLI emits only
|
|
|
|
|
acceptance or error counts, because schema diagnostics can contain rejected
|
|
|
|
|
secret values. Library error strings are internal diagnostics and must not
|
|
|
|
|
be logged against untrusted inputs.
|
|
|
|
|
|
|
|
|
|
Runtime owners must also authenticate the source, bind the expected record ID,
|
|
|
|
|
retain the revision baseline, and re-read for sensitive writes. See the
|
2026-10-03 19:01:13 +02:00
|
|
|
[approved read contract](../../docs/contracts/root-grant-read-contract_v0.1.md)
|
2026-10-03 18:40:41 +02:00
|
|
|
for delivery requirements and cross-repo acceptance receipts.
|
|
|
|
|
|
2026-10-03 12:56:22 +02:00
|
|
|
Fixtures: `valid/` covers grant, revocation and supersession; `invalid/`
|
|
|
|
|
covers projection-only grants, tenant-admin implication, other tenants,
|
|
|
|
|
secret-bearing fields and values, username keys, an over-long cache bound,
|
|
|
|
|
duplicate active grants and an entry both revoked and superseded.
|