railiance-platform/docs/credential-lane-designs/state-hub-preflight-signing.md
codex 5d6d8724b4
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Complete live State Hub signing activation and rotation acceptance
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06ecb-456a-71c2-b41e-0755d336e883
2026-09-05 18:12:37 +02:00

125 lines
7.6 KiB
Markdown

# State Hub repository-rename preflight signing lane
Status: active; accepted 2026-09-05. Owner: railiance-platform, RPF-WP-0035-T04.
CCR-2026-0015 is active at key version 2. See
`state-hub-preflight-activation.md` for the accepted implementation and evidence.
Demand: State Hub message `cd52ba10-de41-46ce-aa8b-9b44050da8f7`,
STATE-WP-0085-T09. Provisioning this lane does not authorize any repository rename.
## Current consumer contract
`../state-hub/api/config.py` loads `REPOSITORY_RENAME_PREFLIGHT_SECRET` once
through module-level settings; token TTL defaults to 900 seconds.
`api/services/repository_rename.py` signs canonical payloads with HMAC-SHA256
and verifies with the same single key plus an expiry check. Missing configuration
denies mutation-token issuance while the read-only report remains available.
There is no multi-key verification or live secret reload in this implementation.
The source chart is `../state-hub/deploy/railiance/apps/charts/state-hub`:
API container `state-hub`, service account `state-hub`, existing env Secret
`state-hub-env`. Namespace/release and live primary/railiance01 binding must be
confirmed against deployed metadata before apply. The sibling chart is source
evidence, not a claim that every live value matches its defaults.
## Proposed custody and delivery
| Object | Proposed contract |
| --- | --- |
| KV mount / CLI path | `platform` / `platform/workloads/state-hub/repository-rename-preflight` |
| KV field | `REPOSITORY_RENAME_PREFLIGHT_SECRET` |
| Generation | At least 32 random bytes from a CSPRNG, encoded as 64 lowercase hex characters; generate in the approved protected writer, never print |
| Read policy | `workload-kv-read-state-hub-rename-preflight`: read only on the one exact data path |
| Kubernetes auth | Existing reviewed mount `kubernetes`; new role `state-hub-rename-preflight-eso` |
| Auth identity | Proposed dedicated service account `state-hub-preflight-eso` in `state-hub`; exact audience `openbao` subject to TokenReview/ESO compatibility proof |
| Token bounds | TTL/max/explicit max `15m`, no default or periodic policy; no write/admin policy |
| ESO scope | Namespace-scoped SecretStore `openbao-state-hub-rename-preflight`, dedicated ExternalSecret of the same workload scope |
| K8s target | Separate Secret `state-hub-rename-preflight`, field mapped to the exact environment name |
| Runtime binding | Explicit `secretKeyRef` in API Deployment only; required/non-optional |
Use the native OpenBao data GET for delivery. If the ESO version requires
metadata read, prove that need and review an exact metadata-path addition;
never grant parent list. ESO TokenRequest/RBAC and the OpenBao Kubernetes role
must agree on service account, namespace and audience. Do not change a shared
mount or borrow the existing Forge-derivation role, AppRole SecretID, admin PAT,
API token, webhook HMAC or database password.
The new Secret avoids having two controllers own `state-hub-env`. Its key must
not be added to ConfigMaps, general `envFrom`, Helm values containing plaintext,
migration Jobs, MCP containers, or the workstation/fallback Hub. Scope the
SecretStore to this namespace and restrict who can create ExternalSecrets or
TokenRequests for the delivery identity. Verify the API's explicit env entry
takes precedence and remove any stale same-name setting under its original
owner's control. Do not overwrite the whole existing shared Secret.
## Governed implementation
Create a proposed `workload-kv-read` CCR through the existing schema once exact
deployment bindings are confirmed. Keep the writer separate: the read CCR
does not authorize key generation or KV writes. The writer's one-time approved
scope is the exact data path with initial CAS zero or current-version CAS for
rotation. The API and ESO never get write access. Add coding-agent high-risk
boundary denies for data and metadata before provisioning.
Stage and review the policy, auth role, service account/RBAC, SecretStore,
ExternalSecret and API chart env entry together. The dedicated Secret should
retain its last value if the external source is unavailable; document the ESO
target ownership/deletion policy explicitly. A stalled ESO update does not
automatically invalidate a key already loaded in a running process. Require
green custody/version/rollout evidence before permitting rename operations.
## Activation and evidence
State Hub owner confirms the exact primary deployment, TTL and authorized
fixture preflight request; platform approves path/field and protected writer;
cluster owner accepts ESO bindings and API-only exposure. Record these owner
receipts and pinned source revisions before any live mutation.
Create a fresh key in protected custody, project it, verify SecretSynced and
safe version metadata, then roll every API replica. Check `/state/health` and
read-only rename preflight against an approved fixture. Any issued preflight
token remains in protected memory and must be redacted from evidence. Prove
local-fixture signing/verification, tamper rejection, expiry, wrong-key rejection,
and no-key denial; the live probe stops before the rename mutation endpoint.
Check wrong-SA/namespace/audience, sibling KV and coding-agent denial. Retain
only deployment revisions, KV version, boolean outcomes and safe timestamps.
## Rotation, revocation and rollback
Fence new preflight issuance AND rename mutation operations at the API's approved
operational admission boundary, across all replicas, before switching keys.
The current application has no documented rotation fence: the State Hub owner
must supply a concrete ingress/admission or controlled-outage procedure before
rotation is executable. Merely waiting 900 seconds while issuance continues
does not drain old tokens. With issuance stopped, drain the configured maximum
token lifetime, or explicitly invalidate outstanding tokens during a coordinated
cutover. Generate a new KV version, wait for ESO, restart all API replicas, then
verify they use one version and only then reopen operations. A rolling mixture
of old/new single-key processes can reject valid preflights unpredictably.
For compromise, invalidate outstanding preflights immediately and remove old
key-bearing processes; waiting for natural expiry is not revocation. Disabling
ESO alone leaves process memory and K8s copies usable. Forward recovery is
preferred: restoring a compromised old key can revalidate still-live tokens.
For a non-compromise failed deployment, keep operations fenced and restore the
prior chart/key version only with owner approval, then verify all replicas.
Keep protected historical KV versions until the retention decision; no automatic
destroy, provider rename, or weakening of preflight checks is part of this lane.
## Demand review — 2026-09-05
STATE-WP-0085-T09 completed its adoption-plan deliverable on 2026-08-31.
The still-proposed FLEX-WP-0020-T05 cutover carries the signing prerequisite.
State Hub is now explicitly transitional in its INTENT; State Hub/repo-manager
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.