--- id: RAILIANCE-WP-0006 type: workplan title: "Workload KV Access Lanes for ops-warden Fetch" domain: financials repo: railiance-platform status: active owner: codex topic_slug: railiance planning_priority: high planning_order: 6 created: "2026-06-27" updated: "2026-06-28" depends_on_workplans: - RAIL-PL-WP-0002 - RAILIANCE-WP-0004 related_state_hub_messages: - "551031d1-335e-4db8-9535-820fea52d0a3" state_hub_workstream_id: "96c8a93d-7a5a-4fa9-8f7b-865119551da3" --- # RAILIANCE-WP-0006 - Workload KV Access Lanes for ops-warden Fetch ## Goal Provision concrete, least-privilege OpenBao workload KV read lanes that `ops-warden` can expose through `warden access --fetch` / `--exec` without holding secret values itself. The immediate request is for `whynot-design` to retrieve its npm publish token. The path must be concrete, policy-scoped, and documented so the ops-warden catalog can replace the current unresolved template path with a live `whynot-design-npm-publish` entry. No task in this workplan may paste, commit, log, or send secret values through Git, State Hub, chat, prompts, or workplan text. ## Requirements Reviewed Ops-warden message `551031d1-335e-4db8-9535-820fea52d0a3` asks `railiance-platform` to provide non-secret pointers for: - a concrete OpenBao KV path and field for `NPM_AUTH_TOKEN`; - the KV mount used by the path; - the OIDC login role for whynot-design or its operator identity; - a read policy scoped to whynot-design's identity/service account; - the flex-auth policy reference, if pre-approval is required. Once these pointers are live, ops-warden will add a dedicated `whynot-design-npm-publish` access catalog entry and a playbook, then notify whynot-design. ## Proposed Contract Use the workload credential convention documented in `docs/openbao.md`: ```text platform/workloads/// ``` For this lane, the proposed non-secret contract is: | Item | Proposed value | | --- | --- | | KV mount | `platform` | | Tenant/org | `coulomb` | | Workload/project | `whynot-design` | | CLI path | `platform/workloads/coulomb/whynot-design/npm-publish` | | KV-v2 policy data path | `platform/data/workloads/coulomb/whynot-design/npm-publish` | | KV-v2 policy metadata path | `platform/metadata/workloads/coulomb/whynot-design/npm-publish` | | Secret field | `NPM_AUTH_TOKEN` | | OpenBao read policy | `workload-kv-read-whynot-design-npm-publish` | | OIDC auth mount | `netkingdom` unless KeyCape compatibility requires `keycape` | | OIDC role | `whynot-design-workload-kv-read` | | Kubernetes auth role | `whynot-design-workload-kv-read` if an in-cluster service account consumes it | | flex-auth ref | `secret.read:whynot-design` if tenant policy requires pre-approval | The expected caller-facing read shape is: ```bash bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read bao kv get -field=NPM_AUTH_TOKEN platform/workloads/coulomb/whynot-design/npm-publish ``` The command shape is illustrative only. Verification must avoid printing the secret value; use attended operator checks or commands that prove read access without persisting the token in logs. ## Tasks ## T01 - Capture ops-warden request and path contract ```task id: RAILIANCE-WP-0006-T01 status: done priority: high state_hub_task_id: "0c93496a-48bf-44e7-a75b-52e51e2639bc" ``` Record the ops-warden request, existing workload path convention, and proposed whynot-design contract in this workplan. Acceptance: - The workplan names the concrete path, field, mount, policy, auth role, and optional flex-auth ref needed by ops-warden. - The plan distinguishes non-secret pointers from secret values. - The plan keeps this workload KV read lane separate from `RAILIANCE-WP-0005`, which tracks short-lived OpenBao token issuance for the ops-warden signing smoke. **2026-06-27:** Reviewed the unread ops-warden request and existing `platform/workloads///` convention. Captured the proposed `whynot-design` npm publish lane above with no secret values. ## T02 - Add least-privilege OpenBao read policy ```task id: RAILIANCE-WP-0006-T02 status: done priority: high state_hub_task_id: "9c06d531-2566-4767-aa2f-8339605f23d5" ``` Create a concrete policy artifact for the whynot-design npm publish lane, derived from `openbao/policies/workload-kv-read-template.hcl` but narrowed to the selected `npm-publish` path. Acceptance: - A policy file under `openbao/policies/` defines read access to the exact `platform/data/workloads/coulomb/whynot-design/npm-publish` path. - Metadata/list capabilities are only as broad as needed for the caller and ops-warden fetch UX. - The policy grants no write, delete, patch, sudo, auth, or unrelated workload capabilities. - The policy name matches the pointer intended for ops-warden: `workload-kv-read-whynot-design-npm-publish`. **2026-06-27:** Added the concrete policy artifact at `openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl`. It grants only `read` on the exact KV-v2 data and metadata paths for `platform/workloads/coulomb/whynot-design/npm-publish`; it does not grant write/delete/list/sudo/auth or sibling workload access. Added `scripts/openbao-apply-workload-kv-lanes.sh`, `make openbao-workload-kv-lanes-dry-run`, and `make openbao-configure-workload-kv-lanes` for the source-owned policy apply step. Dry-run passed. A live apply attempt with `OPENBAO_WORKLOAD_KV_ARGS=--use-token-helper` reached unsealed OpenBao but was denied with `403 permission denied` while writing the policy, so live policy application waits on an approved platform-admin/operator token or a narrow token-helper capability. **2026-06-28:** Using the temporary operator token provided outside the repo, Codex applied/confirmed the live policy in OpenBao. The verification read of the policy succeeded and no secret values were printed or recorded. ## T03 - Define and apply auth bindings ```task id: RAILIANCE-WP-0006-T03 status: done priority: high state_hub_task_id: "a217371a-0f85-40c6-b691-ac67834c86b5" ``` Define the auth role that lets whynot-design or an approved operator identity read the lane as itself. Acceptance: - The OIDC login role is documented as `bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read`, or a different approved role is recorded with the reason. - The role attaches only the whynot-design npm publish read policy. - If an in-cluster whynot-design service account consumes the token, the Kubernetes auth role binds only the approved namespace and service account. - Compatibility with the legacy `keycape` auth mount is either configured or explicitly declined. **2026-06-27:** Documented the intended OIDC role pointer as `auth/netkingdom/role/whynot-design-workload-kv-read` in `docs/workload-kv-access-lanes.md`. Live application is waiting on confirmation of the KeyCape/NetKingdom whynot-design bound claim or approved service-account subject; do not create an unbounded OIDC role. **2026-06-28:** Created/confirmed `auth/netkingdom/role/whynot-design-workload-kv-read` with `groups=["whynot-design"]`, only the `workload-kv-read-whynot-design-npm-publish` policy, `ttl=15m`, and the approved browser/local CLI callback URIs. **2026-06-28:** Positive verification found the OIDC role was missing `oidc_scopes`, causing OpenBao login to fail with `groups claim not found`. Updated the live role and source CCR to request `openid`, `profile`, `email`, and `groups`, matching the platform-admin OIDC scope shape. ## T04 - Provision the KV path without exposing the token ```task id: RAILIANCE-WP-0006-T04 status: done priority: high state_hub_task_id: "c43724a3-c83e-4ab6-b7d1-e427fd93a9a9" ``` Have an approved operator create or confirm the OpenBao KV entry for the npm publish token. Acceptance: - The path exists at `platform/workloads/coulomb/whynot-design/npm-publish`. - The field is named exactly `NPM_AUTH_TOKEN`. - The token value is entered through an approved operator/OpenBao path and is never written to Git, State Hub, chat, prompts, shell history, or workplan text. - Non-secret evidence records only the path, field name, actor, timestamp, policy name, and verification result. **2026-06-27:** The concrete path and field are now documented. Live secret provisioning is waiting on an approved operator/OpenBao custody path for the actual `NPM_AUTH_TOKEN` value. **2026-06-28:** Confirmed the OpenBao metadata at `platform/workloads/coulomb/whynot-design/npm-publish` includes `catalog-id=whynot-design-npm-publish` and that the `NPM_AUTH_TOKEN` field is present. The value was not printed, recorded, or copied into Git, State Hub, chat, or workplans. ## T05 - Verify caller-scoped fetch behavior ```task id: RAILIANCE-WP-0006-T05 status: progress priority: high state_hub_task_id: "dc1f470b-e78a-48a9-9957-965aed47861f" ``` Prove that the authorized identity can read the token through the intended OpenBao path and that unauthorized identities cannot. Acceptance: - An approved whynot-design identity or operator role can authenticate and perform the fetch without unresolved `<...>` placeholders. - Negative verification shows a non-whynot identity cannot read the path. - Verification output contains no token value. - OpenBao audit evidence exists for the authorized read and denied read, with only non-secret request ids/timestamps recorded in the workplan or State Hub. **2026-06-27:** Verification is waiting on live policy/role application and secret provisioning. The runbook requires positive and negative fetch evidence without printing the token value. **2026-06-28:** Non-secret operator checks now pass for policy, auth role, metadata, and field presence. Remaining verification is the attended whynot-design OIDC positive check and a non-whynot denial check, both without printing the token. ## T06 - Coordinate ops-warden catalog activation ```task id: RAILIANCE-WP-0006-T06 status: progress priority: high state_hub_task_id: "8e84ec19-01db-4baf-a532-de87e51d4994" ``` Send ops-warden the non-secret pointers needed to create and activate its dedicated access catalog entry. Acceptance: - The State Hub reply to ops-warden includes only path, field, KV mount, OIDC role, policy name/path, optional flex-auth ref, and runbook location. - Ops-warden confirms the `whynot-design-npm-publish` catalog entry no longer contains unresolved placeholders. - `warden access "npm auth token" --fetch` or the agreed exact selector resolves to the whynot-design lane and proxies the read as the caller. - ops-warden confirms it holds no token value and only proxies OpenBao access. **2026-06-27:** Added `docs/workload-kv-access-lanes.md` with the non-secret handoff payload for ops-warden and sent the pointers by State Hub message. The entry should remain draft/non-active until live OpenBao provisioning and verification complete. **2026-06-28:** The generic `openbao-api-key` ops-warden access lane can proxy the check with explicit `--path` and `--field`, but the dedicated `whynot-design-npm-publish` route is not yet present in the ops-warden routing catalog. Keep activation pending until caller verification and catalog update. ## T07 - Decide whether to batch sibling workload-KV requests ```task id: RAILIANCE-WP-0006-T07 status: done priority: medium state_hub_task_id: "0b3ab5f5-e933-41f2-b29a-ab4ac50593aa" ``` Ops-warden noted similar still-open access lanes for `issue-core-ingestion-api-key` and `openrouter-llm-connect`. Decide whether to batch those paths in the same provisioning pass or keep this workplan scoped to whynot-design. Acceptance: - The decision is recorded without secret values. - If batching is approved, add concrete sub-tasks or a follow-up workplan for each additional lane. - If batching is deferred, notify ops-warden that this workplan will deliver whynot-design first and leave the sibling entries for separate planning. **2026-06-27:** Initially deferred sibling lanes (`issue-core-ingestion-api-key` and `openrouter-llm-connect`) so the whynot-design npm token request could be serviced first. The later ops-warden batch follow-up is now represented as proposed CCRs in `RAILIANCE-WP-0007`, still unapproved and unresolvable until human review and verification. ## Exit Criteria - The whynot-design npm publish token has a concrete OpenBao KV path, field, read policy, and auth role. - The authorized caller can fetch the token as itself through OpenBao and ops-warden without ops-warden storing the value. - Unauthorized reads are denied. - ops-warden has enough non-secret pointers to activate `whynot-design-npm-publish`. - No secret values appear in Git, State Hub, chat, prompts, logs, or workplans.