# OpenBao Attended Ceremony Runbook Date: 2026-07-02 Status: active — production custody model (`attended-ceremony`, NET-WP-0020 T3) Human-attended OpenBao init/unseal for production trust posture. The security bootstrap console **never runs `bao operator init`** (refuse-live-init boundary) — this runbook is executed by the `openbao-ceremony-operator` role and evidenced by a **non-secret** ceremony record. Contrast with `sops-held-automation` (lab posture): there, root token and unseal shares live together in one SOPS bundle for unattended rebuild loops. The attended ceremony keeps unseal shares **out of band** and retires the root token, so no single artifact can open the platform. --- ## Preconditions 1. Console gates green up to the init ceremony: `make security-bootstrap-console` — custody strategy approved, preflight passed. 2. Select profile and model (production blocks the lab default): ```bash python3 tools/security-bootstrap-console/security_bootstrap_console.py \ --metadata .local/security-bootstrap.json \ select-deployment-profile --profile production python3 tools/security-bootstrap-console/security_bootstrap_console.py \ --metadata .local/security-bootstrap.json \ select-openbao-unseal-custody-model --model attended-ceremony ``` 3. OpenBao deployed and reachable: `make -C ../railiance-platform openbao-status` (expect uninitialized/sealed on greenfield). 4. Two people present (operator + witness) where the custody roster requires it; unseal-share escrow destinations agreed per `docs/platform-root-custody.md` (signed custody roster). ## Ceremony Follow `railiance-platform/docs/openbao.md` for the exact commands. Outline: 1. **Init** — operator runs `bao operator init` (3 shares, threshold 2) directly against the pod from a terminal. Output goes only to the operator's screen — never into the console, chat, State Hub, or files inside a Git checkout. 2. **Escrow** — each unseal share is transcribed to its escrow destination (offline packet / password safe per roster). No two shares in the same custody location. 3. **Unseal** — replay threshold shares; verify `initialized=true sealed=false`. 4. **Root retirement** — use the root token only for the initial configuration handoff (`make -C ../railiance-platform openbao-configure-initial`), then revoke it (`bao token revoke -self`) or escrow it per roster; record the disposition. ## Evidence Record the ceremony in a non-secret JSON record and validate it: ```bash python3 tools/security-bootstrap-console/security_bootstrap_console.py \ openbao-ceremony-record-template > .local/openbao-ceremony-record.json # edit: dispositions, dates, roles — NEVER shares, tokens, or key material make security-bootstrap-validate-openbao-ceremony-record ``` The validator refuses records containing secret-looking markers (tokens, key blocks, otpauth URIs) or leftover template placeholders. After a valid record, set the console flags (`openbao_initialized`, `openbao_post_unseal_verified`) in the metadata so the gates advance. ## Related - `docs/openbao-unseal-custody-models.md` — model framework - `docs/platform-root-custody.md` — custody roster and share holders - `docs/security-bootstrap-openbao-ceremony-ux.md` — operator UX notes - `railiance-platform/docs/openbao.md` — deploy + command-level ceremony