nx_restart_routes_gate.nx
buildroot/runtime/nx_restart_routes_gate.nx
about
nx_restart_routes_gate.nx -- PROVES the /api/restart allowlists after they became table-driven
(2026-08-28). Composes md_restart_sub / md_direct_restart_ok / md_tbl_names IN-PROCESS: no forked
binary, no live daemon, no network. The subject is a PURE resolver, so every claim here is decidable.
WHY THIS GATE EXISTS. The two allowlists were if-chains of hand-counted literal lengths and the
published error message was a THIRD hand-written copy. nx_mgmt_data's own history records that copy
drifting (seq1433: office/officejs/toolsapi resolvable but unnamed, so callers were told a supported
service was unknown). Making the tables the single owner removes the drift BY CONSTRUCTION -- but a
refactor of the code path that decides WHICH PROCESS TO KILL must be proven equivalent, never assumed.
★A REFACTOR IS A HYPOTHESIS UNTIL AN ORACLE DISAGREES WITH IT OR FAILS TO.
THE ORACLE IS THE LEGACY BEHAVIOUR, WRITTEN OUT AS DATA. Every one of the 13 (svc -> target) pairs the
if-chains produced is asserted BY VALUE below -- not "it resolves", but "it resolves to exactly this
needle". A resolver that returned 1 with the wrong needle would kill the wrong daemon and every
weaker tooth would still pass.
THE LOAD-BEARING TOOTH is not "the known names resolve". It is that EXACT-LENGTH matching survived the
rewrite: the if-chain got that property from hand-written literal lengths, the table gets it from the
row's own field width. If it were lost, "site" would match "sites" and "office" would match
"officejs" -- a caller asking to bounce the office JS would kill the office DAEMON. Both directions of
every prefix pair in the live tables are asserted as NEGATIVE controls.
NEG-CONTROLS, each a way the trivial wrong implementation passes: a prefix of a real name; a real name
plus a suffix; the empty name; a name from the OTHER table (the two lanes must not leak into each
other); wrong case; and -- the one that matters most for a kill path -- a MALFORMED row must never
yield an empty needle, because md_kill_by_name("") is a kill request with no subject.
NAMED "routes" NOT "allowlist" ON PURPOSE: the fs write deny-list matches "allowlist" in a path
(it protects tool_allowlist.conf, the execution allowlist), so a gate carrying that word is REFUSED
at the write boundary and can never reach the build host. The guard is right; the name moved.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_mgmt_data.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 36 | const RAG_BUF: i64 = 512 |
functions
| 41 | func rag_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 45 | func rag_direct_is(svc: *u8, want: *u8) -> i64 |
| 58 | func rag_sub_is(svc: *u8, want: *u8) -> i64 |
| 73 | func rag_all_names_resolve(tbl: *u8, direct: i64) -> i64 |
| 106 | func rag_names_count(tbl: *u8) -> i64 |
| 116 | func rag_names_eq(tbl: *u8, want: *u8) -> i64 |
| 125 | func main(argc: i64, argv: *i64) -> i64 |