Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02669-87ee-7a31-b111-edc95a16e0fa
132 lines
5.6 KiB
Markdown
132 lines
5.6 KiB
Markdown
# Ephemeral custody projection lifecycle
|
|
|
|
`scripts/custody-projection.py` is the platform-owned interface for future
|
|
short-lived, mount-only credential exercises. It replaces copying the dated
|
|
`audit-core-whitehat-e2-credentials*.py`, HCL, and YAML files. Those dated
|
|
artifacts are retained only as historical evidence and cleanup references for
|
|
their terminal engagement ids.
|
|
|
|
The lifecycle does not authorize an engagement. A projection contract is
|
|
accepted only when it is `approved`, lasts at most 900 seconds, binds exact
|
|
target and runner revisions, names exactly two distinct sender identities, and
|
|
uses engagement- and target-bound KV paths. Kubernetes and OpenBao resource
|
|
names are derived from the SHA-256 of the engagement id; no previous engagement
|
|
name is copied into a new manifest.
|
|
|
|
## Versioned interfaces
|
|
|
|
| Interface | Schema | Producer | Consumer |
|
|
| --- | --- | --- | --- |
|
|
| `railiance.custody-projection-contract` v1 | `schemas/custody-projection-contract.schema.json` | engagement/platform owners | platform lifecycle and Whitehat review |
|
|
| `railiance.custody-broker-readiness` v1 | `schemas/custody-broker-readiness.schema.json` | `whitehat-security` | platform pre-projection gate |
|
|
| `railiance.custody-projection-receipt` v1 | `schemas/custody-projection-receipt.schema.json` | platform lifecycle | Whitehat broker adapter and operator |
|
|
| `railiance.custody-cleanup-receipt` v1 | `schemas/custody-cleanup-receipt.schema.json` | platform lifecycle | engagement owner and evidence record |
|
|
|
|
Receipts contain no bearer, password, value-derived fingerprint, Secret data,
|
|
or registry body. The projection receipt carries an opaque lease id, canonical
|
|
receipt id, exact identity roles and mount paths, contract digests, times,
|
|
resource names, and Kubernetes UIDs. Changing any canonical field invalidates
|
|
the receipt id.
|
|
|
|
## Broker gate owned directly by Whitehat
|
|
|
|
The owner does not need a coding agent to translate the request. Given the
|
|
final projection contract, it can run:
|
|
|
|
```sh
|
|
python3 scripts/wp0025-broker-readiness.py show \
|
|
--contract /path/to/final-projection-contract.json
|
|
|
|
python3 scripts/wp0025-broker-readiness.py verify \
|
|
--contract /path/to/final-projection-contract.json \
|
|
--consumer-root /path/to/whitehat-security
|
|
|
|
python3 scripts/wp0025-broker-readiness.py approve \
|
|
--contract /path/to/final-projection-contract.json \
|
|
--consumer-root /path/to/whitehat-security \
|
|
--reviewer whitehat-owner
|
|
```
|
|
|
|
Verification is closed to
|
|
`src/whitehat_security/platform_custody.py` and
|
|
`tests/test_platform_custody_adapter.py`. It records the full consumer commit,
|
|
adapter SHA-256, focused-test result, exact platform schema hashes, mount paths,
|
|
and cleanup support. Approval posts the canonical receipt directly to State
|
|
Hub as `from_agent=whitehat-security`. A stale schema, changed projection
|
|
contract, wrong engagement, wrong target, absent adapter, or failing focused
|
|
test does not count.
|
|
|
|
The platform lifecycle queries that receipt before token generation and before
|
|
the first mutation. State Hub coordination identity is not a secret transport;
|
|
the receipt contains no secret.
|
|
|
|
## Platform commands
|
|
|
|
The template at `docs/custody-projection-contract.example.json` intentionally
|
|
fails validation until every placeholder and the approval status are replaced
|
|
by the owners.
|
|
|
|
```sh
|
|
python3 scripts/custody-projection.py validate \
|
|
--contract /path/to/final-projection-contract.json
|
|
|
|
python3 scripts/custody-projection.py render \
|
|
--contract /path/to/final-projection-contract.json
|
|
|
|
python3 scripts/custody-projection.py preflight \
|
|
--contract /path/to/final-projection-contract.json
|
|
```
|
|
|
|
`render` is value-free and creates no resource. `preflight` reads only status,
|
|
metadata, names, image/readiness, and the broker receipt. It never reads a
|
|
Kubernetes Secret value.
|
|
|
|
Inside the approved projection interval, an attached custody operator may run:
|
|
|
|
```sh
|
|
python3 scripts/custody-projection.py project \
|
|
--contract /path/to/final-projection-contract.json \
|
|
--confirm '<engagement-id>:attended' \
|
|
--receipt-out /approved/non-repo/path/projection.json
|
|
```
|
|
|
|
If any mutation fails, the transaction invokes exact-scope cleanup. The
|
|
operator must not release the consumer until the returned projection receipt
|
|
passes its adapter. The receipt file is written mode `0600` even though it is
|
|
value-safe.
|
|
|
|
Status and normal attended cleanup require that receipt:
|
|
|
|
```sh
|
|
python3 scripts/custody-projection.py status \
|
|
--contract /path/to/final-projection-contract.json \
|
|
--receipt /approved/non-repo/path/projection.json
|
|
|
|
python3 scripts/custody-projection.py cleanup \
|
|
--contract /path/to/final-projection-contract.json \
|
|
--receipt /approved/non-repo/path/projection.json \
|
|
--confirm '<engagement-id>:cleanup' \
|
|
--receipt-out /approved/non-repo/path/cleanup.json
|
|
```
|
|
|
|
Status reports `active`, `absent`, `partial`, or `mismatched`. It compares live
|
|
resource UIDs with the receipt and does not interpret a connection error as
|
|
absence.
|
|
|
|
## Expired cleanup entry point
|
|
|
|
`cleanup-expired` refuses until the contract expiry and still requires the
|
|
exact projection receipt and confirmation:
|
|
|
|
```sh
|
|
python3 scripts/custody-projection.py cleanup-expired \
|
|
--contract /path/to/final-projection-contract.json \
|
|
--receipt /approved/non-repo/path/projection.json \
|
|
--confirm '<engagement-id>:expired' \
|
|
--receipt-out /approved/non-repo/path/cleanup.json
|
|
```
|
|
|
|
This is an approval-ready reaper entry point, not a deployed scheduler. A
|
|
future controller still needs an owner-reviewed credential route, runtime
|
|
identity, alerting, and rollout decision. Application `expires_at` remains the
|
|
acceptance backstop; evidenced resource deletion remains the cleanup result.
|