RAILIANCE-WP is a family name, not a repository (ADR-007, and the prefix registry already lists it retired). Three repositories independently used one number space for unrelated work — RAILIANCE-WP-0012 was openbao extraction here, a cnpg backup in railiance-apps and a deploy-verify in railiance-cluster. This repository also carried two files both numbered 0016. Active workplans move to the successor prefix and are renumbered from 0001 in historical order. Archived workplans keep their historical identifiers. Projection UUIDs are re-derived from the new canonical ids. Records already registered under the old identifiers leave orphaned hub rows behind; that debt is recorded in CUST-WP-0068 and clears when ADR-012's reset-from-forge lands. Refs CUST-WP-0068-T03 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
183 lines
7.5 KiB
Markdown
183 lines
7.5 KiB
Markdown
---
|
|
id: RPF-WP-0016
|
|
type: workplan
|
|
title: "Version ephemeral custody projection and broker handoff"
|
|
domain: financials
|
|
repo: railiance-platform
|
|
status: finished
|
|
owner: codex
|
|
topic_slug: railiance
|
|
created: "2026-08-22"
|
|
updated: "2026-08-22"
|
|
related:
|
|
- RAILIANCE-WP-0024
|
|
- WHITEHAT-WP-0001
|
|
- AUDIT-WP-0008
|
|
origin: run-review
|
|
origin_ref: "WH-ENG-20260822-AUDIT-E2-02 terminal clean admission abort"
|
|
state_hub_workstream_id: "26165dd5-dca5-5261-b4bf-183d186aad27"
|
|
---
|
|
|
|
# RPF-WP-0016 — Version ephemeral custody projection and broker handoff
|
|
|
|
## Goal
|
|
|
|
Replace engagement-specific credential scripts and prose handoffs with one
|
|
versioned, value-safe, fail-closed lifecycle. A consumer must prove it can
|
|
consume the projection receipt before platform custody mints anything. The
|
|
platform then exposes direct `preflight`, `project`, `status`, `cleanup`, and
|
|
expired-lease cleanup interfaces without transferring bearer values or
|
|
collapsing owner approvals.
|
|
|
|
The implementation is repository code and contracts only. It does not
|
|
authorize or schedule a live credential projection, workload, probe, or
|
|
unattended cleanup controller.
|
|
|
|
## T01 — Define projection, broker-readiness, and cleanup receipts
|
|
|
|
```task
|
|
id: RPF-WP-0016-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "3d95a854-1c54-58c9-90d2-971b9a9ec5c6"
|
|
```
|
|
|
|
Publish versioned JSON Schemas and canonical validation for the projection
|
|
contract, broker-readiness receipt, active projection receipt, and cleanup
|
|
receipt. Bind every receipt to the exact engagement, target revision and image,
|
|
runner and target contract digests, mounted identity handles, expiry, opaque
|
|
lease id, and cleanup authority. Values and value-derived fingerprints are
|
|
forbidden.
|
|
|
|
Done when malformed, stale, mismatched, expired, and value-bearing documents
|
|
fail closed and consumers can implement without interpreting prose.
|
|
|
|
Implemented in four JSON Schemas plus `scripts/custody_contract.py`. Canonical
|
|
projection ids cover all receipt content; validators bind target, contract,
|
|
roles, mount paths, resource names and UIDs, and reject value-bearing fields.
|
|
Broker approvals also pin the current hashes of all four interface schemas.
|
|
|
|
## T02 — Implement a data-driven custody lifecycle
|
|
|
|
```task
|
|
id: RPF-WP-0016-T02
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "783f74b8-d4a6-5ac5-9300-62acfedc53c6"
|
|
```
|
|
|
|
Replace copied per-engagement code and static manifests with one lifecycle that
|
|
derives exact OpenBao and ESO resources from a validated engagement contract.
|
|
Expose value-safe `preflight`, `project`, `status`, and idempotent `cleanup`
|
|
commands. Preserve the existing two-identity sender overlay, application-level
|
|
expiry, exact-key mount, readiness reload, and exact-scope rollback behavior.
|
|
|
|
Done when a new engagement requires data only, not copied Python, HCL, or YAML,
|
|
and an old engagement identifier cannot leak into generated resources.
|
|
|
|
Implemented by `scripts/custody-projection.py` and the intentionally invalid
|
|
placeholder template `docs/custody-projection-contract.example.json`. Policy,
|
|
role, store, KV paths, ExternalSecret data mappings, sender overlays, expiry,
|
|
and cleanup scope derive from one validated contract. Resource names use an
|
|
engagement-id digest rather than a copied run suffix.
|
|
|
|
## T03 — Gate projection on a direct broker capability receipt
|
|
|
|
```task
|
|
id: RPF-WP-0016-T03
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "e2cced83-5beb-5fb1-919a-72bd6cb49dcf"
|
|
```
|
|
|
|
Provide a direct owner interface for `whitehat-security` to inspect, verify,
|
|
approve, or request changes to the contract. Approval must identify the tested
|
|
adapter revision and artifact digest and be posted directly to State Hub. The
|
|
platform lifecycle must find a current matching approval before generating a
|
|
credential.
|
|
|
|
Done when an unconnected, stale, wrong-engagement, or wrong-contract broker is
|
|
rejected before the first OpenBao or sender-registry mutation.
|
|
|
|
Implemented by `scripts/wp0025-broker-readiness.py`. Its closed verification
|
|
surface pins Whitehat's adapter and focused test paths, computes their commit
|
|
and digest, runs only the named focused test, and posts the canonical receipt
|
|
directly as `whitehat-security`. `project` checks State Hub before reading the
|
|
platform-admin token file, generating bearer values, or touching live state.
|
|
No adapter approval is fabricated by this implementation; a future Whitehat
|
|
adapter must pass the interface itself.
|
|
|
|
## T04 — Harden execution and transactional cleanup
|
|
|
|
```task
|
|
id: RPF-WP-0016-T04
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "a14cb95b-6ef4-5872-a4ec-c7b51577cef1"
|
|
```
|
|
|
|
Centralize remote argv quoting, test shell-hostile arguments, and inject
|
|
failures at each mutation boundary. Prove that partial projection invokes exact
|
|
cleanup and that status never infers absence after a connectivity failure.
|
|
Retire the copied `-01`/`-02` procedure from future-run instructions.
|
|
|
|
Done when the SSH expansion defect from the `-02` run and every modeled partial
|
|
failure have regression coverage.
|
|
|
|
Implemented by `scripts/remote_exec.py` and focused tests covering `$`, shell
|
|
substitution, semicolons, quotes, NUL refusal, and value-safe failure messages.
|
|
The lifecycle uses a transaction whose rollback is exercised after every
|
|
modeled mutation boundary. Connectivity failure cannot be interpreted as
|
|
absence, and cleanup refuses a recreated same-name Kubernetes resource whose
|
|
UID differs from the receipt.
|
|
|
|
## T05 — Add an approval-ready expired-lease cleanup entry point
|
|
|
|
```task
|
|
id: RPF-WP-0016-T05
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "8e2840d1-b8e3-5f0f-8c94-f5019fff4e72"
|
|
```
|
|
|
|
Add a fail-closed `cleanup-expired` interface that accepts only a valid
|
|
projection receipt after its expiry, removes only the receipt-bound resources,
|
|
and emits the normal cleanup receipt. Do not install a scheduler or controller;
|
|
deployment of unattended cleanup remains a separate owner decision.
|
|
|
|
Done when an approved future reaper can call a deterministic command without
|
|
receiving projected bearer values or reconstructing cleanup scope from chat.
|
|
|
|
Implemented as `cleanup-expired`. It refuses before expiry, requires the exact
|
|
canonical projection receipt and engagement confirmation, verifies live UIDs,
|
|
uses the ordinary exact cleanup transaction, and emits the versioned cleanup
|
|
receipt. No scheduler, controller, runtime identity, or unattended authority
|
|
was deployed; those remain a separate owner decision.
|
|
|
|
## Acceptance
|
|
|
|
- [x] No projection can begin without a current consumer broker receipt.
|
|
- [x] A new engagement is configuration, not copied executable code.
|
|
- [x] Projection and cleanup receipts are versioned, canonical, and value-safe.
|
|
- [x] Remote command arguments survive shell-hostile templates unchanged.
|
|
- [x] Every modeled partial mutation cleans only its receipt-bound scope.
|
|
- [x] Expired cleanup is executable but no unattended scheduler is deployed.
|
|
|
|
## T06 — Export the broker receipt consumed by admission
|
|
|
|
```task
|
|
id: RPF-WP-0016-T06
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "d815e1b9-73fe-527c-85c9-c20e37cf510f"
|
|
```
|
|
|
|
The first fresh-run setup review found that `approve` posted the canonical
|
|
broker-readiness receipt to State Hub but exposed no safe way to persist the
|
|
raw receipt document required by Whitehat's `--broker-receipt` input. Redirecting
|
|
the command output would save a CLI wrapper rather than the canonical document.
|
|
|
|
`approve` and a ready `status` now accept `--receipt-out`, create parent
|
|
directories, write only the canonical value-safe receipt, and force mode
|
|
`0600`. Other commands fail closed when that option is supplied. Regression
|
|
coverage proves the wrapper is excluded and the file mode is private.
|