| 2026-07-29 |

P4 is DC-aware, 3.7 closed, and lib-net's dc1 arm populated
...
DC references in pre-flight-checks.sh went from 1 (a comment) to 45. CHECK 2/4 now iterate the
selected DC's own HOSTS and resolve system_ids by pinned boot MAC on VR1 -- the cause of 8 of
P4's 11 fatals, which were the gate probing VR0's openstack0..3. Role-node scoping reuses
maas-role-tags.sh's existing D-134 utility-band rule rather than a second copy; the D-104
controller at .5 is named and excluded with its reason, its MAAS record still asserted, and
deliberately not asserted Ready since it is legitimately Deployed after bootstrap.
The two VR0-inherited expectations were RETIRED, NOT DELETED: VID 103 (D-133) and the
metal-admin gateway pin (D-134 -- measured, 10.12.8.1/10.12.68.1 are held by nothing, so the
pin was the defect). A spurious gateway still warns and a missing provider-public gateway still
fails, so both checks kept their teeth.
Item 3.7's guards are not skips: each guarded branch asserts D-133's own invariant instead --
VID must be 0 on VR1, and the metal-internal link must be MAAS type == physical, which asserts
the flat carve and is falsifiable. An UNREADABLE VLAN now REFUSES rather than satisfying the
untagged branch: `.vlan.vid // 0` had rendered "missing" and "untagged" identically.
F5: DC is validated against the D-119 token set and refuses before any gate runs, is exported,
and appears in the header and verdict -- keeping the PREFLIGHT: <verdict> token contiguous,
which ten existing cases grep.
R9 residue: dc1 arm populated (KEYSTONE_VIP_DEFAULT=10.12.64.50). The D-133 guard HELD --
METAL_INTERNAL_VID/IFACE stay unset on both VR1 arms, verified independently here, not from
reported output. Two dc-selector assertions were replaced with the new invariant and explained
in-file, never deleted to go green. The arm is hand-authored with a drift check; R9's generator
half is still owed and is recorded as such.
Corrected from prediction to measurement, and it changes the remaining work: all four other
DC-dependent consumers carry set -u, so adding the selector ALONE to
phase-04-network-{create,verify}.sh makes them ABORT with PLANE_GW[...]: unbound variable on
dc1 (reproduced). The hardcoded PROVIDER_CIDR must be derived in the same edit.
Harnesses: pre-flight-checks 31/31 (new), preflight 26/26 (was 16), dc-selector 69 (was 45).
repo-lint 0 fail.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-28 |

VIP arity gap CLOSED + R11's three ruled gate changes executed
...
provider-bundle-check.py could not express what R2 and R11 already ruled:
:137 required exactly 3 addresses per vip (a dual-family VIP is 6, so it
would have failed EVERY application) and :149's octet extraction returned
the whole string on a v6 literal, leaving every v6 leg trivially unique
and unchecked. The apex now holds the dual-family set a renderer will
emit, so the only gate that validates overlays could not validate what is
about to be produced.
Arity: a vip is now a v4 triple OR a dual-family sextet. The v6 legs are
validated against the per-DC v6 /64s READ FROM THE APEX RECORD (D-136
option (D)), reusing dc-plane-ipam.sh's (role, kind) keying -- the
provider leg takes the dedicated GUA VIP /64, admin/internal their plane
/64s. The v6 host part must MIRROR the v4 octet textually. prefer-ipv6
and the v6 legs are COUPLED in both directions: the measured L3-9 finding
is that the merge order which keeps prefer-ipv6 while dropping the v6
legs is the one that exits 0. An unreadable apex REFUSES at exit 2; a
v4-only bundle needs no apex.
R11 (D-020 amendment, ruled 2026-07-27), same pass: band 50-60 -> 50-99
in both separately-named sites; VIP_COUNT_EXPECT 11 -> 13;
EXPECT_PUBLIC_VIP deliberately stays 11 (measured -- neither vault nor
designate has a public binding); and an hacluster principal with no vip
now FAILS, since cluster_count is asserted nowhere and a 3->1 rewrite of
all 20 values produces a byte-identical PASS.
Measured consequence, not glossed: two sub-checks flip PASS -> FAIL
(designate's missing VIP; CHECK 1 at OK=11 want 13). preflight was
ALREADY exit 1 before this change and is still exit 1 after -- no deploy
path that was open is closed. Both reds are the ruled gate reporting real
work owed; per R6 the .61/.62 VIPs land before the HA overlay.
Harness 15 -> 28. Three cases RE-POINTED rather than deleted: the fixture
base splits into a pristine repo bundle and one carrying designate's
ruled .62, with new case T16 asserting the pristine bundle DOES trip the
new invariant. When .62 lands, T16 gets re-pointed, not deleted. Proven
able to both fail and pass on the same check (T16 red / T18 green).
Gauntlet ALL GREEN (84) on vcloud; repo-lint 0 fail / 604 files scanned.
Scope was operator-gated: "Fix the arity gap first, then start the
renderer", with the arity-alone vs arity-plus-R11 fork put separately and
answered "Arity gap + R11's three ruled changes (Recommended)". OPS under
GA-R3, no D-number.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
dc1 FIP pool RULED 10.12.65.0-10.12.67.254 (GA-R5); lib-net dc1 arm + assertions re-pointed
...
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-23 |
Delivery batch: lib-hosts VR1 arms, D-133 guards, appendix-A pf entry, DoD 8-9 (gauntlet 77 GREEN)
...
lib-hosts vr1-dc0/vr1-dc1 populated from the measured identity table
(tofu-name keys, pinned boot MACs, D-134 octets, per-DC power URIs +
tags) + host_sysid_by_bootmac (the VR1 resolver) + one-selection guard;
dc-selector rewritten, 48 PASS. reenroll-hosts + carve-host-interfaces
gain explicit vr1-* refusals (VR0 flows superseded by D-133 -- populated
arms must not enable them). lib-net vr1-dc0 VID caveat. Appendix-A:
edge pf-never-regenerated symptom (masking trap named). Phase-2 DoD:
items 8 (filter reload + LAN egress probe) + 9 (dc-mirror), item 4
range corrected to D-134 .201-.254. CURRENT-STATE same-commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-22 |
G12 dc1: item-3 substrate landed + harness reconcile (gauntlet 76 ALL GREEN)
...
Lands the disconnected session's authored tree (vr1_dc1 vars, vvr1-dc1 +
uplink modules, inner root vr1-dc1-substrate/ with 54 pre-pinned MACs,
lib-net dc1 arm + one-selection guard) and delivers changelog item 4:
six harnesses reconciled to the ratified dc1 selector arm, phase-00
PLANES/lib-net parity guard (exit 2, refuses cross-DC planning),
rbd-mirror + radosgw parent-shell selection (dc1 reminder now shows
10.12.84.0/22, not dc0's). Gauntlet ALL GREEN 76
(docs/audit/gauntlet-20260722-g12-reconcile.txt); repo-lint 0-fail.
G12 next gated step unchanged: operator-gated apex --commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-14 |

D-119: region-qualify the VR1 DC namespace -- C3 / gap #19 CLOSED (Stage 3 unblocked)
...
THE BUG: the token `dc0` meant TWO DIFFERENT CLOUDS depending on the file --
VR0's LIVE testcloud in scripts/lib-net.sh, VR1's FIRST DC in the NetBox
importer. One string, two clouds, one of them in production.
THE RULING (operator): the repo adopts the apex's names verbatim.
vr0-dc0 VR0's DC0 the LIVE testcloud (a DIFFERENT region)
vr1-dc0 VR1's FIRST DC GUA 2602:f3e2:f02::/48
vr1-dc1 VR1's SECOND DC GUA 2602:f3e2:f03::/48
Bare dc0/dc1/dc2 are now REJECTED LOUDLY everywhere.
D-119 COMPLETES D-117, it does not reverse it: it executes D-117's own amendment
across the three surfaces D-117 never touched. ZERO NetBox writes -- the apex was
already correct and self-consistent (MEASURED: f02::/48 -> vr1-dc0, f03::/48 ->
vr1-dc1); the REPO was the only surface out of step. Renaming the apex to match
the repo was considered and REJECTED (production IPAM write; VR1 would become the
only 1-indexed region; and vr1-dc1 would mean VR1's FIRST DC while vr0-dc1 means
VR0's SECOND).
THE PRIZE: the importer's DC->site map is now an IDENTITY -- there is no offset
table left to get wrong, and an assert enforces it. The original defect was
precisely a WRONG LOOKUP TABLE. The bug class is deleted, not defended.
TWO REAL BUGS the naming fix ALONE would NOT have closed (found by review sweep):
- BREAK-1: descriptions were built with f"VR1 {dc.upper()} ..." -- under D-119 that
renders "VR1 VR1-DC0 provider-public" on all 36 prefixes. Same class as the
original bug (deriving a label by munging a token), hidden in the description
field where slug-focused review missed it. Now looked up from SITES[name].
- BREAK-2 (the important one): DC_GUA_PREFIX was NEVER cross-checked against --dc.
`--dc vr1-dc0 DC_GUA_PREFIX=<f03>` was ACCEPTED: it writes the SECOND DC's GUA,
carved with the FIRST DC's ULA nibble, scoped to the FIRST DC's site -- a
silently mis-bound datacenter assembled from two disagreeing sources. Identity-
mapping the slug leaves the ADDRESSING free-floating. Now guarded by EXPECTED_GUA.
ALSO: vdc1/vdc2 -> vvr1-dc0/vvr1-dc1 (D-114 amendment). D-114's own DR primitive is
`virsh destroy vdc1`, which read as "destroy VR1 DC1" while MEANING "destroy VR1
DC0". A mislabelled destroy command in a DR drill is not cosmetic. Neither VM is
built, so it is free. voffice1/Office1 KEEP their number (operator ruling).
Env var: DC1_/DC2_V4_SUPERNET -> VR1_DC1_V4_SUPERNET (both old names rejected).
rbd-mirror's --site-name aligned: `--dc vr1-dc0 --site-name dc1` was a re-created
two-namespace collision on one command line.
TESTS: dc-selector 21->30, prefixes-import 40->82 (identity invariant; EXPECTED_GUA
in BOTH mismatch directions; mismatched run writes NOTHING; matching pair still
succeeds; no munged description). GAUNTLET ALL GREEN (57). repo-lint 0 fail.
The old harnesses PINNED THE WRONG MAPPING -- they would have gone green while
enforcing the bug.
THE tofu apply IS NOT DONE -- IT IS GATED. Plan: 11 to add, 0 to change, 11 to
destroy (libvirt object names are ForceNew; moved{} makes the plan reviewable but
cannot suppress a replace). MEASURED SAFE: all 11 are EMPTY -- no guests, no
volumes, Stage 3 hasn't run. Office1's live objects are not in the plan.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| 2026-07-10 |
DOCFIX-151: $DC selector convention for lib-net.sh/lib-hosts.sh (gap #1 closed)
...
Adds lib_net_select_dc() (dc0/dc1 no-op per D-101 inherited-layout ruling,
dc2 fails loud pending NetBox) and lib_hosts_select_dc() (dc0 no-op, dc1+dc2
both fail loud -- no per-DC host enrollment exists yet). Backward compatible;
21/21 new harness tests green; full gauntlet unaffected (A/B via git stash).
Unblocks the Stage 5 runbook's "high reuse" claim in the DC-DC deployment
workflow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|
| 2026-07-08 |
DOCFIX-138: S8b -- centralize KEYSTONE_VIP default into lib-net.sh (single source of truth)
...
The keystone endpoint literal 10.12.4.50 was the default in 6 scripts (3 forms); now
all reference lib-net.sh KEYSTONE_VIP_DEFAULT (hard-rule #3). Sourced lib-net where
absent (verified source-safe). Each stays env-overridable. Resolve-checked; gauntlet
39/39, lint 0 fail (L7 re-recorded). S8 fully done (S8a+S8b); S8c won't-do.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
DOCFIX-134: S8a -- FIP pool literals to lib-net.sh (single source of truth)
...
D-003 FIP pool (10.12.5.0-10.12.7.254) was hardcoded in phase-04-network-create
(env-overridable) and -verify (pinned). Both already source lib-net.sh; added
FIP_POOL_START/END there and referenced them. Gauntlet 39/39. S8b (KEYSTONE_VIP,
needs sourcing into client-critical scripts) + S8c (python cross-source) deferred
for operator decision -- bigger than the S estimate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| 2026-06-30 |
D-060: revert to Pattern A; supersede D-057/D-058
...
Revert provider NIC to Pattern A (MAAS-built OVS br-ex) on the existing D-052/D-053 scheme. bundle.yaml clean bf7de5a checkout (provider-public x11, VIP triple .4/.8/.12, all 4 br-ex MACs); lib-net.sh + carve back to D-052/D-053; NEW provider-bundle-check.py gate; standup retargeted; teardown.sh + teardown runbook updated. Retire: phase-00-maas-recidr.sh, provider-vip-standup.sh, d057-bundle-check.py, and the 3 provider-vip/reconfigure runbooks.
|
| 2026-06-29 |
Provider VIP carve updates
|
| 2026-06-27 |
|
| 2026-06-26 |
|