diff --git a/docs/changelog-20260715-docfix195-c2-netbox-of-record.md b/docs/changelog-20260715-docfix195-c2-netbox-of-record.md new file mode 100644 index 0000000..657ec1a --- /dev/null +++ b/docs/changelog-20260715-docfix195-c2-netbox-of-record.md @@ -0,0 +1,75 @@ +# 2026-07-15 -- DOCFIX-195: office1-netbox holds the VR1 IPAM APEX role (working draft); apex write-back deferred; C2 redefined + +## Why + +Operator ruling (2026-07-15): **`office1-netbox` (10.10.1.10) HOLDS THE IPAM APEX ROLE during VR1** -- +it is the authoritative NetBox every consuming system (OpenTofu, MAAS, overlays, the Juju bundle) +derives its values from. It is a *working draft* (edited as the buildout proceeds), but it is the apex. +**`netbox.baldurkeep.com` does not get a write at all during VR1**; it is the eventual production apex, +frozen as a READ-ONLY v1 reference draft and not consulted by VR1 systems. Merging `office1-netbox` back +into `netbox.baldurkeep.com` is a deferred maybe at the very end -- NOT a Stage 2 gate. + +**Confirmed while scoping:** no live system config points at any NetBox URL (`opentofu/`, `scripts/`, +`lib-*.sh` carry none) -- "consuming systems use office1-netbox as apex" is a value-DERIVATION workflow +(we read NetBox by hand to populate `lib-net.sh`/tfvars/bundle), not a live API wiring, so no config +repoint is needed; this is a documentation change only. + +The repo encoded the OPPOSITE model: it called `netbox.baldurkeep.com` the "apex/source of truth" and +`office1-netbox` a throwaway "sandbox", and defined close-out **C2** (the last open Stage 2 gate, and +the branch->`main` merge trigger) as an operator-gated write that feeds the carve UPSTREAM. Under the +ruling that write does not happen in Stage 2, so C2-as-written was wrong. + +**Finding surfaced while drafting (new, previously unlogged):** D-120 Step 6 registers `10.10.1.0/24`'s +child ranges (`ipam/ip-ranges`) and the two service IPs (`ipam/ip-addresses`). Those object classes are +NOT covered by the sandbox loop -- `prod-draft-dump.py`'s `ENDPOINTS` and `sandbox-fidelity-check.py`'s +`KEY`/`EXPECTED_NEW` both stop at rirs/roles/regions/sites/aggregates/prefixes. So the hardened fidelity +check cannot verify the D-120 load; that verification needs a tool extension (+ harness) or a recorded +manual read-back. C2 now records this as a tooling gap and an open C2-execution sub-question. + +This is a DOCFIX, not a D-NNN: it defers the apex WRITE and does not revoke D-010 (netbox.baldurkeep.com +remains the eventual source of truth). Doc-only; no script or live-cloud change. + +## What changed (all documentation) + +1. **`docs/dc-dc-deployment-workflow.md`** -- Stage 2 State-paragraph NetBox bullet + the **C2** row. + C2 redefined: office1-netbox holds the COMPLETE validated dataset (carve + roles + both DCs + the + D-120 child ranges + service IPs), verified by (i) a hardened-fidelity-check re-run on the shared + objects and (ii) a load+verify of the D-120 objects; the tooling gap is logged; apex write-back + deferred. C2 stays **OPEN**. +2. **`docs/dc-dc-netbox-buildout-scope.md`** -- section 8.1 (inverted the upstream/office1 roles: office1 + is the record, the apex is a read-only v1 draft, merge-back deferred) and section 8.6 (retitled and + rewritten from "Feeding the delta upstream" to "office1-netbox holds the validated dataset; apex + write-back DEFERRED", with the D-120 tooling gap and the deferred-merge-back procedure). +3. **`docs/session-ledger.md`** -- five spots corrected (D-120 Step 6 item; OPEN-WORK item 2; the + NetBox WRITE-PATH BUGS preamble; the fidelity-recheck sequence note; the PINNED merge-point bullet) + plus a NEW PINNED bullet recording the deferred apex write-back. All edits are in narrative sections; + the machine-derived block was not touched. +4. **`docs/design-decisions.md`** -- a dated Note under **D-010** recording the VR1-phase apex role + (office1-netbox is the working-draft apex; apex write-back deferred; defers the write, does not + revoke D-010), AND a pointer on **D-103**'s "NetBox remains the IPAM apex; MAAS and overlays consume + NetBox values" bullet naming office1-netbox as that apex during VR1. +5. **`netbox/README.md`** -- a banner so the `NETBOX_URL=https://netbox.baldurkeep.com` examples are not + mistaken for the VR1 write target (that is office1-netbox; the apex URL is for the deferred merge-back + only, gated by `--yes-write-upstream`). + +## Also logged (NOT actioned here) + +- **Tooling gap:** the sandbox dumper + fidelity check do not cover `ip-ranges`/`ip-addresses`; the + D-120 load cannot be machine-verified until they are extended (each with its harness) or a manual + read-back is recorded. This is the real remaining C2-execution work. +- **Durability finding:** `office1-netbox` is now load-bearing VR1 IPAM state on a lab VM; its + backup/durability matters once it is the record (log-only; not part of this DOCFIX). + +## Revert + +Each item is an isolated text edit; revert individually: + +1. `git checkout HEAD -- docs/dc-dc-deployment-workflow.md` +2. `git checkout HEAD -- docs/dc-dc-netbox-buildout-scope.md` +3. `git checkout HEAD -- docs/session-ledger.md` +4. `git checkout HEAD -- docs/design-decisions.md` +5. `git checkout HEAD -- netbox/README.md` +6. `git rm docs/changelog-20260715-docfix195-c2-netbox-of-record.md` + +Reverting restores the prior "feed the carve upstream = C2" framing across all five docs. No code paths, +scripts, harnesses, or live NetBox state are affected by this change or its revert. diff --git a/docs/dc-dc-deployment-workflow.md b/docs/dc-dc-deployment-workflow.md index 91ef8bf..c1d1d94 100644 --- a/docs/dc-dc-deployment-workflow.md +++ b/docs/dc-dc-deployment-workflow.md @@ -120,20 +120,25 @@ the DCs. - **The L3 nesting proof is NO LONGER an unknown -- it is DEFINITIVE.** A guest booted, PXE'd and COMMISSIONED three levels deep. DC1 inherits the proof; D-114's model stands. -- **NetBox is populated in the SANDBOX and proven faithful** (D-115 office carve + the six-plane - roles + both DCs, 90 -> 134 prefixes, field-level fidelity check clean). The apex literals that - blocked it are now assigned: **D-117** (site naming) and **D-118** (`ORG_ULA_48 = - fd50:840e:74e2::/48`). The gate bullet says **authoritative**, and the authoritative NetBox is - `netbox.baldurkeep.com` -- so this bullet is NOT met until the validated carve is fed UPSTREAM. - That write is operator-gated; the tools refuse a non-sandbox target without - `--yes-write-upstream`. +- **NetBox is populated in `office1-netbox` -- the VR1 IPAM APEX, a working draft (DOCFIX-195)** (D-115 + office carve + the six-plane roles + both DCs, 90 -> 134 prefixes). The apex literals that blocked it + are now assigned: **D-117** (site naming) and **D-118** (`ORG_ULA_48 = fd50:840e:74e2::/48`). + **Operator ruling 2026-07-15 (DOCFIX-195):** during VR1, `office1-netbox` (10.10.1.10) takes ALL + NetBox writes and HOLDS THE IPAM APEX ROLE -- every consuming system (OpenTofu, MAAS, overlays, the + Juju bundle) derives its NetBox values from it. It is a *working draft* (edited as the buildout + proceeds), but it is the authoritative NetBox. `netbox.baldurkeep.com` is the production apex, held + as a READ-ONLY v1 reference draft and NOT consulted by VR1 systems; the write-back to it is DEFERRED + to end-of-deployment (may not happen) -- it is NOT a Stage 2 gate. So the "NetBox authoritative + populated" gate is met when `office1-netbox` holds + the COMPLETE validated dataset, NOT by any upstream write. See C2 for what "complete" and "verified" + require (the D-120 additions, plus a fidelity-check re-run -- the earlier "fidelity check clean" + verdict predates the 2026-07-14 hardening and must be re-established). **Stage 2 close-out checklist (what must be true before the merge):** | # | Item | State | |---|---|---| | C1 | Office1 LAN IPv6 deployed (`2602:f3e2:f01:100::1/64` + RA on the edge LAN). WAN v6 leg DEFERRED: v6 does not egress the lab. | **DONE 2026-07-14** -- live and PROVEN ON THE WIRE: address on the kernel, radvd advertising the prefix (`mode=unmanaged`), `voffice1` autoconfigured `...:5054:ff:fe6a:87e5` by SLAAC, edge->voffice1 GUA ping 0.0% loss. NOTE the D-113 AMENDMENT: the ADDRESS half is **not** REST-API-doable (`scripts/opnsense-set-interface-v6.sh`); only the RA half is. `docs/changelog-20260714-office1-lan-ipv6-executed.md` | -| C2 | The validated carve fed UPSTREAM to `netbox.baldurkeep.com` -- the gate says *authoritative*, and the sandbox is not it. Operator-gated write. | **OPEN** | +| C2 | `office1-netbox` (10.10.1.10) is the VR1 IPAM apex -- a working draft (DOCFIX-195) -- and holds the COMPLETE validated dataset: D-115 carve + six-plane roles + both DCs' prefixes/aggregates/RIRs, PLUS the D-120 additions -- `10.10.1.0/24`'s child ranges (`ip-ranges`: static .2-.49 / dynamic .100-.200 / node .201-.254) and the two service IP assignments (`ip-addresses`: office1-netbox 10.10.1.10, office1-tailscale 10.10.1.11). `netbox.baldurkeep.com` stays a READ-ONLY v1 reference draft; the write-back to it is DEFERRED to end-of-deployment (DOCFIX-195, operator ruling 2026-07-15) -- NOT a Stage 2 gate. | **OPEN** -- two sub-tasks: (i) re-run the HARDENED fidelity check on the shared carve/roles/DCs (the "faithful" verdict predates the 2026-07-14 hardening, per section 8.3); (ii) load the D-120 child ranges + service IPs into `office1-netbox` and verify them. **TOOLING GAP (logged DOCFIX-195):** the D-120 objects are `ip-ranges`/`ip-addresses`, object classes the current sandbox loop does NOT cover -- `prod-draft-dump.py` ENDPOINTS and `sandbox-fidelity-check.py` KEY/EXPECTED_NEW stop at rirs/roles/regions/sites/aggregates/prefixes -- so verifying them needs extending both tools (+ harnesses) OR a recorded manual read-back. | | C3 | The `$DC` shell-selector collision resolved. | **DONE 2026-07-14 (D-119)** -- selectors are REGION-QUALIFIED (`vr0-dc0`/`vr1-dc0`/`vr1-dc1`) across `lib-net.sh`, `lib-hosts.sh`, `opentofu/`, the importer and every runbook call site. Bare `dcN` is REJECTED. The importer's DC->site map is now an IDENTITY, so the off-by-one is structurally impossible. Gap #19 CLOSED. | | C4 | The NetBox sandbox loop documented. | **DONE 2026-07-14** -- `docs/dc-dc-netbox-buildout-scope.md` section 8 (rationale + write-guard table + WAF trap) and `runbooks/dc-dc-phase1-office1-standup.md` Step 10b (operational sequence). | | C5 | This doc's Stage 2 row reconciled against reality (it has drifted three times). | **DONE 2026-07-14** | diff --git a/docs/dc-dc-netbox-buildout-scope.md b/docs/dc-dc-netbox-buildout-scope.md index c815cb2..0b4e323 100644 --- a/docs/dc-dc-netbox-buildout-scope.md +++ b/docs/dc-dc-netbox-buildout-scope.md @@ -191,23 +191,32 @@ ## 8. The NetBox sandbox loop (C4) -### 8.1 Why a sandbox exists at all +### 8.1 Why a second NetBox exists -NetBox `netbox.baldurkeep.com` is the IPAM apex and source of truth (D-010, D-103). The section-4 -buildout mutates it (roles, aggregates, org ULA /48, two DCs of six-plane prefixes). We do NOT -rehearse those mutations on the apex. A SECOND NetBox -- `office1-netbox`, `10.10.1.10:8000`, -NetBox 4.6.4 on the Office1 VM (`docs/changelog-20260713-office1-netbox-deployed.md`) -- is the -SANDBOX. The upstream draft is copied in, the planned changes are applied and proven there, and only -then is the validated delta fed back upstream as a separate, operator-gated write. +**DOCFIX-195 (operator ruling 2026-07-15) -- READ THIS FIRST; it INVERTS the roles the rest of this +section was originally written around.** During VR1 the VR1 IPAM APEX is `office1-netbox` +(`10.10.1.10:8000`, NetBox 4.6.4 on the Office1 VM, `docs/changelog-20260713-office1-netbox-deployed.md`): +it takes ALL VR1 writes (the section-4 buildout, the D-120 additions, any further refinement) and every +consuming system (OpenTofu, MAAS, overlays, the Juju bundle) derives its NetBox values from it, not from +`netbox.baldurkeep.com`. It is a *working draft* -- edited as the buildout proceeds -- but it is the +authoritative NetBox. `netbox.baldurkeep.com` is held as a READ-ONLY v1 REFERENCE DRAFT for +the duration -- it gets NO write during VR1. Merging the validated `office1-netbox` dataset back into +`netbox.baldurkeep.com` is a DEFERRED, end-of-deployment MAYBE (8.6), not a Stage 2 gate. This DEFERS +the apex write; it does NOT revoke D-010 -- `netbox.baldurkeep.com` remains the eventual IPAM source of +truth. - upstream (draft source, READ-ONLY) --[prod-draft-dump.py]--> netbox/draft/vr1-draft.json - vr1-draft.json --[sandbox-seed.py]------> Office1 sandbox - ...apply the planned delta in the sandbox (the section-4 importers)... - ...prove sandbox == upstream draft + EXACTLY the planned delta (fidelity check)... - validated refinements --[operator-gated write]-> upstream +The loop that builds and validates `office1-netbox` from the draft is unchanged; only the FINAL step +(feeding the apex) moved OUT of Stage 2: -The sim NEVER `--commit`s upstream as a side effect. Feeding the apex is always a deliberate -operator act (8.4, 8.6). + upstream draft (READ-ONLY, v1 reference) --[prod-draft-dump.py]--> netbox/draft/vr1-draft.json + vr1-draft.json --[sandbox-seed.py]------> office1-netbox (the RECORD) + ...apply the planned delta in office1-netbox (the section-4 importers + the D-120 additions)... + ...prove office1-netbox == draft + EXACTLY the planned delta (fidelity check)... + validated dataset --[DEFERRED, end-of-deployment, operator-gated]-> apex + +The importers NEVER `--commit` the apex as a side effect (8.4). Writing `office1-netbox` is normal and +unguarded (it is in `SANDBOX_HOSTS`); writing `netbox.baldurkeep.com` stays behind +`--yes-write-upstream` and is out of scope until the deferred merge-back. ### 8.2 Why a FIDELITY CHECK, and not just counts @@ -272,12 +281,30 @@ `vcloud` -- the two pynetbox importers must run on `office1-netbox` (pynetbox 7.0.0), which reaches upstream through the edge. -### 8.6 Feeding the delta upstream (C2) -- STILL PENDING +### 8.6 C2 -- office1-netbox holds the validated dataset (apex write-back DEFERRED) -C2 is a production IPAM write and is NOT part of the sim. Preconditions before it runs: (a) re-run -the HARDENED fidelity check against the sandbox -- the "faithful" verdict predates the hardening -(8.3); (b) run the two pynetbox importers from `office1-netbox` (pynetbox + upstream reach); (c) each -importer needs `--yes-write-upstream` on top of `--commit` for the non-sandbox target; (d) present -and individually approve each mutation -- never batched. As of 2026-07-14 C2 has NOT been run; the -upstream apex still lacks the six-plane roles, the RIRs/aggregates, the `vr1-off1` carve, and the -36 DC prefixes (measured read-only). +**DOCFIX-195 (operator ruling 2026-07-15) REDEFINED C2.** C2 is NO LONGER "feed the carve upstream" -- +there is NO `netbox.baldurkeep.com` write in Stage 2 at all. C2 is met when `office1-netbox` (the VR1 +IPAM apex) holds the COMPLETE validated dataset AND it is VERIFIED. Two sub-tasks remain: + + (i) Re-run the HARDENED fidelity check against `office1-netbox` for the shared carve/roles/DCs -- + the "faithful" verdict predates the 2026-07-14 hardening (8.3), so it must be re-established. + (ii) Load the D-120 additions into `office1-netbox` -- `10.10.1.0/24`'s child ranges (`ip-ranges`: + static .2-.49 / dynamic .100-.200 / node .201-.254) and the two service IP assignments + (`ip-addresses`: office1-netbox 10.10.1.10, office1-tailscale 10.10.1.11) -- and verify them. + +**TOOLING GAP (logged DOCFIX-195, NOT fixed here).** The D-120 objects are `ip-ranges`/`ip-addresses` +-- object classes the sandbox loop does NOT cover: `prod-draft-dump.py`'s ENDPOINTS and +`sandbox-fidelity-check.py`'s KEY/EXPECTED_NEW both stop at rirs/roles/regions/sites/aggregates/ +prefixes. So the hardened fidelity check CANNOT see the D-120 load. Verifying sub-task (ii) requires +EITHER extending both tools (add the two endpoints + KEY entries + EXPECTED_NEW bounds + delta field +checks, each with its harness) OR a recorded manual read-back against `office1-netbox`. That choice is +an open C2-execution sub-question, to be ruled when C2 runs. + +**The DEFERRED merge-back (end-of-deployment, MAYBE).** If/when the operator elects to seed +`netbox.baldurkeep.com` from the validated `office1-netbox` dataset, it is a production IPAM write and +NOT part of the sim: (a) run the two pynetbox importers from `office1-netbox` (pynetbox + apex reach); +(b) each needs `--yes-write-upstream` on top of `--commit` for the non-sandbox target; (c) the NetBox +write-path bugs (session-ledger "NetBox WRITE-PATH BUGS") gate THAT write, not Stage 2 close; (d) +present and individually approve each mutation -- never batched. As of 2026-07-15 the apex is untouched +and still holds only the v1 draft (measured read-only). diff --git a/docs/design-decisions.md b/docs/design-decisions.md index 1f19fb5..a08a471 100644 --- a/docs/design-decisions.md +++ b/docs/design-decisions.md @@ -193,6 +193,8 @@ **Decision:** NetBox is the single source of truth for IPAM at the **role and cloud-level pool** layer. Per-project tenant subnets are exempt under the hybrid model (D-016). +**Note (DOCFIX-195, operator ruling 2026-07-15 -- VR1 phase):** During VR1 `office1-netbox` (10.10.1.10) HOLDS THE IPAM APEX ROLE: it is the authoritative NetBox every consuming system (OpenTofu, MAAS, overlays, the Juju bundle) derives its values from. It is a *working draft* (edited as the buildout proceeds), but it is the apex. `netbox.baldurkeep.com` is the eventual PRODUCTION apex, held during VR1 as a READ-ONLY v1 reference draft that takes NO write and is NOT consulted by VR1 systems. Merging the validated `office1-netbox` dataset back into `netbox.baldurkeep.com` is DEFERRED to end-of-deployment (a maybe). This DEFERS the apex write; it does NOT revoke D-010 -- `netbox.baldurkeep.com` remains the single eventual source of truth. See `docs/dc-dc-netbox-buildout-scope.md` section 8 and close-out C2 in `docs/dc-dc-deployment-workflow.md`. + **Workflow:** Update NetBox → update bundle/overlay → commit both with cross-reference. **Standing imports for v1 (gating the bundle):** @@ -2016,7 +2018,7 @@ - OpenTofu owns create / destroy of: the libvirt domains that stand in for DC "hardware"; all virtual networks (the dark-fiber, plane, and ISP-edge segments); the OPNsense edge VMs; and the Office1 service VMs (MAAS-region, NetBox, GitBucket). OpenTofu runs from the Office1 operator VM against the vcloud host libvirt. - OpenTofu registers each DC's libvirt host to that DC's MAAS rack controller as a virsh VM-host, so MAAS DISCOVERS the OpenTofu-created node VMs. - MAAS owns commission / deploy / power / release of those node VMs; it does NOT compose new ones. Juju then deploys the OpenStack bundle onto the MAAS-deployed machines. -- NetBox remains the IPAM apex; MAAS and overlays consume NetBox values, never the reverse. +- NetBox remains the IPAM apex; MAAS and overlays consume NetBox values, never the reverse. **(DOCFIX-195, 2026-07-15: during VR1 that apex is `office1-netbox` (10.10.1.10) -- the working draft every consuming system reads; `netbox.baldurkeep.com` is the eventual production apex, frozen as the v1 reference draft with merge-back deferred. Defers the write, does not change this consume-not-reverse rule.)** **Rationale / tradeoffs:** this keeps the entire physical substrate in versioned OpenTofu (auditable, reproducible, and exactly the "operator scripts the deployment from Office1" model), while MAAS owns the provisioning lifecycle -- mirroring Roosevelt, where MAAS enlists hardware that already exists rather than creating it. "MAAS owns lifecycle" here means the provisioning lifecycle, not domain creation; that reconciles the two operator inputs. diff --git a/docs/session-ledger.md b/docs/session-ledger.md index 3c05954..ab61e41 100644 --- a/docs/session-ledger.md +++ b/docs/session-ledger.md @@ -30,7 +30,7 @@ ## Machine-derived (re-seed from `scripts/ledger-scan.sh`; do not hand-edit) -_Re-seeded from the 2026-07-14 scan. Re-run `bash scripts/ledger-scan.sh` to refresh._ +_Re-seeded from the 2026-07-15 scan. Re-run `bash scripts/ledger-scan.sh` to refresh._ - **PROPOSED / OPEN decisions:** D-068 (Vault substrate hardening, Roosevelt -- 1.16 ruled OUT per amendment; the off-EOL-1.8.8 path remains OPEN), D-071 (routine update cadence + Juju @@ -38,8 +38,9 @@ the pre-DC-DC controller HA/backup session). - **OPEN security rows:** SEC-001, SEC-003, SEC-004, SEC-005, SEC-006, SEC-007, **SEC-008**. (SEC-008 -- the vcloud re-enrolment key -- was MISSING from the prior block.) -- **Next-free numbers:** D = **119**, DOCFIX = 195, BUNDLEFIX = 013. - (The prior block said D=114 -- STALE by five; D-114..D-118 are all assigned and ADOPTED.) +- **Next-free numbers:** D = **121**, DOCFIX = 196, BUNDLEFIX = 013. + (Since the prior block: D-119 + D-120 assigned and ADOPTED, and DOCFIX-195 assigned by this change + -- so next-free advanced D 119->121 and DOCFIX 195->196.) - **Standing numbering rule:** never write an identifier-shaped token (D-/DOCFIX-/BUNDLEFIX-NNN) ABOVE the real high-water mark anywhere in `docs/` or `runbooks/` prose -- `ledger-scan` reads prose and a decoy token inflates the next-free counter. This has bitten twice. @@ -97,7 +98,11 @@ address is set on the guest (netplan + curtin, over `lxc exec`) and MAAS-model drift is accepted (reconciles at next teardown/redeploy). Sweep + gauntlet done; `runbooks/dc-dc-office1-service-reip.md` now records the measured method. **Still owed:** D-120 Step 6 -- register the /24 child ranges + the -two service IPs in the sandbox NetBox and feed upstream; rides with C2 (the only C-item left). +two service IPs in `office1-netbox` (the VR1 IPAM apex, DOCFIX-195); rides with C2 (the only +C-item left). NO apex write -- the upstream write-back is DEFERRED to end-of-deployment. NOTE the +tooling gap logged under C2: these are `ip-ranges`/`ip-addresses`, object classes the sandbox dumper + +fidelity check do NOT cover, so verifying them needs a tool extension (+ harness) or a recorded manual +read-back. The authoritative per-stage tracker is `docs/dc-dc-deployment-workflow.md` (stage table + tooling @@ -190,8 +195,10 @@ (dry-by-default, structurally REFUSES an upstream URL), `netbox/sandbox-fidelity-check.py` (field-by-field -- counts alone HID a bug where 17 of 90 prefixes silently lost their region scope). **STILL PENDING:** capture the loop in `docs/dc-dc-netbox-buildout-scope.md` + the Stage 2 - runbook, and **feed the validated carve UPSTREAM** (close-out C2 -- the Stage 2 gate says - *authoritative*, and the sandbox is not it). The upstream write is operator-gated. + runbook, and **ensure `office1-netbox` holds the COMPLETE validated dataset** (close-out C2, + REDEFINED by DOCFIX-195: `office1-netbox` is the VR1 IPAM apex (the working draft every consuming + system reads); `netbox.baldurkeep.com` is the production apex, held as a READ-ONLY v1 reference draft, + and the write-back to it is DEFERRED to end-of-deployment -- NOT a Stage 2 gate). 3. **`pynetbox` -- CLOSED 2026-07-13.** Installed (7.0.0) on `office1-netbox`, which is where the imports actually run. The stdlib tools (`prod-draft-dump`/`sandbox-seed`/`sandbox-fidelity-check`) deliberately need no dependency at all. @@ -302,8 +309,11 @@ ## OPEN -- NetBox WRITE-PATH BUGS (found 2026-07-14 by adversarial review; LOGGED, NOT FIXED) -These are independent of D-119's naming work. **They matter BEFORE C2** (feeding the carve upstream), -because they are what would corrupt the production apex during that write. +These are independent of D-119's naming work. **DOCFIX-195 (2026-07-15) reclassified WHEN they matter:** +C2 no longer writes the PRODUCTION apex `netbox.baldurkeep.com` (office1-netbox is the VR1 IPAM apex; +the `netbox.baldurkeep.com` write-back is DEFERRED to end-of-deployment). So these bugs gate the DEFERRED merge-back, NOT Stage 2 +close -- they are what would corrupt the production apex during THAT write. They no longer block C2 or +the Stage 2 merge. 1. **`roles-aggregates-import.py` still dies HALF-WAY through a production write.** The preflight it advertises only checks role-NAME collisions. The `ARIN` RIR lookup and `validate_ula_48()` both run @@ -337,8 +347,9 @@ **CONSEQUENCE TO ACT ON:** the sandbox was declared "proven faithful" (2026-07-14) using the fidelity check BEFORE it was hardened -- i.e. under the version that could FALSE-GREEN. RE-RUN `sandbox-fidelity-check.py` against the sandbox under the hardened check before trusting that -"faithful" verdict, and certainly before C2 feeds the carve upstream. (Not done this session: it -needs the sandbox NetBox token, which is operator-held; folds naturally into the C2 step.) +"faithful" verdict -- this re-run IS C2 sub-task (i) (DOCFIX-195), run against `office1-netbox` (the +VR1 IPAM apex), NOT against the production apex `netbox.baldurkeep.com`. (Not done this session: it +needs the office1-netbox token, which is operator-held; folds naturally into the C2 step.) Items 4-6 remain LOGGED not fixed. (Historical rationale: 1 and 3 are partial-write-no-rollback on the production IPAM; 2 is what we would use to prove the write was correct.) @@ -349,11 +360,20 @@ `dc-dc-stage1-phase0-first-exec` merges to `main` when every Stage 2 gate bullet is MET -- not at session end, not "when it feels done." The close-out checklist (C1..C5) lives in `docs/dc-dc-deployment-workflow.md`'s Stage 2 section; that doc is authoritative for what - "closed" means. NEW policy: `main` has never taken a feature merge (its only merge commits + "closed" means. **DOCFIX-195 (2026-07-15) REDEFINED C2** (the last open C-item): it is no longer an + apex write but "`office1-netbox` holds AND verifies the complete validated dataset"; the + `netbox.baldurkeep.com` write-back is DEFERRED to end-of-deployment. The merge still waits on every + gate bullet MET -- only C2's bar changed. NEW policy: `main` has never taken a feature merge (its only merge commits are inherited from the pre-rename `openstack-caracal-ipv4` remote, D-110), so ALL VR1 work -- D-112..D-118, the Office1 headend, the NetBox tooling, 52 commits -- lives only on the branch. `main`'s tip is two ad-hoc operator uploads; it is NOT trunk-of-record for VR1 yet. The merge itself is a gated action: present it, do not run it unasked. +- **UPSTREAM APEX WRITE-BACK -- DEFERRED to end-of-deployment (DOCFIX-195, operator ruling 2026-07-15).** + Seeding `netbox.baldurkeep.com` from the validated `office1-netbox` dataset is a MAYBE at the very + end, NOT a Stage 2 gate. Until then the apex stays a READ-ONLY v1 reference draft (no write during + VR1); `office1-netbox` (10.10.1.10) is the VR1 IPAM apex (the working draft every consuming system + reads). The "NetBox WRITE-PATH BUGS" section gates THAT deferred write, not Stage 2 close. Defers the + write; does NOT revoke D-010. - **D-071** ratification -- held for the dedicated pre-DC-DC Juju controller HA/backup planning session. Backups now exist (a 902MB controller backup was taken; `juju create-backup` / `download-backup` DO exist on juju 3.6 -- the original "removed in 3.0" premise was wrong). diff --git a/netbox/README.md b/netbox/README.md index 6e27e2e..303a150 100644 --- a/netbox/README.md +++ b/netbox/README.md @@ -4,6 +4,14 @@ (IPv4-only, single-site) deployment and the VR1 DC-DC (two-DC, dual-stack) buildout. Each script is idempotent; re-running is safe. +> **DOCFIX-195 (operator ruling 2026-07-15) -- TARGET NetBox during VR1.** The VR1 IPAM apex is +> `office1-netbox` (`http://10.10.1.10:8000`) -- a working draft, edited as the buildout proceeds, and +> the NetBox every consuming system (OpenTofu, MAAS, overlays, bundle) derives its values from. Point +> the importers there (it is in `SANDBOX_HOSTS`, so the writes are unguarded). `netbox.baldurkeep.com` is held as a READ-ONLY v1 reference draft and takes +> NO write during VR1 -- the `NETBOX_URL=https://netbox.baldurkeep.com` shown in the examples below is +> for the DEFERRED end-of-deployment merge-back ONLY, and each apex write additionally requires +> `--yes-write-upstream`. See `docs/dc-dc-netbox-buildout-scope.md` section 8. + ## VR1 DC-DC scripts (2026-07-09, closes tooling gap register #3) ### `dc-dc-prefixes-import.py`