--- id: WARDEN-WP-0016 type: workplan title: "ops-bridge cert_command pilot — readiness gate + handoff" domain: infotech repo: ops-warden status: finished owner: claude topic_slug: custodian planning_priority: high planning_order: 16 created: "2026-06-27" updated: "2026-06-27" state_hub_workstream_id: "a56da8db-38bc-4bbe-8671-823360ec9245" --- # WARDEN-WP-0016 — ops-bridge cert_command pilot (readiness gate + handoff) **Scope:** Close ops-warden's side of the last **Partial** INTENT criterion — *"ops-bridge integrates via a stable `cert_command`"*. The migration playbook (`wiki/playbooks/ops-bridge-tunnel-cert.md`, WP-0013) and the `cert_command` contract (`wiki/CertCommandInterface.md`) already exist, but the pilot has never been run because the readiness checks are scattered manual checkboxes across three owners (ops-warden, ops-bridge, railiance-infra). This WP ships the **automated readiness gate** an operator runs *before* touching tunnel config, plus an offline `cert_command` contract smoke, and hands the verified pilot to ops-bridge. **Boundary (unchanged):** ops-warden issues certs and verifies its own side is ready. The **live tunnel cutover is ops-bridge's to execute** — this WP does not (cannot) flip a running tunnel. "Done" here means *pilot-ready and handed off*, not *tunnel migrated*. **Out of scope:** editing `~/.config/bridge/tunnels.yaml` (ops-bridge owns it); deploying host principals (railiance-infra); requiring a live OpenBao token for the contract smoke (use the local backend). **Depends on:** WP-0013 (playbook + contract), the SSH lane (prod-verified). --- ## Tasks ### T1 — Read-only `cert_command` readiness preflight ```task id: WARDEN-WP-0016-T01 status: done priority: high state_hub_task_id: "fea84495-dbec-480a-b42b-90e39f414b78" ``` - [x] `scripts/check_tunnel_cert_readiness.py` — given `--actor`, `--pubkey`, `--config` (warden.yaml) and optional `--infra` (ssh_principals.yaml), asserts the cert_command path is ready **without signing anything**: config loads + backend known; actor in inventory with a valid type + TTL within the type max; pubkey file exists, parses, and is not a private key; actor principals present; (optional) principals deployed in the infra file (mirrors `check_principals_drift._infra_principals`). Exit 0/1/2. - [x] Checklist-style report (✓/✗/·); never prints a private key or token. - [x] Tests: `tests/test_tunnel_cert_readiness.py` (ready, unknown actor, missing/private pubkey, infra present/missing, TTL-over-max, cert_command string). 9 unit cases. ### T2 — Offline cert_command contract smoke ```task id: WARDEN-WP-0016-T02 status: done priority: medium state_hub_task_id: "e34ae1a8-2ba9-4324-8d1a-005d61dae478" ``` - [x] Opt-in `--sign-smoke` mode runs the actual `cert_command` against the **local** backend and validates the emitted cert: identity matches the actor, principals match inventory, validity window within the type's max TTL. Refuses a vault backend (must be offline). Proves the contract end to end with no live OpenBao. - [x] Window measured from the cert's own `valid_from`→`valid_before` (via `parse_cert_metadata`) so it is timezone-robust — fixes a CEST off-by-2h artifact where local-time ssh-keygen output was read as UTC. - [x] `integration`-marked test (needs `ssh-keygen`, skipped in the default suite) plus a non-integration test that `--sign-smoke` refuses a vault backend. ### T3 — Playbook gate + ops-bridge handoff ```task id: WARDEN-WP-0016-T03 status: done priority: medium state_hub_task_id: "330e01f4-4927-4280-b0e0-49d35b4416d6" ``` - [x] `wiki/playbooks/ops-bridge-tunnel-cert.md` now leads with **Step 0 — Readiness gate** (the exact `check_tunnel_cert_readiness.py` invocation + `--sign-smoke` note); the manual checklist remains as the human-readable backing. - [x] Sent ops-bridge the coordination handoff (pilot `agt-state-hub-bridge`, the readiness-gate command, and the cutover steps ops-bridge owns). ### T4 — INTENT/SCOPE alignment ```task id: WARDEN-WP-0016-T04 status: done priority: low state_hub_task_id: "4726f5bb-4ffd-484f-8674-91ee5658434f" ``` - [x] SCOPE: INTENT gap row moved from "Partial — tunnels still static-key" to "Pilot-ready — readiness gate shipped; live cutover handed to ops-bridge"; known-gaps row updated; readiness script added to the implemented SSH-lane list. --- ## Acceptance - `scripts/check_tunnel_cert_readiness.py` gates the pilot read-only and is tested. - The offline contract smoke validates a real cert against the local backend. - The playbook leads with the automated gate; ops-bridge has the handoff with exact steps. - No secret material in any script, test, doc, or log. ops-warden's boundary is intact: it verifies and hands off; ops-bridge executes the cutover. --- ## See also - `wiki/playbooks/ops-bridge-tunnel-cert.md`, `wiki/CertCommandInterface.md` - `scripts/check_principals_drift.py` (reused helpers) - `history/2026-06-24-intent-scope-gap-analysis.md`