Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477
9.2 KiB
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
- A persistent fact document (
.local/security-bootstrap.json, flat keys such asopenbao_initialized). It lives for weeks. - The stage is derived from the facts (
derive_stage: the most advanced fact wins), not from stepping through a list. - 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.
- 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). - 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_whenon a datapoint value).one_ofchooses 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_okonly asks that a datapoint isok. The console needs "this datapoint is one of these values" and rules across two datapoints (productionexcludessops-held-automation). - G5 Local-only attributes. The console keeps role contacts (email addresses) in an ignored
.localfile. Attribute sets and project files are meant to be committed, so personal data would land in git. An attribute needs alocalvisibility that is never written into a repository file. - G6 Gates satisfied by an automation path. The console's
automationstatus 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.