PREP PACKAGE, NOT A RULING. This file does not rule, does not mint a D-number, and mutates nothing (no live infra, no lib-net.sh, no design-decisions.md, no CURRENT-STATE.md). It exists so the operator can rule the re-IP from one place with the full blast radius, the decision reconciliation, and the owed live checks in view.
docs/audit/netbox-1013-subnetting-draft-20260808.md (the 10.13 subnetting draft), docs/audit/queued-findings-20260808-dc0-tailscale-incident-reip-pivot.txt (F1, F12-F16), docs/design-decisions.md D-101/D-115/D-124/D-134 (each block in full), scripts/lib-net.sh (defaults + the three selector arms).grep this session, not an estimate. No operational command was improvised (tool-index consulted; the checks that need live/control-plane access are listed as OWED, Section D).docs/design-decisions.md:7966; every D-143 hit in the repo is "next-free" bookkeeping, not an assignment). NOT minted here -- grep next-free again at ruling time.For each governing decision: what it ruled, how the re-IP interacts with it, and the verb (supersedes / amends / terminates / consistent-with). One framing in this section DIVERGES from the draft and from F12/F13 -- flagged inline so the operator can overrule it.
D-101 (ADOPTED 2026-07-09, docs/design-decisions.md:2243) rules the per-DC v4 layout and the IPv6 family matrix. The load-bearing v4 clause, verbatim:
"Per-DC distinct v4: DC1 INHERITS the DC0 six-plane v4 layout (provider-public 10.12.4.0/22 ... replication 10.12.36.0/22) unchanged, so DC1 equals the validated template." (
docs/design-decisions.md:2304; per the DOCFIX-205 annotation at :2247, in this 2026-07-09 text "DC1" = VR1's first DC =vr1-dc0and the inherited "DC0" = VR0's DC0 =vr0-dc0, the LIVE cloud.)
Interaction: the live 10.12 cloud IS vr0-dc0. Moving VR1 to 10.13 means vr1-dc0 no longer inherits vr0-dc0's v4 layout -- it gets a distinct, non-overlapping one. That is the termination of D-101's inherit-VR0-DC0-v4-unchanged clause (F13). Note the reason D-101 gave for inheritance (":2304" -- "minimize delta to Roosevelt", reuse the validated bundle) is what the re-IP trades away, so the ruling should acknowledge the cost, not just the mechanics. The IPv6 family matrix, the "IPv6 unless IPv4 is necessary" standing principle (:2282), and the dual-stack ruling are untouched -- this is a v4-only re-IP. Verb: TERMINATES the v4-inheritance clause; CONSISTENT-WITH everything else in D-101.
D-115 (ADOPTED 2026-07-13, docs/design-decisions.md:3711; amendment at :3827) ruled: v4 stays role-based; offices get a /22; and DC2 (vr1-dc1) moves INSIDE the Cloud /16 at 10.12.64.0/19. The clause that names 10.13, verbatim:
"This SUPERSEDES
docs/dc-dc-netbox-buildout-scope.md'sDC2_V4_SUPERNET = 10.13.0.0/19, which sat outside every allocated block." (docs/design-decisions.md:3856-3858)
and the finding it rested on:
"DC2's planned
10.13.0.0/19is OUTSIDE the Cloud/16. ... NetBox's Cloud role is10.12.0.0/16;10.13.xis unallocated." (docs/design-decisions.md:3766-3767)
Interaction -- and the framing divergence. F12 and the draft (OQ (c)) call the re-IP a "D-115 SUPERSESSION." I read the text more narrowly and flag it for operator override: D-115's ruling (v4 role-based; /22 per office; DC2 inside the Cloud /16) is NOT being reversed -- the re-IP keeps v4 role-based and keeps the octet-preserving structure. What the re-IP overturns is one factual premise: that "10.13.x is unallocated / outside every allocated block" makes it unusable. Post-pivot, 10.13.0.0/16 is deliberately allocated under the 10.0.0.0/8 Corp Private parent. So the defensible verb is AMENDS D-115 (its role-based principle holds; its 10.13-is-unallocated finding is superseded by the collision discovery), not a wholesale supersession. If the operator prefers the draft's stronger word, that is their call -- but the text at :3856 only supersedes a scope-doc recommendation, not a rule, so "amendment" is what the record supports. Verb: AMENDS D-115 (factual premise); the role-based ruling is CONSISTENT-WITH the re-IP. The apex fork this opens is Section B.
D-124 (ADOPTED 2026-07-16, docs/design-decisions.md:4961; addressing pinned at :5019, dc1 at :5039) rules Scheme A: a dedicated transit role on 172.31.0.0/24 (NOT under Cloud), region<->rack /30s (172.31.0.0/30 dc0, 172.31.0.4/30 dc1), and the rack metal-admin statics (10.12.8.2 dc0, 10.12.68.2 dc1).
Interaction: the transit supernet 172.31.0.0/24 is not in 10.12 and does not move -- D-124's addressing stands. BUT the rack metal-admin statics ARE in 10.12 (10.12.8.2 -> 10.13.8.2, 10.12.68.2 -> 10.13.68.2; draft Section 3.7) and the routes carried over the transit /30s point at 10.12. DC destinations and must re-point to 10.13. (draft Section 6 caveat). Also note (:5036) the NetBox --commit for D-124 addressing runs ON office1-netbox because the apex token is unreachable from vcloud -- same access limit that makes the live-NetBox 10.13 free-check an OWED foreground step (Section D). Verb: CONSISTENT-WITH; transit addresses stay, rack statics shift by the 12->13 rule, transit ROUTES re-point.
D-134 (ADOPTED 2026-07-23, docs/design-decisions.md:5858; contiguous-band amendment at :5900; the standing octet map at :5935 and :5984) rules the per-plane last-octet bands (.4-.49 utility, .50-.99 VIP, .100-.200 nodes, .201-.254 dynamic) and the STANDING cross-DC utility octet map (.4 artifact / .5 juju / .6 MAAS region / .7 tailscale). The load-bearing half, verbatim:
"THE OCTET MAP IS A STANDING CROSS-DC STANDARD. ... They FOLLOW ALL DC DEPLOYMENTS so that standardized configuration is upheld through multiple datacenter stand ups." (
docs/design-decisions.md:5965-5968)
Interaction: D-134's bands and octet map are offset-relative to the plane /22, not tied to the second octet. 10.12.8.5 -> 10.13.8.5 preserves "juju = .5" exactly. The re-IP therefore preserves D-134 by construction -- and the standing cross-DC rule (":a new DC standup reads the same table") is precisely what makes an octet-preserving shift the natural mapping. This is a POSITIVE: D-134 survives the re-IP unchanged and actively argues FOR the 1:1 shift. Verb: CONSISTENT-WITH (survives unchanged; endorses the octet-preserving map).
Summary of verbs: D-101 TERMINATES (v4-inheritance clause only) | D-115 AMENDS (factual premise; role-based ruling holds) | D-124 CONSISTENT (routes re-point) | D-134 CONSISTENT (survives, endorses the map).
The live cloud occupies 10.12.0.0/16 (NetBox Cloud role) and, per the operator's standing constraint ("never editing live infra"), it STAYS there untouched. The re-IP therefore does not "move a subnet"; under the plain reading of D-115 it creates 10.13.0.0/16 as a NEW allocation under the 10.0.0.0/8 Corp Private parent (which already covers 10.13 -- draft Section 4 confirms the 10.0.0.0/8 aggregate needs no change). The fork is where that new /16 lands in the role model:
Option B1 -- Cloud role gains 10.13.0.0/16 as a SECOND prefix (10.12 retained as vr0-dc0's record).
Option B2 -- NEW role (e.g. "Cloud -- VR1 rebuild") owns 10.13.0.0/16; Cloud stays 10.12-only.
Cloud (10.12, VR0/live) + a new VR1-scoped role (10.13).Office/Edge roles and D-124 seeded transit). Costs one new role + a small conceptual asymmetry (two "Cloud-ish" roles). No live record is re-labelled.Option B3 -- Cloud role MOVES to 10.13; 10.12 re-homed to a legacy/VR0 role.
Cloud becomes 10.13 (VR1); 10.12 is relabelled onto a new legacy/VR0 role.Recommendation surfaced (operator decides): B1 or B2 over B3. B2 if the apex should make the VR0-live / VR1-rebuild split explicit (most defensible against "never edit live infra"); B1 if minimizing role churn is preferred. B3 only if the operator explicitly wants "Cloud" to always mean the current build and accepts touching a live record.
GA-R5 = one decision per exchange, must reconcile D-101/D-115/D-124/D-134, quote verbatim when ruled. The re-IP actually contains THREE ruling-grade sub-questions. GA-R5's one-decision-per-exchange rule means the operator may want to take them in sequence (C.1 first -- it governs the others), or rule all three in one exchange if they prefer. Presented so each can be quoted verbatim.
"The VR1 rebuild moves off 10.12.0.0/16 (which collides with the live vr0-dc0 cloud) onto a newly-allocated 10.13.0.0/16 under the 10.0.0.0/8 Corp Private parent. The live cloud stays on 10.12, untouched. In the NetBox IPAM apex, does 10.13.0.0/16: (B1) join the existing Cloud role as a second prefix alongside 10.12; (B2) become a NEW role ('Cloud -- VR1 rebuild') with Cloud staying 10.12-only; or (B3) become the Cloud role, with 10.12 re-homed to a legacy/VR0 role? This AMENDS D-115 (its v4-role-based ruling holds; its finding that 10.13.x is unallocated is superseded by the collision discovery), TERMINATES D-101's 'VR1 DC0 inherits VR0 DC0's v4 layout unchanged' clause, is CONSISTENT-WITH D-124 (172.31 transit stays; routes re-point) and CONSISTENT-WITH D-134 (the octet bands/map survive unchanged)."
"Adopt the octet-preserving 10.12.a.b -> 10.13.a.b shift for the entire VR1 Cloud DC space (both DCs, second octet 12->13, octets 3/4 unchanged), preserving the six-plane layout, dc1's /19 supernet, the D-134 octet map, the VIP columns, and the FIP pool offsets? Or use this greenfield /16 to regularize dc0's non-contiguous plane offsets (4/8/12/16 then 32/36) into a contiguous /19-shaped block symmetric with dc1 -- at the cost of breaking octet-preservation and diverging further from the Roosevelt/VR0 template?"
Recommendation surfaced: the 1:1 octet-preserving shift (C.2 first option). D-134's standing cross-DC octet map (:5965) actively endorses it, and it minimizes the blast-radius diff.
This sub-question is surfaced by my read of scripts/lib-net.sh:22-83, which the draft did not carry. The file's flat defaults (PLANE_CIDRS, PLANE_ROLES, PLANE_GW incl. 10.12.8.1, VIP_PREFIX_*, FIP_POOL_*, KEYSTONE_VIP_DEFAULT) ARE vr0-dc0's real as-built values -- the file says so at line 37: "10.12.8.1 is VR0's REAL as-built value (phase-00-maas-standup.sh:119)". The vr0-dc0 selector arm is a documented no-op over these defaults (:119-121); the vr1-dc0 arm currently inherits them and overrides only PLANE_GW (drops the metal-admin router) and unsets the VID (:123-159). So the re-IP is not "edit the literals" -- it is a structural inversion of the file, and which shape it takes is a ruling-grade choice:
"In scripts/lib-net.sh the flat defaults ARE vr0-dc0's live as-built values and the vr0-dc0 arm is a no-op over them. After the re-IP: (i) keep the flat defaults at 10.12 (= vr0-dc0 live) and give BOTH VR1 arms (vr1-dc0, vr1-dc1) their own complete 10.13 literal blocks; or (ii) make the flat defaults 10.13 (VR1 is the forward build) and give vr0-dc0 a full explicit 10.12 override arm?"
Either way, the comment at scripts/lib-net.sh:124-134 ("Same PLANE values as vr0-dc0 ... INHERITS VR0 DC0's v4 layout UNCHANGED") becomes FALSE and owes an update in the same change (F13). NOT recommended for the operator here beyond noting (i) keeps the documented invariant and (ii) breaks it.
Separated: verified read-only by me vs OWED live/control-plane checks (F16(a)).
10.13 hit (full grep, excl .git) is one of: (1) this pivot's own artifacts (the draft, the findings, CURRENT-STATE's pivot banner, session-ledger); (2) historical/superseded references to the old 10.13.0.0/19 DC2 default (docs/archive/..., docs/dc-dc-netbox-buildout-scope.md:158,190, docs/design-decisions.md:3766/3797/3809/3856); (3) stale/test literals (see the collision hazard below). None is a live-object record.netbox/draft/vr1-office1-current-20260801.json, a DATED SNAPSHOT. Absence there is NOT a measured LIVE absence. The 10.12 collision that caused this whole pivot was found by discovery at Headscale, not by any scan -- so 10.13 must be proven free the same way, LIVE, before any dependent work.Naming-collision hazard I verified (feed into the ruling / a DOCFIX): 10.13 already carries TWO pre-existing meanings in-repo before this re-IP mints a third:
netbox/README.md:49 -- stale importer default VR1_DC1_V4_SUPERNET=10.13.0.0/19 (pre-D-115; D-115 moved dc1 to 10.12.64.0/19). Draft Section 5 flags this.tests/dc-rack-mgmt-import/test_logic.py:265 -- uses 10.13.0.5 as a live test literal (--rack-ip); mirrored in docs/archive/stage3-review-base.patch:3667. The draft MISSED this test-fixture use. Reusing 10.13.0.0/16 as the rebuild /16 will make a rack-IP test literal fall inside the new Cloud space -- reconcile so the three 10.13 meanings do not confuse.Per docs/tool-index.md discipline, I name the check AND whether a tested artifact exists. None of the three below has a tool that answers "is this /16 in use," so each is documented as a procedure, not improvised:
docs/tool-index.md covers Headscale route enumeration; it is control-plane access I do not have. This is the exact overlap class that caused the pivot. Check: list the advertised + approved routes on the tailnet and confirm no route overlaps 10.13.0.0/16 (Headscale has no 4via6; routes must be non-overlapping). Also confirm the dc0 .7 subnet router's UNAPPROVED 10.12.8.0/22 advert (findings F1 / already-on-surface) is not later approved onto a 10.13 conflict.http://10.10.1.10:8000) -- OWED, operator token. The apex token is operator-held and unreachable from vcloud (D-124 amendment, docs/design-decisions.md:5036; also findings F11). Check (read-only): query prefixes / aggregates for any object under 10.13.0.0/16; confirm the /16 is free and that adding it under 10.0.0.0/8 collides with nothing. Run on office1-netbox where the token lives.scripts/dc-egress-check.sh and scripts/maas-profile-assert.sh exist but neither answers "is this /16 in use" -- so this is a tooling gap: if the operator wants it repeatable, propose a small read-only "is-this-prefix-free" checker rather than improvising maas ... subnets read grep at the prompt.10.12. literal references, excluding frozen history (asbuilt/, docs/audit/, docs/archive/, .git/). Counts are grep -rl (files) and grep -rn (line hits).
| Surface | Files | Line hits | Change class | Key members |
|---|---|---|---|---|
scripts/ |
28 | 182 | MUST CHANGE | lib-net.sh (source of truth, 47 hits), phase-00-maas-standup, dc-rack-net, dc-snap-proxy, provider-bundle-check.py (independent octet band) |
tests/ |
69 | 566 | MUST CHANGE (twins + fixtures) | dc-selector (re-parses overlay), provider-bundle-check, render-baseline fixtures, phase-04 fixtures |
netbox/ |
11 | 222 | MUST CHANGE | dc-dc-prefixes-import, dc-plane-apex-import, d115-office-carve, importers + draft JSONs |
runbooks/ |
22 | 144 | MUST CHANGE | procedure text citing plane CIDRs |
opentofu/ |
5 | 31 | MUST CHANGE | variables.tf (vr1_dc1_planes -- lib-net.sh's named twin), per-DC substrate main.tf |
overlays/ |
3 | 27 | MUST CHANGE (ratified VIP source) | vr1-dc0-vips.yaml, vr1-dc1-vips.yaml, vr1-dc0-machines.yaml |
render/ |
2 | 6 | MUST CHANGE | render/values/vr1-dc{0,1}-vips.yaml |
bundle.yaml |
1 | 13 | MUST CHANGE | deploy input (VIPs) |
docs/ (excl audit+archive) |
31 | 549 | MUST NOT REWRITE | design-decisions.md, CURRENT-STATE.md -- prose record; D-117 ruled treatment = ANNOTATE in place / new dated entries, NOT rewrite |
Total live-surface 10.12 hits (excl asbuilt/audit/archive/.git): 3765 across 326 files. Read that number correctly: the ~549 docs/ prose hits are the historical record and are not a remap target (D-117: annotate, do not rewrite) -- the actual code/config remap work is the eight MUST-CHANGE rows above (~1191 hits). Do not read 3765 as the work estimate.
Twin-file coupling (must change in the SAME commit, per CLAUDE.md delivery discipline): lib-net.sh <-> opentofu/variables.tf (vr1_dc1_planes), and lib-net.sh <-> overlays/*-vips.yaml (via tests/dc-selector). Each script change ships its tests/<name>/run-tests.sh green + repo-lint clean + a changelog entry with a revert.
NetBox object counts (from the draft, vr1-office1-current-20260801.json): 13 prefixes, 24 ip-ranges, 80 ip-addresses (78 VIP legs + 2 rack .2 statics), 0 aggregate changes (10.0.0.0/8 already covers 10.13). Plus 2 FIP pools that are MAAS reserved ipranges, not NetBox objects (record gap, Section F).
Held (not in 10.12; do NOT remap): 172.31.0.0/24 transit (routes re-point), 10.10.x office (D-115), 172.30.0.0/16 edge (D-115), 10.16/10.17 dev clouds, all IPv6 (2602:f3e2::/36, fd50:840e:74e2::/48), the 10.0.0.0/8 aggregate.
4/8/12/16 then 32/36, skipping 20/24/28) and the dc0-vs-dc1 asymmetry (dc1 fits a /19; dc0 does not). Greenfield is the only cheap moment to regularize -- at the cost of octet-preservation and further Roosevelt divergence. Drafted as C.2.scripts/lib-net.sh:22-83,37. Needs a ruling on whether the defaults stay 10.12 (live vr0-dc0, invariant preserved) or become 10.13 (VR1 forward, invariant broken).scripts/phase-04-network-verify.sh) -- standing NetBox record gap./19 supernet has no NetBox prefix object (only its six child /22s).10.13.0.0/19 importer default at netbox/README.md:49 (pre-D-115).tests/dc-rack-mgmt-import/test_logic.py:265 uses 10.13.0.5 as a rack-IP test literal -- a third 10.13 meaning; reconcile to avoid confusion.docs/design-decisions.md:3856 supersedes only a scope-doc recommendation, not a rule; the operator should confirm "amendment" or rule "supersession" explicitly, since GA-R5 is graded on this reconciliation.docs/CURRENT-STATE.md pivot/checkpoint update, and a GA-R5 ruling for the MAAS-topology-no-migration posture (F4) and the checkpoint scope (F6) -- separate from this re-IP ruling.PREP PACKAGE -- not ruled, not committed, no D-number minted.