diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index c35418f..f2d67ba 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -700,7 +700,7 @@ | G11 | Operator signs THIS document | [R] read top-to-bottom; discrepancies resolved in the document | operator | CLOSED: RE-SIGNED 2026-07-19 at audit exit, section 11 (replaces the 2026-07-18 signature) | | G12 | `vr1-dc1` build | [R] operator rules dc1 transit/rack addressing; then vars + substrate authored | operator + session | CLOSED 2026-07-23 (operator-ruled "Merge to main + full close"; commissioning 9/9 READY, merge commit on `main`, branch retired) -- [R] leg CLOSED 2026-07-21: addressing RATIFIED (D-124 amendment 2026-07-21, utterance quoted). [V] leg IN PROGRESS (branch `dc-dc-g12-dc1-substrate`): apex confirm-free DONE 2026-07-21 -- planes/uplink already assigned+consistent, transit 172.31.0.4/30 + rack 10.12.68.2 FREE (`docs/audit/dc1-apex-confirm-20260721.txt`); importer per-site dc1 support shipped (harness 117/117) with live dry-run preflight PASS (`docs/audit/dc1-rack-import-dryrun-20260721.txt`). vars + substrate root + lib-net dc1 arm COMMITTED 2026-07-22 (successor session landed the disconnected item 3 + the harness reconcile as changelog item 4): six harnesses reconciled to the ratified dc1 arm, phase-00 PLANES parity guard added, rbd-mirror/radosgw cross-DC reminder fixed; gauntlet **ALL GREEN (76)** (`docs/audit/gauntlet-20260722-g12-reconcile.txt`), repo-lint 0-fail. Apex `--commit` EXECUTED 2026-07-22 (operator-gated): 172.31.0.4/30 + 10.12.68.2/22 CREATED, post-commit read-back idempotent (`docs/audit/dc1-rack-import-commit-20260722.txt`). dc1 svc key minted (creds-audit CLEAN), tfvars authored (local), **outer step-A apply DONE 2026-07-22**: saved plan 5/0/0 exact, converged ZERO DIFF (section 5), vvr1-dc1 RUNNING, prior guests untouched (as-executed log dc1-deploy; changelog-20260722-g12-dc1-build.md). **Step B COMPLETE 2026-07-22**: cloudinit-vm interface_macs port + voffice1 dc1-transit NIC (0/2/0 exact, MACs pinned both domains, post-bounce battery ALL PASS, converged zero diff -- `docs/audit/outer-plan-20260722-voffice1-dc1nic.txt`), transit LIVE (voffice1 .5/30 <-> rack .6/30, dc1-key ssh proven), rack ENROLLED (region lists vvr1-dc1 `nmpcq4`), SEC-010 applied+verified BOTH ends, OPNsense 26.7 base staged via hash-verified copy of dc0's proven artifact; named gate EXIT 0 `docs/audit/dc1-stepB-check-20260722-final.txt` (changelog-20260722 items 5-8, three queued findings). **Step C COMPLETE 2026-07-22**: inner apply FROM voffice1 -- plan 28/0/0 exact (54 pinned MACs verified in-capture), one fix-forward (serial-log staging dir absent on dc1; queued to standup DoD), resume 10/0/0 exit 0; 28/28 in state, convergence ZERO DIFF (`docs/audit/inner-converge-20260722-dc1-stepC.txt`), **10/10 domains RUNNING inside vvr1-dc1**, edge at the 26.7 FreeBSD login prompt (D-112 datapoint #2); dc1 inner tfstate ON voffice1 (site backup set). **D-125 egress gate PASS 2026-07-22** (two identical runs, dc0 criteria exact, isolation confirmed -- `docs/audit/d125-egress-gate-20260722-dc1.txt`). **Edge bootstrap + v4 addressing COMPLETE 2026-07-23** (changelog-20260723-g12-dc1-edge.md): D-112(c) console bootstrap done (SSH + dc1 edge key materialized; payload needed `util.inc`/`shell_safe()` -- dc0 lesson iv the `.b64` artifact lacked), key-only SSH VERIFIED (`15.1-RELEASE-p1`); D-113(a2) API key MINTED via the vendor model + smoke test `GET core/firmware/status` exit 0 `product_abi 26.7` (second 26.7 datapoint); edge ADDRESSED -- WAN `172.30.3.2/24` gw `172.30.3.1` (egress 1.1.1.1 0% loss), LAN `192.168.1.1` -> `10.12.64.1/22` (ruled provider-public gw), API answers at the new LAN; interim reach leg removed, rack provider-public leg `10.12.64.2/22` LIVE on virbr4. Creds consolidated to `~/vr1-dc1-creds/opnsense-api.txt` (creds-audit CLEAN, 5 entries); rack edge-key copy shredded (**SEC-015** transient, remediated). Two queued findings: bootstrap `.b64` missing `util.inc`; `opnsense-bootstrap-apikey.sh` scp had a transient post-restart-sshd failure (readiness-wait/retry candidate). **Rack standup + region MAAS config DONE 2026-07-23** (changelog-20260723 items 7-11): dc-rack-net.sh dc1 arm shipped (harness 18/18, gauntlet 76 GREEN) + INSTALLED on the rack (check 10/10, forwarder answers authoritative maas-internal SOA -- D-131 fix; `docs/audit/dc1-rack-net-install-20260723.txt`); region MAAS on metal-admin subnet 11 -- D-120 range 10.12.68.100-.200, D-131 dns_servers=10.12.68.3 allow_dns=false, DHCP dhcp_on=true primary_rack=nmpcq4 (dhcpd verified RUNNING on virbr6, no Temporal incident); **dc1 enlistment PROVEN** via canary (machines 11->12 in ~2 min). **SEC-016 RULED + WIRED 2026-07-23** (operator: "Mint a dedicated dc1 power key" -- per-DC isolation; dedicated key authorized on the rack + installed in the region MAAS snap with per-host ssh config, dc0's SEC-012 key untouched). **COMMISSIONING 9/9 READY 2026-07-23** (`docs/audit/dc1-commissioning-verify-20260723.txt`): all 9 nodes PXE-enlisted by pinned 52:54:01:d1 MACs, `power_type=virsh` set + verified by real query-power-state (SEC-016 path proven), commissioned to **ALL 9 READY in ~3.5 min** (no timeout, no SERVFAIL), shapes EXACT to D-121 Option C (3x16cpu/64GiB + 2x12cpu/48GiB + 4x8cpu/24GiB). dc0's two stacked faults pre-empted by pinned MACs + the dc-rack-net forwarder. **G12 [V] leg (the dc1 build) is COMPLETE.** NEXT: G12 close-out only -- consolidate this session's changelogs (GA-R2), final gauntlet + repo-lint, GA-R7 memory review, skill sweep, **operator-gated merge of `dc-dc-g12-dc1-substrate` -> `main`** (merge commit), branch retirement; then G12 CLOSES. NOTE open SEC rows now include SEC-014/-015/-016 (G14 row count stale -- reconcile in the close). | | G13 | D-129 residuals | [R] operator-gated live plugin install on office1-opnsense; qga channel retrofit at that edge's next scheduled restart. All 4 sub-decisions RULED 2026-07-21 (D-129 Status line) -- only the two execution items remain | operator | CLOSED 2026-07-23 (operator-approved full maintenance bundle, logged window ops-sec010-reassert): qga channel retrofitted via outer tofu saved-plan apply 0/1/0 exact (`docs/audit/outer-plan-20260723-office1-qga.txt`; the apply's edge bounce = the ruled "next scheduled restart"; MACs were pinned 07-22 so the in-place-update trap class was closed); edge updated 26.7 -> 26.7.1 via REST (no reboot required; os-iperf had been REFUSED on 26.7 pending exactly this update); both plugins installed=1 by firmware-info read-back, `guest-ping` -> `{"return":{}}`, agent reports both legs, egress 0% loss, outer plan re-converged ZERO DIFF (`docs/audit/outer-plan-20260723-postqga-converged.txt`). Named close capture: `docs/audit/g13-close-20260723.txt` | -| G14 | 12 OPEN SEC rows (SEC-001, -003..-008, SEC-012, -013, -014, plus SEC-015 + SEC-016 opened 2026-07-23 for dc1 credentials; SEC-010/-011 CLOSED) | [R] per-row: rotations/flips at v1 close (external to VR1 track); SEC-012/-016 carry the same libvirt-group SCOPE hardening question; SEC-016 also a snap-refresh re-assert (queued to DC standup DoD) | operator / external | `docs/security-ledger.md` (register of record, GA-R4/F3); count re-verified vs `bash scripts/ledger-scan.sh` 2026-07-23 (12 open) | +| G14 | 12 OPEN SEC rows (SEC-001, -003..-008, SEC-012, -013, -014, plus SEC-015 + SEC-016 opened 2026-07-23 for dc1 credentials; SEC-010/-011 CLOSED) | [R] per-row: rotations/flips at v1 close (external to VR1 track); SEC-012/-016 carry the same libvirt-group SCOPE hardening question; SEC-016 also a snap-refresh re-assert (queued to DC standup DoD) | operator / external | `docs/security-ledger.md` (register of record, GA-R4/F3). **COUNT RECONCILED 2026-07-25: 19 open**, measured `bash scripts/ledger-scan.sh` (SEC-001, -003..-008, -012..-023). The row's own title text ("12 OPEN SEC rows") is the 2026-07-23 figure and is SUPERSEDED by this cell -- the gate is the ledger, not the count. Since 07-23: SEC-017 (caveman supply-chain), -018/-019 (per-DC MAAS API keys), -020 (MAAS region superuser passwords), and **-021/-022/-023 opened 2026-07-25** from the D-137 credential research -- dc0 custody defects (a consolidated credential ABSENT from its recorded location + per-DC power-key divergence), UNAUDITED shadow `*-creds/` stores on voffice1 (a scope gap in `creds-audit` itself, which has no remote capability), and sprawl-glob blind spots incl. a PREDICTED Stage-5 `~/admin-openrc` exposure. All three are logged-not-actioned (hard rule 1); remediation is coupled to the unruled D-137 forks | | G15 | D-068 / D-071 rulings | [R] operator rules (section 8); neither blocks the VR1 substrate | operator | D-071 ADOPTED 2026-07-21 (all four points); D-068 items 2-3 RULED 2026-07-21; item 1: plan DRAFTED + Q1/Q2-structure/Q3 ALL RULED 2026-07-23 (three amendments, utterances quoted; monthly-review lines delivered). Sole D-068 remainder: Q2 path selection at Roosevelt Vault design time -- G15 is otherwise decision-complete | | G16 | office1 edge `channels = []` state reconcile (the D-129 module-schema residual) | [R] operator rules the mechanism; then [V] the converged re-plan capture | operator + session | CLOSED 2026-07-21: RULED "State surgery (Recommended)" (GA-R5, session changelog item 16); executed per G6 precedent -- channels null -> [] injected, serial 29 -> 30, backup kept, guests untouched (office1-opnsense Id 2 running throughout); convergence = ZERO DIFF (`docs/audit/outer-plan-20260721-postG16-converged.txt`); section 5 re-recorded | diff --git a/docs/changelog-20260725-maas-admin-recovery.md b/docs/changelog-20260725-maas-admin-recovery.md index 34007b3..e009043 100644 --- a/docs/changelog-20260725-maas-admin-recovery.md +++ b/docs/changelog-20260725-maas-admin-recovery.md @@ -173,3 +173,40 @@ identity-conflation question is kept SEPARATE to avoid batching two rulings. **Revert:** delete the D-137 block from `docs/design-decisions.md`, CURRENT-STATE section 8 item 9, and the ledger machine-block D-137 clause (restore count to 4). + +## Item 10 -- SEC-021/-022/-023 opened: live credential defects found during D-137 research + +**What:** three new `docs/security-ledger.md` rows recording defects MEASURED read-only +while researching the credential matrix. None actioned (hard rule 1). Open SEC rows +16 -> 19; CURRENT-STATE G14's evidence cell reconciled to 19 in this commit (its title +text keeps the 07-23 figure and is marked superseded); ledger machine block re-seeded. +- **SEC-021 -- dc0 custody defects.** (a) `changelog-20260719-dc0-deploy-stepB.md:263` + records the dc0 edge REST API credential written to `~/vr1-dc0-creds/opnsense-api.txt`; + a `find` over vcloud `$HOME` returns that filename for office1 and dc1 ONLY -- no dc0 + copy -- and `creds-audit vr1-dc0` reports CLEAN because it was never manifested. + Severity is a custody/record defect + API-access gap, NOT a lockout: the dc0 edge SSH + key is present and D-112(c) makes key-only SSH the primary management path. (b) dc0's + power key is `maas-virsh_ed25519` on voffice1 vs dc1's declared + `vr1-dc1-maas-power_ed25519{,.pub}` on vcloud -- same purpose, different name, host and + custody, dc0 with no `.pub`. +- **SEC-022 -- unaudited shadow stores.** `voffice1` holds `~/vr1-dc0-creds/` AND + `~/vr1-dc1-creds/` with real key material. `creds-audit.sh:29-31` resolves the folder + under `$HOME` on whatever host it runs on (vcloud) and contains no ssh at all, so these + are structurally invisible. A SCOPE gap in the control, not a one-off -- D-128 puts + Plane-2 execution on voffice1, so headend-resident credentials will keep appearing. +- **SEC-023 -- sprawl blind spots + a PREDICTED Stage-5 exposure.** The globs at + `creds-audit.sh:72-73` miss `admin.pass`, `*.apikey`, `*.key`, `*.pem`, `*_ed25519` and + even `maas-api-key.txt`. `phase-03-admin-openrc.sh:32,72` will write `OS_PASSWORD` into + `$HOME/admin-openrc` at Stage 5 -- home root, outside any creds folder, matching no + glob. Recorded BEFORE it exists so the mint is not missed. +**Why:** the ledger mandate is a row at discovery, never only a note. These are live +defects independent of any D-137 ruling, and the approved plan lists recording them as +the one action not gated behind the five open forks. They also constitute the empirical +case for the matrix: SEC-021/-023 are absence-and-drift (invisible to discovery) while +SEC-022 is an unknown-unknown (invisible to declaration) -- the two halves are +complementary, which could not be argued from the discovery-only D-137. +**NOT done:** no remediation, no tooling, no glob widening -- all coupled to unruled +forks. Interim obligations are stated per row (notably: whoever runs Stage 5 phase-03 +must consolidate `~/admin-openrc` BY HAND at mint time). +**Revert:** delete the three rows, restore the G14 evidence cell, re-seed the ledger +block to 16. diff --git a/docs/security-ledger.md b/docs/security-ledger.md index 9573324..0a69e9e 100644 --- a/docs/security-ledger.md +++ b/docs/security-ledger.md @@ -35,6 +35,12 @@ | SEC-020 | 2026-07-25 | **MAAS region superuser passwords: an un-consolidated VM-minted secret, plus a new human GUI identity -- and the human/service identity conflation underneath both.** (a) The `admin` superuser's password was minted ON the region VM by `scripts/site-headend-install.sh:452` (`newpass` -> 28 chars alphanumeric, no trailing newline) and sat root-only at `voffice1:/root/maas-secrets/admin.pass` since 2026-07-13, never consolidated to `~/vr1-office1-creds/` -- the SAME SEC-009 miss class the NetBox token established (a site-VM-minted secret with no forcing function to reach the folder). It was NOT lost and NOT unset: MEASURED working this session (login POST 204 with the stored value vs 400 with a wrong-password control; Django `has_usable_password=True`). The prior claim that MAAS web-GUI login "does NOT exist / was never minted" (session-ledger 2026-07-25 close) is FALSIFIED and corrected in the same commit. (b) ROOT CAUSE of the miss: `admin` is simultaneously the human GUI login AND the automation identity -- the installer mints its API key (`:453`) and logs the CLI in as profile `admin` (`:455`), and 19 `maas admin ...` call sites across 4 scripts (`site-headend-install.sh` 10, `phase-04-network-verify.sh` 5, `phase-04-network-create.sh` 3, `phase-00-teardown-release.sh` 1) hardcode that profile. Automation only ever needed the KEY, so nobody ever needed the PASSWORD, so nothing forced it into the folder. (c) NEW standing credential: superuser `operator` (email `jesse.austin@neumatrix.com`) minted 2026-07-25 for HUMAN GUI login, 32-char base64 generated on vcloud, set via **stdin -- never argv** (SEC-018 discipline; note `maas changepassword` has no `--password` and `createadmin --password` would expose it in argv, the shape `site-headend-install.sh:452` uses). Both passwords now at `~/vr1-office1-creds/{maas-admin-password,maas-operator-password}` 0600, declared in `creds-manifests/vr1-office1.manifest`, `creds-audit vr1-office1` CLEAN. | this session (operator-ruled scope: "New account + consolidate only" -- no existing password rotated); measured captures in `docs/changelog-20260725-maas-admin-recovery.md`; `scripts/site-headend-install.sh:452-455` | operator | **OPEN -- rotation obligation on TWO credentials** (`admin` + `operator` region superusers; rotate at v1 close, or immediately if vcloud/the region is rebuilt or shared). `admin`'s password was deliberately NOT rotated this session (operator-ruled) -- so `voffice1:/root/maas-secrets/admin.pass` REMAINS source-of-record and the vcloud file is a byte-identical (sha256-verified) working copy; **any future `admin` rotation MUST update both copies in one operation or the VM copy becomes a stale trap.** ALSO OPEN, un-actioned by ruling (hard rule 1, findings are logged not executed): (i) `voffice1:/root/maas-secrets/{admin.apikey,db.pass,lxd-trust.pass}` are still un-consolidated -- `admin.apikey` is deliberately NOT copied (trivially regenerable via `maas apikey --username=admin`, and a second copy is pure added surface), `db.pass`/`lxd-trust.pass` are region infrastructure and out of this task's scope; (ii) the DURABLE fix for the miss class is a `site-headend-install.sh` amendment to consolidate at mint time (queued, unruled); (iii) the human/service conflation in (b) is proposable as the next-free D-number, tagged [ARCH], a Roosevelt-delta (per-identity MAAS separation / audit attribution on a multi-tenant cloud) -- NOT assigned, GA-R3 doubt-resolves-DOWN, operator's call. Count note: this row takes open SEC rows 15 -> 16; CURRENT-STATE G14 (which still reads 12) reconciles at Stage 4 close per its existing deferral. Custody off-repo per D-069. | +| SEC-021 | 2026-07-25 | **dc0 credential custody defects -- a consolidated credential is ABSENT from its recorded location, and the per-DC power key diverges in name, host and custody.** (a) `docs/archive/changelogs/changelog-20260719-dc0-deploy-stepB.md:263` records the dc0 edge REST API credential written to `~/vr1-dc0-creds/opnsense-api.txt` (0600, secret never printed). A `find` over vcloud `$HOME` returns `opnsense-api.txt` for `vr1-office1` (2026-07-13) and `vr1-dc1` (2026-07-23) ONLY -- **there is no dc0 copy**. It was never added to dc0's manifest, so `creds-audit vr1-dc0` reports CLEAN. A changelog asserting consolidation is not evidence the consolidation survived. SEVERITY: this is a custody/record defect plus an API-access gap, NOT a management lockout -- `vr1-dc0-edge_ed25519{,.pub}` IS present, and D-112(c) makes key-only SSH the primary edge management path. (b) The dc0 MAAS->libvirt power key (SEC-012) is `maas-virsh_ed25519` on **voffice1**, while dc1's equivalent (SEC-016) is `vr1-dc1-maas-power_ed25519{,.pub}` on **vcloud** and manifest-declared: same purpose, different filename, different host, and dc0 carries no `.pub`. Per-DC rows that should be symmetric are not, and nothing compares them. | measured read-only this session (folder listings both hosts, `find` over vcloud `$HOME`, both manifests); D-137 research; plan `whimsical-wandering-spindle` findings F1+F3 | operator | **OPEN.** (a) needs a decision between RE-MINT (D-113(a2) vendor model, the dc1-proven path) and locating an off-jumphost copy; until then dc0 has no API management path from vcloud. (b) needs a naming/custody reconciliation to the dc1 shape, and dc0's key should gain a jumphost copy + manifest row -- note SEC-016's standing fragility applies harder to dc0: the snap-side key lives under per-revision `/var/snap/maas/current/` and may not survive a snap refresh, and dc0 currently has NO jumphost copy to re-assert from. NOT actioned this session (hard rule 1; findings are logged, never executed mid-task). Custody off-repo per D-069. | + +| SEC-022 | 2026-07-25 | **Two UNAUDITED shadow `*-creds/` credential stores exist on voffice1 -- an entire parallel store outside every control.** `ssh voffice1 'ls -d ~/*-creds/'` returns `~/vr1-dc0-creds/` AND `~/vr1-dc1-creds/`, holding real key material (dc0: `maas-virsh_ed25519` 464 bytes 2026-07-20, `vr1-dc0_svc_ed25519{,.pub}`). SEC-009's convention says ALL site secrets live in `~/-creds/` on the JUMPHOST; nothing anticipated a second store on the headend. `scripts/creds-audit.sh:29-31` derives `CREDS="$CREDS_ROOT/${SITE}-creds"` with `CREDS_ROOT` defaulting to `$HOME` **on whatever host it runs on** -- i.e. vcloud only -- and the script contains no `ssh`/`scp` at all, so these stores are structurally invisible to every check that exists. This is a SCOPE gap in the control itself, not a one-off miss: the D-128 operating model puts Plane-2 execution ON voffice1, so headend-resident credentials are expected to keep appearing. | measured read-only this session; `scripts/creds-audit.sh:29-31` (no remote capability); D-137 research finding F2 | operator | **OPEN -- scope gap + rotation obligation.** Every file in those stores is a live credential with no manifest row, no mode/presence enforcement, and no rotation tracking. Remediation is coupled to the D-137 `--remote` fork (declared-directories vs broader sweep) which is UNRULED -- so no tooling is built yet. Interim: treat `voffice1:~/*-creds/` as in-scope for any rotation performed at v1 close. Custody off-repo per D-069. | + +| SEC-023 | 2026-07-25 | **Sprawl detection has systematic blind spots, and one exposure is already PREDICTED for Stage 5.** `scripts/creds-audit.sh:72-73` sprawl-globs exactly `*.env`, `.*.env`, `*appcred*`, `*-cred*.txt`, `*authkey*`, `*.token`. That set misses whole file classes this repo actually uses: `admin.pass`, `*.apikey`, `*.key`, `*.pem`, `*_ed25519`, and `maas-api-key.txt` (which is manifest-declared in TWO sites yet would not be caught loose). PREDICTED EXPOSURE: `scripts/phase-03-admin-openrc.sh:32` writes `RC="${RC:-$HOME/admin-openrc}"` and `:72` writes `export OS_PASSWORD='$ADMIN_PASS'` into it -- a credential-bearing file in the HOME ROOT, outside any `*-creds/` folder, whose filename matches NONE of the sprawl globs. It does not exist yet (Stage 5 has not run), so no discovery sweep can flag it today; it is recorded here in advance so the mint is not missed when Stage 5 executes. NOTE the keystone admin password is CHARM-generated but OPERATOR-materialized (`:52` extracts it via `juju run keystone/leader get-admin-password`) -- the operator-ruled "materialization test" puts it firmly in scope. | measured read-only this session; `scripts/creds-audit.sh:72-73`; `scripts/phase-03-admin-openrc.sh:32,52,72`; D-137 research finding F4 | operator | **OPEN -- latent, becomes live at Stage 5.** Two remediations, both UNRULED and NOT built: widen the sprawl globs (cheap, independent of D-137), and add an expected-state row so the openrc credential is asserted rather than discovered. Until then, whoever runs Stage 5 phase-03 must consolidate `~/admin-openrc` into the site creds folder BY HAND at mint time. Count note: SEC-021/-022/-023 take open SEC rows 16 -> 19. Custody off-repo per D-069. | + **STANDING CONVENTION (SEC-009, 2026-07-15): per-site credential/env consolidation.** ALL sensitive files AND environment/config files for a site live in a single `~/-creds/` folder on vcloud, mode 0700, files 0600 (public keys 0644). No loose env files in `~`. Sites: `~/vr1-office1-creds/` diff --git a/docs/session-ledger.md b/docs/session-ledger.md index ae77e48..4e65266 100644 --- a/docs/session-ledger.md +++ b/docs/session-ledger.md @@ -44,13 +44,15 @@ overlays and tfvars [ARCH] -- PROPOSED 2026-07-25 in Chat, non-gating for the dc1 deploy). D-071 and D-129 previously listed here are ADOPTED/RESOLVED and correctly drop off the scan. Status lines in `docs/design-decisions.md` are the only ruling authority. -- **OPEN security rows:** 16 open per `bash scripts/ledger-scan.sh` (re-seeded 2026-07-25). Since the - last seeding this went 12 -> 16: SEC-017 (caveman plugin supply-chain re-verify), SEC-018/-019 +- **OPEN security rows:** 19 open per `bash scripts/ledger-scan.sh` (re-seeded 2026-07-25). Since the + last seeding this went 12 -> 19: SEC-017 (caveman plugin supply-chain re-verify), SEC-018/-019 (per-DC MAAS API keys for the Juju cloud credentials), SEC-020 (MAAS region superuser passwords -- - the `admin` un-consolidation + the new `operator` human GUI identity). The SEC register of record + the `admin` un-consolidation + the new `operator` human GUI identity), and SEC-021/-022/-023 + (2026-07-25 D-137 credential research: dc0 custody defects, unaudited shadow `*-creds/` stores on + voffice1, sprawl-glob blind spots + a predicted Stage-5 `~/admin-openrc` exposure). The SEC register of record is `docs/security-ledger.md`; row-level dispositions live THERE only (GA-R4 amendment F3) -- - this block carries pointer + count, never rows. NOTE the CURRENT-STATE G14 gate row still reads - 12 and is a known-stale surface, deferred to Stage 4 close by its existing deferral. + this block carries pointer + count, never rows. The CURRENT-STATE G14 evidence cell was + RECONCILED to 19 in the same commit as SEC-021/-023 (its title text keeps the 07-23 figure). - **Next-free numbers:** D = **137**, DOCFIX = **204**, BUNDLEFIX = 053. - **Standing numbering rule:** never write an identifier-shaped token (D-/DOCFIX-/BUNDLEFIX-NNN) ABOVE the real high-water mark anywhere in `docs/` or `runbooks/` prose -- historically a decoy