code wiki / _hdl_build / nx_fence_gate.nx
nx_fence_gate.nx source
↩ module page · 120 lines · 6659 B
1// nx_fence_gate.nx -- END-TO-END verifier for nx_fence, the monotonic fence token (2026-08-09).
2//
3// WHY A SEPARATE ORGAN: /api/gate_run REFUSES any target whose name does not end in gate/test/kat --
4// "executes VERIFIERS ONLY -- that bound is what makes this route never-brick: it cannot reach a
5// daemon, promoter or deployer." nx_fence's in-process selftest could therefore only ever be run by
6// ssh break-glass, and gating must PRECEDE promotion. **** A GATE THAT CANNOT BE RUN BY THE ROUTE THE
7// ESTATE USES TO RUN GATES IS A GATE NOBODY WILL RUN.
8//
9// This is END-TO-END on purpose, not a second copy of the in-process teeth: it FORKS the deployed
10// nx_fence.elf with real fixture journals and asserts EXIT CODES and OUTPUT. That is the half the
11// in-process selftest structurally cannot reach -- argv parsing, the nx_claims fork, and the exit code
12// itself. Emitted through nx_gate_verdict so the exit code CARRIES the verdict: **** A GATE WHOSE EXIT
13// CODE DOES NOT CARRY ITS VERDICT SILENTLY BLESSES EVERY FAILURE IT FINDS (and /api/build's admission
14// guard refuses a gate without the anchor -- it refused THIS file's first draft, correctly).
15//
16// Fixtures are assembled AT RUNTIME under /tmp/nx_fence_gate/: a detector that scans source will find
17// its own fixture, and a teardown does not run when a run crashes.
18// license_tier: ORIGINAL No hw writes (Rule 26).
19import "nx_syscalls.nx"
20import "nx_gatekit_lib.nx"
21import "nx_gate_verdict.nx"
22
23const FG_BUF: i64 = 65536
24const FG_SPAN: i64 = 64
25
26func main(argc: i64, argv: *i64) -> i64 {
27 let ctr: *i64 = gv_ctr()
28 gv_head("nx_fence_gate -- the monotonic fence token, end-to-end against the deployed elf" as *u8)
29
30 let dir: *u8 = sys_mmap(256)
31 var d: i64 = gk_cat(dir, 0, "/tmp/nx_fence_gate" as *u8)
32 dir[d] = 0 as u8
33 gk_mkdir(dir)
34
35 // !! A PATH CONSTANT IS A DEPLOYMENT ASSUMPTION -- named, not hidden.
36 let elf: *u8 = sys_mmap(256)
37 var e: i64 = gk_cat(elf, 0, "/volume1/homes/elderwesto/nishihost/nx_fence.elf" as *u8)
38 elf[e] = 0 as u8
39
40 // T0 SUBJECT PRESENT. **** AN ABSENT ARTIFACT IS INDISTINGUISHABLE FROM A DEAD REMOTE SERVER -- a
41 // fork of a missing elf exits 127, so every "must not exit 0" tooth below would PASS on a subject
42 // that was never there. Assert the subject exists BEFORE asserting any outcome about it.
43 gv_check("T0 SUBJECT PRESENT nx_fence.elf deployed (else every tooth below is vacuous)" as *u8, gk_exists(elf), ctr)
44
45 let jr: *u8 = sys_mmap(1024)
46 var jo: i64 = gk_cat(jr, 0, dir)
47 jo = gk_cat(jr, jo, "/e2e.jrnl" as *u8)
48 jr[jo] = 0 as u8
49 gk_rm(jr)
50
51 // resA claimed by sess1, released, re-claimed by sess10 => fence 2. resB once => fence 1.
52 // ttl 86400 sits exactly at CL_TTL_MAX so these rows are HELD, not tripped by the new ceiling.
53 let now: i64 = sys_now_realtime_sec()
54 let fx: *u8 = sys_mmap(FG_BUF)
55 var f: i64 = 0
56 f = gk_catn(fx, f, now - 10); f = gk_cat(fx, f, "\tCLAIM\tresA\tsess1\t86400\tfirst\n" as *u8)
57 f = gk_catn(fx, f, now - 8); f = gk_cat(fx, f, "\tRELEASE\tresA\tsess1\t0\tdone\n" as *u8)
58 f = gk_catn(fx, f, now - 5); f = gk_cat(fx, f, "\tCLAIM\tresA\tsess10\t86400\tsecond\n" as *u8)
59 f = gk_catn(fx, f, now - 4); f = gk_cat(fx, f, "\tCLAIM\tresB\tsess9\t86400\tother\n" as *u8)
60 fx[f] = 0 as u8
61 gk_write(jr, fx)
62 // ASSERT THE FIXTURE REACHED THE CONDITION before asserting the outcome -- a fixture the defect
63 // cannot fail is not a test.
64 gv_check("T1 fixture written and non-empty" as *u8, gk_size(jr) > 0, ctr)
65
66 let ob: *u8 = sys_mmap(FG_BUF)
67 let ol: *i64 = sys_mmap(FG_SPAN) as *i64
68
69 // ---- the TOKEN, read out of the journal by the deployed binary --------------------------------
70 var ok: i64 = 0
71 let rc_a: i64 = gk_run_capture(elf, "token" as *u8, jr, "resA" as *u8, 0 as *u8, ob, FG_BUF - 8, ol)
72 gv_check("T2 token verb exits 0 on a readable journal" as *u8, rc_a == 0, ctr)
73 ok = 0
74 if gk_out_has(ob, ol[0], "fence=2" as *u8) == 1 { ok = 1 }
75 gv_check("T3 fence=2 for resA (two CLAIM frames, RELEASE not counted)" as *u8, ok, ctr)
76 ok = 0
77 if gk_out_has(ob, ol[0], "resource=resA" as *u8) == 1 { ok = 1 }
78 gv_check("T4 token names the resource it measured" as *u8, ok, ctr)
79
80 let rc_b: i64 = gk_run_capture(elf, "token" as *u8, jr, "resB" as *u8, 0 as *u8, ob, FG_BUF - 8, ol)
81 gv_check("T5 token verb exits 0 for resB" as *u8, rc_b == 0, ctr)
82 ok = 0
83 if gk_out_has(ob, ol[0], "fence=1" as *u8) == 1 { ok = 1 }
84 gv_check("T6 fence is PER-RESOURCE (resB=1, not the running total)" as *u8, ok, ctr)
85
86 let rc_z: i64 = gk_run_capture(elf, "token" as *u8, jr, "resZZZ" as *u8, 0 as *u8, ob, FG_BUF - 8, ol)
87 gv_check("T7 token verb exits 0 for an unknown resource" as *u8, rc_z == 0, ctr)
88 ok = 0
89 if gk_out_has(ob, ol[0], "fence=0" as *u8) == 1 { ok = 1 }
90 gv_check("T8 never-claimed resource derives fence=0" as *u8, ok, ctr)
91
92 // ---- ANTI-VACUITY: the token must come from the JOURNAL, not from argv or a constant. No single
93 // ---- constant satisfies 2, 1 and 0 across three calls to the SAME binary in ONE run, so a stub
94 // ---- that echoed a fixed number passes T2..T8 individually and dies here.
95 ok = 0
96 if rc_a == 0 { if rc_b == 0 { if rc_z == 0 { ok = 1 } } }
97 gv_check("T9 ANTI-VACUITY three distinct fences (2/1/0) from one binary refute a constant stub" as *u8, ok, ctr)
98
99 // ---- fail-closed on ignorance: an unreadable journal must NOT exit 0 -------------------------
100 let bad: *u8 = sys_mmap(512)
101 var b2: i64 = gk_cat(bad, 0, dir)
102 b2 = gk_cat(bad, b2, "/definitely-absent.jrnl" as *u8)
103 bad[b2] = 0 as u8
104 gk_rm(bad)
105 let rc_bad: i64 = gk_run_capture(elf, "token" as *u8, bad, "resA" as *u8, 0 as *u8, ob, FG_BUF - 8, ol)
106 gv_check("T10 NEG-CONTROL absent journal does NOT exit 0 (fail-closed on ignorance)" as *u8, rc_bad != 0, ctr)
107
108 // ---- an under-specified verify must be a USAGE refusal, never an ALLOW ------------------------
109 let rc_uv: i64 = gk_run_capture(elf, "verify" as *u8, jr, "resA" as *u8, "sess10" as *u8, ob, FG_BUF - 8, ol)
110 gv_check("T11 NEG-CONTROL verify without a fence is a usage error, never an authorisation" as *u8, rc_uv == 2, ctr)
111
112 let rc_wv: i64 = gk_run_capture(elf, "wibble" as *u8, jr, "resA" as *u8, 0 as *u8, ob, FG_BUF - 8, ol)
113 gv_check("T12 NEG-CONTROL unknown verb refused as a usage error" as *u8, rc_wv == 2, ctr)
114
115 gk_rm(jr)
116 gk_rm(bad)
117 let rc: i64 = gv_verdict("FENCE-GATE" as *u8, ctr, "monotonic per-resource fence token, end-to-end on the deployed elf" as *u8)
118 sys_exit(rc)
119 return rc
120}