diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index bf2a505..c046e32 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1226,8 +1226,32 @@ pool -- both encoded a state the ruling retired. Each was replaced with a STRONGER assertion (the ruled VALUE, plus a guard that the still-unset group stayed unset, plus a check that dc1 plans its OWN pool and never dc0's). dc-selector 48 -> 51 checks; gauntlet ALL GREEN (83). - **STILL NOT DONE, each an operator-gated live mutation:** the rack-bridge v6 legs (U17), and - the apex population (bands + VIPs as scoped objects). +- **APEX POPULATED 2026-07-27 -- the fourth rendering pull is now REAL** (operator: "Populate + the apex with the bands and VIPs"). Tool `netbox/dc-plane-apex-import.py`, dry by default, + write-guarded to the DOCFIX-195 apex host, every object READ BACK. Applied both DCs: + **12 ip-ranges + 78 ip-addresses each, read-back 12/12 and 78/78, errors=0.** Idempotent + re-run plans ZERO with 90 already present. **Apex totals: ip-ranges 3 -> 27, ip-addresses + 4 -> 160, of which IPv6 0 -> 78, and 156 VIP objects** (13 apps x 3 legs x 2 families x 2 + DCs). Everything derived, not hardcoded, except the ruled app->octet map: plane CIDRs from + `lib-net.sh`, v6 prefixes read from the apex's own prefix layer, VIP legs computed as the + three plane bases + octet (NOT from `VIP_PREFIX_*`, which lib-net unsets for dc1 because R9 + rules that group generated), v6 host part mirroring the octet TEXTUALLY per the 2026-07-27 + ruling. **vault `.61` and designate `.62` ARE included though RULED-BUT-NOT-BUILT (R11)** -- + reserving a planned address is precisely what an IPAM apex is for, and it means the renderer + will emit them without a second reconciliation. + **TWO CORRECTIONS WORTH KEEPING.** (i) **D-136's named prerequisite does not gate this + write.** Its prose says extending `netbox/sandbox-fidelity-check.py` "gates every apex + reconciliation this coupling depends on"; MEASURED, that script COMPARES TWO JSON DUMPS AND + TOUCHES NO NETBOX -- it proves a seeded SANDBOX faithfully replicates the upstream DRAFT, + i.e. it validates the SEEDER, not apex writes. The real verification for an apex write is + read-back, which this tool does. The extension is still owed for the sandbox loop; it is not + a blocker here. (ii) **A live-vs-dump shape difference bit the first version**: the LIVE API + returns `scope.name` as the DISPLAY name ("VR1 DC0") with `scope.slug` as the site key, while + the repo's dump files normalise `name` to the slug. Written against the dump, the tool found + ZERO prefixes live and REFUSED rather than writing nothing silently -- the refusal is what + surfaced the bug. Now matches slug-then-name. Same class as this audit's own "used a + two-day-old dump instead of polling live" finding. + **STILL NOT DONE, an operator-gated live mutation:** the rack-bridge v6 legs (U17). - Position inside Stage 3: deploy step A EXECUTED 2026-07-19 (6/0/6 exact; convergence zero -- `docs/audit/outer-plan-20260719-postA-converged.txt`). **Deploy step B diff --git a/docs/changelog-20260727-stage5-phase0.md b/docs/changelog-20260727-stage5-phase0.md index afc0f15..8bf5004 100644 --- a/docs/changelog-20260727-stage5-phase0.md +++ b/docs/changelog-20260727-stage5-phase0.md @@ -368,3 +368,36 @@ **Revert.** Delete the iprange whose start_ip is `10.12.65.0`, and restore the `unset FIP_POOL_START FIP_POOL_END` line in `lib-net.sh`'s dc1 arm. + +## 12. LIVE -- NetBox apex populated with the D-134 bands and the ruled VIP set + +**What.** New `netbox/dc-plane-apex-import.py` (dry by default, write-guarded, read-back +verified), applied to both DCs. Apex: ip-ranges **3 -> 27**, ip-addresses **4 -> 160** +(IPv6 **0 -> 78**), **156 VIP objects**. Read-back 12/12 ranges and 78/78 addresses per +DC, errors=0; idempotent re-run plans zero. + +**Why.** D-136 option (D) rules the apex be populated FIRST and the renderer generated +from it. Measured before: the apex held the whole prefix layer but ZERO bands and ZERO +VIPs -- the sub-prefix gap the coupling exists to close. + +**Derived, not hardcoded**, except the ruled app->octet map: planes from `lib-net.sh`; +v6 prefixes read from the apex itself; VIP legs = the three plane bases + octet (NOT +`VIP_PREFIX_*`, which lib-net unsets for dc1 per R9); v6 host part = textual octet mirror +per the 2026-07-27 ruling, with the provider leg in the DEDICATED GUA VIP /64. + +**vault .61 / designate .62 included** though ruled-but-not-built (R11) -- reserving a +planned address is what an IPAM apex is for, and the renderer will now emit them. + +**Correction to D-136.** Its prose says `sandbox-fidelity-check.py` "gates every apex +reconciliation". Measured: that script compares two JSON dumps and touches no NetBox -- +it validates the SEEDER against the upstream draft. It does not gate apex writes; read-back +does. The extension is still owed for the sandbox loop, but it was not a blocker here. + +**Bug caught by the tool's own refusal.** The live API returns `scope.name` as the display +name ("VR1 DC0") and `scope.slug` as the site key; the repo's dumps normalise `name` to the +slug. Built against the dump, the tool matched zero prefixes live -- and REFUSED rather than +writing nothing silently. Now matches slug-then-name. + +**Revert.** Delete the created objects by description prefix: `ip-ranges` whose description +starts `D-134 `, and `ip-addresses` whose description starts `VIP `. Both are additive +records; no live address is affected.