# Changelog 2026-07-09 -- $DC selector convention for lib-net.sh/lib-hosts.sh (DOCFIX-151)

No live infrastructure touched -- library-script additions + test harness only.
Closes tooling gap register item #1 in `docs/dc-dc-deployment-workflow.md`,
which explicitly BLOCKED the Stage 5 "high reuse" claim (`phase-01..08`
runbooks reused per-DC) from being operationally true.

## Item

### 1. DOCFIX-151 -- `lib_net_select_dc()` / `lib_hosts_select_dc()`
FILES: `scripts/lib-net.sh`, `scripts/lib-hosts.sh`, new
`tests/dc-selector/run-tests.sh`.

WHAT: added one opt-in selector function to each library, following the same
pattern as the existing `$REPO` convention (DOCFIX-139/141) -- an explicit,
measured selector, never an inferred default.

- `lib_net_select_dc()` in `lib-net.sh`: `dc0`/`dc1` are both a no-op (D-101,
  ADOPTED 2026-07-09, rules DC1 inherits DC0's v4 plane layout UNCHANGED --
  so there is deliberately no second copy of the CIDR literals to drift out
  of sync with the first); `dc2` FAILS LOUD (no NetBox-assigned literals
  exist yet -- gap #3, still open); an unknown token FAILS LOUD.
- `lib_hosts_select_dc()` in `lib-hosts.sh`: `dc0` is a no-op (the real,
  enrolled VR0 four-host set); `dc1` AND `dc2` BOTH fail loud -- unlike the
  network side, DC1's host *inventory* does not exist yet either (its node
  VMs haven't been created by `opentofu/modules/node-vm` or enrolled in
  MAAS), so aliasing dc1 to dc0's real hosts would be a silent-reuse bug,
  not a valid inheritance. This asymmetry (`lib_net_select_dc dc1` no-ops,
  `lib_hosts_select_dc dc1` fails) is intentional and is called out in both
  the changelog and the source comments so a future reader isn't confused by
  the two libraries behaving differently for the same DC token.

Backward compatible by construction: sourcing either file with no further
action is completely unaffected -- every existing script that sources
`lib-net.sh`/`lib-hosts.sh` today never calls the new functions, so nothing
about its behavior changes. This is an additive, opt-in mechanism.

VERIFIED:
- New harness `tests/dc-selector/run-tests.sh`: 21/21 PASS. Covers: backward
  compatibility (flat vars unaffected by sourcing alone), dc0/dc1 no-op +
  dc2/unknown-token/missing-arg fail-loud for the net selector, dc0 no-op +
  dc1/dc2/unknown-token/missing-arg fail-loud for the hosts selector, error
  messages cite the correct blocking reason (NetBox gap vs. no-enrollment),
  and an explicit assertion that the dc1 asymmetry between the two libraries
  is real and intentional (not a bug).
- Caught and fixed a real bug in the harness itself while writing it: the
  first draft piped `lib_net_select_dc dc2 2>&1 >/dev/null | grep -q
  "NetBox"` under `set -o pipefail` -- since the selector function's own
  exit code is 1 (by design, for the fail-loud case), `pipefail` made the
  whole pipeline report failure even when `grep` matched correctly. Fixed by
  capturing stderr into a variable via command substitution instead of
  piping through grep, so the assertion checks message content independent
  of the (expected-nonzero) selector exit code.
- `bash scripts/repo-lint.sh`: 0 fail, 1 documented legacy WARN (unchanged).
- `bash scripts/run-tests-all.sh`: confirmed via `git stash` A/B that the
  SAME 23 pre-existing failures (all either "jq required" -- not installed
  on this Windows workstation -- or live juju/cloud-dependent suites like
  `cloud-assert`/`preflight`/`tenant-*`, none of which touch
  `lib-net.sh`/`lib-hosts.sh`) exist identically with and without this
  change. `dc-selector` itself and `vault-kv-health` (the only other harness
  that sources either library) both PASS cleanly. This session is running
  from the operator's workstation, not the vopenstack-jesse jumphost -- no
  live cloud/juju/MAAS access is expected or required for tonight's prep
  work (operator instruction, 2026-07-09 evening).

REVERT: `git checkout HEAD~ -- scripts/lib-net.sh scripts/lib-hosts.sh &&
rm -rf tests/dc-selector` (safe -- no other script calls either new
function yet, so nothing downstream depends on their presence).

## Next actionable step

Tooling gap register item #1 CLOSED. Stage 5's runbook (Juju controller +
OpenStack bundle, per DC) can now honestly claim the `phase-01..08` reuse
path IS DC-safe once it's written to call `lib_net_select_dc "$DC"` /
`lib_hosts_select_dc "$DC"` explicitly -- that call-site wiring is part of
authoring the Stage 5 runbook itself (task list item), not this delivery.
Gap #3 (NetBox multi-DC import pipeline) is the next dependency: `dc2`
remains fail-loud in both libraries until it closes.
