user-engine/docs/root-custody-runtime.md
tegwick 608cbff477
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Complete live empty custody consumer acceptance
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1029d-2c93-7500-a0e0-e3e089668b29
2026-10-03 20:39:15 +02:00

5.5 KiB

Root custody consumer delivery

USER-WP-0037-T02 implements accepted NK-ADR-0017 without creating custody entries. The runtime remains disabled unless USER_ENGINE_CUSTODY_ENABLED=true. Optional AccountAuthority.root_grant is a source fact, never a flex-auth decision.

Configuration and owner boundary

The deployment owner is rapp-user-engine: namespace user-engine, Deployment user-engine, ServiceAccount user-engine. A dedicated projected JWT with audience openbao must be supplied; the existing flex-auth audience token is unsuitable. railiance-platform supplies auth/kubernetes role user-engine-root-custody-reader, exact-path-only reader policy, no default policy, and maximum 60-second token TTL. No ESO AppRole or operator token is used. Login occurs on every read; revoke-self is best-effort and may be denied by the exact-path policy. TTL limits that residue; the consumer does not claim confirmed revocation.

Variable Binding
USER_ENGINE_CUSTODY_ENABLED true to opt in; unset defaults disabled
USER_ENGINE_CUSTODY_BAO_URL Owner-confirmed origin only; no path or credentials
USER_ENGINE_CUSTODY_AUTH_MOUNT kubernetes
USER_ENGINE_CUSTODY_ROLE user-engine-root-custody-reader
USER_ENGINE_CUSTODY_JWT_FILE Dedicated audience=openbao projected JWT file
USER_ENGINE_CUSTODY_TIMEOUT Total request deadline, default 3 seconds
USER_ENGINE_CUSTODY_ALLOW_HTTP Default false; true requires reviewed in-cluster transport trust and network controls

The path is fixed to /v1/platform/data/custody/net-kingdom/platform-root and the whole JSON document is data.data.document. Responses are bounded to 256 KiB; redirects, proxy environment settings, reported cache hits, compressed bodies, invalid records and source changes are rejected. Errors never print values. HTTPS uses system CA verification by default. The currently proposed in-cluster HTTP route has no TLS origin authentication; owner-approved network confinement and exact origin binding are required before enabling it. A configured origin alone does not prove live trust.

The embedded custody_canon package contains validator/schema and provenance hashes, pinned to NetKingdom db319335b27b61b855382ee5af5d690f06eeb010. Only schema lookup is relocated. Policy updates require reviewing canon and refreshing pin/hashed provenance. No sibling checkout is used in production. root_grant retains exact subject, fixed grant, record id/revision, owner read observed_at, and expires_at from the record's tighter cache bound. Check time is sampled after I/O; local reads never renew owner read time.

Durable baseline and controlled initialization

The existing USER_ENGINE_DATABASE_URL holds the singleton user_engine_custody_baseline table using a separate connection. Compare-and-swap prevents competing workers overwriting a newer baseline. Empty/revoked records also persist. Startup never creates an initial baseline from a record automatically.

After the publisher has returned a reviewed source/read admission receipt, an attended owner may initialize an absent baseline. An explicitly approved empty entries[] document establishes no grant and needs no invented ceremony. Every non-empty grant still requires human custody-ceremony provenance. Initialize using:

python -m user_engine.custody_bootstrap --expected-sha256 <publisher-document-digest>

Run with the same secret-backed runtime environment and dedicated reader JWT. The non-secret digest must come from a reviewed publisher receipt, not fixtures; it hashes UTF-8 JSON with sorted keys, compact separators and ensure_ascii=True. The command performs a fresh authenticated read, validates record/id/time and digest, then atomically initializes only an absent baseline. It emits one boolean outcome and never resets an existing baseline. It creates no custody entry.

Source/record changes and database restores require owner reconciliation; there is intentionally no automatic reset command. Preserve baseline high-water records outside the restored database and compare with publisher history/audit receipts. If both source and consumer databases restore backwards, their mutually agreeing old state cannot detect rollback by itself. Keep this feature disabled through restore until owner audit/history establishes the latest revision and a reviewed reconciliation updates the baseline. Never delete the row to make a read pass.

Live acceptance and remaining owner gates

Live empty-source consumer acceptance is now complete; see the receipt. The code and offline fixtures do not establish a real grant. Full estate acceptance also needs reviewed publisher provenance (the approved empty entries[] baseline establishes no grant), role/policy receipts, projected-token packaging, network trust, owner-reviewed baseline initialization, image digest promotion and positive/denial/outage/revocation/supersession/restore receipts through the actual Hub workload route. USER-WP-0037-T03 retains its separate Hub admission blocker.

Approved initial-empty candidate document digest: 33a2ae086385028db1b654aa5646b7a98bcde1c5878c804e19315dadc3f87248. It comes from NetKingdom examples/custody-record/initial-empty-record.json and the owner provenance packet, not from positive-grant fixtures. Publication and an actual authenticated read matching this receipt are still required before baseline initialization.

USER-WP-0037-T02 is done for the delivered no-grant source and actual restart acceptance. USER-WP-0037-T03 real Hub admission/private integration and platform producer recovery/audit gates remain independently owned.