code wiki / _hdl_build / nx_routeguard_gate.nx

nx_routeguard_gate.nx source

↩ module page · 103 lines · 5225 B

1// nx_routeguard_gate.nx -- proves the deploy-contract guard DETECTS a vanished route and does NOT 2// cry wolf on a legitimate feature deploy. Synthetic images, so the answer is known by construction. 3// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 4import "nx_routeguard_lib.nx" 5import "nx_gate.nx" 6 7func rgg_num(v: i64) -> i64 { 8 let b: *u8 = sys_mmap(32) 9 if v == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 10 let t: *u8 = sys_mmap(32) 11 var n: i64 = 0 12 var x: i64 = v 13 while x > 0 { t[n] = ((x % 10) + 48) as u8; x = x / 10; n = n + 1 } 14 var o: i64 = 0 15 while n > 0 { n = n - 1; b[o] = t[n]; o = o + 1 } 16 sys_write(1, b, o) 17 return 0 18} 19 20func rgg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 21 22func main() -> i64 { 23 gw("=== nx_routeguard_gate: deploy contract (route superset) ===\n" as *u8) 24 var pass: i64 = 0 25 var tot: i64 = 0 26 27 let lnames: *u8 = sys_mmap(RG_MAXR * RG_NAMEMAX) 28 let llens: *i64 = sys_mmap(RG_MAXR * 8) as *i64 29 let trunc: *i64 = sys_mmap(16) as *i64 30 let miss: *i64 = sys_mmap(RG_MAXR * 8) as *i64 31 32 // A synthetic "live" image carrying the real shape: a route-list literal plus dispatch literals. 33 let live: *u8 = "\"routes\":[\"/api/health\",\"/api/build\",\"/api/gate_run\",\"/api/proc_kill\",\"/api/deploy\"] dispatch /api/gate_run /api/proc_kill" as *u8 34 let ln: i64 = rgg_len(live) 35 let lcnt: i64 = rg_extract(live, ln, lnames, llens, trunc) 36 37 // T1: extraction finds the distinct routes and DEDUPES the dispatch repeats 38 tot = tot + 1 39 var t1: i64 = 0 40 if lcnt == 5 { if trunc[0] == 0 { t1 = 1 } } 41 if t1 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 42 gw("T1 extract: 5 distinct /api/ routes recovered from a binary image, repeats deduped\n" as *u8) 43 44 // T2 THE REGRESSION: a candidate MISSING gate_run + proc_kill -- the exact 21->19 loss, 5x live. 45 let bad: *u8 = "\"routes\":[\"/api/health\",\"/api/build\",\"/api/deploy\"] dispatch" as *u8 46 let m2: i64 = rg_missing(lnames, llens, lcnt, bad, rgg_len(bad), miss, RG_MAXR) 47 tot = tot + 1 48 var t2: i64 = 0 49 if m2 == 2 { t2 = 1 } 50 if t2 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 51 gw("T2 REGRESSION CAUGHT: candidate dropping gate_run+proc_kill reports exactly 2 missing\n" as *u8) 52 53 // T3 NEG-CONTROL, the cry-wolf test: an IDENTICAL candidate must report ZERO missing. 54 let m3: i64 = rg_missing(lnames, llens, lcnt, live, ln, miss, RG_MAXR) 55 tot = tot + 1 56 var t3: i64 = 0 57 if m3 == 0 { t3 = 1 } 58 if t3 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 59 gw("T3 NEG: an identical candidate reports 0 missing (no false alarm on a no-op deploy)\n" as *u8) 60 61 // T4 ASYMMETRY: a candidate that ADDS a route is FINE. Only disappearance is a defect -- 62 // otherwise every legitimate feature deploy would be blocked and the guard would be disabled. 63 let more: *u8 = "\"routes\":[\"/api/health\",\"/api/build\",\"/api/gate_run\",\"/api/proc_kill\",\"/api/deploy\",\"/api/brandnew\"]" as *u8 64 let m4: i64 = rg_missing(lnames, llens, lcnt, more, rgg_len(more), miss, RG_MAXR) 65 tot = tot + 1 66 var t4: i64 = 0 67 if m4 == 0 { t4 = 1 } 68 if t4 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 69 gw("T4 ASYMMETRY: a candidate ADDING a route is not a regression (superset, not equality)\n" as *u8) 70 71 // T5 RENAME MUST NOT PASS: /api/health is GONE if only /api/healthcheck remains. A plain substring 72 // scan blesses this silently, which would let a rename erase a route while the guard says 0 missing. 73 // This tooth failed-as-designed on the first build and drove the boundary check in rg_contains. 74 let ren: *u8 = "\"routes\":[\"/api/healthcheck\",\"/api/build\",\"/api/gate_run\",\"/api/proc_kill\",\"/api/deploy\"]" as *u8 75 let m5: i64 = rg_missing(lnames, llens, lcnt, ren, rgg_len(ren), miss, RG_MAXR) 76 tot = tot + 1 77 var t5: i64 = 0 78 if m5 == 1 { t5 = 1 } 79 if t5 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 80 gw("T5 RENAME CAUGHT: /api/healthcheck does NOT satisfy /api/health (boundary-checked, not substring)\n" as *u8) 81 82 // T6 EMPTY-LIVE REFUSAL: extracting from an image with no routes yields 0, and the CALLER must 83 // refuse rather than report "0 missing = safe" -- guarding against nothing is not a guarantee. 84 let none: *u8 = "no routes here at all" as *u8 85 let lc6: i64 = rg_extract(none, rgg_len(none), lnames, llens, trunc) 86 tot = tot + 1 87 var t6: i64 = 0 88 if lc6 == 0 { t6 = 1 } 89 if t6 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 90 gw("T6 REFUSAL INPUT: an image with no /api/ literals extracts 0 routes (caller must REFUSE)\n" as *u8) 91 92 gw("\n=== nx_routeguard_gate " as *u8) 93 rgg_num(pass) 94 gw("/" as *u8) 95 rgg_num(tot) 96 gw(" ===\n" as *u8) 97 if pass == tot { 98 gw("ROUTEGUARD GREEN -- catches the 5x mgmt route loss, no false alarm on add-or-noop\n" as *u8) 99 return 0 100 } 101 gw("ROUTEGUARD RED\n" as *u8) 102 return 1 103}