nx_fsops_write_gate.nx source
↩ module page · 209 lines · 14962 B
1// nx_fsops_write_gate.nx -- END-TO-END gate for the estate's WRITE PATH (the binary behind the nx_fs_write tool).
2// Until 2026-09-05 this organ -- every seat's edit, append and write -- had NO gate at all. This one forks the SUBJECT
3// ARTIFACT on a fixture tree under /tmp/<gate>/ and proves the idempotency-key contract added the same day
4// (/compare/dataio DI4): a keyed write applied once is returned, not re-applied, on a retry carrying the same key;
5// a different key or no key keeps today's behaviour exactly (a neg-control each), and a REFUSAL never poisons a key.
6// The subject is forked IN PLACE by an absolute path (NAS /tmp is noexec); only its CWD is inside the fixture, which
7// is where its CWD-relative ledger knowledge/status/fswrite_idem.jrnl lands.
8// exit: 0 GREEN / 1 RED (gv_verdict law).
9import "nx_syscalls.nx"
10import "nx_gate_verdict.nx"
11import "nx_tool_run.nx"
12
13const WG_OUT: i64 = 65536
14const WG_PATH: i64 = 512
15const WG_MODE_755: i64 = 493
16const WG_MODE_644: i64 = 420
17const WG_DIR: *u8 = "/tmp/nx_fsops_write_gate" as *u8
18
19func wg_find(q: *u8, n: i64, lit: *u8) -> i64 {
20 var ll: i64 = 0
21 while lit[ll] != (0 as u8) { ll = ll + 1 }
22 if ll == 0 { return 0 }
23 var i: i64 = 0
24 while i + ll <= n {
25 var j: i64 = 0
26 var ok: i64 = 1
27 while j < ll { if q[i + j] != lit[j] { ok = 0; j = ll } else { j = j + 1 } }
28 if ok == 1 { return 1 }
29 i = i + 1
30 }
31 return 0
32}
33func wg_exists(path: *u8) -> i64 {
34 let fd: i64 = sys_openat_rd(path)
35 if fd < 0 { return 0 }
36 sys_close(fd)
37 return 1
38}
39func wg_size(path: *u8) -> i64 {
40 let fd: i64 = sys_openat_rd(path)
41 if fd < 0 { return 0 - 1 }
42 let sz: i64 = sys_lseek(fd, 0, 2)
43 sys_close(fd)
44 return sz
45}
46func wg_write_text(path: *u8, s: *u8) -> i64 {
47 let fd: i64 = sys_openat_wr(path, WG_MODE_644)
48 if fd < 0 { return 0 - 1 }
49 var n: i64 = 0
50 while s[n] != (0 as u8) { n = n + 1 }
51 sys_write(fd, s, n)
52 sys_close(fd)
53 return n
54}
55// Exercise a payload larger than the capture buffer without putting its bytes in argv.
56func wg_artifact(path: *u8) -> i64 {
57 let n: i64 = WG_OUT + 1
58 let b: *u8 = sys_mmap(n)
59 let pattern: *u8 = "line\n\"quote\" \\ path\r\n" as *u8
60 var pn: i64 = 0
61 while pattern[pn] != (0 as u8) { pn = pn + 1 }
62 var i: i64 = 0
63 while i < n { b[i] = pattern[i % pn]; i = i + 1 }
64 let fd: i64 = sys_openat_wr(path, WG_MODE_644)
65 if fd < 0 { return 0 - 1 }
66 var sent: i64 = 0
67 while sent < n {
68 let w: i64 = sys_write(fd, b + sent, n - sent)
69 if w <= 0 { sys_close(fd); return 0 - 1 }
70 sent = sent + w
71 }
72 if sys_close(fd) < 0 { return 0 - 1 }
73 return sent
74}
75func wg_equal(a: *u8, b: *u8) -> i64 {
76 let an: *i64 = sys_mmap(8) as *i64
77 let bn: *i64 = sys_mmap(8) as *i64
78 let ab: *u8 = sys_read_file(a, an)
79 let bb: *u8 = sys_read_file(b, bn)
80 if (ab as i64) == 0 || (bb as i64) == 0 { return 0 }
81 if an[0] != bn[0] { return 0 }
82 var i: i64 = 0
83 while i < an[0] { if ab[i] != bb[i] { return 0 } i = i + 1 }
84 return 1
85}
86// run the subject with up to 6 argv words; returns exit code, output in cout/colen
87func wg_run(sub: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8, a6: *u8, cout: *u8, colen: *i64) -> i64 {
88 let av: *i64 = sys_mmap(80) as *i64
89 av[0] = sub as i64
90 var k: i64 = 1
91 if (a1 as i64) != 0 { av[k] = a1 as i64; k = k + 1 }
92 if (a2 as i64) != 0 { av[k] = a2 as i64; k = k + 1 }
93 if (a3 as i64) != 0 { av[k] = a3 as i64; k = k + 1 }
94 if (a4 as i64) != 0 { av[k] = a4 as i64; k = k + 1 }
95 if (a5 as i64) != 0 { av[k] = a5 as i64; k = k + 1 }
96 if (a6 as i64) != 0 { av[k] = a6 as i64; k = k + 1 }
97 av[k] = 0
98 colen[0] = 0
99 return tr_run_capture(sub, av, cout, WG_OUT - 8, colen)
100}
101
102func main(argc: i64, argv: *i64) -> i64 {
103 let ctr: *i64 = gv_ctr()
104 gv_head("nx_fsops_write_gate -- the write path's idempotency-key contract: same key applies once, different or no key applies again, a refusal never poisons a key" as *u8)
105 let built: *u8 = "buildroot/_build/nx_fsops_write.sov.elf" as *u8
106 let built_local: *u8 = "_build/nx_fsops_write.sov.elf" as *u8
107 let promoted: *u8 = "./nx_fsops_write.elf" as *u8
108 var subject: *u8 = promoted
109 var which: *u8 = "PROMOTED" as *u8
110 if wg_exists(built_local) == 1 { subject = built_local; which = "JUST-BUILT-local" as *u8 }
111 if wg_exists(built) == 1 { subject = built; which = "JUST-BUILT" as *u8 }
112 if argc > 1 { subject = argv[1] as *u8; which = "EXPLICIT" as *u8 }
113 gv_puts("SUBJECT " as *u8); gv_puts(which); gv_puts(" " as *u8); gv_puts(subject); gv_puts("\n" as *u8)
114 gv_check("T1 subject artifact resolved" as *u8, wg_exists(subject), ctr)
115 if wg_exists(subject) == 0 { return gv_verdict("nx_fsops_write_gate" as *u8, ctr, "no subject at any root; nothing proven" as *u8) }
116 // absolute subject path BEFORE chdir (NAS /tmp is noexec: fork in place, CWD in the fixture)
117 let cwd: *u8 = sys_mmap(WG_PATH * 8)
118 let cl: i64 = sys_getcwd(cwd, WG_PATH * 8 - 1)
119 let absub: *u8 = sys_mmap(WG_PATH * 8)
120 var ao: i64 = 0
121 var ci: i64 = 0
122 if subject[0] != (47 as u8) {
123 while cwd[ci] != (0 as u8) { absub[ao] = cwd[ci]; ao = ao + 1; ci = ci + 1 }
124 absub[ao] = 47 as u8
125 ao = ao + 1
126 }
127 var si: i64 = 0
128 if subject[0] == (46 as u8) { if subject[1] == (47 as u8) { si = 2 } }
129 while subject[si] != (0 as u8) { absub[ao] = subject[si]; ao = ao + 1; si = si + 1 }
130 absub[ao] = 0 as u8
131 // fixture tree: SETUP creates it (a crash skips teardowns); a fresh ledger every run so the gate is idempotent
132 sys_mkdir(WG_DIR, WG_MODE_755)
133 sys_mkdir("/tmp/nx_fsops_write_gate/knowledge" as *u8, WG_MODE_755)
134 sys_mkdir("/tmp/nx_fsops_write_gate/knowledge/status" as *u8, WG_MODE_755)
135 let lfd: i64 = sys_openat_wr("/tmp/nx_fsops_write_gate/knowledge/status/fswrite_idem.jrnl" as *u8, WG_MODE_644)
136 if lfd >= 0 { sys_close(lfd) }
137 // the NEW-file tooth needs the file to be absent: a prior run's f_new.txt made T3 a would-clobber refusal (MEASURED
138 // 2026-09-05 by the dataio referee: 9/11 RED on a re-run, 11/11 at ship). A gate that is not idempotent reports on its
139 // first run and lies about every run after.
140 sys_unlinkat("/tmp/nx_fsops_write_gate/f_new.txt" as *u8)
141 let w0: i64 = wg_write_text("/tmp/nx_fsops_write_gate/f_edit.txt" as *u8, "alpha\nANCHOR\nomega\n" as *u8)
142 let a0: i64 = wg_write_text("/tmp/nx_fsops_write_gate/f_app.txt" as *u8, "row0\n" as *u8)
143 let x0: i64 = wg_write_text("/tmp/nx_fsops_write_gate/f_exists.txt" as *u8, "keep me\n" as *u8)
144 let cd: i64 = sys_chdir(WG_DIR)
145 gv_check("T2 fixture written and CWD inside it (the ledger path is CWD-relative)" as *u8, ((w0 > 0) as i64) * ((a0 > 0) as i64) * ((x0 > 0) as i64) * ((cd == 0) as i64) * ((cl > 0) as i64), ctr)
146 let cout: *u8 = sys_mmap(WG_OUT)
147 let colen: *i64 = sys_mmap(16) as *i64
148 // ---- WRITE: key=k1 twice -> created once, replayed once ----
149 let e1: i64 = wg_run(absub, "write" as *u8, "f_new.txt" as *u8, "hello\n" as *u8, "key=k1" as *u8, 0 as *u8, 0 as *u8, cout, colen)
150 gv_check("T3 keyed write of a NEW file applies (exit 0, OK receipt)" as *u8, ((e1 == 0) as i64) * wg_find(cout, colen[0], "NX-FS-WRITE OK" as *u8), ctr)
151 let e2: i64 = wg_run(absub, "write" as *u8, "f_new.txt" as *u8, "hello\n" as *u8, "key=k1" as *u8, 0 as *u8, 0 as *u8, cout, colen)
152 gv_check("T4 the SAME keyed write again is REPLAYED (exit 0, no clobber refusal, nothing re-applied)" as *u8, ((e2 == 0) as i64) * wg_find(cout, colen[0], "NX-FS-IDEM REPLAY request_fingerprint=matched first_outcome=" as *u8) * ((wg_find(cout, colen[0], "would-clobber" as *u8) == 0) as i64), ctr)
153 // ---- EDIT: a self-anchored INSERT, the class whose plain retry double-applies ----
154 let s0: i64 = wg_size("f_edit.txt" as *u8)
155 let e3: i64 = wg_run(absub, "edit" as *u8, "f_edit.txt" as *u8, "ANCHOR\n" as *u8, "ANCHOR\ninserted\n" as *u8, "key=k2" as *u8, 0 as *u8, cout, colen)
156 let s1: i64 = wg_size("f_edit.txt" as *u8)
157 gv_check("T5 keyed self-anchored insert applies once (exit 0, size grew by the insert)" as *u8, ((e3 == 0) as i64) * ((s1 == s0 + 9) as i64), ctr)
158 let e4: i64 = wg_run(absub, "edit" as *u8, "f_edit.txt" as *u8, "ANCHOR\n" as *u8, "ANCHOR\ninserted\n" as *u8, "key=k2" as *u8, 0 as *u8, cout, colen)
159 let s2: i64 = wg_size("f_edit.txt" as *u8)
160 gv_check("T6 the SAME keyed insert is REPLAYED: size unchanged, receipt confirms matched request and mutation not re-executed" as *u8, ((e4 == 0) as i64) * ((s2 == s1) as i64) * wg_find(cout, colen[0], "NX-FS-IDEM REPLAY request_fingerprint=matched first_outcome=" as *u8) * wg_find(cout, colen[0], "mutation not re-executed" as *u8), ctr)
161 let e5: i64 = wg_run(absub, "edit" as *u8, "f_edit.txt" as *u8, "ANCHOR\n" as *u8, "ANCHOR\ninserted\n" as *u8, "key=k3" as *u8, 0 as *u8, cout, colen)
162 let s3: i64 = wg_size("f_edit.txt" as *u8)
163 gv_check("neg-control-T7 a DIFFERENT key applies again (size grew again): the key is what makes the difference" as *u8, ((e5 == 0) as i64) * ((s3 == s2 + 9) as i64), ctr)
164 let e6: i64 = wg_run(absub, "edit" as *u8, "f_edit.txt" as *u8, "ANCHOR\n" as *u8, "ANCHOR\ninserted\n" as *u8, 0 as *u8, 0 as *u8, cout, colen)
165 let s4: i64 = wg_size("f_edit.txt" as *u8)
166 gv_check("neg-control-T8 NO key applies again (legacy behaviour unchanged, size grew again)" as *u8, ((e6 == 0) as i64) * ((s4 == s3 + 9) as i64), ctr)
167 // ---- APPEND: key=k4 twice -> one row ----
168 let p0: i64 = wg_size("f_app.txt" as *u8)
169 let e7: i64 = wg_run(absub, "append" as *u8, "f_app.txt" as *u8, "row1\n" as *u8, "key=k4" as *u8, 0 as *u8, 0 as *u8, cout, colen)
170 let e8: i64 = wg_run(absub, "append" as *u8, "f_app.txt" as *u8, "row1\n" as *u8, "key=k4" as *u8, 0 as *u8, 0 as *u8, cout, colen)
171 let p1: i64 = wg_size("f_app.txt" as *u8)
172 gv_check("T9 keyed append twice lands ONE row (the coordination verb is finally safe to retry)" as *u8, ((e7 == 0) as i64) * ((e8 == 0) as i64) * ((p1 == p0 + 5) as i64) * wg_find(cout, colen[0], "NX-FS-IDEM REPLAY request_fingerprint=matched first_outcome=" as *u8), ctr)
173 // ---- REFUSAL never poisons a key: a clobber-refused write with k5, then the same key WITH expect=any applies ----
174 let e9: i64 = wg_run(absub, "write" as *u8, "f_exists.txt" as *u8, "new body\n" as *u8, "key=k5" as *u8, 0 as *u8, 0 as *u8, cout, colen)
175 let refused: i64 = wg_find(cout, colen[0], "would-clobber" as *u8)
176 let e10: i64 = wg_run(absub, "write" as *u8, "f_exists.txt" as *u8, "new body\n" as *u8, "key=k5" as *u8, "expect=any" as *u8, 0 as *u8, cout, colen)
177 gv_check("neg-control-T10 a REFUSED write (rc 8, would-clobber) is not recorded: the same key with expect=any then applies (exit 0, OK)" as *u8, ((e9 == 8) as i64) * refused * ((e10 == 0) as i64) * wg_find(cout, colen[0], "NX-FS-WRITE OK" as *u8), ctr)
178 // ---- non-vacuity: the ledger holds rows, and a replayed key reports rc=0 ----
179 gv_check("T11 non-vacuity: the fixture ledger is non-empty after the keyed writes" as *u8, (wg_size("knowledge/status/fswrite_idem.jrnl" as *u8) > 0) as i64, ctr)
180 sys_unlinkat("artifact-destination.txt" as *u8)
181 sys_unlinkat("missing-payload.txt" as *u8)
182 let generated: i64 = wg_artifact("payload source.txt" as *u8)
183 gv_check("T12 large artifact fixture contains all requested bytes" as *u8, (generated == WG_OUT + 1) as i64, ctr)
184 let af1: i64 = wg_run(absub, "write-file" as *u8, "artifact-destination.txt" as *u8, "payload source.txt" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, cout, colen)
185 gv_check("T13 write-file preserves every byte and accepts a source path with spaces" as *u8, ((af1 == 0) as i64) * wg_equal("artifact-destination.txt" as *u8, "payload source.txt" as *u8), ctr)
186 let replacement: i64 = wg_write_text("replacement.txt" as *u8, "changed\n\"quoted\"\\path\n" as *u8)
187 let af2: i64 = wg_run(absub, "edit-files" as *u8, "artifact-destination.txt" as *u8, "payload source.txt" as *u8, "replacement.txt" as *u8, 0 as *u8, 0 as *u8, cout, colen)
188 gv_check("T14 edit-files replaces the large anchor with exact replacement bytes" as *u8, ((replacement > 0) as i64) * ((af2 == 0) as i64) * wg_equal("artifact-destination.txt" as *u8, "replacement.txt" as *u8), ctr)
189 let af3: i64 = wg_run(absub, "write-file" as *u8, "artifact-destination.txt" as *u8, "payload source.txt" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, cout, colen)
190 gv_check("T15 artifact writes preserve the existing overwrite refusal" as *u8, ((af3 == 8) as i64) * wg_equal("artifact-destination.txt" as *u8, "replacement.txt" as *u8), ctr)
191 let af4: i64 = wg_run(absub, "edit-files" as *u8, "artifact-destination.txt" as *u8, "replacement.txt" as *u8, "missing-payload.txt" as *u8, 0 as *u8, 0 as *u8, cout, colen)
192 gv_check("T16 missing replacement names the failing stage and preserves destination" as *u8, ((af4 != 0) as i64) * wg_find(cout, colen[0], "stage=open" as *u8) * wg_find(cout, colen[0], "native_result=-2" as *u8) * wg_equal("artifact-destination.txt" as *u8, "replacement.txt" as *u8), ctr)
193 let nulfd: i64 = sys_openat_wr("nul-payload.bin" as *u8, WG_MODE_644)
194 let nulbuf: *u8 = sys_mmap(1)
195 nulbuf[0] = 0 as u8
196 var nulwritten: i64 = 0 - 1
197 if nulfd >= 0 { nulwritten = sys_write(nulfd, nulbuf, 1); sys_close(nulfd) }
198 let af5: i64 = wg_run(absub, "write-file" as *u8, "artifact-destination.txt" as *u8, "nul-payload.bin" as *u8, "expect=any" as *u8, 0 as *u8, 0 as *u8, cout, colen)
199 gv_check("T17 embedded NUL refuses before destination mutation" as *u8, ((nulwritten == 1) as i64) * ((af5 != 0) as i64) * wg_find(cout, colen[0], "stage=embedded-NUL-offset" as *u8) * wg_equal("artifact-destination.txt" as *u8, "replacement.txt" as *u8), ctr)
200 let af6: i64 = wg_run(absub, "write-file" as *u8, "artifact-destination.txt" as *u8, "." as *u8, "expect=any" as *u8, 0 as *u8, 0 as *u8, cout, colen)
201 gv_puts("directory_fixture_output=");sys_write(1,cout,colen[0]);gv_puts("\n")
202 let directory_read:i64=wg_find(cout,colen[0],"stage=read path=. native_result=-21")
203 let directory_seek:i64=wg_find(cout,colen[0],"stage=size-seek path=. native_result=-22")
204 gv_check("T18 directory payload preserves native read or size-seek refusal and destination",((af6==4) as i64)*((directory_read==1||directory_seek==1) as i64)*wg_find(cout,colen[0],"destination_mutated=0")*wg_equal("artifact-destination.txt","replacement.txt"),ctr)
205 gv_kv("edit_size_start" as *u8, s0)
206 gv_kv("edit_size_after_k2_twice_k3_nokey" as *u8, s4)
207 gv_kv("ledger_bytes" as *u8, wg_size("knowledge/status/fswrite_idem.jrnl" as *u8))
208 return gv_verdict("nx_fsops_write_gate" as *u8, ctr, "a keyed write applies once and replays on the same key; a different key and no key apply again; a refusal never poisons a key; the estate's write path now has a gate" as *u8)
209}