Newer
Older
openstack-caracal-dc-dc / docs / changelog-20260715-fidelity-check-scope-correctness.md

2026-07-15 -- C2 sub-task (i): sandbox re-verified faithful; fidelity checker scope false-positive fixed

Context

C2 (Stage 2 close-out) sub-task (i), per DOCFIX-195: re-run the HARDENED fidelity check against office1-netbox (the VR1 IPAM apex, a working draft), because the "faithful" verdict predated the 2026-07-14 hardening. Executed this session from the jumphost, off the newly-consolidated sandbox token (see SEC-009 note below) through an SSH tunnel to 10.10.1.10:8000.

What happened

  1. Read-only dump of office1-netbox via netbox/prod-draft-dump.py (token sourced from ~/vr1-office1-creds/vr1-netbox-sandbox.env, never printed). Sandbox: 3 RIRs / 29 roles / 5 regions / 11 sites / 5 aggregates / 134 prefixes.

  2. The hardened checker flagged 2 problems -- 10.10.0.0/16 (office) and 172.30.0.0/16 (edge) "have NO SCOPE" -- exit 1.

  3. Investigated rather than accepted the failure. Both are role-level container /16s that netbox/d115-office-carve.py creates with scope=None by design (lines 74/84). And the upstream apex draft ALREADY carries 27 unscoped role containers (10.0.0.0/8, 172.16.0.0/12, 23.157.124.0/24, ...). So unscoped role containers are the established convention; these two conform. A full cross-check of all 44 delta prefixes against their INTENDED scope (from the two importers) was 44/44 exact -- every DC prefix bound to the CORRECT DC site (f02/nibble-2 -> vr1-dc0, f03/nibble-3 -> vr1-dc1), no wrong-target binding, no hidden scope drop. The sandbox is faithful. The checker over-flagged.

  4. The checker had a false-positive defect. Its 2026-07-14 hardening added a "DELTA prefix has NO SCOPE -> fail" rule to catch silent scope drops, but it over-corrected: it failed ANY unscoped delta prefix, including the legitimately- unscoped role containers. A checker that reds on a faithful sandbox is as useless as one that greens on an unfaithful one, so it had to be fixed before sub-task (i) could close on a real exit 0.

The fix (netbox/sandbox-fidelity-check.py + harness)

  • New EXPECTED_PREFIX_SCOPE: the INTENDED scope per delta prefix -- ("site",slug) / ("region",slug) / None for an intentionally-unscoped org container. The DC half is generated by _dc_prefix_scopes() (the D-119 DC->site identity), so the CIDR set and the scope map cannot drift apart; EXPECTED_NEW["ipam/prefixes"] is now set(EXPECTED_PREFIX_SCOPE).
  • The delta check now asserts scope == INTENDED (reading the dumper's slug-rewritten scope_site/scope_region), not merely "has a scope." This kills the false-positive AND is strictly STRONGER: it still catches a dropped scope, and now also catches a WRONG-TARGET binding -- a DC0 prefix bound to vr1-dc1, the exact D-117 near-miss the old presence-only test was blind to.
  • NOT fixed by exempting the two CIDRs (that would re-open a false-green hole on precisely those prefixes). Intended-None is asserted like any other intended scope.
  • Harness (tests/sandbox-fidelity-check/run-tests.sh): fixtures moved to the dump format (scope_site), T1 now sets each planned prefix's scope from the checker's own EXPECTED_PREFIX_SCOPE, and two cases added -- T9 (wrong-target scope -> fail) and T10 (legitimately-unscoped role container -> pass). 10 -> 12 tests.

Result

  • Re-run against the real sandbox dump: exit 0 -- "SANDBOX = upstream draft + EXACTLY the planned delta (D-115/D-117/D-118). Nothing lost, nothing stray."
  • Harness 12/12; gauntlet ALL GREEN (58); repo-lint 0 fail (1 legacy WARN).
  • C2 sub-task (i) is CLOSED -- the sandbox is faithful, established by a checker that no longer false-fails. Sub-task (ii) (load + verify the D-120 ip-ranges + service IPs) remains, with its logged tooling gap (dumper/checker don't yet cover ip-ranges/ip-addresses).

SEC-009 note (sandbox token consolidation)

The SEC-009 consolidation had MISSED the sandbox NetBox token: it lived only at /root/netbox-secrets/api.token on office1-netbox, never in ~/vr1-office1-creds/, contrary to the standing convention ("ALL sensitive files for a site live in ~/<site>-creds/"). Consolidated this session to ~/vr1-office1-creds/vr1-netbox-sandbox.env (0600), token copied off the VM without being printed. Recorded in the SEC-009 row.

Revert

  • git checkout HEAD -- netbox/sandbox-fidelity-check.py tests/sandbox-fidelity-check/run-tests.sh restores the pre-fix checker (which false-fails on the two role-container /16s).
  • git checkout HEAD -- docs/security-ledger.md docs/session-ledger.md reverts the notes.
  • git rm docs/changelog-20260715-fidelity-check-scope-correctness.md.

No NetBox state was changed by any of this -- the dump and the check are read-only, and the token consolidation is a jumphost-local file copy.