nx_deploy_guard.nx source
↩ module page · 54 lines · 2990 B
1// nx_deploy_guard.nx -- ENFORCED adversarial deploy gate (census gap #1, the ratchet that makes "adversarial
2// verification is REQUIRED" enforced, not advisory). NO mutating control-plane action (selfswap/deploy/restart/etc.)
3// runs unless the adversarial CI is GREEN: it runs nx_adversarial_ci FAIL-CLOSED, and ONLY on GREEN does it invoke
4// nx_aw_hostctl <sub>. A RED suite -> DEPLOY BLOCKED, nothing changes. Composes _offc/nx_adversarial_ci.elf +
5// _offc/nx_aw_hostctl.elf. Usage: nx_deploy_guard <nx_aw_hostctl-sub> [arg] (e.g. nx_deploy_guard selfswap). license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
8
9const DG_CI: *u8 = "_offc/nx_adversarial_ci.elf" as *u8
10const DG_HOSTCTL: *u8 = "_offc/nx_aw_hostctl.elf" as *u8
11
12func dg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
13// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
14// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
15// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
16// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
17func dg_putn(v: i64) -> i64 { nxi_out(v); return 0 }
18
19// fork+exec path [a1] [a2], INHERIT stdout/stderr (visible), wait, return WEXITSTATUS (128+sig on a crash).
20func dg_run(path: *u8, a1: *u8, a2: *u8) -> i64 {
21 let pid: i64 = sys_fork()
22 if pid == 0 {
23 let argv: *i64 = sys_mmap(32) as *i64
24 argv[0] = path as i64; var ai: i64 = 1
25 if (a1 as i64) != 0 { argv[ai] = a1 as i64; ai = ai + 1 }
26 if (a2 as i64) != 0 { argv[ai] = a2 as i64; ai = ai + 1 }
27 argv[ai] = 0
28 let envp: *i64 = sys_mmap(16) as *i64; envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
29 sys_execve(path, argv, envp)
30 sys_exit(127)
31 }
32 let st: *i64 = sys_mmap(16) as *i64
33 sys_wait4(pid, st, 0)
34 let sig: i64 = st[0] & 0x7f
35 if sig != 0 { return 128 + sig }
36 return (st[0] >> 8) & 0xff
37}
38
39func main(argc: i64, argv: *i64) -> i64 {
40 if argc < 2 { dg_puts("usage: nx_deploy_guard <nx_aw_hostctl-sub> [arg] (e.g. selfswap) -- CI-gated deploy\n" as *u8); sys_exit(2); return 2 }
41 let sub: *u8 = argv[1] as *u8
42 var a2: *u8 = 0 as *u8
43 if argc >= 3 { a2 = argv[2] as *u8 }
44 dg_puts("=== nx_deploy_guard: the adversarial CI (fail-closed) MUST pass before '" as *u8); dg_puts(sub); dg_puts("' ===\n" as *u8)
45 let ci: i64 = dg_run(DG_CI, 0 as *u8, 0 as *u8)
46 if ci != 0 {
47 dg_puts("\nDEPLOY BLOCKED: adversarial CI RED (exit=" as *u8); dg_putn(ci); dg_puts(") -- NOTHING deployed. Fix the RED gate first.\n" as *u8)
48 sys_exit(1); return 1
49 }
50 dg_puts("\nadversarial CI GREEN -> proceeding: nx_aw_hostctl " as *u8); dg_puts(sub); dg_puts("\n" as *u8)
51 let rc: i64 = dg_run(DG_HOSTCTL, sub, a2)
52 sys_exit(rc)
53 return rc
54}