| 2026-07-29 |

Dangling-reference sweep: one dead pointer, and the retired DC1/DC2 spelling in two places
...
Swept every repo-relative path referenced by this session's changed files against the tree.
Most hits were regex artefacts from wrapped prose; two were real.
bundle.yaml pointed the Octavia PKI at runbooks/01a-octavia-pki-generation.md, which does not
exist and has no history in this repo. The generator is phase-01-bundle-deploy.md Step
1.0-GEN, now run once PER DC with DC exported. A reader following the old pointer would have
found nothing and had no way to know whether the step existed elsewhere.
The phase-6 hostnames-overlay proposal still used the dc1/dc2 spelling that item 3.1 retired
this session -- the exact ambiguity 3.1 measured, where "DC1" meant vr1-dc0 on one surface and
vr1-dc1 on another. Region-qualified, with the reason recorded inline. The surrounding text is
deliberately left as-is otherwise: it correctly states the files do NOT exist and must never be
passed to --overlay, which is the honest framing for a proposed-but-unauthored pattern.
provider-bundle-check still PASSes for both DCs; repo-lint 0 fail / 618 files.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

3.8 fixed per-DC -- and the fix exposed two repo records naming the wrong NIC
...
bridge-interface-mappings is out of bundle.yaml and per-DC in overlays/vr1-dc0-machines.yaml
(new) and vr1-dc1-machines.yaml. The machines overlay was chosen over the vips overlay for a
measured reason: both *-vips.yaml are marked GENERATED / do-not-hand-edit, so a key added
there is clobbered on the next render, and preflight.sh already assembles ${DC}-machines.yaml.
Creating the dc0 file also closes NEW-3 from the other side -- preflight's [ -f ] guard was
silently skipping a file the deploy needs.
THE WORSE DEFECT THE FIX EXPOSED. dc0's compute provider-public MACs are 52:54:00:8c:2a:8c /
52:54:00:50:48:88 -- position [1] in each node's macs list. Audit register row U5 and the
D-124 correction both name the [0] values, which are the PXE/boot MACs, and D-124 further
tells the reader to source them "from lib-hosts.sh" -- verified independently: lib-hosts.sh
declares only HOST_BOOT_MAC and cannot supply a provider MAC at all. Following either record
would have bridged br-ex onto the boot NIC: not a missing mapping that fails loudly, but a
wrong one that comes up and misbehaves. Confirmed three ways -- substrate main.tf:109-116 list
order, the macpin plan capture, and live MAAS showing br-ex over enp2s0. The correct values
and the [0]-vs-[1] trap are now recorded in the overlay, next to the data.
NEW-1: 10.12.12.0/22 was named as the geneve/DATA plane; that is metal-internal, data-tenant
is 10.12.16.0/22. Deliberately not swept repo-wide -- the 10.12.12.5x VIP legs are correct
metal-internal values.
NEW-2 phantom vr0-dc0-testcloud.yaml removed. NEW-4/6 stale octavia-pki name and the phantom
${DC}-hostnames.yaml removed (juju errors on a missing overlay). NEW-7 scale-up removed from
the VIP deploy command per R6, ${DC1_MODEL} -> ${DC_MODEL}.
R5/D-106 BUILT: phase-6 Step 5 rewritten configure-not-deploy, the unsatisfiable diff gate
replaced by a presence-and-state assertion, and the "no designate block exists" claim
corrected against bundle.yaml. os-public-hostname stays unset, per the ruling's refused
option (c).
Verified independently rather than from reported output: provider-bundle-check PASSes for
both DCs in preflight P2's own overlay order. repo-lint 0 fail / 617 files.
Logged not fixed: provider-bundle-check treats an absent bridge-interface-mappings as a silent
skip and never checks the MAC prefix against --dc, so it could not fail on either variant.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

Ruling 3 commit 1: bundle.yaml is VIP-free; dc0's VIPs are now a RENDERED overlay
...
The 11 inline vip: lines are gone from bundle.yaml and live in
overlays/vr1-dc0-vips.yaml, GENERATED by scripts/render-dc-overlays.py from
render/values/vr1-dc0-vips.yaml -- the renderer's first real output.
placement's then-empty options: block was dropped rather than left parsing
as null. Ruling 3's dual-stack ADD is commit 2 and is NOT in here.
PROVEN NEUTRAL by the ruling's own named check: provider-bundle-check on the
pre-extraction bundle and on the merged pair produce line-for-line identical
output, same known designate failure included. A structural diff separately
confirmed only vip moved -- applications 56 -> 56, relations 108 -> 108,
every other key byte-identical.
The 11 inline comments were carried, not dropped: extracted verbatim by
parser rather than retyped, via new optional per-app comment support in the
renderer. An app with no comment emits none, so dc1 still reproduces
byte-for-byte at 1634 bytes. The B1/B5 tokens stay DEFINED in bundle.yaml's
header and the overlay header names that, so the references do not dangle.
The blast-radius repair is the bulk of this, and every item was found BEFORE
the edit by the read-only agent sweep:
- preflight.sh P2 validated the bare base (11 phantom failures post-move) ->
merged input.
- pre-flight-checks.sh CHECK 1 read the base as raw text and would have seen
ZERO VIPs. This is BLOCKER-1, fixed the ruled way and not by bumping the
count. Measured trap: the file sets IFS=$'\n\t', so a space-joined string
reached grep as ONE filename, grep exited 2, pipefail propagated and the
gate died silently mid-check. Fixed with a bash array.
- phase-01's RUN block gates juju deploy on 11/11/0 and would have read
0/0/0 and ABORTED THE DEPLOY. Both guards now span base + overlay, and a
second latent bug was fixed in the same edit: grep -c over two files prints
one count PER FILE, so the bare $( ) captured a two-line string and every
numeric test would have failed anyway. Now awk-summed; verified 11/11/0.
- phase-01's Octavia SAN derivation raised KeyError, swallowed by || true
into an empty VIP. Now reads the overlay, deriving 10.12.4.57.
- phase-00 teardown, dc-dc-phase4's "NO VIP edits" guidance, appendix-A L3,
and render-baseline's now-unverifiable bundle hash all repaired.
Harness 30 -> 31. The fixture base is now bundle + dc0 overlay, since that
pair is the deploy input; T16 renamed to match. NEW T31 asserts the bare base
fails for every clustered principal, so "deployed without its overlay" is a
tested state rather than an assumption.
Gauntlet ALL GREEN (85) on vcloud; repo-lint 0 fail / 610 files scanned.
Still red and expected: CHECK 1 at OK=11 want 13, and designate -- R11's
.61/.62 remain ruled-but-not-built, which is commit 2's job.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-24 |

vr1-dc1 bundle render (9-node role-separated) + expansion review record
...
Render (committee Fork-2 hand-render), validated by the extended checker:
- bundle.yaml: machines "8"-"11" (tags=openstack) -> "0"-"8" role+DC tags (block
style); every `to:` re-homed (quorum trio -> control 0/1/2; nova-compute 3->2 on
compute 3/4; ceph-osd -> storage 5-8; scaled apps + utilities -> control);
ovn-chassis -> the 2 dc1 compute provider MACs (52:54:01:d1:04:02/05:02).
- overlays/vr1-dc1-machines.yaml (NEW): per-DC retag (machines-overlay merge is
VERIFY-LIVE at `juju deploy --dry-run`).
- overlays/dc-ha-scaleup.yaml: tokens rendered to logical control ids 0/1/2
(DC-neutral); header updated; stale ceph-osd-3 comment -> 4.
- provider-bundle-check.py: ovn-chassis MAC check skips the VR0 Pattern-A set on a
role-separated bundle (the validator CAUGHT a real YAML flow-comma render bug).
Validated: base + FULL dc1 deploy input (3 overlays, --dc vr1-dc1) PASS; harness
15/15; gauntlet ALL GREEN (78); repo-lint 0-fail.
Expansion review (3 read-only reviewers) recorded in
docs/audit/stage5-expansion-review-20260724.md: relations/bindings/subordinates
HOLD under role-sep (uniform 6-NIC, SEC-011); no channel/pin change; open
resolve-before-deploy items (vault VIP, v4-vs-dual-stack phasing) + deploy-gate
script gaps + VERIFY-LIVE gates. NetBox->deploy coupling routed to Chat as a new
PROPOSED D-number (Fork-2 escalation). No cloud state mutated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|

Stage-5 dc1: committee review + Fork-1 ruling (D-104 amendment) + BUNDLEFIX-052
...
Track-2 bundle-render blocker, committee-adjudicated (4 read-only lenses:
Roosevelt-delta / HA-DR / operational-risk / Juju-MAAS-mechanism). Every
load-bearing claim re-verified against the repo before adoption.
- Committee record: docs/audit/committee-20260724-track2-bundle-render.md
- Fork 1 RULED (operator, GA-R5): dedicated 10th per-DC controller VM ->
D-104 amendment. Capacity gate PASS (measured): 10-node x 2-DC =
854/1024 GiB (83%, FIT, 170 GiB headroom);
docs/audit/stage5-controller-capacity-20260724.txt
- BUNDLEFIX-052: removed an orphaned `bindings:` block absorbed into
ceph-rbd-mirror (clobbered its D-108 replication bindings + injected a
phantom `dashboard` endpoint -> juju deploy reject). provider-bundle-check PASS.
- CURRENT-STATE Stage-4 bullet updated same change set (GA-R1/C1).
No cloud state mutated. Fork 2/3 = OPS committee-unanimous, executed under gating.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-10 |
DOCFIX-172: full-project sweep -- bundle.yaml fixes
...
magnum-dashboard had NO bindings: block at all -- a real, pre-existing bug
(confirmed via git log, present since the D-052 explicit-bindings commit,
not a regression from tonight's DOCFIX-167 work) violating this bundle's
own stated "explicit per-application blocks" discipline. Fixed with a
minimal block confirmed against the real charm-magnum-dashboard metadata
(subordinate, only a real `dashboard` endpoint -- not a copy of
octavia-dashboard's fuller shape). Also relocated two section-header
comments that visually (not functionally) misattributed to the wrong app,
and corrected a stale "11 API charms" HA-chain count to 12. 56 apps/108
relations unchanged; provider-bundle-check.py PASS throughout.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|

DOCFIX-167: bundle.yaml -- Designate reactivation + D-108 DR mechanism (gaps #6+14)
...
Adds designate/designate-bind/designate-mysql-router/designate-hacluster
(D-106, supersedes D-019) and cinder-backup/ceph-rbd-mirror (D-108) to
bundle.yaml -- the same file this repo's jumphost uses against the live
VR0/DC0 rehearsal cloud, edited with corresponding care. Every new charm's
relation/binding shape was checked against its real metadata.yaml, not
guessed: caught and fixed three mistakes this way during self-review
(designate's real endpoint is dnsaas, not public; cinder-backup is a
subordinate with no amqp relation; ceph-rbd-mirror needs ceph-local/
ceph-remote, not a single invented binding key). Corrected ceph-mon's
rbd-mirror binding from storage to replication. Documents, rather than
invents, that ceph-remote (the peer DC's ceph-mon) needs a cross-model
relation or the manual CLI flow -- D-104's per-DC-independent-controller
design means it can't be a same-bundle relation line. Deliberately does
NOT reactivate os-public-hostname in this shared bundle (pushed to a
proposed per-DC overlay instead). Bundle parses clean (56 apps, 108
relations); provider-bundle-check.py PASS, all invariants unaffected.
Not applied to any live model.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|
| 2026-07-05 |
D-072 dashboard TLS repair (executed) + DOCFIX-089 fail-closed check + BUNDLEFIX-011
...
Identifiers consumed: D-072, DOCFIX-089, BUNDLEFIX-011.
Since-deploy dashboard VIP TLS defect fixed: cluster binding -> metal-admin
(live bind + durable bundle edit); https 200 CA-verified on both reachable
VIPs, all gates green, post-fix BOM committed. phase-03 3.3 rewritten
fail-closed; appendix-A symptom entry added; Launchpad bug draft ready for
operator submission.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FCGjrRXtbPRu5qEThw3CDz
|

vault bundle revert to 1.8/stable (BUNDLEFIX-010) + D-068 AMENDMENT + G2/G3 close (ops-update-20260705)
...
Identifiers consumed: BUNDLEFIX-010. Also records the operator's D-068
AMENDMENT (no new D number) and window addendum 15.
- bundle.yaml: vault channel 1.16/stable -> 1.8/stable, comment replaced
with amendment rationale (1.16 = incompatible charm line for this
reactive cloud). Gates: provider-bundle-check PASS, channel_assert PASS
(29 pins), repo-lint 0 fail.
- docs/design-decisions.md: D-068 AMENDMENT (2026-07-05) verbatim from
operator; 1.16 ruled out, off-EOL-1.8 remains OPEN; D-002 item-3
supersession withdrawn. Evidence: docs/D-068-vault-1.8-vs-1.16-analysis.md.
- changelog addendum 15: G2 (octavia 542) + G3 (dashboards 750/122/168)
complete; dashboard-VIP-HTTPS RCA = since-deploy build defect (haproxy
L4-masked vhost-less backend), phase-03 3.3 check fails open; G3 stands,
no revert; upstream bug + DOCFIX candidates queued post-window.
- session-ledger: jumphost fence updated; machine-derived reseeded
(BUNDLEFIX next-free 011).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FCGjrRXtbPRu5qEThw3CDz
|
| 2026-07-03 |
|
| 2026-07-02 |
|
|
|
|
|
| 2026-06-30 |
|
BUNDLEFIX: seed mysql-innodb-cluster single-node for deploy
...
num_units 3->1 + to:[lxd:8]; ramp to 3 in phase 2 via sequential add-unit (D-009). Sidesteps 3-way GR formation race that parked units blocked (metadata half-join).
|
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-26 |
D-053 rename network space fabric-data -> data-tenant Bundle: 4 bindings + 2 header-comment lines (nova-compute:neutron-plugin, ovn-chassis:data, ovn-chassis-octavia:data, octavia:ovsdb-cms). Space-name only; subnet/VLAN/role/binding-semantics unchanged. Live MAAS already on data-tenant; bundle now matches. Verifier 8/8. docs: D-053 appended (D-052 body left intact, append-only).
|
| 2026-06-25 |
D-052 explicit network-space bindings + D-051 SCS Domain Manager policy ...
|
| 2026-06-18 |
|
| 2026-06-10 |
repo: sanitation sweep -- canonical phase-NN runbook + appendices; design-decisions D-001..D-042; canonical bundle; superseded files moved to remove/ for review
|
| 2026-06-02 |
bundle: Section-G hardening (subset-rule bindings, Ceph public/cluster, raw amphora)
|
| 2026-05-30 |
BUNDLEFIX-007: drop cinder loop block-device storage (Ceph-backed cinder; loop incompatible with LXD container placement)
|
| 2026-05-29 |
bundle: dual provider+metal HA VIPs on API charms (BUNDLEFIX-006, D-020)
|
bundle: add memcached + nova-cc relation (BUNDLEFIX-004)
|
bundle: bind mysql-router subordinates to metal (BUNDLEFIX-005)
|
fix(bundle): cluster_count=1 on testcloud haclusters (BUNDLEFIX-003)
...
Single-unit principals can't reach the default 3-peer quorum; haclusters
blocked 'insufficient peers'. cluster_count=1 forms a 1-node cluster and
brings up the (public->provider, reachable) VIP. Matches the runtime
juju config already applied. Roosevelt's 3-unit bundle keeps the default.
|
fix(bundle): api-bindings minimal + de-HA vault for v1 (Option A)
...
- &api-bindings -> {":metal, public:provider}; drop 7 redundant metal keys
that broke keystone/ceph-radosgw/openstack-dashboard at deploy
- vault: *internal-bindings, drop options(vip 10.12.4.236 provider / hostname),
comment vault-hacluster + vault:ha. vault is metal-only single-unit on the
testcloud; provider VIP unreachable from metal & pointless at 1 unit.
HA restored at Roosevelt (3 units, metal VIP via NetBox).
Counts: VIPs 11->10, apps 51->50, relations 98->97.
|
| 2026-05-28 |
bundle: remove Designate per D-019 (deferred to v2)
...
Removes the designate, designate-bind, designate-mysql-router,
and designate-hacluster applications, plus all seven designate-
related relations. Updates header comments to reflect the deferral.
Rationale per D-019: v1 testcloud topology investigation confirmed
outside-in DNS is not needed (corporate clients reach the cloud via
the openstack.baldurkeep.com HTTPS proxy chain, not via *.cloud.
neumatrix.local FQDNs). Tenant subnets use public DNS directly via
--dns-nameserver. FIP DNS auto-registration is not load-bearing for
any v1 acceptance criterion.
VIP 10.12.4.227 becomes unused space in 10.12.4.224-.254 (same
status as 10.12.4.225 reserved for v2 ceph-radosgw HA).
|
bundle: remove ceph-osd storage block to match expected-osd-count
...
The storage: block declared a second osd-devices entry (loop,1024M)
which is additive to options.osd-devices per the charm config. That
produced 8 OSDs against expected-osd-count: 4 on ceph-mon, with
1 GB loopback OSDs as the asymmetric secondaries - a CRUSH-weighting
anti-pattern.
Real production storage (DB/WAL on actual SSDs) will be declared on
Roosevelt. For the testcloud, BlueStore co-locates DB/WAL on the data
device which is the documented default for single-device setups.
osd-journals is unused under BlueStore.
|