# Pass 1 -- Worker W1.1: redeploy/teardown PLANNING under the confirmed Option-1 target

**Author:** W1.1 (Phase 1, container-elimination pass). **Date:** 2026-08-09. **Scope:**
what the CONFIRMED Option-1 target topology (`pass0-admin-report.md` Section 7a) changes in
the teardown and redeploy PLANNING ARTIFACTS -- `runbooks/dc-dc-teardown-rollback.md`, the
`runbooks/dc-dc-phase0..6*.md` runbooks, and how D-143's re-IP interleaves with the
container-elim change-set in the redeploy sequence. **READ-ONLY.** No mutation, no live
commands. Every claim below is anchored to a `path:line` read this session; where a value is
not yet knowable it is marked UNKNOWN with what resolves it.

**Reminder of the confirmed target (do not re-derive):** flat node VMs directly on vcloud
libvirt; `vvr1-dcN` ELIMINATED; a small non-hypervisor `vr1-dcN-client` VM (metal-admin +
transit legs) inherits the D-138 client role + that DC's credential residencies; MAAS region
stays on `vr1-dcN-maas-01` unchanged; rack-controller remainder / D-131 forwarder / artifact
service placement is OPEN (client VM vs maas-01, carried into this phase per Section 6 item 3
of `pass0-admin-report.md`); cross-DC isolation (a) is a REQUIRED Phase-1/2 design deliverable
(a new vcloud-level host isolation control); this rides D-143 but must stay DISTINGUISHABLE
from it.

---

## 1. The teardown-primitive answer

**Today:** `runbooks/dc-dc-teardown-rollback.md`'s whole structure is built on the D-123
Model-B TWO-ROOT/TWO-HOST shape -- an OUTER root on vcloud that creates `vvr1-dcN`, and an
INNER root run FROM THE OFFICE1 HEADEND (`voffice1`) via `qemu+ssh` into the containment VM
(lines 26-65, the "MODEL B RESHAPE" banner; lines 136-152, "TWO CLONES, TWO HOSTS"). D-122's
site-down lever is explicitly one object: `virsh destroy vvr1-dcN` (line 48). Every Path
(A/B/C/M) is written against this shape.

**Under Option 1, the two-root/two-host shape COLLAPSES to one root on vcloud.** There is no
containment VM to hold an inner libvirt, so there is no `qemu+ssh` provider dial, no inner
state file on `voffice1`, and no D-122 single-object site-down (that lever is explicitly
named a "REAL D-123 regression to carry honestly" in `pass0-admin-report.md` row 9). The
teardown primitive becomes:

> **A single-root, module-scoped `tofu destroy` per DC, run entirely on vcloud** --
> `tofu destroy -target=module.vr1_dcN_planes -target=module.vr1_dcN_node -target=module.vr1_dcN_wan -target=module.vr1_dcN_opnsense -target=module.vr1_dcN_client -target=module.vr1_dcN_storage` (module
> names illustrative -- Phase 2/W2.1 owns the real post-flattening module names), OR (preferred, since
> a flat root holding exactly one DC's resources needs no `-target` at all, same logic the current
> runbook already uses for the per-DC INNER root, lines 751-758) **one dedicated root per DC** so a
> plain `tofu destroy` there is inherently scoped -- re-earning the "scope by choosing the root"
> discipline (current lines 155-168) without a second host.

This is the **group-destroy of the `vr1-dcN-*` domain set**, not a single-object destroy --
D-122's convenience is genuinely lost, and Section 5's cross-DC isolation gap (Section 5) is
one more reason NOT to try to re-earn it via "add a synthetic wrapper VM back" -- that would
just re-import the eliminated pattern. The honest replacement discipline: (a) a *tofu*-level
group-destroy scoped by root/module (safe, plan-reviewable, the mechanism above), and (b) for
a "stop this DC's compute NOW" emergency lever (the actual use case D-122's single-`virsh`
convenience served), a SCRIPTED loop over `virsh destroy` for the named domain set derived
from `lib-hosts.sh`'s roster for that DC -- not a manual enumeration. **Both are NEW artifacts
this pass must hand to Phase 2/4 (tooling + module design), not something already built.**

### 1.1 Per-Path change list

| Path | Today's assumption (path:line) | Option-1 change |
|---|---|---|
| **"TWO CLONES, TWO HOSTS" preamble** (`:136-152`) | Every command runs on `$REPO` (vcloud, outer) OR `$O1_REPO` (voffice1, inner substrate roots) | COLLAPSES to ONE clone/one host: `$REPO` on vcloud only. The whole two-host framing is DELETED; `$O1_REPO` no longer holds a DC substrate root (voffice1 keeps its OWN unrelated Office1 role, D-114 -- untouched, see Section 2) |
| **Path A -- scoped teardown** (`:154-173`, Steps 3-5) | "Scope by choosing the ROOT first" between OUTER (vcloud, all 3 sites) and INNER (per-DC, voffice1, `qemu+ssh`); order = INNER then OUTER, backups from TWO hosts (Step 1, `:600-631`) | Root choice becomes: OUTER (shared: Office1 + mesh + both DC-storage-pool-parent, if any survives flat) vs. a PER-DC flat root holding that DC's planes/nodes/edge/client VM. Order collapses to ONE apply per DC (no inner/outer split); Step 1's backup is ONE state file per DC root, taken on vcloud only. Step 3's module table (`:765-775`) is rewritten with post-flattening module names (Phase 2/W2.1 -- names not yet minted, UNKNOWN pending that design) |
| **Path A -- Step 2 (MAAS census)** (`:635-747`) | "WHERE: from the OFFICE1 HEADEND ... the region MAAS and its CLI profile live there" (`:655-658`); LENS 2 sources `lib-hosts.sh` boot-MAC roster via `lib_hosts_select_dc` | MAAS region is UNCHANGED (stays `vr1-dcN-maas-01`, confirmed at the Phase-0 gate) -- **this step's WHERE clause survives if maas CLI still runs from voffice1** (D-128 Plane 2), but the machine roster it's checking against no longer includes the containment VM itself (there is none) and now includes `vr1-dcN-client`. Mechanically the SAME two-lens structure, refreshed roster |
| **Path A -- Step 4 verify** (`:838-891`) | "The DC's node, edge and plane objects live inside the containment VM, so a local `virsh` on vcloud can never see them" (`:858-860`); verify INNER half via `qemu+ssh` from voffice1, OUTER half via local `virsh` on vcloud (two verify blocks) | COLLAPSES to ONE verify block, local `virsh` on vcloud only -- planes/nodes/edge/client VM are all now vcloud-libvirt-visible directly. The "vcloud-local grep 'passes' against a fully intact DC" caveat (`:861-864`) becomes MOOT (there is nothing hidden behind a second libvirt any more) |
| **Path B -- full VR1 teardown** (`:914-957`) | "everything" = THREE roots on TWO hosts (`:920-932`) | "everything" = N+1 roots (one shared/outer + one per DC, or a single unified root -- module design decides, Phase 2) on ONE host. Verify block (`:941-953`) drops its `qemu+ssh` refusal-guard branch entirely |
| **Path M -- juju MODEL teardown** (`:188-392`) | Untouched by containment: it is one layer ABOVE substrate (juju model on top of already-provisioned MAAS machines). No `qemu+ssh` or `vvr1-dcN` reference in the body | **UNCHANGED as a procedure.** Only its execution-HOST assumption (implicit: wherever `juju` runs, i.e. the DC rack today) moves with D-138's client-VM re-home -- see Section 3 below (phase4's table, not this runbook) |
| **Path C -- juju CONTROLLER teardown/rebuild** (`:394-596`) | Untouched by containment for the SAME reason as Path M -- it operates on MAAS machine records and the juju controller, one layer above substrate. C.1's MAAS census and C.6's tag check are host-agnostic (maas CLI location unaffected: still MAAS-region-side, i.e. voffice1 per D-128 Plane 2, unchanged) | **UNCHANGED as a procedure.** No edit needed in this runbook; the D-138 client-VM re-home is the phase4 change, not this one |
| **Mesh-link teardown** (`:960-995`) | Three OUTER-root legs (`mesh_vr1_dc0_vr1_dc1`, `mesh_vr1_dc0_office1`, `mesh_vr1_dc1_office1`) + netem, sharing the D-125 caveat that `mesh_vr1_dc0_office1` "carries the live rack<->region transit ... the inner root's own qemu+ssh path" (`:981-983`) | The mesh legs and netem module PERSIST (confirmed non-eliminated, `pass0-admin-report.md` Sec 1.3). The `mesh_vr1_dc0_office1`/`mesh_vr1_dc1_office1` caveat's WORDING changes: it no longer carries "the inner root's qemu+ssh path" (that's gone) but DOES still carry the `vr1-dcN-client`'s reach to voffice1/MAAS-region and the operator `ssh -J` path (Section 6 item 5 of `pass0-admin-report.md`, still OPEN) -- reword, don't delete the caution |
| **"Relationship to D-061"** (`:86-134`) | Frames the coordination principle as OpenTofu's resource view vs. MAAS's per-machine view (unaffected by which root creates the resources) | **UNCHANGED in principle.** No containment-specific text here to edit |
| **Rollback decision tree** (`:998-1069`) | "Question 0 -- WHICH ROOT failed? There are three" (`:1006-1010`); item 5's containment-VM-destroy caution (`:1059-1067`) is written entirely around `virsh destroy vvr1-dcN` as the reversible site-down lever | Question 0 becomes "which DC's flat root" (fewer roots, no inner/outer split). **Item 5 needs a REPLACEMENT lever entirely** -- there is no single reversible power-off object any more; the nearest analog is a scripted `virsh destroy` loop over that DC's node-VM domain set (irreversible-feeling but mechanically the same primitive, just N domains instead of 1) -- flag as a NEW tested artifact this pass owes (Section 1 above), not a drop-in rename |
| **Verification footer** (`:1071-1091`) | Notes all module/network/pool names were "RE-MEASURED against the tree and the live hosts on 2026-07-29" for the two-root shape | The whole footer's provenance is for a shape being eliminated -- a rewritten runbook needs its OWN re-measurement pass against the new flat module tree (Phase 2/4 delivery item, not this planning pass) |

**Net verdict on this runbook:** it needs a REWRITE comparable in scope to the 2026-07-16
"MODEL B RESHAPE" banner that was bolted on for the *previous* topology change -- likely the
same pattern (a prominent "OPTION-1 FLATTEN" banner up top plus the Steps re-grouped), not a
line-by-line patch. Paths M and C are the two genuinely LOW-delta paths (they sit above the
substrate layer entirely); Paths A/B and the rollback tree carry the real rewrite weight.

---

## 2. Per-phase-runbook change list

### 2.0 What does NOT change

- **`runbooks/dc-dc-phase0-vcloud-prep.md`** -- grep for `vvr1-dc`/`containment`/`qemu+ssh`/
  `inner root`/`outer root` returns ZERO hits in the body (only a generic `qemu+ssh://...` example
  at `:113,123` describing the libvirt-URI syntax itself, and `libvirt_uri = "qemu:///system" # or
  qemu+ssh://... -- Step 1` at `:364`, which is the OUTER root's own provider block, unaffected).
  This runbook covers vcloud host prep, the D-100 mesh triangle, storage pools, the shared base
  image -- none of it is containment-specific. **No change required.**
- **`runbooks/dc-dc-phase1-office1-standup.md`** -- its "containment VM" is `voffice1` under
  **D-114**, a DIFFERENT decision than D-123's Model-B DC containment (`:9,13,44-47,313-337` --
  D-114 is cited by name throughout, never D-123). `voffice1` simulates the Office1 FACILITY
  and hosts MAAS-region/LXD for MAAS-composed service VMs (NetBox, tailscale) -- it is not the
  object the container-elim pass targets, and Phase-0's scope explicitly named the container
  layer as `vvr1-dcN` only (`SCOPE-AND-EXECUTION-PLAN.md` Sec 2, `pass0-admin-report.md` Sec 1.3 "It is
  NOT: ... the DC edge ..." -- Office1 wasn't even in scope). **No change required for THIS pass.**
  Flag for the record: D-114's own containment pattern is architecturally the same shape D-123
  used, and if the operator's "eliminate the container layer" intent is read as broader than the
  Phase-0 gate scoped it, that is a SEPARATE decision outside this pass's mandate -- not assumed
  here.

### 2.1 `runbooks/dc-dc-phase2-tofu-dc-substrate.md` -- the largest single change

This runbook IS the two-root apply sequence, and its "D-123 MODEL B RESHAPE" callout
(`:144-204`) is the direct predecessor of the change this pass makes. Per-step:

| Step (path:line) | Today's assumption | Option-1 change |
|---|---|---|
| **A. OUTER apply** (`:151-152`) -- creates + sizes `vvr1-dc0` (~480 GiB, `expose_nested_virt=true`) + transit | Sizes and provisions the CONTAINMENT VM itself | Sizes and provisions the FLAT node-VM set + edge + `vr1-dcN-client` directly. `expose_nested_virt=true` DROPS (no nested libvirt needed anywhere in this DC -- confirm no OTHER consumer needs nesting before deleting the flag; none found in Phase-0's inventory). Overhead sizing (~480 GiB minus node/edge sizes) is FREED -- ties to the owed FIT recompute (`pass0-admin-report.md` Sec 8.2) |
| **B. BOOTSTRAP GATE** -- `site-headend-install.sh --role rack --host-nodes ...` (`:153-157`) | A DISTINCT stage between the two applies: enrolls the rack to the Office1 region AND makes `vvr1-dc0` a nested libvirt host (kvm nested=1, inner pool dir, AppArmor, SEC-010 transit FORWARD-drop). GATE: `--check` must pass | **THIS STAGE IS ELIMINATED WHOLESALE.** There is no "make a VM a nested libvirt host" step because there is no nested libvirt host. What SURVIVES from its payload, re-homed: (i) rack enrollment to the Office1 region -- lands wherever the rack-controller remainder is placed (client VM / maas-01 / retire -- Section 6 item 3 of `pass0-admin-report.md`, still OPEN, UNKNOWN pending that placement decision); (ii) the SEC-010 transit FORWARD-drop -- REBUILT for the new boundary, not moved (`pass0-admin-report.md` row 6, "must be REBUILT ... not moved"); this is the SAME control the Phase-0 gate's cross-DC isolation deliverable (handling (a)) needs a new design for -- the two are related but distinct (SEC-010 is transit-leg-scoped; (a) is host-level cross-DC). `site-headend-install.sh --host-nodes` mode becomes DEAD CODE for VR1 (confirmed `pass0-admin-report.md` row 6) |
| **C. INNER apply** (`:158-161`) -- provider = `qemu+ssh` to `vvr1-dc0`, run FROM voffice1; the 6 planes + wan + edge + inner pool + 9 node VMs | A SEPARATE apply, separate state, separate host, gated behind B | **MERGES INTO STEP A.** One apply, one root, one host (vcloud), one state file. The 6 planes / wan / edge / node VMs (now +1 for the client VM) are ALL created by the single OUTER apply -- there is no "inner" any more. Steps 5-6 (wiring `modules/opnsense-edge` and `modules/node-vm` calls into `main.tf`, `:129-141`) collapse from "authored in the inner root" to "authored directly in the (now singular) root's `main.tf`" |
| **D. maas-vm-host** (Step 9, `:162-163,588-640`) -- register `vvr1-dc0`'s OWN local `qemu:///system` virsh to the Office1 region | Registers the CONTAINMENT VM's inner libvirt as a MAAS vm-host | Registers vcloud's OWN libvirt (already the case for the OUTER root's objects) OR is retired if the flat topology never needed per-machine `power_type=virsh` registration to change shape -- **this step was already DEFERRED (DOCFIX-179) before this pass**; Option 1 does not resurrect it, it just removes the "vvr1-dc0's OWN inner virsh" framing since there is no inner virsh |
| **E. netem** (Step 11, `:164-168`) -- runs on vcloud-level mesh bridges, OUTER, already correctly targets the dc0<->dc1 leg, NOT the transit leg that "carries ... the inner root's own qemu+ssh" | Already outer-scoped, mostly unaffected | The caveat text needs its "the inner root's qemu+ssh" clause reworded (that path no longer exists) but the netem TARGET and mechanism are unaffected -- low-delta edit |
| **D-125 bridge-in** (`:193-203`) -- OUTER creates the vcloud ISP NAT + a 2nd IP-less uplink NIC + `br-vr1-dc0-wan` bridge on `vvr1-dc0`; BOOTSTRAP `--check` verifies the bridge; INNER's `vr1-dc0-wan` is a BRIDGE (`modules/wan-bridge`) onto it | Exists SOLELY to fix OBS-3 nesting egress -- an artifact of the containment VM being a two-NIC transit-only host with no egress of its own | **DELETED per `pass0-admin-report.md` row 3.** The DC edge WAN attaches DIRECTLY to the outer `vr1_dc0_uplink` NAT (same /24, no re-address) -- there is no intermediate host needing a bridge-in fix. `modules/wan-bridge` becomes dead code for VR1; the BOOTSTRAP `--check`'s bridge-verify clause is deleted with the gate itself |
| **"Sequence" step list** (`:114-142`) | Numbered 1-12 against the single-root FRAMING, then regrouped A-E for Model B | Needs a THIRD regrouping (or, cleaner, a fresh linear list -- Option 1's flat shape doesn't need the A-E lettering since there's no bootstrap-gate seam to letter around). This is the step-list equivalent of the runbook-wide rewrite flagged in Section 1 |
| **DC standup definition-of-done** (`:822-887`) | References "the containment/service net" MEASUREMENT and "containment ssh shape" (`:830-833`) and objects "created by `site-headend-install.sh --host-nodes`" (`:842`) | Both references need re-homing to "how vcloud reaches the DC's node-VM planes directly" and drop the `--host-nodes` citation (dead per row above) |
| **Step 13 backup** (`:741-822`) | Backs up "the inner tfstate" via `voffice1` (`:764-804`), noting a `qemu+ssh`-only provider dependency is "strong[er]" evidence of correctness (`:764`) | Backs up ONE state file (the flat per-DC root), taken and stored on vcloud -- the voffice1-hop and its "no key in state" argument are MOOT (no `qemu+ssh` provider block exists to make that argument about) |

**Net verdict:** Phase 2 needs the SAME weight of rewrite as its own prior D-123 reshape --
arguably heavier, since this pass ELIMINATES a whole apply stage (B) rather than adding one.

### 2.2 `runbooks/dc-dc-phase3-maas-enlist-deploy.md`

- **`:424,430`** -- `ssh -i ~/vr1-dcN-creds/... -J voffice1 jessea123@<dcN-rack-transit-ip> 'sudo bash -s' -- check dcN < scripts/dc-mirror.sh` (dc0) / `dc-cache-proxy.sh` (dc1). **Today's assumption:** the jump target is the rack transit IP, i.e. the CONTAINMENT VM (`vvr1-dcN`'s own transit leg, per `lib-hosts.sh`'s `VIRSH_POWER_ADDRESS`). **Option-1 change:** the jump target becomes `vr1-dcN-client`'s transit IP -- the artifact-service check (dc-mirror/dc-cache-proxy) still runs via SSH-through-voffice1 into the DC, but the far end of that hop is a different (non-hypervisor) VM. The artifact-service PLACEMENT itself (client VM vs. `vr1-dcN-maas-01` vs. retire) is the OPEN item from `pass0-admin-report.md` Section 6 item 3 -- if it lands on `maas-01` instead, this whole SSH target changes to that VM's address, not the client VM's. **UNKNOWN pending that placement ruling; do not pick one here.**
- Everything else in Phase 3 (MAAS enlist/commission/deploy of the node fleet, Steps 1-7 generally) is about MAAS machine-level operations against a fleet that is already flat from MAAS's point of view TODAY (per-machine `power_type=virsh`, no pod) -- `pass0-admin-report.md` confirms this is NOT a two-root/containment-keyed concern (row 4/5: only the POWER ADDRESS changes, the mechanism is topology-agnostic). **Low delta beyond the two SSH-target lines above.**

### 2.3 `runbooks/dc-dc-phase4-juju-bundle-per-dc.md`

- **`:158-185`, the "RUN LOCATION" table** -- this is the runbook's own record of getting D-138
  wrong once already (superseded text quoted at `:169-178`: "Every juju and maas command runs
  on voffice1" was WRONG; D-138 moved juju/openstack CLI onto "THIS DC's RACK"). **Under
  Option 1, "THIS DC's RACK" is retired vocabulary --** the concrete host D-138's principle
  points at becomes `vr1-dcN-client` (per `pass0-admin-report.md` Sec 3.3, Option 1's client VM is
  "consistent with D-138's principle"; the concrete-host CHANGE still needs recording, Phase 4's
  [ARCH] decision). This table needs a THIRD correction pass: row 1 ("juju/openstack CLI") ->
  runs on `vr1-dcN-client`, not "the rack" (the rack as a distinct host no longer exists); row 2
  (maas/NetBox/tofu) stays on voffice1, UNCHANGED (D-128 Plane 2 survives -- MAAS region and
  NetBox are not containment-layer objects); row 3 (never vcloud) UNCHANGED.
- **`:180-185`, the staged-scripts caveat** -- "the rack has NO repo clone" and needs
  `~/repo-stage/scripts/` staged there. This caveat TRANSFERS verbatim to `vr1-dcN-client`
  (still a non-repo-clone host by design, same staging discipline needed) -- no logic change,
  just a re-pointed noun.
- **`:840-848`, the "considering destroying anything BELOW the juju layer" caution** -- names
  "the containment VM, the DC's libvirt resources, MAAS records" and points at the (currently
  Model-B-shaped) teardown runbook. **Needs updating to point at the REWRITTEN teardown
  runbook (Section 1 above) and drop the containment-VM noun** -- the caution's PRINCIPLE (don't
  reach for a substrate destroy while nodes are MAAS-enrolled) is unchanged.
- Path M and Path C content itself (the juju model/controller procedures phase4 delegates to
  the teardown runbook) needs NO change here -- confirmed low-delta in Section 1.

### 2.4 `runbooks/dc-dc-phase5-dr-failover-drill.md`

- No `vvr1-dc`/`containment`/`qemu+ssh` hits (grep confirmed). Its only execution-host
  reference worth flagging is INDIRECT: it delegates the per-DC deploy command to Phase 4
  (`:430-433`) and otherwise operates at the juju/openstack layer, which is D-138-scoped
  (client VM under Option 1) rather than containment-scoped. **No direct edit required by
  container-elim**; it inherits whatever Phase 4's table says.

### 2.5 `runbooks/dc-dc-phase6-designate-cos-magnum.md`

- **`:437-444`** -- "`juju` is ABSENT on vcloud ... Run them from the Plane-2 host (voffice1)
  per D-128" and "**CHECK (read-only) -- from the Office1 headend (voffice1)**" immediately
  precedes a `juju status -m ...` command. **This is ALREADY WRONG independent of the
  container-elim** -- it predates phase4's own D-138 correction (juju runs on the DC's
  execution host, not voffice1; `pass0-admin-report.md` and phase4's `:174-178` both confirm
  `juju controllers` on voffice1 returns "No controllers registered"). Flagging here because
  the SAME fix phase4 needed (rack -> client VM) applies to this line too, and both should be
  corrected in the SAME pass since they share the root cause (a stale D-138 pointer). Not
  itself a NEW container-elim delta, but a pre-existing defect this pass's rewrite sweep should
  not leave behind.

### 2.6 `runbooks/dc-dc-office1-service-reip.md`

- Entirely Office1-scoped (`voffice1`'s own MAAS-composed LXD VMs -- NetBox, tailscale). No
  `vvr1-dcN` reference; **out of this pass's scope** (D-114, not D-123).

---

## 3. D-143 (re-IP) vs. container-elim: keeping the two axes distinguishable in the redeploy sequence

D-143's OWED EXECUTION list (`docs/design-decisions.md:8163-8174`) is FIVE items, all
address-only:

1. NetBox apex -- new B2 role `Cloud -- VR1 rebuild` owning `10.13.0.0/16`; re-carve VR1
   prefixes/VIPs/ranges under it, octet-preserving.
2. `scripts/lib-net.sh` -- flat defaults STAY 10.12; `vr1-dc0`/`vr1-dc1` arms get full 10.13
   literal blocks; fix the stale ":124-134" comment.
3. `10.13` naming-collision DOCFIX (`netbox/README.md:49`, a test literal).
4. D-124 transit routes re-point + rack statics shift (`10.12.8.2 -> 10.13.8.2`, etc.).
5. Teardown must REVOKE the dc0-substrate credentials before redeploy.

**None of these five items touch topology** -- they are a value substitution (12->13) plus
one NetBox role-model addition. The container-elim change-set is orthogonal: it changes WHICH
objects exist and WHERE they run, not what numbers they carry. Concretely, keeping them
distinguishable in the redeploy plan means:

- **Sequence within one redeploy, not two redeploys.** Since both changes ride the SAME
  teardown+rebuild, the interleave is: (i) teardown the CURRENT 10.12 Model-B checkpoint
  (Section 4 below) -- an ADDRESS-AGNOSTIC, TOPOLOGY-AGNOSTIC action (you're destroying
  objects, not re-carving them); (ii) apply D-143 item 1 (NetBox apex) and item 2 (`lib-net.sh`
  literal blocks) as the FIRST rebuild inputs -- these are pure data, no topology dependency,
  so they can be done before or independent of the module rewrite; (iii) rebuild against the
  Option-1 flat module design (this pass's Phase 2/4 deliverable), consuming the NEW 10.13
  literals from step (ii) -- the flat root's tfvars/module calls reference `lib-net.sh`'s
  10.13 arm the same way the old two-root shape referenced its 10.12 arm, so the flattening
  and the re-IP compose cleanly (one substitutes VALUES, the other substitutes SHAPE) rather
  than colliding.
- **Attribution discipline for the change-set (Phase 4's job, flagged here so it isn't lost):**
  every diff in the rebuilt `opentofu/` tree should be traceable to EITHER "this line's value
  changed because of D-143" OR "this line/module/step exists or doesn't because of
  container-elim" -- not both folded into one undifferentiated rewrite. A rewritten Phase-2
  runbook that silently also renumbers octets (or vice versa) would make a future revert-one-
  axis-not-the-other impossible to reason about. Concretely: the module RENAME/RESTRUCTURE
  (e.g., `module.vvr1_dc0` disappearing, `module.vr1_dc0_client` appearing) is container-elim;
  the VALUES inside surviving modules changing from `10.12.x` to `10.13.x` is D-143. A resource
  that is BOTH new AND carries a 10.13 literal (e.g., the client VM's transit IP) is fine to
  create once, but its commit/changelog framing should name both governing changes, not blur
  them into "the redeploy."
- **D-143 item 5 (revoke dc0-substrate credentials before redeploy) interacts directly with
  the container-elim's credential-residency migration** (`pass0-admin-report.md` row 8 /
  Section 6 item 6): the OLD credentials being revoked are resident on the (about to be
  eliminated) `vvr1-dc0`; the NEW credentials being minted for the rebuild are resident on
  `vr1-dc0-client`. This is naturally sequenced (revoke old -> destroy old host -> build new
  host -> mint new credential) but it means D-143 item 5 and the container-elim's SEC-028/
  SEC-029 re-pointing are the SAME step wearing two decision-labels -- call it out as one
  action justified by both D-NNNs when it's executed, not two separate ones.

---

## 4. Teardown of the CURRENT (Model-B, 10.12) live checkpoint -- order

This is the FIRST action of the redeploy (dc0 is already at the confirmed FULL-deployment
checkpoint per the operator's pivot memory; dc1 is held). Per the teardown runbook's own
discipline (Section 1 above, still valid for tearing down the CURRENT Model-B shape -- the
runbook doesn't need to be rewritten to tear down what it already describes correctly):

1. **Path M first, per DC with a live model** -- tear down the juju MODEL(s) before touching
   substrate (`dc-dc-teardown-rollback.md` Path M, `:188-392`). This is the D-143 item-5
   credential-revoke's natural anchor point too (revoke, then destroy).
2. **D-143 item 5** -- revoke the dc0-substrate credentials (folded into or immediately after
   step 1, per Section 3 above).
3. **Path C, if a controller needs to come down** with the model (only if the controller itself
   is being retired, not just the model) -- `:394-596`.
4. **Path B substrate teardown, ordered INNER then OUTER, per DC** -- `:914-957`: from
   voffice1, `tofu destroy` each `opentofu/vr1-dcN-substrate/` root; THEN, on vcloud, `tofu
   destroy` the outer root's `vvr1_dc0`/`vvr1_dc1`/`vr1_dcN_uplink`/`vr1_dcN_storage` modules.
   Step 2's MAAS census (`:635-747`) runs FIRST, per DC, before any destroy -- this is
   unaffected by container-elim (still the load-bearing "attribute every `power_type=virsh`
   record" gate).
5. **Mesh legs -- destroy ONLY if the whole VR1 layer (both DCs) is going away together**
   (`:960-995`); a checkpoint-then-redeploy that keeps the SAME two DCs (new IPs, new shape,
   same DCs) should almost certainly PRESERVE the mesh triangle and simply let the flat rebuild
   re-target it -- destroying and recreating the mesh legs is extra churn with no benefit unless
   the mesh module ITSELF needs to change shape for the flat topology (UNKNOWN pending Phase
   2/W2.1's tofu-module design -- the mesh legs are NOT named as changing in `pass0-admin-
   report.md`'s "persists" list, Sec 1.3, so the working assumption is they survive; confirm at
   Phase 2, don't destroy speculatively).
6. **Only after 1-5 converge (Step 5's untargeted `tofu plan` gate, `:894-911`, showing zero
   unexpected drift)** does the rebuild begin -- against the Option-1 flat module design,
   consuming D-143's new NetBox/lib-net.sh literals per Section 3's sequencing.

**This order is UNCHANGED by container-elim** -- it is the teardown runbook's existing Path
M -> C -> B ordering, applied to what is CURRENTLY built (Model-B, 10.12). Container-elim only
changes what gets BUILT next (Section 2), not the order in which the current thing comes down.

---

## 5. Open items this pass surfaces (not resolved here -- feed to Phase 2/4)

1. **Root topology: one merged root per DC, or a shared outer + per-DC root split retained
   minus the containment seam?** Section 1/2.1 above illustrate BOTH as plausible; Phase
   2/W2.1 (OpenTofu module design) is where this gets decided, not this planning pass. This
   document's `tofu destroy` illustrations are DELIBERATELY marked illustrative for that
   reason.
2. **The new teardown-primitive script (module-scoped group-destroy / `virsh destroy` loop)
   does not exist yet** -- it is a NEW tested artifact this pass identifies as owed, to be
   built and harnessed per repo discipline (CLAUDE.md "Delivery") once the module design lands.
3. **D-128's Plane-1/Plane-2 split is written entirely around the two-root shape**
   (`docs/design-decisions.md:5354-5364`). Under Option 1 there is no more "Plane 2 = the
   INNER tofu root run from voffice1" -- Plane 2 shrinks to MAAS/NetBox only (tofu is now
   entirely Plane 1, vcloud). **This is a D-128 amendment this pass's Phase 4 [ARCH] framing
   should fold in alongside the D-123 container-elim ruling itself** -- flagged here because it
   was found while reading phase2/phase4's execution-host tables, not because W1.1 is ruling on
   it.
4. **Artifact-service / rack-controller-remainder / D-131-forwarder placement remains OPEN**
   (`pass0-admin-report.md` Section 6 item 3) and DIRECTLY determines the SSH-jump-target edit
   in Section 2.2 above and the maas-vm-host re-homing in Section 2.1's Step-D row. This
   pass's findings are written generically ("client VM OR maas-01") precisely because that
   placement is not yet ruled -- do not let a later pass silently pick one without updating both
   citations here.

---

## 6. Verification note

Every `path:line` cite above was read directly this session from `runbooks/dc-dc-teardown-
rollback.md`, `runbooks/dc-dc-phase0-vcloud-prep.md` through `phase6-designate-cos-magnum.md`,
`runbooks/dc-dc-office1-service-reip.md`, `opentofu/main.tf` (module list), and
`docs/design-decisions.md` (D-128, D-143). No value in this document is inferred from a prior
session's summary or from memory -- where a placement or a module name is not yet knowable it
is marked UNKNOWN with what resolves it, per hard rule 2.
