Orchestrata Ultimate › Plans › subnet-renumbering-design

Subnet renumbering — env-octet scheme (ruling 2026-08-15)

Source: plans/subnet-renumbering-design.md at 8a2cb42ad · last changed 2026-08-15 · first committed 2026-08-15 · 96 lines.

Prose pending.

Plan text

Subnet renumbering — env-octet scheme (ruling 2026-08-15)

Ruling (Mohamed, 2026-08-15, backlog 413): environment subnets must be FORCED apart so they can never be confused — the environment lives in its own dedicated octet (XXX.XXX.001.XXX / XXX.XXX.002.XXX), replacing the one-digit-apart 10.92.53.x / 10.93.53.x scheme whose single-digit difference put a mistyped test client on the prod kernel. Enforced by gate, not convention (force doctrine: standards, reviews, validation and verification are all forced by machinery).

Target scheme

Env Today (bridge) Target Third octet = env
prod incusbr0 10.92.53.0/24 10.53.1.0/24 1
test orch-test-br 10.93.53.0/24 10.53.2.0/24 2
dev orch-dev-br 10.95.53.0/24 10.53.3.0/24 3

Host addresses keep their final octet (e.g. prod redis 10.92.53.10 → 10.53.1.10, test fleet 10.93.53.13 → 10.53.2.13) so per-host identity survives the move and diffs stay mechanical.

Measured blast radius (2026-08-15)

Enforcement gate (built FIRST, ships with each phase)

scripts/check_env_subnet_scheme.py — the RUL-030-style mechanism:

  1. Reads env/{dev,test,prod}.env; every RFC-1918 literal in a profile must match that profile's assigned env octet (prod→10.53.1., test→10.53.2., dev→10.53.3.).
  2. Refuses scheme drift: all env subnets must share the identical 10.53.<env>. frame — first two octets identical across envs, third octet unique per env. What made 92/93 dangerous was a variable digit buried in a position that carried no meaning; here the only varying octet IS the environment, by definition.
  3. Carries a MIGRATED = {"test": bool, ...} ratchet: an env asserts the new scheme the moment its cutover commit lands; an env still on the old subnet must be listed with the migration item id — an unlisted old-scheme profile FAILS the gate. No advisory tier.
  4. Wired into the gates.py battery + validate_ci.

Cutover order

  1. Gate + design (this commit). Ratchet: all three envs listed as pending with this plan.
  2. dev (lowest risk, 4 containers): incus network set orch-dev-br subnet, re-pin container IPs, env/dev.env, flip ratchet dev=True, ship.
  3. test (authoritative fleet, 5 containers incl. app kernel/gateway): same flow + deploy/orchestrata-test provisioner, dr-hannah env/test.env + its hard-pin tests, conftest worker-DB mapping, full authoritative suite on the new fleet, ship.
  4. prod (maintenance window — 20 bridge consumers, live cluster): stop the 5 orchestrata units + dependents; renumber incusbr0 + terraform pins (terraform apply after plan review); re-bootstrap orchgraph coordination (ADD COORDINATOR ×3, REGISTER INSTANCE ×2 AS ASYNC, SET MAIN — data dirs untouched); update env/prod.env, ~/.env, kg-ready probe, prometheus scrape target; redeploy via promote_env promote --to prod; boot-health + kg-ready + SHOW REPLICAS verification. Flip ratchet prod=True; delete the ratchet entirely once all three are migrated (gate then asserts the scheme unconditionally).
  5. Sweep the words: repo-wide literal updates (builders, per-file Edit), wiki pages, memories, dr-hannah, knowledge-wiki configs. The gate keeps the end state honest; check_env_contract keeps profiles authoritative.

Verification standard (refuses false success)

Each phase ends with: gate battery green, live endpoint probes from the env profile (redis PING, graph RETURN 1 via READ routing, kernel gRPC verify), and for prod additionally SHOW REPLICAS = async + boot-health PASS.

Rollback

Bridges/pins are declarative: revert the phase commit + re-apply terraform / incus network set with the old subnet; orchgraph re-bootstrap is re-runnable with old addresses (same documented flow). Data never moves — only addresses do.