Newer
Older
openstack-caracal-dc-dc / docs / archive / changelogs / changelog-20260727-stage5-grounding-audit.md

Session changelog -- 2026-07-27 -- Stage-5 grounding audit

ONE changelog for this session (GA-R2/D1). Branch dc-dc-stage5-grounding-audit off post-merge main at 71519a2. Status claims live ONLY in docs/CURRENT-STATE.md; this file records what CHANGED and how to revert it.

Operator direction: a full reconciliation and grounding from a fresh session before Stage 5 opens -- current status, the changes required to reach the as-built, configuration versus project goal, readiness to enter the next stage error-free, then a review of the upcoming stages. Run autonomously while the operator was away, with rulings QUEUED not adopted.


1. Session-scoped permission expansion (settings.local.json -- GITIGNORED)

The operator offered a broad exception; a SCOPED READ-ONLY expansion was taken instead, on the grounds that the task is read-only by construction and the ask rules ARE the enforcement of hard rule 3 (CLAUDE.md says not to work around them). Design: the allow list enumerates READ verbs, the ask list enumerates MUTATING verbs, and anything matching neither falls through and FAILS SAFE -- logged UNMEASURED, never assumed absent.

Added (allow): read-only shell tooling (sed -n, head, tail, wc, sort, uniq, comm, diff, find, stat, cut, nl, file, column, tee docs/audit/*); read-only virsh (local + quoted remote variants); ssh voffice1 *maas admin * read* and query-power-state; the per-DC artifact and rack checkers; Write/Edit on docs/**; git commit/git push; WebSearch + eight upstream doc domains. Replaced (ask): the five broad ssh voffice1 "maas admin <noun> * rules, which walled READ calls because ask beats allow regardless of specificity, with 23 verb-scoped MUTATION asks. Quoted variants used throughout, per the 2026-07-26 finding that a quote breaks pattern matching. NOT granted and not requested: jumphost sudo, tofu apply|destroy|import|state rm, any maas admin write, juju deploy|add-model|bootstrap, opnsense-api.sh POST, scripts/* apply|install, *--commit*, rm *. Edit(.claude/settings*.json) deliberately LEFT as ask so the session could not widen its own permissions unattended. Deny list and the PreToolUse guard untouched. Deliberately NOT requested: blanket Bash(cat *) -- the guard's NEVER list covers vault-init/, as-executed/, tenant-*/, *-cred.txt, appcred, *.pem but NOT the ~/vr1-*-creds/ key files, so a blanket cat would open exactly the hazard CLAUDE.md forbids.

REVERT: delete the added allow entries and restore the five original ssh voffice1 "maas admin <noun> * ask rules. The file is gitignored, so docs/audit/stage5-grounding-audit-scope-20260727.md section 6 is its only durable record. REMOVE THE BLOCK AT SESSION CLOSE.

Flagged NOT fixed (hard rule 1): Bash(awk *), Bash(grep *) and Bash(python3 *) were ALREADY broadly allowed and can each read a ~/*-creds/ key file without tripping the guard. Pre-existing gap, not introduced here.

Known remaining wall for a future session: there is no Bash(timeout *) allow rule. Lens 1's timeout 240 bash scripts/preflight.sh fell through to the auto-mode classifier and was denied, even though bare bash scripts/preflight.sh is allowed -- the timeout prefix means no rule MATCHES. Same failed-to-match class as the 2026-07-26 quoted-sudo finding, NOT a classifier override. Add Bash(timeout * bash scripts/*) (or drop the prefix) if a future session needs it.

2. Deliverables (all new files)

  • docs/audit/stage5-grounding-audit-scope-20260727.md -- the charter, committed BEFORE any agent was spawned so a session that died mid-run still left the plan.
  • docs/audit/stage5-readiness-20260727.md -- the ordered precondition checklist.
  • docs/audit/stage5-committee-raw-20260727.md -- all 7 lenses verbatim, kept separate from synthesis so synthesis cannot quietly reshape a lens's claim.
  • docs/audit/queued-rulings-20260727.md -- 11 Stage-5-blocking + 4 standing questions, GA-R5 shape, blank utterance lines. NONE adopted.
  • docs/audit/stage5-live-measurement-20260727.txt -- this session's measurements.
  • docs/audit/outer-plan-20260727-stage5-audit.txt, docs/audit/preflight-20260727-stage5-audit.txt, docs/audit/stage5-creds-privileged-20260727.txt -- captures.

REVERT: git revert the three audit commits (514f0aa, 6d511e8, fb8f6bc, de11bf4); every file is new.

3. CURRENT-STATE edits (GA-R1 amendment C2 -- measurement corrects the record

in the capture's own commit; also what repo-lint L10 requires)

  • Section 7 pin table: Juju row corrected to the MEASURED 3.6.27 on voffice1 (was 3.6.25). In-channel patch refresh, which D-071 permits -- policy-compliant drift, not an incident, but it is the client that will bootstrap the controller.
  • Section 7: NEW row recording that the openstack client is ABSENT on BOTH hosts while ten Stage-5/6/7 scripts invoke it. No prior surface carried this.
  • Section 5: convergence history extended with the three-root ZERO-DIFF re-confirmation and the validity proof behind the inner pair.
  • D-137 block: the 2026-07-27 privileged re-run recorded as a RE-CONFIRMATION of the 2026-07-26 run, not a newly-closed item (an overclaim corrected mid-session).
  • Section 1: the audit's verdict and pointers to the five artifacts.
  • Gate row G3 CORRECTED -- the one mechanical fix taken. See below.

REVERT: each edit is additive except G3; restore G3's prior cell text from git show de11bf4^:docs/CURRENT-STATE.md.

4. The single mechanical fix (deliberately chosen, not opportunistic)

Gate row G3 read OPEN with "FREEZE holds for un-gated surfaces", contradicted by its OWN cited evidence file (docs/audit/phase6-exit-runs-20260719.md:84,91-92 records the re-signature PASS and "G3 + G11 CLOSED") and by row G11 and section

  1. No ruling was required -- two surfaces already declared it closed. The consequential half was the FREEZE clause, not the state token: left standing it would have blocked the very DOCFIX batch this audit queues.

REVERT: restore the prior cell text (see 3).

5. Logged, NOT executed (hard rule 1)

The 21-item DOCFIX remediation batch in Phase 3 of the readiness doc, and every gate-integrity fix in Phase 4. Nearly every runbook fix interlocks with an unanswered ruling, so landing them now would encode assumptions. No D-, DOCFIX- or BUNDLEFIX- number was assigned; next-free is unchanged at D 138 / DOCFIX 205 / BUNDLEFIX 053, correctly, because nothing was remediated.

6. Owned errors, recorded rather than quietly corrected

  • The per-DC artifact checkers were first run LOCALLY on vcloud, producing a comprehensive FAIL with every probe MISS -- output indistinguishable from "never installed". Both scripts are designed to be PIPED TO THE RACK. Corrected by direct functional probe; lens 2 independently ran the canonical piped form and got PASS on all three. The scripts were not at fault.
  • The first exit-code reading of those checkers captured tail's status through a pipe, not the script's. Re-measured: both correctly exit 1.
  • The measurement capture initially waved P3's "33 pins, 0 fail, 33 warn" through as expected. Lens 4 established the CAUSE was a missing juju binary, so ZERO pins are verified against charmhub. The count was expected; the cause was not. Capture amended.
  • The privileged credential sweep was first described as closing an item outstanding since 2026-07-26. It was not -- that sweep completed on 07-26. Today's run RE-CONFIRMS it against the current 82-row matrix.

7. Committee mechanics

Seven read-only lenses, each under a contract requiring: no mutating shape; the claim / evidence / blocks-Stage-5 / disposition schema; and any denied or prompted tool call reported UNMEASURED with its exact command, never folded into a negative finding. Lens 5 died on an API error with no output and was relaunched with the interim findings folded in. Lens 1 hit one classifier denial (timeout 240 bash scripts/preflight.sh) and correctly reported it UNMEASURED; root cause was a missing Bash(timeout *) allow rule -- a failed-to-MATCH, the same class as 2026-07-26, not a classifier override. The audit session had measured preflight independently, so that gap was closed.

8. RULINGS TAKEN (operator returned; one exchange each, GA-R5)

Fourteen rulings, two withdrawals, one gate opened. Ruling AUTHORITY is each D-number's Status block in docs/design-decisions.md, or docs/CURRENT-STATE.md for the OPS ones. docs/audit/queued-rulings-20260727.md records the questions as put and the exact utterances.

# Outcome Recorded as
R1 ceph-osd gets a real second disk, 4 storage nodes/DC (8 volumes, not 18) D-121 AMENDMENT
R2 Dual-stack as ruled D-101 RULING NOTE
R2a WITHDRAWN -- literals already assigned under D-111 --
R3 Finish the jumbo underlay (two lagging segments) D-101 RULING NOTE
R4 DC-aware band tool; v4 + FIP now, v6 after the carve D-134 AMENDMENT
R5 Designate deploys at Stage 5, configured at Stage 7 D-106 RULING NOTE
R6 VIP gaps first, then the HA overlay whole D-121 RULING NOTE
R7 Per-DC independent Octavia PKI D-109 AMENDMENT
R8 Octavia creates and owns its own IPv6 network D-101 RULING NOTE
R8a Extend the o-hm0 verifier to compare MTUs D-101 sub-ruling (OPS)
R9 Derive lib-net's dc1 arm from the overlay + drift check D-119 AMENDMENT
R10 Fix the stale clone; all working directories current CURRENT-STATE (OPS)
R11 vault .61, designate .62, dual-family triples D-020 AMENDMENT
R12 Fold time verification into G17; make its check falsifiable EXECUTED in the G17 row
R13 Register-first credential fixes, no new tool D-137 SUB-RULING 6
R14 WITHDRAWN -- the register already did what the question assumed it could not --
R15 All three gate floors, harness MANIFEST not a count CURRENT-STATE (OPS)
G18 OPENED -- IPAM apex completeness, BLOCKING, deferred until the cloud is live CURRENT-STATE gate table

REVERT: each ruling is one commit, 420275f..10b1abc; revert individually. R12 also EXECUTED a change to the G17 gate row -- reverting it restores the prior [V] text.

NO NUMBER CONSUMED: next-free stays D 138 / DOCFIX 205 / BUNDLEFIX 053, because every ruling's execution remains LOGGED NOT EXECUTED.

9. SESSION-CLOSE SWEEP + SKILL SWEEP

Sweep capture: docs/audit/queued-findings-20260727-stage5-audit.txt. It found THREE stale surfaces the audit itself created (readiness doc's 13 stale NEEDS-RULING markers, queued-rulings' "nothing is adopted" header, six blank utterance lines) -- all fixed in 5dd7b2c.

SKILL SWEEP done although NO STAGE CLOSED, on operator direction. Folded into .claude/skills/openstack-cloud-ops/SKILL.md:

  • A FINDING IS AN OBSERVATION, NOT A CONCLUSION -- measure before putting it to the operator; four of the first six questions changed shape, three were withdrawn or re-scoped.
  • A CITATION IS AN EXISTENCE CLAIM; ONLY ITS CONTENT IS EVIDENCE -- both bugs behind the v4-only lb-mgmt draft failed on reading, and the conclusion inverted.
  • RULED IS NOT BUILT -- D-134's bands and D-020's vault VIP were both ruled and never implemented, and passed every gate for weeks. Into references/script-authoring.md: the repo-lint L5 heading trap, the commit-gated-on-lint pattern, and the space-aligned .tsv. Into references/operating-discipline.md: the probe PATH determines the answer. Snapshot REGENERATED as .claude/skills/openstack-cloud-ops-consolidated-20260727.md -- 1695 lines, ASCII/LF byte-verified, all five new items present.

REVERT: git revert the close commit; the skill edits are additive and the snapshot is a derived artifact regenerable from any commit.