From 8ccd6827cb7252ff5f16f50dcc37156f6f988485 Mon Sep 17 00:00:00 2001 From: codex Date: Sat, 3 Oct 2026 18:51:26 +0200 Subject: [PATCH] Prepare conditional platform-root custody document producer Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a1029d-2c93-7500-a0e0-e3e089668b29 --- openbao/root-grant/README.md | 79 ++++++++++++++++ openbao/root-grant/reader.hcl | 4 + openbao/root-grant/writer.hcl | 5 + scripts/root_grant_publish.py | 42 +++++++++ tests/test_root_grant_publish.py | 60 ++++++++++++ ...9-platform-root-custody-record-delivery.md | 94 +++++++++++++++++++ 6 files changed, 284 insertions(+) create mode 100644 openbao/root-grant/README.md create mode 100644 openbao/root-grant/reader.hcl create mode 100644 openbao/root-grant/writer.hcl create mode 100644 scripts/root_grant_publish.py create mode 100644 tests/test_root_grant_publish.py create mode 100644 workplans/RPF-WP-0049-platform-root-custody-record-delivery.md diff --git a/openbao/root-grant/README.md b/openbao/root-grant/README.md new file mode 100644 index 0000000..09aa553 --- /dev/null +++ b/openbao/root-grant/README.md @@ -0,0 +1,79 @@ +# Conditional platform-root producer packet + +Prepared for NK-WP-0045-T05 / RPF-WP-0049, 2026-10-03. This is source-only +preparation, not surface selection, identity admission, custody or live readiness. +NetKingdom canon remains authoritative; reviewed baseline is net-kingdom commit +`0122db64fdfc8cc6ba9076e167652b084f1a3f04`. Deployments must pin the validator +and its schema together, and reconcile amendments before publication. + +## Proposed source and transport + +- KV v2 mount: `platform` (existing owner convention; live suitability unverified). +- Exact API path: `/v1/platform/data/custody/net-kingdom/platform-root`. +- `record_id`: `nk-custody:platform-root`; `owner_system`: `net-kingdom-custody`. +- API response unwrap: `data.data.document` is the complete canon document. + `data.metadata.version` is KV concurrency state, distinct from canon revision. +- Reader: user-engine only. Its repository currently has no deployed workload + namespace/ServiceAccount, so no Kubernetes identity binding is claimed. + User-engine must name its real runtime identity and an existing supported auth + route. Platform admits it only after review. Reader policy is exact-path read; + no list, sibling read or write. Never distribute an attended writer token. +- Writer: separate human custody lane, bounded attended MFA operator login, + reviewed exact-path policy. This packet does not grant a credential or role. +- Reader timeout 5 seconds, maximum document 256 KiB. A successful authenticated + owner read, not document time or a cache read, sets observed_at. Failure means + no grant. No raw server response/error logging. + +## Offline implementation + +`scripts/root_grant_publish.py` creates a single KV v2 CAS payload from a +candidate, previous document, exact previous KV version and the pinned +NetKingdom validator module. No network or publication is implemented here. +It validates both documents, exact source identity and successor semantics; +refuses missing existing baselines, same-revision changes and rollback. CAS=0 +is bootstrap-only, CAS=current-version updates; a CAS conflict requires a fresh +owner read and revalidation, never blind retry. It never prints documents. + +The attended executor still needs implementation after the source/identity +choice: suppress output, read document and KV version together, verify retained +high-water mark, call preparation helper, write one complete payload, read back +and compare, and emit non-secret revision/digest receipts. An unvalidated direct +writer bypass is not an accepted delivery path. Policies alone cannot enforce +the human ceremony, validator or global revision monotonicity. + +## Exact later live approval packet + +After ADR/surface selection and real consumer identity confirmation, request +one explicit attended approval naming the reviewed platform and NetKingdom +commits, exact mount/path/record ID, real reader auth binding, separate writer +binding, audit owner, abort operator, window and provenance reference. Its +bounded actions are: inspect existing mount and identity without values; +configure exact-path admission and KV per-key CAS requirement; publish a +human-reviewed initial document only from real ceremony evidence (or an +explicitly approved empty baseline); verify authenticated reader success, +anonymous/wrong-identity/parent-list/sibling/write denial and failed-read behavior; +return only source ID, revision, content digest, actor/time/provenance references +and pass/fail checks. No synthetic fixture can seed the authoritative record. + +Acceptance also needs revocation/supersession exercise and rollback/restore +receipts. Exercise real grant changes only under their own custody ceremony +approval. Use isolated synthetic paths for non-live algorithm exercises. + +## History, recovery and audit + +OpenBao audit is owned by railiance-platform; the custody fact and ceremony are +owned by net-kingdom-custody. Confirm mount backup owner and restoration before +calling this source live. Retain KV history and independent publication digest / +revision high-water receipts. Readers persist their own trusted baseline across +restart. A restored snapshot must not reactivate an older grant: suspend reads, +compare restored record with independently retained latest baseline, reconcile +all later custody actions, and re-enable only after owner receipts. Do not +reset baselines, destroy versions or recreate an old record under the same ID. +KV CAS prevents races, but is not proof against snapshot rollback. Retention +settings and independent backup location remain an owner implementation gate. + +No control was relaxed and no live action was taken. Emergent knowledge 0.2.3 +start was withheld/orientation-only (digest +60f8811c6b94b30d357a0d9e5022f2a8ea52e69b47138d3a536755f3295310b5); +source review read the-custodian agent-environment-orientation section 0 and +informed-decision README, plus the source NetKingdom contract/schema/validator. diff --git a/openbao/root-grant/reader.hcl b/openbao/root-grant/reader.hcl new file mode 100644 index 0000000..f547c74 --- /dev/null +++ b/openbao/root-grant/reader.hcl @@ -0,0 +1,4 @@ +# Conditional draft: not applied. No list or write capability. +path "platform/data/custody/net-kingdom/platform-root" { + capabilities = ["read"] +} diff --git a/openbao/root-grant/writer.hcl b/openbao/root-grant/writer.hcl new file mode 100644 index 0000000..fff6364 --- /dev/null +++ b/openbao/root-grant/writer.hcl @@ -0,0 +1,5 @@ +# Conditional attended human writer, not a reader workload grant. +# No metadata delete, destroy, list or policy/auth administration. +path "platform/data/custody/net-kingdom/platform-root" { + capabilities = ["create", "update", "read"] +} diff --git a/scripts/root_grant_publish.py b/scripts/root_grant_publish.py new file mode 100644 index 0000000..baaceb9 --- /dev/null +++ b/scripts/root_grant_publish.py @@ -0,0 +1,42 @@ +"""Offline CAS payload preparation; this module never calls OpenBao. + +The caller supplies the reviewed NetKingdom validator. Its deployment must pin +both validator and schema. Returning a payload does not approve a custody action. +""" +import copy +import json + +RECORD_ID = "nk-custody:platform-root" +OWNER_SYSTEM = "net-kingdom-custody" +MAX_BYTES = 262144 + + +def prepare_payload(candidate, previous, previous_kv_version, validator): + """Require current authoritative baseline; CAS also fences concurrent writes. + + Bootstrap must use cas=0 and no previous document. Existing records require + both the last successful owner-read document and its exact KV version. + The caller must obtain those together and retain the high-water baseline. + Errors intentionally disclose neither documents nor rejected values. + """ + if type(previous_kv_version) is not int or previous_kv_version < 0: + raise ValueError("invalid KV version") + if (previous is None) != (previous_kv_version == 0): + raise ValueError("missing or inconsistent publication baseline") + documents = [candidate] if previous is None else [previous, candidate] + for document in documents: + try: + encoded = json.dumps(document, allow_nan=False).encode("utf-8") + if len(encoded) > MAX_BYTES or validator.validate(document): + raise ValueError + if document["record_id"] != RECORD_ID or document["owner_system"] != OWNER_SYSTEM: + raise ValueError + except Exception: + raise ValueError("invalid custody document") from None + if previous is not None: + try: + if candidate["revision"] <= previous["revision"] or validator.successor_errors(previous, candidate): + raise ValueError + except Exception: + raise ValueError("invalid custody transition") from None + return {"options": {"cas": previous_kv_version}, "data": {"document": copy.deepcopy(candidate)}} diff --git a/tests/test_root_grant_publish.py b/tests/test_root_grant_publish.py new file mode 100644 index 0000000..6b8f50b --- /dev/null +++ b/tests/test_root_grant_publish.py @@ -0,0 +1,60 @@ +"""Offline producer checks using the real reviewed NetKingdom validator.""" +import copy +import importlib.util +import json +from pathlib import Path +import unittest + +ROOT = Path(__file__).resolve().parents[1] +NK = ROOT.parent / "net-kingdom" + + +def module(name, path): + spec = importlib.util.spec_from_file_location(name, path) + result = importlib.util.module_from_spec(spec) + spec.loader.exec_module(result) + return result + + +publisher = module("publisher", ROOT / "scripts/root_grant_publish.py") +validator = module("custody_validator", NK / "tools/custody-record/validate.py") + + +class ProducerTests(unittest.TestCase): + def setUp(self): + self.first = json.loads((NK / "tools/custody-record/fixtures/valid/grant.json").read_text()) + self.first["record_id"] = publisher.RECORD_ID + self.next = copy.deepcopy(self.first) + self.next["revision"] += 1 + + def test_bootstrap_requires_absent_baseline_and_cas_zero(self): + self.assertEqual(publisher.prepare_payload(self.first, None, 0, validator)["options"], {"cas": 0}) + for old, version in [(None, 1), (self.first, 0), (None, True), (None, -1)]: + with self.assertRaises(ValueError): + publisher.prepare_payload(self.first, old, version, validator) + + def test_update_is_whole_document_and_exact_cas(self): + result = publisher.prepare_payload(self.next, self.first, 7, validator) + self.assertEqual(result["options"], {"cas": 7}) + self.assertEqual(result["data"]["document"], self.next) + result["data"]["document"]["entries"].clear() + self.assertTrue(self.next["entries"]) + + def test_rollback_same_revision_and_entry_deletion_denied(self): + for doc in [self.first, dict(self.next, revision=1), dict(self.next, entries=[])]: + with self.assertRaises(ValueError): + publisher.prepare_payload(doc, self.first, 1, validator) + + def test_wrong_record_and_secret_errors_do_not_echo(self): + for doc in [dict(self.first, record_id="nk-custody:other"), dict(self.first, password="DO-NOT-ECHO")]: + with self.assertRaises(ValueError) as raised: + publisher.prepare_payload(doc, None, 0, validator) + self.assertNotIn("DO-NOT-ECHO", str(raised.exception)) + + def test_invalid_previous_cannot_reset_baseline(self): + with self.assertRaises(ValueError): + publisher.prepare_payload(self.next, {}, 1, validator) + + +if __name__ == "__main__": + unittest.main() diff --git a/workplans/RPF-WP-0049-platform-root-custody-record-delivery.md b/workplans/RPF-WP-0049-platform-root-custody-record-delivery.md new file mode 100644 index 0000000..38d6606 --- /dev/null +++ b/workplans/RPF-WP-0049-platform-root-custody-record-delivery.md @@ -0,0 +1,94 @@ +--- +id: RPF-WP-0049 +type: workplan +title: "Prepare conditional OpenBao delivery of the platform-root custody fact" +domain: financials +repo: railiance-platform +status: blocked +owner: codex +topic_slug: railiance-platform +created: "2026-10-03" +updated: "2026-10-03" +related: [NK-WP-0045, USER-WP-0037] +--- + +Conditional response to net-kingdom message bc0c620c. Owner source preparation +is feasible; OpenBao has not been selected and no production source exists. +Contract: ../net-kingdom/docs/contracts/root-grant-read-contract_v0.1.md. +Packet: [conditional producer](../openbao/root-grant/README.md). + +## Prepare reviewed producer interface and exact-path drafts + +```task +id: RPF-WP-0049-T01 +status: done +priority: high +``` + +Prepared whole-document CAS payload builder with real NetKingdom schema and +transition validation, strict trusted ID binding, sanitized exceptions and +exact-path reader/separate attended writer policies. Offline tests cover +bootstrap/current version, concurrent-write CAS binding, rollback, mutation, +entry removal, wrong identity, secret diagnostics and invalid previous record. +These are preparation artifacts, not an admitted or operational source. + +## Obtain source selection and exact real reader identity + +```task +id: RPF-WP-0049-T02 +status: wait +priority: high +needs_human: true +decision_id: cef97ccd-4ee7-40fe-859e-1df9c9360ecb +depends_on: [NK-WP-0045-T01, NK-WP-0045-T04] +blocked_on: message-from:user-engine +blocking_reason: "Founder ADR acceptance/OpenBao owner selection and user-engine real runtime reader identity/auth route are required; no deployed ServiceAccount is known." +``` + +Propose platform/data/custody/net-kingdom/platform-root, record ID +nk-custody:platform-root and exact-path read using the existing owner-routed +workload admission. user-engine confirmed nested document compatibility; +its adapter is transport-neutral and runtime identity remains unconfirmed. + +## Implement attended executor, recovery and audit after selection + +```task +id: RPF-WP-0049-T03 +status: wait +priority: high +depends_on: [RPF-WP-0049-T02] +blocking_reason: "Surface and actual reader/writer custody bindings must be selected before final executor/admission/restore configuration can be implemented." +``` + +Implement reviewed value-safe executor with owner-read baseline + CAS, exact +identity admission configuration, per-key required CAS, retention/independent +high-water history, audit and rollback-safe restoration. Pin canon source. +Do not let direct writer capability bypass transition or ceremony requirements. + +## Approve bounded live provisioning and custody bootstrap + +```task +id: RPF-WP-0049-T04 +status: wait +priority: high +depends_on: [RPF-WP-0049-T03] +needs_human: true +blocking_reason: "Separate founder go for named commits, exact read/writer bindings, attended window and real custody provenance; decision on design alone is not live approval." +``` + +Assemble exact later approval packet from producer README. Source-only draft +policies are not approval to apply or create entries. Bootstrap ceremony facts +are supplied by human custodian, never inferred from IAM or test fixtures. + +## Return delivery and consumer acceptance receipts + +```task +id: RPF-WP-0049-T05 +status: wait +priority: high +depends_on: [RPF-WP-0049-T04, USER-WP-0037-T02] +blocking_reason: "Live authenticated/denial/outage/revocation/restore/audit receipts and user-engine integration against delivered source remain absent." +``` + +Return non-secret revision/provenance/digest receipts to NK-WP-0045-T05/T06. +No live readiness claim until all producer and consumer contract checks pass.