2026-08-22 21:56:42 +02:00
|
|
|
---
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016
|
2026-08-22 21:56:42 +02:00
|
|
|
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"
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_workstream_id: "26165dd5-dca5-5261-b4bf-183d186aad27"
|
2026-08-22 21:56:42 +02:00
|
|
|
---
|
|
|
|
|
|
2026-08-25 22:58:35 +02:00
|
|
|
# RPF-WP-0016 — Version ephemeral custody projection and broker handoff
|
2026-08-22 21:56:42 +02:00
|
|
|
|
|
|
|
|
## 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
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016-T01
|
2026-08-22 21:56:42 +02:00
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_task_id: "3d95a854-1c54-58c9-90d2-971b9a9ec5c6"
|
2026-08-22 21:56:42 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016-T02
|
2026-08-22 21:56:42 +02:00
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_task_id: "783f74b8-d4a6-5ac5-9300-62acfedc53c6"
|
2026-08-22 21:56:42 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016-T03
|
2026-08-22 21:56:42 +02:00
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_task_id: "e2cced83-5beb-5fb1-919a-72bd6cb49dcf"
|
2026-08-22 21:56:42 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016-T04
|
2026-08-22 21:56:42 +02:00
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_task_id: "a14cb95b-6ef4-5872-a4ec-c7b51577cef1"
|
2026-08-22 21:56:42 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016-T05
|
2026-08-22 21:56:42 +02:00
|
|
|
status: done
|
|
|
|
|
priority: medium
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_task_id: "8e2840d1-b8e3-5f0f-8c94-f5019fff4e72"
|
2026-08-22 21:56:42 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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.
|
2026-08-22 23:23:41 +02:00
|
|
|
|
|
|
|
|
## T06 — Export the broker receipt consumed by admission
|
|
|
|
|
|
|
|
|
|
```task
|
2026-08-25 22:58:35 +02:00
|
|
|
id: RPF-WP-0016-T06
|
2026-08-22 23:23:41 +02:00
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 22:58:35 +02:00
|
|
|
state_hub_task_id: "d815e1b9-73fe-527c-85c9-c20e37cf510f"
|
2026-08-22 23:23:41 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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.
|