diff --git a/docs/console-mapping.md b/docs/console-mapping.md new file mode 100644 index 0000000..413c5c2 --- /dev/null +++ b/docs/console-mapping.md @@ -0,0 +1,109 @@ +# 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. diff --git a/workplans/RBT-WP-0005-legacy-adapter-and-console-migration.md b/workplans/RBT-WP-0005-legacy-adapter-and-console-migration.md index d6673b4..82411be 100644 --- a/workplans/RBT-WP-0005-legacy-adapter-and-console-migration.md +++ b/workplans/RBT-WP-0005-legacy-adapter-and-console-migration.md @@ -50,12 +50,12 @@ with a stub server. ```task id: RBT-WP-0005-T03 -status: todo +status: done priority: high state_hub_task_id: "dbb5553d-fb0c-5298-85c8-cebc9dd63312" ``` -Classify the 5,300-line `security_bootstrap_console.py` into generic engine +Done 2026-09-29 (RBT-WP-0009-T05): `docs/console-mapping.md`. Classify the 5,300-line `security_bootstrap_console.py` into generic engine concerns (record and state model, gates, stage derivation, copyable blocks, approval phrase, localhost server) and NetKingdom-specific content (custody, OpenBao ceremony, KeyCape, privacyIDEA checks). Output: a migration map with @@ -65,12 +65,13 @@ the tests that pin current behaviour. ```task id: RBT-WP-0005-T04 -status: todo +status: cancel priority: medium state_hub_task_id: "14261c00-65d0-55be-8ab2-bd81e579e20d" ``` -Move the generic parts into `rtut` behind the run record. The console in +Cancelled 2026-09-29: extracting the console's engine now would freeze its workarounds into the engine, because v0.2 lacks conditional applicability, gate +recheck and outputs that feed later members (`docs/console-mapping.md` G1, G3, G7). It may return as part of a v0.3 design. Original scope: move the generic parts into `rtut` behind the run record. The console in `net-kingdom` then imports them. Gate: the existing `tools/security-bootstrap-console/tests` pass unchanged before and after, and `make security-bootstrap-ui` behaves the same. @@ -79,13 +80,14 @@ Move the generic parts into `rtut` behind the run record. The console in ```task id: RBT-WP-0005-T05 -status: todo +status: done priority: low state_hub_task_id: "c54cfa35-1a34-5d5a-b85b-86ae8771dcfb" ``` -With Bernd: keep the console as a permanent legacy pack, migrate its runbooks -to native packs, or a mix. Record as a decision. +Decided 2026-09-29 (Bernd, with RBT-WP-0009): the console stays a permanent legacy pack, launched unchanged. Its seven runbooks can become native v0.2 +packs as separate content work (they need none of G1 to G7). Original question: keep the console as a permanent legacy pack, migrate its runbooks +to native packs, or a mix. ## Acceptance Criteria diff --git a/workplans/RBT-WP-0009-finalize-the-runbook-tutorials-workplans.md b/workplans/RBT-WP-0009-finalize-the-runbook-tutorials-workplans.md index 789dd7a..1213a96 100644 --- a/workplans/RBT-WP-0009-finalize-the-runbook-tutorials-workplans.md +++ b/workplans/RBT-WP-0009-finalize-the-runbook-tutorials-workplans.md @@ -77,11 +77,11 @@ refused (409). Added `rtut seal ` so an exported record can be verified an ```task id: RBT-WP-0009-T05 -status: todo +status: done priority: high ``` -`docs/console-mapping.md`: map the security bootstrap console's 6 stages, 14 gates, roles, subsystems, integrations, 12 artefacts +Done 2026-09-29. Verdict: the structure maps, the behaviour does not fully; seven gaps (G1 to G7) are the v0.3 candidates. `docs/console-mapping.md`: map the security bootstrap console's 6 stages, 14 gates, roles, subsystems, integrations, 12 artefacts and 7 runbooks onto v0.2 and say honestly where a special case is needed. This is the acceptance evidence for the model. It closes RBT-WP-0005-T03, records the decision to keep the console as a permanent legacy pack (T05), and moves the extraction (T04) to the backlog.