# ops-warden → secrets-engine Routing Contract ops-warden issues **SSH certificates only**. Every other credential or scoped capability need (API keys, provider tokens, DB passwords, npm publish tokens, and OpenBao capability lanes) routes to **secrets-engine**. secrets-engine returns non-secret pointers and safe next commands while OpenBao remains the custody, policy, lease, and audit backend. ops-warden must never request, hold, cache, or vend a raw secret value. A route result is a **pointer**, not a key. ## What ops-warden calls ```bash secrets-engine route --json ``` ## What it returns (the contract) ```json { "catalog_id": "whynot-design-npm-publish", "kind": "kv", "owner": "coulomb/whynot-design", "stage": "prod", "decision_status": "resolved", "decision_ref": "e6381a56-6b04-4fd5-b2de-f3ef59cde888", "review_url": "http://127.0.0.1:8000/decisions/", "metadata_applied": true, "value_present": true, "ready": true, "next_command": "secrets-engine exec --catalog whynot-design-npm-publish -- ", "missing": "" } ``` | Field | Meaning | | --- | --- | | `decision_status` | `resolved`/`approved` => approved; `missing`/`pending` => not yet | | `kind` | `kv` for stored-value lanes, `auth-capability` for policy/AppRole capability lanes | | `metadata_applied` | OpenBao ACL policy + approle exist for the lane | | `value_present` | for `kv`, the secret value has been provisioned (boolean only — value never read); for `auth-capability`, there is no KV value and this is true once metadata is handoff-ready | | `ready` | approved **and** applied **and** provisioned or handoff-ready | | `next_command` | the single safe command the caller should run next | | `missing` | the one human/provisioning step still outstanding | ## Guarantees - **No value crosses this boundary.** `route` reports a boolean `value_present`, derived from a metadata/presence check for KV lanes or from policy/AppRole readiness for auth-capability lanes — it never reads or mints a secret. - **Actionable when not ready.** If a lane is unapproved, unapplied, or unprovisioned, `next_command` + `missing` tell the caller exactly what to do. - **Idempotent / read-only.** `route` performs no mutation. - **Custody stays in OpenBao.** secrets-engine orchestrates approved issuance, delivery, handoff, verification, and revocation paths; it does not make ops-warden a secret store or token broker. ## whynot-design retry flow 1. whynot-design CI needs a publish token → asks ops-warden. 2. ops-warden runs `secrets-engine route whynot-design-npm-publish --json`. 3. If `ready=false`, it surfaces `missing` + `next_command` to the human (e.g. "needs approved decision" or "needs provisioning"). 4. Once `ready=true`, the workload runs `secrets-engine exec --catalog whynot-design-npm-publish -- npm publish`. Safe whynot-design pointer payload for ops-warden: ```json { "catalog_id": "whynot-design-npm-publish", "kind": "kv", "decision_ref": "e6381a56-6b04-4fd5-b2de-f3ef59cde888", "owner": "coulomb/whynot-design", "stage": "prod", "next_command": "secrets-engine exec --catalog whynot-design-npm-publish -- npm publish" } ``` ## warden-sign auth-capability flow 1. ops-warden needs a scoped `VAULT_TOKEN` for the FLEX-WP-0007 T4 smoke. 2. ops-warden runs `secrets-engine route warden-sign --json`. 3. If `ready=false`, it surfaces `missing` + `next_command` to the human. 4. Once `ready=true`, `next_command` points to `secrets-engine handoff ...`; the operator receives `role_id` and `secret_id` out-of-band and performs AppRole login on CoulombCore. 5. State Hub receives only non-secret pointers: addr, mount, policy, AppRole, TTLs, allowed paths, and status. It must not receive `role_id`, `secret_id`, `VAULT_TOKEN`, token accessor, or raw smoke output containing token material. See [warden-sign-auth-capability.md](warden-sign-auth-capability.md). ## Anti-patterns (forbidden) - ops-warden `POST /messages/` asking for `NPM_TOKEN` / `OPENROUTER_API_KEY` / `VAULT_TOKEN`. - Caching `value_present` as if it were the value. - Inventing `warden secret` / `warden bao` — they do not exist.