feat: prepare scoped State Hub preflight signing custody and rotation
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06ed7-828d-7ca0-a8d4-0c3e5a0c4102
This commit is contained in:
codex 2026-09-05 16:38:26 +02:00
parent a46a6d8213
commit 5d288938f7
4 changed files with 117 additions and 8 deletions

View file

@ -3,7 +3,7 @@ kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: State Hub repository-rename preflight signing read lane
status: proposed
status: approved
created: '2026-09-05'
updated: '2026-09-05'
requester:
@ -23,6 +23,19 @@ review:
comment: 'Live primary/railiance01: namespace/release/deployment state-hub, API
SA state-hub, one replica; ESO CRD supports serviceAccountRef.audiences. New
dedicated delivery identity requires live acceptance.'
- at: '2026-09-05T14:37:03+00:00'
reviewer: codex
decision: binding_confirmed
comment: Live dedicated state-hub/state-hub-preflight-eso ServiceAccount observed;
minted subject and audience openbao verified by TokenReview. API workload TokenRequest
and ExternalSecret create denied.
- at: '2026-09-05T14:37:03+00:00'
reviewer: user via RPF-WP-0035-T04 instruction
decision: approved
comment: User explicitly requested execution of RPF-WP-0035-T04 on 2026-09-05.
Scope is the reviewed transitional State Hub signing lane, exact data-only ESO
grant and protected CAS writer with controlled-outage rotation acceptance. No
repository rename authorized. Operator OIDC remains required.
target:
domain: infotech
tenant: state-hub
@ -47,7 +60,7 @@ openbao:
- state-hub-preflight-eso
service_account_namespaces:
- state-hub
bound_claims_confirmed: false
bound_claims_confirmed: true
policies:
- workload-kv-read-state-hub-rename-preflight
ttl: 15m

View file

@ -0,0 +1,92 @@
# State Hub preflight signing activation — RPF-WP-0035-T04
CCR-2026-0015 is the exact read grant. The user requested this task on 2026-09-05;
FLEX-WP-0020-T05 remains its consuming demand. A fresh non-mutating live preflight
for flex-auth -> access-engine returned 200 with exactly one blocker:
`preflight_signing_unavailable`. No rename or operation journal is authorized.
## Observed target and access boundary
Primary/railiance01, namespace/release/deployment `state-hub`, API container and
service account `state-hub`, one replica, existing image `main-cdff3b7`.
The dedicated ESO identity is `state-hub/state-hub-preflight-eso`, audience
`openbao`; installed CRDs accept `serviceAccountRef.audiences`. ESO is already a
trusted cluster-wide controller with TokenRequest/Secret permissions; this lane
adds no broad RBAC. The API SA cannot create ExternalSecrets or TokenRequests
for the delivery identity (live `kubectl auth can-i` returned no for both).
Only trusted namespace administrators may create pod/ExternalSecret/TokenRequest
resources; no workload RBAC grant is added. Namespace-scoped SecretStore prevents
cross-namespace store references. Coding-agent data AND metadata are denied.
## Review and apply
1. Review CCR-2026-0015, its generated policy/auth payload, delivery.yaml, and
State Hub chart diff together. Confirm the dedicated SA binding and record
CCR approval from the user's task authorization. Keep the lane non-resolvable.
2. Commit/push the reviewed source in both repositories before live apply.
3. Run the silent writer through the contained attended login envelope:
```sh
warden access openbao-platform-admin-login --exec -- \
/usr/bin/python3 /home/worsch/railiance-platform/scripts/state_hub_preflight_lane.py \
provision --expected-version 0 --kubeconfig /home/worsch/.kube/config \
--receipt /tmp/statehub-preflight-provision.json --confirm 'APPLY CCR-2026-0015'
```
The identity act requires operator OIDC/MFA. The expired ambient token is not
usable. Warden captures both streams and revokes/removes the contained helper;
the writer emits only a mode-0600 metadata receipt. Never fall back to root,
a workload token or another service's secret. Generation is CSPRNG 32 bytes,
CAS zero, with no raw key on argv/disk/output. Subsequent CAS rotation is a
separately named writer action, never granted to ESO or API.
4. Verify SecretStore Ready and ExternalSecret SecretSynced. Compare accepted KV
version with the Secret's safe metadata and check key presence without output.
Check shared `state-hub-env` has no same-name key; do not overwrite that Secret.
5. Enable `renamePreflight.enabled` in production values and deploy the reviewed
chart with the current image. Only API gets the required explicit key ref;
MCP and migration jobs remain excluded. Verify all API replicas' process key
matches the materialized version using in-memory equality and boolean output.
6. Call only the non-mutating preflight endpoint for the observed fixture, keep
its token private, and record blocker codes and signing-verification booleans.
Do not call start/apply/rollback mutation endpoints or print the full response.
## Executable rotation fence and forward recovery
The single-key application has no hot reload. Use a controlled API outage; it
fences issuance and every rename mutation equally, including direct pod callers.
Retain the live replica count and Helm revision. Confirm no HPA or other
reconciler is changing the deployment during this attended window.
```sh
kubectl -n state-hub scale deployment/state-hub --replicas=0
kubectl -n state-hub wait --for=delete pod -l app=state-hub --timeout=120s
kubectl -n state-hub get pods -l app=state-hub
```
No API process may remain, including terminating pods. Explicit invalidation of
outstanding preflight tokens replaces a TTL drain: do not wait while issuance
continues. Preserve an old signed fixture only in protected memory/file, never
in receipts. The rotation helper independently refuses nonzero replicas, any
matching pod, or an HPA before generating a key.
Run the same attended envelope with `rotate --expected-version <current>` and
a fresh receipt path. Wait for ESO to project the new version, then scale to
the retained replica count, wait for rollout and verify health, one accepted key
across all replicas, new-token validity and old-token rejection. Never reopen
with a mixed-key population. Update production source and record exact Helm,
image and KV versions. No repository rename is performed by this rehearsal.
On failure after CAS, leave the API fenced until ESO and forward recovery pass.
The receipt retains the new KV version even if a later check fails. The `verify`
action rechecks custody without regenerating or overwriting a key. Initial
partial metadata apply is deliberately not silently overwritten: inspect the
exact role/policy and receipt before continuing. Do not replay CAS zero against
an existing lane. Restore availability without signing only by disabling the
chart binding after confirming no signing key remains in shared env; retain
custody for reviewed recovery. Never restore a compromised predecessor key.
## Completion gate
T04 remains open until live custody/auth negatives, ESO delivery, API-only
exposure, all-replica equality, signed preflight, rotation/invalidation and
recovery receipts pass. Source tests and server dry-run alone are preparation.

View file

@ -1,6 +1,6 @@
# State Hub repository-rename preflight signing lane
Status: proposed, not provisioned. Owner: railiance-platform, RPF-WP-0034.
Status: implementation staged, not provisioned. Owner: railiance-platform, RPF-WP-0035-T04.
Demand: State Hub message `cd52ba10-de41-46ce-aa8b-9b44050da8f7`,
STATE-WP-0085-T09. Provisioning this lane does not authorize any repository rename.
@ -112,3 +112,12 @@ and the migration owner must confirm the target runtime and continued need
before provisioning this design. RPF-WP-0035-T04 is the current platform task;
RPF-WP-0034 is the archived design record. No demand withdrawal or activation
is inferred from retirement planning alone.
## Implementation preparation — 2026-09-05
CCR-2026-0015, the exact data-only policy and bounded role, namespace-scoped
ESO manifests, silent CAS writer and API-only chart binding are staged.
The fresh live fixture has only the signing-unavailable blocker.
`state-hub-preflight-activation.md` supplies the controlled-outage rotation
fence and recovery sequence. Live acceptance still requires attended OIDC/MFA;
the existing operator session returned 403.

View file

@ -48,11 +48,6 @@ class SigningLaneTests(unittest.TestCase):
def test_proposed_ccr_cannot_reach_writer(self):
proposed = copy.deepcopy(self.ccr)
proposed['status'] = 'proposed'
with patch.object(lane.importlib.util, 'module_from_spec', return_value=cc), \
patch.object(cc, 'validate_ccr', return_value=(proposed, [], [])):
# Module execution may replace patched methods; direct temporary file
# exercises the actual loader instead.
pass
import tempfile, yaml
with tempfile.TemporaryDirectory() as tmp:
file = Path(tmp) / 'ccr.yaml'