runbook-tutorials/docs/console-mapping.md

110 lines
9.2 KiB
Markdown
Raw Permalink Normal View History

# Is v0.2 expressive enough? Mapping the security bootstrap console
Status: analysis, 2026-09-29 (RBT-WP-0009-T05; closes RBT-WP-0005-T03).
The plan for adopting `runbook-pack/v0.2` said: use the NetKingdom security bootstrap console
(`net-kingdom/tools/security-bootstrap-console/`, 5,300 lines, invented in NET-WP-0016) as the first real test. If the model
can express its stages, gates and runbooks without special cases, it is expressive enough. This is that test, done from the
console's own definitions (read from its running `/api/status` and its source, against a throwaway metadata file).
## Verdict
**The structure maps; the behaviour does not fully.** v0.2 expresses the console's stages, gates, actors, dimensions, artefacts,
evidence validators, typed approval and alternatives. It does not yet express five behaviours the console relies on: conditional
applicability, re-evaluation of gates that can regress, outputs of one member feeding the next, local-only attributes, and
gates satisfied by an automation path. So v0.2 is adequate for **procedures** (every runbook in the console, and the three
NetKingdom packs) and **not yet proven adequate for a long-lived staged bootstrap** as a whole. Decision: the console stays a permanent
legacy pack (RBT-WP-0005-T05); extracting its engine parts (T04) is moved to the backlog until the gaps below are closed.
## What the console contains
| Element | Count | Notes |
| --- | --- | --- |
| Stages | 6 | S1 Low-trust assembly, S2 King credential preparation, S3 OpenBao bootstrap, S4 Admin identity integration, S5 Cleanup and hardening, S6 Reopen under custody |
| Top-level gates | 14 | statuses `done`, `blocked`, `human`, `automation` |
| Sub-checklists | 11 + 4 + 4 | king-credential kit items, key-custody items, admin-identity integrations |
| Section statuses | 9 | view-level completeness of the UI's own sections, not gates |
| Roles | 6 | setup-operator, platform-root-custodian, identity-admin, openbao-ceremony-operator, recovery-custodian, future-quorum-custodian; each with a designated contact |
| Subsystems, integrations | 6 + 6 | LLDAP, privacyIDEA, KeyCape, OpenBao, custodian age envelope, bootstrap bundle |
| Runbooks | 7 | all `template` state; 23 copyable command blocks in total |
| Artefacts | 12 | references only (a password-safe entry, an age key location, unseal shares held elsewhere); states nil, set, ok |
| Approval | 1 | typed phrase `approve custody mode`, two approvable modes |
## How the console works, which decides the mapping
1. **A persistent fact document** (`.local/security-bootstrap.json`, flat keys such as `openbao_initialized`). It lives for weeks.
2. **The stage is derived from the facts** (`derive_stage`: the most advanced fact wins), not from stepping through a list.
3. **Gates are computed on every view**, from the facts and from live probes (files present, a Secret deployed in the cluster). A gate can go
back from done to blocked when the system changes.
4. **Gate status is a small vocabulary**: `done`; `blocked` (a precondition is missing); `human` (ready, waiting for a person);
`automation` (satisfied by an unattended path, for example the SOPS-held init).
5. **Applicability depends on choices**: the unseal custody model (sops-held, attended ceremony, auto-unseal) changes which init gate
applies, and the production profile forbids one of them.
## The 14 gates
| # | Gate | Stage (proposed) | v0.2 form | Verdict |
| --- | --- | --- | --- | --- |
| 1 | King credential kit | S2 | gate `datapoints_ok` over the 11 kit items (datapoints, confirmed by steps) | direct |
| 2 | Custody strategy approval | S2 | irreversible step with `confirm_phrase: approve custody mode`; gate on the `custody_mode` datapoint | **caveat G4**: only some modes may approve live init; needs a value predicate, or an enum limited to the approvable modes |
| 3 | OpenBao preflight | S3 | gate check `command`, exit 0 (`make ... openbao-status`) | direct |
| 4 | OpenBao unseal custody model | S3 | enum datapoint `custody_model`; the production profile blocks one value | **caveat G4** (cross-datapoint rule) and G1 |
| 5 | OpenBao init ceremony | S3 | step with alternatives (attended ceremony / automated init), recommended by `custody_model` | alternatives fit, but the automated path is executed by a script: **needs execution (G6)**, and refusing live init under some profiles is G1 |
| 6 | OpenBao initial configuration | S3 | step, then gate on an evidence datapoint | direct |
| 7 | KeyCape OpenBao client definition | S4 | gate check `command` probing the source | direct; **G3** (recheck) |
| 8 | KeyCape OpenBao client deployed | S4 | gate check `command` probing the live Secret | direct; **G3** |
| 9 | OpenBao OIDC auth | S4 | step plus evidence datapoint | direct |
| 10 | OIDC admin login | S4 | manual check (a browser login through KeyCape and MFA), plus a claims check by command | direct |
| 11 | Root-token disposition | S5 | enum datapoint limited to `revoked` and `offline-sealed`; gate `datapoints_ok` | direct |
| 12 | Restore drill | S5 | a separate pack (7 command blocks, evidence validator); gate check runs the validator | **caveat**: needs a dependency between runbooks (`requires_packs`, RBT-WP-0006-T04), or the drill inlined |
| 13 | Cleanup and rotation | S5 | gate with several manual checks | direct |
| 14 | Platform reopen | S6 | gate check by the custodian actor, with an irreversible confirmation | direct |
**Ten map directly, three with a caveat, one needs execution.** The console does not tie gates to stages explicitly; v0.2 does, which is
the improvement asked for in the UX review (each gate belongs to one stage and names its quality goal). The sub-checklists map to
datapoints and steps in the stage they belong to.
## The rest of the model
| Console | v0.2 | Fit |
| --- | --- | --- |
| Stages S1 to S6 | `stages`, completion derived from members | good; order by `requires` |
| Roles with designated contacts | `actors`, plus a datapoint per contact carrying the `actor` dimension | good; see G5 for the contacts |
| Subsystems | the `subsystem` dimension on datapoints | good; the data view already groups by it |
| Artefacts (nil, set, ok) | `artefacts` with a location datapoint | good; artefact state is derived from the location datapoint |
| The 7 runbooks | 7 native packs | good and independent of the gaps: each is a linear procedure with commands |
| The 23 command blocks | step commands; the interactive `read -rs` prompts stay operator-run | good; nothing secret is ever entered into the engine |
| Typed approval phrase | `confirm_phrase` on an irreversible step | good |
| Evidence validators (`validate-*`) | gate or step checks by `command`, exit 0 | good |
| Copyable command blocks, next action | the guided flow | the new UI does both |
## The gaps
These are candidates for a v0.3. None blocks closing the runbook-tutorials workplans, and none affects the procedures that exist today.
- **G1 Conditional applicability.** Stages, steps and gates that apply only for some choices (`applies_when` on a datapoint value). `one_of`
chooses between alternatives inside a step; it cannot switch a whole gate on or off.
- **G2 A longer horizon.** A run untouched for seven days counts as abandoned. A multi-week ceremony needs a per-pack (or per-run) horizon.
- **G3 Re-evaluating a gate.** A passed gate is final in a run. The console's gates regress when the system changes. A gate needs a recheck,
and a passed gate that fails a recheck needs a state of its own.
- **G4 Value predicates.** `datapoints_ok` only asks that a datapoint is `ok`. The console needs "this datapoint is one of these values" and
rules across two datapoints (`production` excludes `sops-held-automation`).
- **G5 Local-only attributes.** The console keeps role contacts (email addresses) in an ignored `.local` file. Attribute sets and project
files are meant to be committed, so personal data would land in git. An attribute needs a `local` visibility that is never written into a
repository file.
- **G6 Gates satisfied by an automation path.** The console's `automation` status means an unattended script did the work. Auto-confirm
only confirms; running the script is the opt-in execution level (RBT-WP-0006-T01).
- **G7 Outputs feed later members.** A project run snapshots its attributes at the start. Facts established by one member (the custody
model chosen in S2, "OpenBao initialized" in S3) do not flow into the members after it. A staged bootstrap as a project needs that flow.
## Consequences
- **The seven runbooks and the three NetKingdom packs can be native v0.2 packs now.** The three NetKingdom packs are ported in
RBT-WP-0009-T06. The seven console runbooks are ready to port as a separate content task in net-kingdom; they need none of G1 to G7.
- **The console stays.** It is a permanent legacy pack, launched unchanged. What it does well and v0.2 cannot yet do (live probes,
regression, a fact store that outlives a session, conditional gates) is exactly G1, G3, G5 and G7.
- **The engine extraction (RBT-WP-0005-T04) waits for G1, G3 and G7.** Extracting the generic parts first would freeze the console's
workarounds into the engine.
- **The console is a project, not a run.** The right long-term shape is a project whose members are runbook packs per stage, with facts
flowing between them (G7). That is a design task for a v0.3, not a migration.