| 2026-07-27 |

Stage-5 grounding audit: session bookend (GA-R4) + ledger rotation
...
Close bookend for the autonomous Stage-5 grounding audit. Bounded ledger
summary (9 bullets, cap 15); full body archived in the same commit as
docs/archive/changelogs/changelog-20260727-stage5-grounding-audit.md, the ONE
changelog for this session per GA-R2/D1, carrying a per-item revert.
Ledger rotation: the bookend pushed the live ledger to 305 lines against the
300-line cap, so the oldest remaining live summary (2026-07-24, caveman
guardrails + DC1 proxy-build start) moved VERBATIM to
docs/archive/session-ledger-rotated-20260727.md as a clearly-labelled second
rotation pass. Live ledger now 289 lines. Sessions from 2026-07-25 remain live.
Reconciled against repo ground truth at close: ledger-scan reports 21 open SEC
rows and next-free D 138 / DOCFIX 205 / BUNDLEFIX 053 -- all UNCHANGED, which
is correct: this session assigned no number because it remediated nothing. The
machine-derived block needed no re-seed.
The changelog records, prominently, that a SESSION-SCOPED PERMISSION BLOCK is
live in the gitignored .claude/settings.local.json and must be removed at
close; the scope doc's section 6 is its only durable record.
Revert: git revert this commit; then restore the 2026-07-24 summary from the
rotation archive if the ledger rotation is also being undone.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

close-out durability sweep: 4 transcript-only items landed; dc1-is-not-a-mirror warning
...
Operator-requested sweep for content that existed only in the session transcript, before
clearing. Precedent: docs/audit/queued-findings-20260726.txt. Capture:
docs/audit/queued-findings-20260727.txt.
THE CONSEQUENTIAL ONE. scripts/dc-mirror.sh's dc1 site row carried NO warning that dc1 is no
longer a mirror site, so `dc-mirror.sh install dc1` would have SILENTLY REBUILT everything the
same-day teardown removed -- units, nginx vhost, sync helper, and an ENABLED daily debmirror
timer that would start a fresh ~950G pull on a rack whose ruled artifact path is the proxy. That
is precisely the command someone would reach for after treating a failing `check dc1` as a
regression. The row now states dc1 is proxy-only per the D-135 amendment, that `check dc1` FAILS
BY DESIGN, and that `install dc1` is a deliberate strategy change and never a repair. The row is
RETAINED so its measured values survive a legitimate rebuild.
QUEUED, not built (hard rule 1): a RUNTIME guard in do_install for a site whose ruled path is
not the mirror. A comment is strictly weaker than a guard, and prose-only prevention has already
failed twice on this project (DoD item 8 missed dc1; D-137's wiring sat as prose and missed BOTH
DC standups). Recording that the interim is an interim.
A WRONG CLAIM CORRECTED. docs/audit/stage4-mirror-gate-20260727.txt said `systemctl reset-failed`
would re-arm the paused dc1 debmirror. It cannot: reset-failed on the SERVICE does not start an
INACTIVE TIMER. The real vector was a REBOOT -- `enabled` starts the timer at boot and
`Persistent=yes` fires it IMMEDIATELY because its window had passed. Correction APPENDED rather
than edited in place: the file is dated evidence, so a wrong analytical claim is superseded
openly, not quietly rewritten.
THE GENERALISABLE LESSON, previously unrecorded, is now platform-traps section 5:
5a "stopped is not dormant across a reboot" -- enabled + inactive + EMPTY NextElapse looks
harmless and is not; plus reset-failed does not re-arm, and Result=signal/status=15 on a
oneshot means it was SIGTERM'd and never wrote a terminal state (so a stale RUNNING is a
corpse, not progress).
5b a `oneshot` with RemainAfterExit=yes does NOT undo its work on stop, so stopping it proves
NOTHING about dependents -- which is exactly why the dc1 teardown test deleted the live
address and route instead of stopping the mirror net unit.
Three rows added to the verbatim-error index. Note dc0-mirror-sync.timer is still enabled with
Persistent=yes, so 5a describes dc0 today -- benign while its syncs succeed, same shape.
HARD RULE 2. dc-cache-proxy.sh stated that the two net units coexist safely on one host as
FACT. It is REASONED (idempotent replace verbs, identical measured values), never MEASURED --
the proxy has only run on dc1, where the mirror unit was then removed, so nobody has run both.
Marked accordingly, with an instruction to verify rather than trust the sentence.
VERIFICATION: dangling-reference sweep over docs/, runbooks/, scripts/ and the skill -- every
path this session introduced or cited RESOLVES; all pre-existing dangles are legitimate
(deleted-as-history, not-yet-built, or the deliberately-absent octavia PKI overlay preflight P4
fails on). ledger-scan reconciled against the machine-derived block. Gauntlet ALL GREEN (81),
repo-lint 0-fail, dc-mirror 24/24, dc-cache-proxy 20/20.
Revert: text + comments only; the capture correction is an append.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

session-ledger: rotate to restore the GA-R4 cap (317 -> 260); re-seed the scan header
...
CORRECTION to the previous commit's message, which said "ledger 317 lines, under the 300-line
cap". That is wrong and self-contradictory -- 317 is OVER the 300-line cap, so GA-R4 F1
rotation was OWED, not deferred. Recording the correction rather than quietly fixing it,
because mis-stating an owed obligation as satisfied is the failure mode the cap exists to
prevent (the 2026-07-25 close had to record exactly this breach as OWED).
ROTATED oldest-first per GA-R4 rule 3, matching the 2026-07-26 precedent: the three oldest live
summaries (all 2026-07-23 -- G12 dc1 edge->commission+merge, Stage 4 OPEN+carve+mirrors, queue
pass + D-068 rulings) moved VERBATIM to docs/archive/session-ledger-rotated-20260727.md. Each
still points at its own archived full body; only the summaries moved. Live ledger 317 -> 260,
under the cap. Sessions from 2026-07-24 onward remain live.
Re-seeded the machine-derived block header, which still credited a 2026-07-26 scan while
carrying 2026-07-27 values. Verified against `bash scripts/ledger-scan.sh` this session:
21 open SEC rows, D next-free 138, DOCFIX 205, BUNDLEFIX 053 -- all match.
repo-lint 0-fail. The session is now durably bookended: Stage 4 CLOSED and merged (6f5701d),
ledger under cap, scan values reconciled, every finding on a surface rather than in a commit
message. Safe to clear.
Revert: text-only; the rotation is a verbatim move.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

session bookend: correct the stale merge status + land a finding that lived only in a commit
...
Two defects in the durable record, both because the bookend was written BEFORE the merge.
Fixing them before the session is cleared, since the ledger is what the next session reads.
1. The bookend said "Merge to `main` is the ONLY remaining step and is operator-gated" -- stale
the moment the merge landed. Now records the actual end state: merge commit 6f5701d (2
parents, not squashed, 77 commits), branch retired local + remote, post-merge gauntlet ALL
GREEN (81) + repo-lint 0-fail ON main, close recorded by 1023596.
2. A finding was logged only in commit c29059b's MESSAGE, which is findable but is not a surface
any session reads at open: `tests/creds-matrix` T24's finding-class baseline covers TIER 1
ONLY, so tier-2/3 classes (E1/E3/E4/V1/V2) have no baselined red state and a future false
green there would not turn the gauntlet red. That is the same class as the two false greens
this session fixed, so burying it in a commit message was the wrong home. Now in the
bookend, together with the still-open `creds-mint.sh` advice -- worth ruling BEFORE Stage 5,
which is the largest credential-minting event in the deployment.
Bookend stays within the GA-R4 15-line cap (9 body lines); ledger 317 lines, under the 300-line
cap's rotation trigger for the next close to handle. repo-lint 0-fail.
Revert: text-only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

Stage 4 close-out set: GA-R2 consolidation, skill sweep, snapshot, GA-R7 review
...
Every substantive Stage 4 item is closed or split to gate row G17. This is the GA-R6 close-out
set; only the operator-gated merge to `main` remains.
GA-R2 CONSOLIDATION: the 7 stage changelogs archived to docs/archive/changelogs/ (top-level
docs/ 25 -> 18, 113 archived total) and the stage record written at
docs/archive/stage-records/vr1-stage4-record.md. It records what the stage actually delivered
(READY handoff, not deployed nodes), the three things a future session should read first, and
the false-green pattern this stage kept surfacing. 12 stale `docs/changelog-*` paths in live
surfaces rewritten to the archive -- including several already dangling from the G12 close, so
every changelog reference in CURRENT-STATE / session-ledger / security-ledger now resolves.
SKILL SWEEP: three new INVARIANTS folded in --
- per-DC ARTIFACT DELIVERY is a per-DC STRATEGY (dc0 full mirror / dc1 caching proxy, D-135
amendments); checking dc1 as a mirror fails BY DESIGN. Corollary, learned the hard way: a
per-DC utility service OWNS ITS OWN network prerequisites -- never let one strategy's
teardown be able to break the other's.
- Stage 4 hands off READY nodes, NOT deployed ones (DOCFIX-200). Any surface saying "nodes
Deployed" as a Stage-4 exit is a defect; four were found and fixed. Consequence: nothing
node-side is probeable in Stage 4, which is why G17 exists.
- "A CHECKER THAT CANNOT FAIL IS NOT A GATE", with the working rules that came out of two
measured false greens: assert on CONTENT not existence; an unrecognised state REFUSES;
"could not look" is never "nothing there"; ENUMERATE what exists rather than only auditing
what is declared, because a register cannot report the absence of a row it does not have;
and when a test asserts a literal finding string, REPLACE the assertion, never delete it.
Plus two routing rows (per-DC artifact checks; D-137 as the credential-lifecycle authority).
SNAPSHOT REGENERATED: .claude/skills/openstack-cloud-ops-consolidated-20260727.md (1589 lines,
ASCII + LF byte-verified, all 7 sections). The superseded 20260725 snapshot is REMOVED rather
than kept alongside -- a stale snapshot being uploaded is the exact failure
docs/audit/skill-divergence-20260725.md records (a failed clone + a mis-shaped handoff), and it
is a derived artifact regenerable from any commit.
GA-R7 MEMORY REVIEW: NO new memory written -- everything durable from this stage graduated to
the skill and the repo, which is the correct GA-R7 outcome, not an omission. Both existing
entries verified against the repo (the finding-class baseline they cite does exist) and extended
with the two reasoning traps this stage produced: the register cannot see a credential it has no
ROW for, so enumerate what exists; and diagnose a denied call by checking whether an existing
rule failed to MATCH before blaming the classifier (the measured 2026-07-26 root cause). Also
marked the ask-vs-allow precedence claim UNVERIFIED so no future session relies on it.
Noted, not actioned (hard rule 1): T24's finding-class baseline covers TIER 1 only, so tier-2/3
classes have no baselined red state and a future false green there would not be caught.
Gauntlet ALL GREEN (81), repo-lint 0-fail.
Revert: git revert this commit; the changelog moves are renames and the snapshot is derived.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

G17 opened by operator ruling; Stage 4 DoD bullets 5-6 repaired (DOCFIX-204)
...
RULING (GA-R5), 2026-07-27. Question as presented: "The node-side half of bullet 5. Nodes are
powered off by the READY-handoff ruling, so no node-side probe can run as things stand. Either a
gated rescue-boot check on one node per DC now (closes it inside Stage 4), or split it into its
own gate row targeted at Stage 5 first boot (GA-R6 E3 explicitly permits this; a conditional
close is not permitted)." Operator answer, exact utterance: "split it into its own gate row".
Recorded in the G17 row of docs/CURRENT-STATE.md (the authority); pushed before dependent work.
G17 "Per-DC artifact source reachable FROM A NODE", [V], OPEN. dc0 -> curl 200 from a booted
node against the D-135 item-1 mirror; dc1 -> apt fetches through the proxy at 10.12.68.4:3142,
since dc1's ruled path is the CACHING PROXY with no node-facing mirror (D-135 amendment) and
checking it as one fails by design. Trigger: Stage 5 first boot. The row states that G17 is NOT
a Stage-5 precondition -- Stage 5's bootstrap needs open edge egress for the juju agent stream
and snaps (D-135 items 2-3 unbuilt), a different path from the apt artifact source.
Stage 4 retains bullet 5's rack-side half: the source answers on its own address with an
attested-current sync. dc1's proxy PASSES; dc0 pends the sync re-run.
DOCFIX-204 -- bullet 6 was UNSATISFIABLE and its stale text had spread to four surfaces. "NTP
from the DC's own OPNsense edge working" is superseded by D-129(iv) (RULED 2026-07-21, "Keep
MAAS hierarchy", no NTP role on the edge): the DoD asked for confirmation the edge is the time
source, which the ruling had already refused, so a correctly-built DC could never meet it.
Repaired in the phase-3 DoD (bullet 6 struck, bullet 5 rewritten per-DC), the phase-3 Step 7
(REWRITTEN -- it branched on gap #5 that D-135 resolved, applied one mirror check to both DCs
which fails on dc1 by design, and asked for checks "from a deployed node" that the READY handoff
makes impossible), the workflow-doc Gate cell (which also still said "Nodes deployed",
contradicting DOCFIX-200), the buildout design, and the phase-4 prerequisites (same "nodes
Deployed" error -- exactly the expectation DOCFIX-200 removed to stop Stage 5 breaking).
phase-4 also gains a block making it the OWNER of G17's captures, warning that first boot is the
observation window and missing it forces a deliberate rescue-boot.
Text and gate-record only; no live state touched. repo-lint 0-fail. DOCFIX next-free -> 205.
Revert: git revert this commit; all changes are documentation and the G17 gate row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

creds consolidation batch: SEC-021(b) dc0 power key, SEC-025 NetBox GUI, V2 ruled deferral
...
Operator asked whether vcloud holds a consolidated set of login creds for every account that
exists, and what is missing / needs creating / was never moved in. Audited, then cleared the
consolidation batch on operator direction ("clear the whole consolidation batch first").
The audit's own headline: creds-audit read CLEAN on all three sites while the matrix returned
13 findings -- and the two most consequential gaps were in NEITHER surface. They were found by
enumerating the accounts that ACTUALLY EXIST. Absence of a ROW is invisible to the register,
which generalises D-137's founding argument one level up.
VERIFIED POSITIVE (both previously only asserted):
- MAAS account set COMPLETE: all 6 live accounts accounted for; admin + operator passwords on
vcloud, juju-vr1-dc0/dc1 random+unstored BY RULING with API keys present, MAAS +
maas-init-node MAAS-internal.
- tier-3 V1 now MEASURES maas-admin-password byte-identical to the headend source-of-record,
so SEC-020's stale-trap risk is clear as of this date.
DONE:
- dc0 SEC-012 power key consolidated to vcloud + .pub DERIVED (SEC-021(b) as written).
MEASURED FIRST, because the naming looked like a defect and was not: the headend
maas-virsh_ed25519 and the snap's id_ed25519 are the SAME key; it IS dedicated (distinct
from the dc0 service key, which is what SEC-012 requires); and dc0 using the snap's default
identity is SEC-016's RULED design. So no re-mint, no live power path touched.
- dc1 svc .pub backfilled to the headend store (public-key material, sha256-verified).
- NetBox web-GUI admin password consolidated -- a HUMAN login that had never left the VM it
was minted on, the third instance of the SEC-009/SEC-020 miss class. SEC-025 OPENED for the
at-rest exposure the copy CREATES, not the gap it closed. Open rows 20 -> 21.
- V2 taught the ruled-deferral state: SEC-006's standing "revoke at completion of this
deployment" ruling is now ACKNOWLEDGED (still naming the credential live and exposed)
instead of failing every run. Reissuing the token would have CONTRAVENED that ruling, so the
register was what needed to change. Match demands the cased state word AND explicit operator
ruling attribution, and cannot cross a ledger table cell -- T58/T59 lock the evasion out.
- Added --ledger (default unchanged): V2 read the register via --repo, which the harness must
point at the real repo for S4, so V2 had shipped with ZERO harness cases. T56-T59 added.
Findings 13 -> 7. Matrix 82 rows, harness 60/60 (was 56), creds-audit CLEAN x3, gauntlet ALL
GREEN (81), repo-lint 0-fail. The register is NOT green and is not expected to be.
RESIDUAL, all recorded: dc0-edge-api x2 (the opnsense-api.txt re-mint is a live edge mutation,
deliberately EXCLUDED from this batch), S5 x3 (RULED by SEC-016 -- needs a ruled-exception
mechanism, operator decision), S6 conflation x1 (the SEC-020 defect), E4 x2 (Stage-5/6 rows).
LOGGED NOT ACTIONED (hard rule 1): no registered root/console credential at EITHER DC edge
(measured absence of row/manifest/SEC row; what those passwords ARE is UNKNOWN and
deliberately unprobed per hard rule 2 -- vector is the LAN-reachable GUI and serial console,
not SSH, which is key-only and proven); plus the two structural blind spots that let it hide
-- S5 compares only cardinality=per-DC while all six per-site rows are office1-only, and
vm-secret-locations declares no rack/edge/cloud/unit/client location though the checker
accepts them.
Revert: per-item reverts in docs/changelog-20260727-creds-consolidation.md. The headend, snap
and NetBox VM source copies were never modified, so every file move is reversible by deletion.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

SESSION CLOSE 2026-07-26 -- D-137 build + committee audit + remediation (GA-R4)
...
Bounded 15-line summary in docs/session-ledger.md; full body archived to
docs/archive/session-20260726-d137-build.md in this same commit (GA-R4
rule 2). Status remains CURRENT-STATE.md's alone (GA-R1).
GA-R4 F1 cap handled as designed: writing the close summary took the ledger
to 300 against the 300-line cap, so the next-oldest summary rotated out --
a long session forces older summaries out rather than being truncated
itself. Ledger 280/300, close summary 15/15.
GA-R7 memory review: the creds-folder-convention entry asserted the D-137
matrix was NOT BUILT, which this session falsified. Corrected, and the
reasoning-trap half kept (creds-audit CLEAN is still not evidence of
completeness, because absence is invisible to a declaration-based sweep).
Memory index line updated to match.
Stage 4 stays OPEN; no stage closed by this session. The live mission did
not move -- the DC1 Stage-5 chain is where it was at session open, and the
next session resumes it per CURRENT-STATE.
Gauntlet ALL GREEN (81), repo-lint 0-fail, ledger-scan exit 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-26 |

session-ledger: rotate oldest-first to restore the GA-R4 cap (413 -> 280)
...
The live ledger was 413 lines against GA-R4's 300-line cap, a breach the
2026-07-25 close recorded as OWED and did not perform.
Rotated oldest-first as amendment F1 specifies: the eight summaries from
2026-07-18 through the fifth 2026-07-21 session moved VERBATIM to
docs/archive/session-ledger-rotated-20260726.md. Sessions from 2026-07-22
onward stay live. Nothing lost -- 8 moved + 8 remain = the 16 that were
there, and each rotated summary still points at its own archived full body.
TIMING: F1 binds the cap at session close; this was done mid-session at
operator direction, which is early rather than late. Rule 3's protection (an
open session's in-flight section is never rotated) is not implicated -- this
session has no in-flight section in the ledger.
Machine-derived block re-seeded from a fresh scan; fences intact. It had gone
stale: open SEC rows 19 -> 20 (SEC-024), next-free D 137 -> 138.
A status CLAIM corrected to narrative per GA-R4 rule 5: the 2026-07-26
addendum asserted D-137 implementation was "UNBLOCKED, not started" and
directed a fresh session to build it -- both falsified by this same session
hours later. Marked superseded and repointed at CURRENT-STATE, with the
original kept as the record of where that session stood.
Gauntlet ALL GREEN (80), repo-lint 0-fail, ledger-scan exit 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

D-137: repo-carried build spec for the fresh-session handoff
...
Operator directed the build to a fresh session. The design and committee review
lived in a plan file under ~/.claude/plans/ -- outside the repo -- so a session
bootstrapping via the GA-R4 path (CURRENT-STATE -> session-ledger ->
ledger-scan) would never have surfaced it. That is a real durability gap given
repo-is-authoritative, so the spec now lives at
docs/D-137-implementation-plan.md (precedent: docs/D-068-vault-migration-plan-draft.md).
Carries the five ruled decisions and their consequences, the matrix schema
(logical keys only per the SEC-004 ruling), the checker model with file:line
precedents (provider-bundle-check for structure, sandbox-fidelity-check:131-143
for both-bounds), the three tiers, inherited constraints (metadata-only
source-grep guard, gauntlet excerpt regex, preflight 0/1/2, L1/L10), the file
list, and the acceptance test.
Explicitly instructs the next session NOT to make the first run green: the
acceptance test is that the checker REPRODUCES SEC-021/-022/-023 and the
predicted admin-openrc case as NAMED failures. A checker that passes on today's
tree is wrong. Going green is a separate remediation project.
CURRENT-STATE item 9 + the ledger addendum point at it. Auto-memory pointer
updated: policy authority is D-137 per sub-ruling 4, with a verify-first caveat
that creds-audit CLEAN is not evidence of completeness.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

D-137 sub-ruling 5 RULED + D-137 ADOPTED: implementation unblocked
...
Question as presented: "D-137 ruling 5 of 5 -- identity fold-in ... the matrix
has a principal column, which would make the conflation machine-detectable.
Fold it in, or keep it separate?" Operator selection, exact: "Fold in as a
D-137 invariant (Recommended)".
D-137 gains the invariant ONE IDENTITY SERVES ONE PRINCIPAL TYPE, enforced by
the matrix principal column: a credential serving both human and service is a
FAIL, not an observation. The SEC-020 conflation becomes machine-detectable and
needs no separate D-number -- the question SEC-020 left proposable-but-unassigned
is absorbed here. First run is expected RED by design: admin serves a human GUI
row and a service API row simultaneously, which is the defect.
ALL FIVE SUB-RULINGS RULED -> Status flips to ADOPTED 2026-07-26. Each was its
own operator exchange, committed and pushed before the next was asked (GA-R5).
Also fixes the Status LINE to lead with ADOPTED so ledger-scan attributes it
correctly (it keys on the last **Status:** line, and the entry was still being
counted as an open decision); scan now shows 4 open decisions. Ledger machine
block re-seeded, POST-CLOSE ADDENDUM added per the 07-18/07-21 precedent.
Implementation is UNBLOCKED but NOT STARTED.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-25 |

SEC-021/-022/-023: live credential defects found during D-137 matrix research
...
Recorded, NOT actioned (hard rule 1). Open SEC rows 16 -> 19. These surfaced
while gathering inputs for the credential matrix and are live defects
independent of any D-137 ruling.
SEC-021 dc0 custody defects. (a) changelog-20260719-dc0-deploy-stepB.md:263
records the dc0 edge REST API credential consolidated to
~/vr1-dc0-creds/opnsense-api.txt; that file exists for office1 and dc1 only --
no dc0 copy -- and creds-audit vr1-dc0 says CLEAN because it was never
manifested. A changelog asserting consolidation is not evidence it survived.
Not a lockout: the dc0 edge SSH key is present, D-112(c) SSH is the primary
path. (b) dc0 power key = maas-virsh_ed25519 on voffice1 vs dc1's declared
vr1-dc1-maas-power_ed25519{,.pub} on vcloud -- name/host/custody divergence.
SEC-022 two UNAUDITED shadow *-creds/ stores on voffice1 holding real key
material. creds-audit.sh:29-31 resolves under $HOME on the host it runs on
(vcloud) and has no ssh, so an entire parallel store is structurally
invisible. A scope gap in the control, not a one-off: D-128 puts Plane-2
execution on voffice1.
SEC-023 sprawl globs (creds-audit.sh:72-73) miss admin.pass, *.apikey, *.key,
*.pem, *_ed25519, maas-api-key.txt. Plus a PREDICTED exposure recorded before
it exists: phase-03-admin-openrc.sh:32,72 writes OS_PASSWORD into
$HOME/admin-openrc at Stage 5, home root, matching no glob.
Also reconciles the CURRENT-STATE G14 evidence cell to a measured 19 (it read
12 from 07-23) since this commit adds three of them, and re-seeds the ledger
machine block.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

D-137 PROPOSED: credential mint-and-consolidate pipeline -- make consolidation structural [ARCH]
...
Operator ask: a better method for minting/saving credentials, plus "a durable
rule to make sure when accounts are created there is a consolidation that
happens every time so credentials aren't misplaced or lost."
PROPOSED only -- no tooling built, no enforcement wired, no SEC-009 demotion.
Three forks are presented for ruling, one exchange each (GA-R5).
Measured diagnosis: the existing SEC-009 control CANNOT DETECT THE FAILURE
CLASS IT WAS BUILT FOR, because creds-audit is DECLARATION-based -- the
manifest IS the declaration, so an undeclared secret is structurally
invisible and a green CLEAN is not evidence nothing was missed.
- creds-audit vr1-office1 read CLEAN on 2026-07-15 while four secrets minted
on the region VM on 2026-07-13 (site-headend-install.sh:416-455) sat
undeclared; admin.pass surfaced only 2026-07-25 (SEC-020), 12 days later,
and only because a task went looking.
- No --all (creds-audit.sh:25 takes one mandatory site).
- Enforcement is PROSE in exactly one place (phase-3 runbook:498), absent from
preflight/cloud-assert/repo-lint/gauntlet -- and it did not fire at EITHER
DC standup (dc0 3 + dc1 1 undeclared at this session's open).
- No D governs credential mint/custody generally (D-069 = Vault unseal keys,
D-126 = per-env key isolation), so the rule lives only in the security
ledger -- a register of exposures, which no gate can cite as authority.
Proposal: mint-and-consolidate as ONE operation (creds-mint.sh), plus the
DISCOVERY inversion (creds-audit --all/--remote against declared VM secret
locations -- the only piece that would have caught admin.pass), plus gate
wiring, plus a site-headend-install.sh amendment at the source.
The SEC-020 identity-conflation question stays SEPARATE (not batched, GA-R5)
and remains D-unassigned.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

session-ledger: 2026-07-25 close bookend (SEC-020 MAAS admin recovery, 15 lines)
...
GA-R4 rule 1 bounded summary for the MAAS admin-account recovery session.
Landed EARLY per the 07-21 precedent -- this ledger carries FOUR
"disconnected before its bookend" entries and this is a background session,
so durable-early beats narrating a close that may not happen. Further work
this session appends a POST-CLOSE ADDENDUM.
Also FLAGS, without acting on it, a pre-existing GA-R4 F1 breach: the live
ledger was already 370 lines at session OPEN against the 300-line cap, so
rotation of the oldest closed-session summaries is OWED. Not done here --
that is a judgment call about what to archive, it predates this session, and
unilaterally rotating 90+ lines of other sessions' summaries is exactly the
record-churn the GA-R7 circuit-breaker warns about. Better placed at the
imminent Stage 4 close, with the operator aware.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

SEC-020: MAAS admin-account recovery -- consolidate `admin`, mint `operator`, creds-audit CLEAN x3
...
Operator task: recover the MAAS admin accounts and save the creds retrievably.
The task premise was FALSIFIED by measurement before any mutation: the ledger's
2026-07-25 "MAAS web-GUI login does NOT exist / never minted" was wrong. The
`admin` password was minted 2026-07-13 by site-headend-install.sh:452 and is
MEASURED working (login 204 vs 400 wrong-password control). It was merely
root-only on voffice1 and un-consolidated -- the SEC-009 miss class, not a
missing account. Scope re-ruled by the operator after that finding:
"New account + consolidate only" -- no existing password rotated.
- NEW MAAS superuser `operator` for human GUI login; password generated on
vcloud, set via stdin (never argv -- SEC-018 discipline; changepassword has
no --password and createadmin --password would expose it).
- `admin` password CONSOLIDATED byte-identical (sha256-verified) to
~/vr1-office1-creds/. NOT rotated, so the VM copy REMAINS source-of-record;
a future rotation must update both or the VM copy becomes a stale trap.
- juju-vr1-dc0/dc1 untouched BY RULING: their SEC-018/019 API keys are
load-bearing for the blocked Stage-5 bootstrap.
- Manifest backfill -> creds-audit CLEAN on all three sites (was RED: dc0 3 +
dc1 1 undeclared), closing the dc0 edge-keypair queued finding named in
vr1-dc1.manifest:18-20.
- Root cause recorded: `admin` doubles as the automation identity (19 `maas
admin` call sites in 4 scripts), so automation never needed the password and
nothing forced it into the folder. Proposable as the next-free D-number
[ARCH]; NOT assigned (GA-R3 doubt-resolves-DOWN).
- Falsified ledger claim struck+corrected; machine-derived block re-seeded
(was stale on every line: SEC 12->16, next-free D 133->137, DOCFIX 200->204).
Evidence: docs/audit/maas-admin-recovery-20260725.txt (generated, no secret
values; scanned for password bytes = 0 hits with a planted-control check).
repo-lint 0 fail; gauntlet ALL GREEN (79).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
session-ledger: 2026-07-25 close block (GA-R4, 14 lines)
...
Bounded session-close summary at the ledger tail (machine-derived fence untouched).
LEAD item = the MAAS web-GUI login gap (operator locked out; SEC-018/019 are
API/Juju-only, service accounts have random unstored passwords) -- flagged as the
IMMEDIATE-NEXT to process first on the fresh session. Records the completed record
phase (rulings/D-136/DOCFIX-201-203), DC0 mirror complete, and the pending gated
execution path. Durable for /clear.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-24 |
Session bookend 2026-07-24: DC1 proxy-build started, BLOCKED on bundle rework
...
CURRENT-STATE + ledger handoff for a fresh session (context exhausted). DC1
Stage-5 deploy setup done (MAAS creds SEC-018/-019, Juju on voffice1, vr1-maas
cloud + credentials, VIP overlay, phase-4 Step 2.0). Committee-reviewed BLOCKER:
committed bundle.yaml is still VR0 4-node hyperconverged; VR1 dc1 needs 9-node
role-separated HA (D-121 Option C) -- architecture decided, deploy artifacts
(bundle/overlays/runbook) never rendered to it. DNS confirmed green for bootstrap
(D-131 forwarder resolves external; hang can't recur) with a hard egress-OPEN
ordering caveat. Owned: fabricated "D-193" in analysis (corrected to D-121; not
persisted). NEXT SESSION: render the vr1-dc1 role-separated HA bundle + wire
overlays + de-stale phase-4, then bootstrap.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-23 |
Session bookend: Stage 4 open+carve+mirrors session CLOSED (ledger summary)
...
Syncs RUNNING at close (dc0 13G / dc1 15G); next session verifies
last-sync.status, runs the mirror node-side gate, then the stage
close-out set. Changelog stays live until stage-close consolidation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
Mirrors installed both racks, syncs RUNNING; dc1 edge pf incident resolved; HOME fix (harness 19)
...
Item 9: fresh dc1 edge passed no LAN traffic -- pf ruleset never
regenerated after v4 addressing (set-interface reloads the interface,
not the filter; dc0 masked by 07-20 plugin work). configctl filter
reload -> egress 0%/301. Appendix-A + standup-DoD + script amendment
queued to stage close. Item 10: installs PASS 15/15 both racks, first
sync HOME-under-systemd failure fixed in the unit (T19), reinstalls +
syncs running (dc0 400M/dc1 343M in the first minute). Ledger in-flight
entry added; CURRENT-STATE same-commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
Session bookend: queue-pass CLOSED (ledger summary, changelog archived, scan fix)
...
Bounded GA-R4 close entry; changelog-20260723-queue-pass.md -> docs/archive/
changelogs/; as-executed index row broadened to the window's full scope.
AT CLOSE: ledger-scan false-close defect (detached-amendment status hijack,
D-132 dropped) found by the close reconciliation itself -- fixed number-keyed
with regression cases (48/48; gauntlet 76 ALL GREEN), machine block re-seeded,
scan re-verified truthful. GA-R7 memory review: no changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
NetBox write-path residue routed to docs/netbox-write-path-findings.md
...
Open items only (#4/#5 unfixed, fidelity re-run + fix re-verify owed), gated
on the next NetBox write campaign; ledger retained block repointed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
Session bookend: G12 dc1 CLOSED + merged (edge->commission->close in one session)
...
Bounded GA-R4 close summary + machine-derived reseed (SEC 10->12: SEC-015/-016);
G14 SEC-row count reconciled to 12. dc1 substrate built + commissioned 9/9,
merged to main (a5c0a49), branch retired. Full body in the archived changelog.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-22 |
Session bookend: G12 dc1 build session closed (steps A-C + D-125 gate delivered)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
Session bookend (successor-landed): G12 dc1-authoring session disconnected mid-item-3
...
Drop-state recorded, not delivered: dc1 vars + substrate root + lib-net dc1
arm authored UNCOMMITTED in tree; gauntlet 6/76 FAILED (six harnesses still
assert the retired vr1-dc1 fail-loud arm -- capture in docs/audit/). G12 row
updated same-commit (GA-R1/C1). Working-tree authoring intentionally left
uncommitted pending harness reconcile.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GksWgeVyXqhrojhKTiS8J5
|
| 2026-07-21 |
Session bookend: queue-pass session closed (9 rulings, A9 delivery, dc1 addressing ratified)
...
Bounded GA-R4 summary appended; both same-day changelogs archived in
this close commit; netem changelog pointer updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aLU6j24tjquxgYQaAHgsV
|
D-071 point 4 RULED + D-071 ADOPTED closure: all four update-policy points ruled (GA-R5)
...
In-channel-only refreshes adopted; D-071 status ADOPTED; G15 row,
CURRENT-STATE queue item 4, ledger machine block coupled (C1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aLU6j24tjquxgYQaAHgsV
|
D-129 sub (iv) RULED: MAAS NTP hierarchy stays -- all four D-129 subs now ruled (GA-R5)
...
Status flipped to RULED; office1 install + qga retrofit re-pointed at
G13 as execution items. G13 row + CURRENT-STATE + ledger coupled (C1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aLU6j24tjquxgYQaAHgsV
|
D-129 sub (iii) RULED: per-site Tailscale = dedicated node on metal-admin, edge excluded (GA-R5)
...
Operator clarification recorded verbatim (per-site metal-admin tailscale
planned for this deployment + Roosevelt); D-107 shape becomes the
standing per-site pattern; D-131 sub-2 revisit clause never triggers.
Couplings same-commit (C1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aLU6j24tjquxgYQaAHgsV
|
D-129 sub (ii) RULED: os-frr pinned to Roosevelt design time (GA-R5, utterance quoted)
...
VR1 stays static per D-124/D-125; rules alongside D-100 link spec +
D-132 topology at Roosevelt network design. Couplings same-commit (C1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aLU6j24tjquxgYQaAHgsV
|
D-129 sub (i) RULED: COS scrapes the edge, in-scope per-DC (GA-R5, utterance quoted)
...
Status line updated (ruling authority); Step-10 exporter pin ungated at
its deployment step. CURRENT-STATE + ledger coupled same-commit (C1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aLU6j24tjquxgYQaAHgsV
|