--- id: RAILIANCE-WP-0011 type: workplan title: "reuse-surface Runtime Secrets OpenBao Lane" domain: financials repo: railiance-platform status: finished owner: codex topic_slug: railiance created: "2026-07-07" updated: "2026-07-07" depends_on_workplans: - RAILIANCE-WP-0007 - RAILIANCE-WP-0008 related_repos: - railiance-apps - reuse-surface - ops-warden state_hub_workstream_id: "3f9fd8de-7235-4486-aaa7-634dba2bb6fa" --- # RAILIANCE-WP-0011 — reuse-surface Runtime Secrets OpenBao Lane ## Goal Promote reuse-surface hub runtime secrets from bootstrap Kubernetes Secret custody to a reviewed OpenBao workload KV lane delivered by External Secrets Operator, matching the platform pattern used by issue-core, OpenRouter, and Forgejo mailer. Today both secrets live in `reuse/reuse-surface-env` on Railiance01: | Field | Consumer | | --- | --- | | `REUSE_SURFACE_TOKEN` | Hub write API; operators via `warden access` / kubectl | | `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` | Hub webhook receiver; Forgejo org webhook HMAC | Functional custody in K8s is sufficient for production today (live since 2026-07-07). This workplan is **hygiene and standardization**, not a blocker. No task may paste, commit, log, or send secret values through Git, State Hub, chat, prompts, shell history, or workplan text. ## Proposed contract | Item | Proposed value | | --- | --- | | CCR | `CCR-2026-0005` | | Tenant/org | `reuse` | | Workload | `reuse-surface` | | KV mount | `platform` | | OpenBao CLI path | `platform/workloads/reuse/reuse-surface/runtime-secrets` | | Secret fields | `REUSE_SURFACE_TOKEN`, `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` | | Read policy | `workload-kv-read-reuse-surface-runtime` (name TBD at CCR) | | K8s auth role | `external-secrets-reuse-surface` (name TBD at CCR) | | ExternalSecret | `reuse/reuse-surface-runtime` → target Secret `reuse-surface-env` | | ops-warden catalog | migrate `reuse-surface-hub-write-token` handoff to Bao path | Dual-consumer note: Forgejo org webhook must be updated whenever the webhook HMAC rotates — document in `railiance-apps/docs/reuse-surface-on-railiance01.md` and keep `make reuse-forgejo-webhook` idempotent. ## Draft OpenBao + ESO Lane ```task id: RAILIANCE-WP-0011-T01 status: done priority: medium state_hub_task_id: "8a89c5a0-6ed5-4240-9ce1-1d529ac13b11" ``` - Draft CCR for the lane (path, fields, policy, k8s role, ESO target) - Align with `docs/openbao.md` path convention and `docs/credential-lane-lifecycle-runbook.md` - Negative review: no secret values in CCR or workplan text **2026-07-07:** Drafted `CCR-2026-0005` and policy `openbao/policies/workload-kv-read-reuse-surface-runtime.hcl`. Metadata review confirms Railiance01 `reuse/reuse-surface-env` (two fields), ESO operator SA, and forgejo-style interim ClusterSecretStore delivery. CCR remains `proposed`; T02 blocked on platform-operator and reuse-surface-owner approval. ## Platform Apply And Verification ```task id: RAILIANCE-WP-0011-T02 status: done priority: medium state_hub_task_id: "69cf1728-8034-4309-b8ad-eb14184af6b6" ``` Blocked on CCR-2026-0005 approval. - Apply OpenBao policy + Kubernetes auth role (mirror forgejo-mailer / issue-core scripts) - Seed path from existing cluster Secret (one-time operator step; value never logged) - Add `manifests/reuse-surface-runtime-externalsecret.yaml` in `railiance-apps` - Verify ExternalSecret `SecretSynced` and pod env injection after rollout - Record non-secret audit evidence (positive + negative reads) **2026-07-07:** CCR-2026-0005 approved; delegated metadata apply recorded; KV path seeded (version 1); `openbao-reuse` ClusterSecretStore + `reuse-surface-runtime` ExternalSecret live on Railiance01 (`SecretSynced` 2026-07-07T20:33:17Z). Positive: `/v1/federated` 200, signed webhook 200. Negative: default-policy token denied on path. CCR status `verified`. T03 catalog migration remains open. ## Consumer Handoff And Catalog Migration ```task id: RAILIANCE-WP-0011-T03 status: done priority: low state_hub_task_id: "52fc7baf-5257-44cd-ae2c-298ef7edbe96" ``` Blocked on T02 verification. - Update `railiance-apps/docs/reuse-surface-on-railiance01.md` custody section - Update ops-warden `reuse-surface-hub-write-token` playbook + routing catalog (`fetch_command` → `bao kv get -field=...`) - Add lane to `docs/workload-kv-access-lanes.md` - Deprecate direct kubectl fetch as primary handoff (keep as break-glass note) **2026-07-07:** ops-warden catalog `reuse-surface-hub-write-token` migrated to `bao kv get -field=REUSE_SURFACE_TOKEN platform/workloads/reuse/reuse-surface/runtime-secrets` (owner `railiance-platform`, `resolvable=true`). Playbook, CredentialRouting index, `docs/workload-kv-access-lanes.md`, and railiance-apps export handoff updated; kubectl documented as break-glass only. CCR-2026-0005 front door `ready`/`resolvable=true`. ## Forgejo Webhook Rotation Runbook ```task id: RAILIANCE-WP-0011-T04 status: done priority: low state_hub_task_id: "eafc4011-69cf-473f-842c-c58d6a2bece7" ``` Blocked on T03. - Document rotation: update OpenBao field → ESO sync → rollout → `make reuse-forgejo-webhook` (updates org hook secret) - Add smoke: signed webhook POST returns 200/accepted or expected no-op **2026-07-07:** Added `docs/reuse-surface-runtime-secrets-rotation-runbook.md`, CCR-2026-0005 lane in `docs/credential-lane-lifecycle-runbook.md`, and `railiance-apps` `make reuse-webhook-smoke` (unsigned 401, signed no-op 200, ESO Ready, `/v1/federated`). Live smoke passed on production. ## Acceptance - [x] Both fields readable from `platform/workloads/reuse/reuse-surface/runtime-secrets` - [x] ESO owns `reuse-surface-env`; manual `kubectl create secret` no longer required for steady state - [x] `warden access reuse-surface-hub-write-token --fetch` uses OpenBao path - [x] Forgejo org webhook and hub HMAC aligned (smoke verifies signed/unsigned paths; rotation runbook documents reconcile step)