code wiki / (root) / nx_restart_routes_gate.nx

nx_restart_routes_gate.nx

buildroot/runtime/nx_restart_routes_gate.nx

13632 B213 linesdepth 10pulls 29 transitivereach 0 importersview sourcekind gate/prooftopic restart
docsdependenciesstructsconstsfunctions

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

nx_syscalls.nx nx_gate_verdict.nx nx_mgmt_data.nx nx_restart_routes_gate.nx

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

main gv_head gv_puts sys_write gv_ctr sys_mmap nxa_die sys_write ↻ sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_check gv_puts ↻ rag_direct_is sys_mmap ↻ rag_slen md_direct_restart_ok md_tbl_lookup sys_mmap ↻ md_tbl_row md_tbl_row_ok md_slice_eq md_copy_slice_z md_slice_eq ↻ rag_sub_is sys_mmap ↻ rag_slen ↻ md_restart_sub md_tbl_lookup ↻ md_slice_eq ↻ rag_names_eq

structs

none

consts

36const RAG_BUF: i64 = 512

functions

41func rag_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
45func rag_direct_is(svc: *u8, want: *u8) -> i64
58func rag_sub_is(svc: *u8, want: *u8) -> i64
73func rag_all_names_resolve(tbl: *u8, direct: i64) -> i64
106func rag_names_count(tbl: *u8) -> i64
called by 1: main calls 2: sys_mmapmd_tbl_names
116func rag_names_eq(tbl: *u8, want: *u8) -> i64
125func main(argc: i64, argv: *i64) -> i64