Orchestrata Ultimate › Gates › env-subnet-scheme
Gate: env-subnet-scheme
At a glance
| Purpose | Refuse an address in env/{dev,test,prod}.env that is off its environment's octet (prod 10.53.1.x, test 10.53.2.x, dev 10.53.3.x). |
| Where it runs | The scripts/gates.py battery (registered as env-subnet-scheme). |
| Trigger | A battery run whose fingerprint changed, or whose last cached verdict was not ok. |
| Exact command | python scripts/check_env_subnet_scheme.py |
| Blocks | Exit 1 on violations, 2 on invalid invocation or a missing profile, 0 pass. |
| Ruling / ADR | Backlog-413 ruling (Mohamed, 2026-08-15), quoted below; no RUL page names this gate. |
| Last recorded verdict | ok: false in the primary checkout's .cache/gates.json (file last written 2026-09-22 10:01 local; the cause is not recorded there). wt-MAP-PRECOMMIT has no .cache/gates.json. |
What it refuses
An address in env/{dev,test,prod}.env that does not sit on its environment's
dedicated subnet octet — the drift that lets a test client silently aim at the prod
fleet.
Why it exists
Module docstring, quoting the ruling:
"Env-subnet-scheme gate — the mechanism for the backlog-413 ruling (Mohamed, 2026-08-15): environment subnets are FORCED apart by a dedicated environment octet so they can never be confused.
Ratified scheme (
plans/subnet-renumbering-design.md): all environments share the10.53.<env>.frame — first two octets identical, third octet IS the environment: prod → 10.53.1.0/24, test → 10.53.2.0/24, dev → 10.53.3.0/24.The old scheme (prod 10.92.53.x / test 10.93.53.x / dev 10.95.53.x) put the discriminating digit mid-address with no dedicated meaning; one mistyped digit aimed a test client at the prod kernel."
Scope rationale: "env/{dev,test,prod}.env — the authoritative endpoint layer …
Enforcing the authoritative layer is enforcing the system; literal stragglers
elsewhere are swept by the migration phases."
How it runs
- Command:
python scripts/check_env_subnet_scheme.py - When it fires: the
scripts/gates.pybattery (registered asenv-subnet-scheme). - The ratchet: an environment not yet cut over is listed in
PENDING_MIGRATIONand "is pinned to its EXACT legacy subnet — any address outside that legacy subnet fails, so the window cannot absorb drift." The table has been empty since 2026-08-16 — the docstring preserves the migration history (dev 2026-08-15 phase 2, test 2026-08-15 phase 3 with "full authoritative suite green on the new fleet (33k+ tests)", prod 2026-08-16 phase 4 with "data verified intact (orchkg 254,560 / memgraph 768,462 nodes)"). "The mechanism stays: a future new environment lists itself here" during its own window. - Inputs: fingerprint roots
("env", "scripts/check_env_subnet_scheme.py")— the gate's own script is a root "because the migration ratchet (PENDING_MIGRATION) lives in the script: flipping an env from pending to enforced is a script edit that must re-run the gate." - Caching — the blind spot is live. An earlier version of this page described
a
.envsuffix mask as the fix for anenv/root that "contributed ZERO bytes to this gate's fingerprint". No such mask exists:git log --all -S GATE_MASKS -- scripts/gates.pyfinds no commit that ever contained one (checked 2026-10-23)._fingerprint()hashes only files whose suffix is.py,.toml,.pl,.json,.mdor.sh(_interesting(), read through the AST toolkit), so the fiveenv/*.envfiles (ast-roots,dev,prod,test,toolchain) contribute nothing. After a PASS is cached, an edit to a profile does not re-run this gate; only an edit toscripts/check_env_subnet_scheme.pydoes (derived from the code, not measured by a run).
Typical failures and how to fix them
- Exit codes: "0 pass, 1 violations, 2 invalid invocation/missing profile."
- What a PASS looks like (real recorded battery output,
.cache/gates.json):0.0s | PASS: 3 profiles obey the env-octet scheme (pending migration: none) - What a failure looks like (representative): the offending profile named with each address that is off-scheme (or, for a PENDING env, outside its pinned legacy subnet).
- Un-blocking: move the address onto the environment's octet; for a genuinely
new environment mid-migration, add a
PENDING_MIGRATIONentry with its exact legacy prefix and a tracking note — and remove it "in the SAME commit as that environment's cutover." - A profile edit that the battery reports as unchanged. Because of the caching
blind spot above, run the gate fresh after any
env/*.envchange:python scripts/gates.py --only env-subnet-scheme --all.
Wiring
- Invokers:
scripts/gates.py(battery). - Tests:
tests/scripts/test_check_env_subnet_scheme.py,tests/scripts/test_check_env_subnet_scheme_coverage.py.
Related
- Gates master index
- Development workflow
- RUL-003 — Env config from the active env profile
- ADR-0080 — every fleet container's address is pinned
- env-contract — forces processes to read these profiles; this gate forces the profiles to be right
- validate-ci — Gate 11 refuses
hardcoded
10.53.1.xproduction literals in code - prod-separation — the systemd-unit side of environment separation