diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index c2ab809..be3fc41 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -2133,6 +2133,26 @@ passing), `chronyc sources` column format could not be measured (chrony absent -- so the check matches address literals only, parses no columns and invents no flag), `node dc1` could not be run on a real node, and the gauntlet could not be run on voffice1. +- **OCTAVIA PKI GENERATION HOST RULED 2026-07-29 (GA-R5) -- exact utterance "Generate on + voffice1 (Recommended)"**, recorded as a **D-109 RULING NOTE (2026-07-29 (b))**, which is the + authority. OPS under GA-R3; next-free D stays 138. + **THE QUESTION WAS FOUND BY A CLOSING CHECK, NOT BY THE AUDIT, and it would have bitten within + the hour.** The operator had already approved the generation and the handoff instructions were + written -- against `phase-01` Step 1.0-GEN's own **RUN -- jumphost** label. Measured before + execution, three surfaces disagreed: that label and the eighteen `host-role=jumphost` register + rows (bound by `host-identity` to **vcloud**) against `dc-dc-phase4`'s RUN LOCATION of + **`voffice1`, "NOT the vcloud jumphost"**, which explicitly expects the octavia overlay to be + present there. **`juju` is ABSENT on vcloud and 3.6.27 on voffice1** -- so following the + runbook's own label would have minted the PKI on a host the deploy cannot read it from. + Option (b), generate-then-transfer, was declined on R7's own posture ground: a second at-rest + copy of a CA private key plus a plaintext passphrase widens the SEC-004 exposure instead of + containing it. **Timing was the whole point:** F3 had established both hosts hold NOTHING, so + this was a free path edit; after the first mint it becomes a key MOVE. + WORK IMPLIED, each gated and NOT authorised by the ruling: relabel Step 1.0-GEN's RUN markers + to `voffice1` and state `$REPO` there means the headend clone; move the 18 Octavia rows to + `host-role=headend`; repoint the Octavia entries in `vm-secret-locations`; and bind `headend` + in `host-identity` so the F6 wrong-host refusal covers them -- on vcloud they must read NOT + PROBED rather than absent. **F3 -- both `~/octavia-pki/` and `overlays/octavia-pki.yaml` are ABSENT here** (existence checked, no contents read). So this is generation FROM SCRATCH for both DCs: there is nothing to reuse, which retires the reuse-vs-regenerate choice diff --git a/docs/design-decisions.md b/docs/design-decisions.md index bf88f9a..221ab0d 100644 --- a/docs/design-decisions.md +++ b/docs/design-decisions.md @@ -2712,6 +2712,48 @@ --- +## RULING NOTE 2026-07-29 (b) -- D-109: each DC's Octavia PKI is GENERATED ON the Plane-2 headend + +**Status: RULED 2026-07-29.** OPS under GA-R3 -- it fixes an execution LOCATION for an +already-ruled artifact, so doubt resolves DOWN and no new D-number is assigned. Recorded here +because D-109 is the Octavia-PKI authority after its 2026-07-27 amendment (R7), and because the +choice fixes where a CA PRIVATE KEY lives at rest, which is security posture rather than +mechanics. + +**Question as presented.** Three surfaces contradicted each other, measured 2026-07-29: +`runbooks/phase-01-bundle-deploy.md` Step 1.0-GEN says **RUN -- jumphost**; +`creds-manifests/host-identity` binds `jumphost` to **vcloud** and the eighteen Octavia rows in +`creds-matrix.tsv` carry `host-role=jumphost`; but `runbooks/dc-dc-phase4-juju-bundle-per-dc.md` +sets RUN LOCATION to **`voffice1`, "NOT the vcloud jumphost"**, and states that the +"deliberately-absent gitignored octavia PKI overlay ... is another reason this runs on +`voffice1`". Measured client inventory settles which host can deploy at all: **`juju` is ABSENT +on vcloud and 3.6.27 on voffice1.** So generating per the runbook's own label would have put the +PKI on a host the deploy cannot read it from. + +Options presented: (a) generate ON voffice1 -- one at-rest location per DC's CA; (b) generate on +vcloud as the register declares, then transfer the overlay to voffice1 as an explicit gated step +-- TWO at-rest locations per CA private key, each needing its own register rows; (c) hold and +rule separately, leaving Stage 5 blocked on the overlay. + +**Operator selection, exact utterance: "Generate on voffice1 (Recommended)".** + +**WHY THIS WAS PUT BEFORE GENERATION RATHER THAN AFTER.** F3 of the same session established +that `~/octavia-pki/` and the overlay are ABSENT on both hosts, so nothing exists to migrate and +the fix is free -- and that window closes permanently the moment the first CA is minted, because +from then on any change of location is a key MOVE rather than a path edit. Option (b) was +declined on the same posture ground R7 used to refuse a shared CA: the overlay carries CA +private keys plus a plaintext issuing-CA passphrase, SEC-004 records this repo as PUBLIC, and a +second at-rest copy widens that exposure instead of containing it. + +**Work implied (each gated, NOT authorised by this ruling):** relabel Step 1.0-GEN's RUN +markers to `voffice1` and state that `$REPO` there means the headend clone; move the eighteen +Octavia rows from `host-role=jumphost` to `headend`; point the Octavia entries in +`vm-secret-locations` at the headend; and bind `headend` in `host-identity` so the F6 wrong-host +refusal covers them -- on vcloud they must read NOT PROBED rather than absent. + +**Roosevelt analog:** artifacts are generated on the host that consumes them, so a per-DC secret +has exactly one at-rest location and no copy step to forget. + ## RULING NOTE 2026-07-29 -- D-109: the Octavia controller cert gains IPv6 IP SANs **Status: RULED 2026-07-29.** OPS under GA-R3 -- a generator change extending an