spec: runbook-pack/v0.2 id: nk.openbao-operating-path title: "OpenBao: consume, attend, recover" owner: net-kingdom outcome: You can reach the already-deployed private OpenBao, know which owner serves a credential, know the custody model and the attended recovery path, and have seen the ceremony-record validator refuse a secret marker. engine: native framing: - Init output, unseal shares and tokens go to the operator's screen only, never to chat, State Hub, logs or a Git checkout. - Never use a public Bao URL; bao.coulomb.social is retired. - Never place the root token and unseal shares in one artifact outside a lab. - This pack never initializes or unseals the live estate. Greenfield deployment is a lab exercise and is not part of it. actors: - id: operator role: Operator description: Reaches OpenBao through the named tunnel with their own identity and reads what they are entitled to. privileges: [open-tunnel, read-routed-secret] datapoints: - id: need label: The credential you need type: text default: read a database password help: Plain words; used only to look up the owner. dimensions: {actor: operator, kind: request, subsystem: ops-warden} ask_in: access - id: tunnel label: OpenBao tunnel type: string default: openbao-ui-railiance01 pattern: "[a-z0-9-]+" help: The named ops-bridge tunnel; never a public Bao URL (bao.coulomb.social is retired). dimensions: {kind: target, subsystem: ops-bridge} ask_in: access - id: record_state label: Has an attended ceremony produced a record yet? type: enum values: [exists, none-yet] default: none-yet help: Decides which way the record step is recommended. Only meaningful after an attended ceremony. dimensions: {kind: state, subsystem: openbao} ask_in: records - id: evidence label: Ceremony record path type: path default: .local/openbao-ceremony-record.json help: Relative to the net-kingdom checkout. dimensions: {kind: location, subsystem: openbao} ask_in: records - id: probe label: Scratch path for the negative probe type: path default: .local/ceremony-negative-probe.json help: Created and removed by the probe step. dimensions: {kind: location, subsystem: openbao} ask_in: records stages: - id: access title: Reach OpenBao goal: You know who owns the credential and the private tunnel to OpenBao is up and healthy. steps: - id: prerequisites title: Confirm the prerequisites actor: operator owner: workstation description: "The bridge CLI and the named tunnel definition (ops-bridge); the warden CLI for credential routing (ops-warden); OpenBao already deployed and private (railiance-platform); a net-kingdom checkout, because commands run from its root (net-kingdom)." idempotent: idempotent verify: done_when: All four prerequisites hold expect: manual - id: route title: Find who owns the credential actor: operator owner: ops-warden requires: [prerequisites] uses: [need] command: warden route find "{{need}}" --json | head -30 idempotent: idempotent evidence: [owner_repo] verify: done_when: You know which repository owns the credential and that warden only routes, it does not vend expect: manual - id: tunnel-status title: Check the OpenBao tunnel is connected actor: operator owner: ops-bridge requires: [route] uses: [tunnel] command: bridge status idempotent: idempotent verify: done_when: The tunnel row shows connected command: bridge status | grep -E "{{tunnel}} +connected" expect: exit-0 - id: tunnel-check title: Run the end-to-end tunnel diagnostic actor: operator owner: ops-bridge requires: [tunnel-status] uses: [tunnel] command: bridge check {{tunnel}} idempotent: idempotent verify: done_when: The diagnostic passes command: bridge check {{tunnel}} expect: exit-0 gates: - id: access-ready title: OpenBao is reachable over its private tunnel goal: private-access blocking: true downstream_risk: Reading secrets over an unhealthy or public path would put values where they must not go. checks: - done_when: The tunnel shows connected command: bridge status | grep -E "{{tunnel}} +connected" expect: exit-0 - done_when: The end-to-end diagnostic passes command: bridge check {{tunnel}} expect: exit-0 - id: custody title: Know the custody goal: You know the unseal custody model in force and the attended recovery path. requires: [access] steps: - id: custody-models title: See the unseal custody models actor: operator owner: net-kingdom command: python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-unseal-custody-models idempotent: idempotent verify: done_when: attended-ceremony is listed as implemented command: python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-unseal-custody-models | grep -q attended-ceremony expect: exit-0 - id: console-gates title: Read the custody gates for the selected model actor: operator owner: net-kingdom requires: [custody-models] command: make security-bootstrap-console idempotent: idempotent verify: done_when: You have read every gate and know which are met and which are not expect: manual - id: recovery-read title: Read the attended recovery path actor: operator owner: net-kingdom requires: [console-gates] command: sed -n 1,82p docs/openbao-attended-ceremony-runbook.md idempotent: idempotent verify: done_when: You can state who must be present, where each unseal share goes, and when the root token is revoked expect: manual gates: - id: custody-understood title: The custody path is understood goal: attended-custody blocking: true checks: - done_when: You can name the custody model, who must be present at a ceremony, and where each unseal share goes expect: manual - id: records title: The evidence rules goal: You have seen the ceremony-record validator refuse a secret marker, and know where a real record stands. requires: [custody] steps: - id: probe-refused title: Watch the ceremony-record validator refuse a secret marker actor: operator owner: net-kingdom uses: [probe] description: Writes a scratch file holding a fake token-shaped marker, runs the validator on it, and removes the file. The marker is assembled at run time so this pack never contains one. command: | printf '{"note":"%s%s"}\n' hvs. AAAAAAAAAAAAAAAA > {{probe}} make security-bootstrap-validate-openbao-ceremony-record EVIDENCE={{probe}} 2>&1 | grep "secret-looking marker present" rm -f {{probe}} idempotent: idempotent idempotent_note: Writes a scratch file and removes it in the same command. rollback: rm -f the probe file; nothing else is written. verify: done_when: The validator names a secret-looking marker as a reason for refusal command: | printf '{"note":"%s%s"}\n' hvs. AAAAAAAAAAAAAAAA > {{probe}} make security-bootstrap-validate-openbao-ceremony-record EVIDENCE={{probe}} 2>&1 | grep -q "secret-looking marker present" r=$? rm -f {{probe}} exit $r expect: exit-0 - id: ceremony-record title: Look at the ceremony record actor: operator owner: net-kingdom requires: [probe-refused] uses: [record_state, evidence] description: A real record exists only after an attended ceremony. Choose the way that matches where you are; the recommended one follows the answer you gave. idempotent: idempotent one_of: - id: validate-record title: Validate the real ceremony record recommended_when: {record_state: [exists]} command: make security-bootstrap-validate-openbao-ceremony-record EVIDENCE={{evidence}} verify: done_when: The validator passes on the ceremony record command: make security-bootstrap-validate-openbao-ceremony-record EVIDENCE={{evidence}} expect: exit-0 - id: no-record-yet title: No ceremony has been held yet recommended_when: {record_state: [none-yet]} verify: done_when: You know that no attended ceremony has produced a record, so there is nothing to validate yet expect: manual gates: - id: evidence-rules-seen title: The evidence rules are understood goal: no-secrets-in-evidence blocking: true checks: - done_when: The validator refused a secret-looking marker, and you know where a real record stands expect: manual - id: use title: Read one secret goal: You read one secret you are entitled to, from the path routing named, with your own identity. requires: ["gate:access-ready", records] steps: - id: read-secret title: Read one secret you are entitled to actor: operator owner: railiance-platform auto_confirm: manual-only description: Authenticate with your own identity and read only the path the routing result names, following railiance-platform/docs/openbao.md. Never paste the value anywhere. idempotent: idempotent rollback: Close the session; the read changes no state. If a value was exposed, treat it as compromised and rotate it through its owner. verify: done_when: You read only the routed path with your own identity and no value was pasted into chat, logs, State Hub or a checkout expect: manual ownership: - {concern: "OpenBao deployment, configuration and unseal execution", owner: railiance-platform} - {concern: Custody canon and the ceremony-record validator, owner: net-kingdom} - {concern: Tunnel, owner: ops-bridge} - {concern: Credential routing, owner: ops-warden}