diff --git a/docs/archive/session-20260726-d137-build.md b/docs/archive/session-20260726-d137-build.md new file mode 100644 index 0000000..3a0dfef --- /dev/null +++ b/docs/archive/session-20260726-d137-build.md @@ -0,0 +1,133 @@ +# Session body 2026-07-26 -- D-137 credential matrix: build, committee audit, remediation + +Full session record (GA-R4 rule 2). The bounded summary is in `docs/session-ledger.md`; +status is in `docs/CURRENT-STATE.md` ONLY (GA-R1). Session changelog with per-item reverts: +`docs/changelog-20260726-d137-tier1.md` (items 1-22 -- the filename says "tier1" and the +content outgrew it; noted rather than renamed, since the name is cited in commits). + +Branch `dc-dc-stage4-phase3-maas-deploy`, 17 commits `af1b682..1696d08`, all pushed. +Opened at `8e72ff1`. Stage 4 remains OPEN; no stage was closed by this session. + +## What was built + +D-137 was ADOPTED but unimplemented at session open. All three tiers now exist. + +- **Tier 1 STATIC** -- `creds-matrix.tsv` (81 rows), `creds-matrix-notes.md`, + `scripts/creds-matrix.py` (S1 schema / S2 manifest coverage both-bounds / S3 render drift + / S4 mint-ref resolution / S5 per-DC symmetry / S6 ruling-5 principal invariant / S7 notes + integrity), harness `tests/creds-matrix`. +- **Tier 2 EXISTENCE** -- `creds-manifests/vm-secret-locations` (ruling 3's absolute bound), + E0-E4 checks, `--remote`/`--privileged` with escalation retried only where needed. +- **Tier 3 VALIDITY** -- V1 cross-copy sha256 provenance (external `sha256sum` both sides so + only digests enter the process), V2 declared-state reconciliation, and + `scripts/creds-probe.sh` for the behavioural half. +- **Enforcement** -- preflight **P5** runs tier 1 + tier 2 LOCAL, blocking, fail-closed. + `creds-manifests/stages-reached` replaces `--pending-stage`, coupled to CURRENT-STATE by + new **repo-lint L12**. +- **Schema** -- 10 -> 12 columns (`custody`, `notes-ref`), rows re-keyed to + (credential, location); `custody` later gained `verbatim-copy` for tier 3. + +Harnesses: creds-matrix 56, creds-probe 9, creds-audit 15, preflight 10, repo-lint 47. +Gauntlet 79 -> **81 ALL GREEN**. repo-lint 0-fail throughout. + +## Operator rulings (GA-R5 form; utterances quoted in design-decisions.md D-137) + +1. "go with the 12-column amendment" -- schema amendment. +2. "wire tier 1 as the blocking preflight Pn" -- ruling 1 enforcement, tier 1. +3. Tier 2 gate shape: "Local-only blocking; remote operator-run"; stage input: "Declared + file + lint coupling". +4. Tier 3 boundary: "Full -- including OpenStack service credentials"; cadence: "Stage close + + DC standup close". (I recommended passive-only and flagged the costs; ruled otherwise.) +5. SEC-024: "chmod 600 both, now"; snapshots "Keep, decide at stage close". +Ruling 4 (SEC-009 demotion) needed no exchange -- already ruled, trigger passed. + +## The committee, and what it found + +Six independent read-only lenses (correctness, coverage, claim-verification, +ruling-fidelity, record-integrity, Roosevelt-transfer). **Four converged independently on +the same root cause.** Every defect was reproduced, not theorised. + +**Eight confirmed false greens in the delivered build**, all since fixed and individually +regression-locked. The most consequential: tier 2 keyed existence on host-role ALONE and +never consulted `site-key`, so a credential present at one site satisfied the row for every +site -- which had masked SEC-021's dc0 `opnsense-api.txt` on-disk absence while tier 1 +flagged it. Also: `probe_remote` reporting UNREACHABLE for a location it had read; literal +paths skipping absent/unreadable detection; an empty locations file bypassing ruling 3; +no non-empty floor; a mint-ref crash exiting 1 indistinguishably from findings; mode +enforcement custody-gated (43 of 77 rows unchecked); and S5's second direction untested. + +**~21 inferred filenames, not the six I had owned.** Only the rows the first sweep +physically touched had been re-measured. Octavia's 8 were invented AND its declared location +matched none of them (the artifacts live in three subdirectories); vault used a directory +name as a filename; the tenant rows lacked the `-` prefix; `.maas.cli` was never +measured at all and does not exist (the MAAS snap CLI profile is `.maascli.db`). + +**`sec-ref` mis-attribution was systemic.** One instance was fixed by hand earlier in the +session without asking whether the class recurred. It did. + +## Defects found in my own work by running it + +Recorded because the pattern is the lesson: several defects were invisible to review and +appeared only on contact with real hosts. + +- The first privileged sweep reported `/root/maas-secrets` as "does not exist". It exists -- + an unprivileged `[ -d ]` on a root-owned parent is indistinguishable from absent. +- Role-level gating manufactured false absences when one location was unprobed. +- `shlex.quote` on the probe directory broke `~` expansion, so every home-relative remote + location read as unreadable. +- **Tier 3's first draft reported provenance DRIFT on `maas-region-admin` and + `dc1-svc-key`.** Manual `sha256sum` showed both IDENTICAL. Reporting it would have raised + a false credential-rotation alarm on exactly the SEC-020 pair. Root cause was a schema + gap: nothing expressed which rows are byte-copies. +- **The first `creds-probe.sh --run` was a false green:** `ssh` ate the `while read` loop's + stdin, 1 of 13 probes ran, exit 0. Now locked by a total-accounting check. + +## Records corrected + +CURRENT-STATE had asserted remote filenames and modes citing a checker VERDICT file that +contained none of them (GA-R1 rule 2); it said the `virsh` gap was unfixed after it was +fixed; it carried contradictory counts. The "ZERO undeclared files / fully accounted for" +claim was WITHDRAWN as resting on the site-blind check, and "SEC-021's on-disk half +REPRODUCED" was narrowed to the power-key artifacts -- then genuinely earned after the fix, +when `E1 dc0-edge-api 'opnsense-api.txt'` appeared for the first time. The 12-column +amendment was recorded on D-137, having existed only in a non-citable changelog. + +## Security ledger + +- **SEC-024 OPENED then REMEDIATED (mode).** `terraform.tfstate.backup` at 0664 carrying the + MAAS API key in plaintext, found by the fixed checker on its first clean run. Severity was + CORRECTED before remediation: `opentofu/` is 0700 and `~` is 0750, so it was never + effectively readable -- defence-in-depth, not live exposure. Retention of the two `pre-*` + snapshots deferred to stage close. +- **V2 surfaced a standing defect:** SEC-006 records the NetBox upstream token as BURNED + since 2026-07-12 while the matrix carried it as a healthy consolidated row. Nothing had + reconciled those surfaces. +- Open SEC rows 19 -> 20. + +## Housekeeping + +Permission rules: `Bash(ssh * sudo *)` never matched quoted remote commands, so remote sudo +fell through to the classifier; quoted variants added for `sudo` and `virsh`, all `ask`. +Session ledger rotated oldest-first 413 -> 280 (GA-R4 F1), discharging a debt the 07-25 +close recorded as OWED. + +## Advice given, not built + +Secrets-storage recommendation delivered on request (no HSM/KMS available): resolve the +Vault-vs-OpenBao licensing fork first; build `creds-mint.sh` as an atomic +mint->store->register; enable MAAS 3.7's Vault integration (measured `disabled`) rehearsed +in VR1 because of the MAAS/Vault circular dependency on bare metal; Vault SSH CA to retire +the static keypairs; Tang/Clevis + transit auto-unseal for the no-HSM bootstrap. Recommended +DROPPING the sops/age stopgap as churn. None of this is built or ruled. + +## State at close + +Stage 4 OPEN. **The live mission did not move**: the DC1 Stage-5 chain is exactly where it +was at session open -- verify MAAS role tags live, the 10th controller VM, the dc0 VIP +extract, the vault-VIP repair, BLOCKER-1/2 and the DC-aware gate fixes, then `juju +bootstrap` with edge egress OPEN. This session hardened the credential control that will +protect Stage 5; it did not advance Stage 5. + +Preflight exits 1, with P5 among the reasons -- but it was ALREADY exiting 1 before P5 +existed (P4: `overlays/octavia-pki.yaml` absent, MAAS unreachable from the jumphost). +No deploy path that was open is closed by this session's work. diff --git a/docs/archive/session-ledger-rotated-20260726.md b/docs/archive/session-ledger-rotated-20260726.md index f3ded8f..41aef1b 100644 --- a/docs/archive/session-ledger-rotated-20260726.md +++ b/docs/archive/session-ledger-rotated-20260726.md @@ -150,3 +150,32 @@ - Details: docs/changelog-20260721-g12-dc1-authoring.md (item 3 = drop-state record). Status lives ONLY in CURRENT-STATE.md. + + +--- + +# Second rotation pass, same day (GA-R4 F1) + +F1 binds the cap AT CLOSE: after writing the 2026-07-26 close summary the ledger +stood at 300 against the 300-line cap, so the next-oldest summary rotates. This is +the rule working as designed -- a long session forces older summaries out rather +than being truncated itself. + +## SESSION CLOSE 2026-07-22 -- G12 dc1 build session (bounded, GA-R4) + +- Opened from the drop-state; predecessor's owed reconcile DELIVERED (six harnesses + two sighted + surfaces; gauntlet 76 ALL GREEN; landed as authoring-changelog item 4). Duplicate idle Claude + session checked at operator request -- already exited, nothing culled. +- G12 [V] leg executed through the D-125 gate, every mutation operator-gated, all pushed: + apex --commit (transit /30 + rack IP, read-back idempotent); dc1 svc key minted (audit CLEAN); + outer step A 5/0/0 exact; cloudinit-vm interface_macs shipped + voffice1 dc1-transit NIC 0/2/0 + (full MAC pins, post-bounce battery ALL PASS); transit .5<->.6 live; rack ENROLLED (nmpcq4) with + SEC-010 both ends + 26.7 base (hash-verified dc0 copy); inner step C 28/28 from voffice1 (one + fix-forward: serial-staging dir), 10/10 domains RUNNING, edge at the 26.7 login prompt; D-125 + egress gate PASS (two identical runs). Queued findings: changelog items 7/9 (four tool gaps). +- NEXT session: edge bootstrap (D-112(c) driver rebuild -- v6 + five measured lessons at + changelog-20260719-dc0-deploy-stepB.md:241-260; edge keypair mint first) -> API key -> v4 + addressing -> rack standup DoD -> commissioning 9/9 -> G12 close-out; operator-gated merge to + main is the hard new-session gate after that. +- Details: docs/changelog-20260722-g12-dc1-build.md (items 1-10). Status lives ONLY in CURRENT-STATE.md. + diff --git a/docs/session-ledger.md b/docs/session-ledger.md index 57b225b..2bcea7a 100644 --- a/docs/session-ledger.md +++ b/docs/session-ledger.md @@ -109,24 +109,6 @@ OWED. Each rotated summary still points at its own archived full body; only the summaries moved. Sessions from 2026-07-22 onward remain live below. -## SESSION CLOSE 2026-07-22 -- G12 dc1 build session (bounded, GA-R4) - -- Opened from the drop-state; predecessor's owed reconcile DELIVERED (six harnesses + two sighted - surfaces; gauntlet 76 ALL GREEN; landed as authoring-changelog item 4). Duplicate idle Claude - session checked at operator request -- already exited, nothing culled. -- G12 [V] leg executed through the D-125 gate, every mutation operator-gated, all pushed: - apex --commit (transit /30 + rack IP, read-back idempotent); dc1 svc key minted (audit CLEAN); - outer step A 5/0/0 exact; cloudinit-vm interface_macs shipped + voffice1 dc1-transit NIC 0/2/0 - (full MAC pins, post-bounce battery ALL PASS); transit .5<->.6 live; rack ENROLLED (nmpcq4) with - SEC-010 both ends + 26.7 base (hash-verified dc0 copy); inner step C 28/28 from voffice1 (one - fix-forward: serial-staging dir), 10/10 domains RUNNING, edge at the 26.7 login prompt; D-125 - egress gate PASS (two identical runs). Queued findings: changelog items 7/9 (four tool gaps). -- NEXT session: edge bootstrap (D-112(c) driver rebuild -- v6 + five measured lessons at - changelog-20260719-dc0-deploy-stepB.md:241-260; edge keypair mint first) -> API key -> v4 - addressing -> rack standup DoD -> commissioning 9/9 -> G12 close-out; operator-gated merge to - main is the hard new-session gate after that. -- Details: docs/changelog-20260722-g12-dc1-build.md (items 1-10). Status lives ONLY in CURRENT-STATE.md. - ## SESSION CLOSE 2026-07-23 -- G12 dc1 edge->commission + CLOSE + MERGE (bounded, GA-R4) - Resumed from the 07-22 handoff (edge at login prompt); drove dc1 to a commissioned fleet, @@ -278,3 +260,21 @@ in the same-day successor session (tiers 1-3 built, six-lens committee audit, remediation, preflight P5 wired, SEC-009 demoted). Current status: CURRENT-STATE only. - Status ONLY in CURRENT-STATE.md. Detail: docs/changelog-20260725-maas-admin-recovery.md. + +## SESSION CLOSE 2026-07-26 -- D-137 build + committee audit + remediation (bounded, GA-R4) + +- D-137 was ADOPTED-not-built at open; all THREE tiers now exist plus enforcement (preflight + P5 blocking). 17 commits `af1b682..1696d08` pushed. Stage 4 stays OPEN; no stage closed. +- Six-lens committee audited the build; FOUR converged on one root cause -- tier 2 keyed + existence on host-role alone, ignoring site-key, so one site's credential satisfied every + site, MASKING SEC-021's dc0 on-disk absence. 8 false greens, all reproduced and fixed. +- Owned: ~21 inferred filenames (reported six); systemic sec-ref mis-attribution; + CURRENT-STATE cited a verdict file for measurements it lacked. 2 claims WITHDRAWN. +- Five operator rulings (GA-R5, quoted on D-137): 12-column schema; tier 1 as blocking P5; + tier 2 local-blocking + `stages-reached` coupled by new repo-lint L12; tier 3 probe + boundary; SEC-024 chmod. Ruling 4 (SEC-009 -> pointer) executed. +- SEC-024 opened then remediated (mode), severity corrected first. SEC 19 -> 20. Ledger + rotated twice (GA-R4 F1). Gauntlet 79 -> 81 GREEN; repo-lint 0-fail. +- NEXT: live mission has NOT moved -- resume the DC1 Stage-5 chain per CURRENT-STATE. + Unbuilt/unruled advice: `creds-mint.sh` BEFORE Stage 5 (largest minting event). +- Full body: `docs/archive/session-20260726-d137-build.md`. Status ONLY in CURRENT-STATE.md.