nx_chat_store_gate.nx source
↩ module page · 504 lines · 23015 B
1// nx_chat_store_gate.nx -- REFEREE for C1 (nx_chat_store, contract cs_store_forward). END-TO-END:
2// writes its own fixture conf (store_root pointed at /tmp/csgate/ so production planes are never
3// touched -- a gate must not share its fixture with a production beat), forks the PROMOTED elf per
4// verb, and reads every answer back from the store through the organ itself.
5// It proves the DONE-RULE pre-declared in comms.plan before the organ existed:
6// "a message sent to an offline member is delivered on reconnect byte-identical and in order;
7// history survives room close; additive-only with soft-delete; REFUSES loudly at its conf-named
8// size budget instead of silently dropping."
9// Process-survival is structural here: EVERY verb is its own fork, so anything T6 replays was
10// written by an earlier, already-dead process. NEGATIVE CONTROLS: reopen, regress, budget-msgs,
11// budget-bytes, body-too-big, room-absent (absent is not empty), bad-kind, double-delete.
12// Fixture rooms are epoch-suffixed so every run is fresh (idempotent gate law) and live in /tmp.
13// license_tier: ORIGINAL expect_exit: 0
14import "nx_syscalls.nx"
15import "nx_tool_run.nx"
16import "nx_gate_verdict.nx"
17const CSG_CAP: i64 = 65536
18func csg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
19func csg_write(path: *u8, s: *u8) -> i64 {
20 let fd: i64 = sys_openat_wr(path, 420)
21 if fd < 0 { return 0 - 1 }
22 let n: i64 = csg_len(s)
23 var w2: i64 = 0
24 while w2 < n { let r: i64 = sys_write(fd, (s as i64 + w2) as *u8, n - w2); if r <= 0 { break } w2 = w2 + r }
25 sys_close(fd)
26 return 0
27}
28func csg_read(path: *u8, buf: *u8, cap: i64) -> i64 {
29 let fd: i64 = sys_openat_rd(path)
30 if fd < 0 { return 0 - 1 }
31 var tot: i64 = 0
32 while tot < cap { let r: i64 = sys_read(fd, (buf as i64 + tot) as *u8, cap - tot); if r <= 0 { break } tot = tot + r }
33 sys_close(fd)
34 return tot
35}
36func csg_count(buf: *u8, n: i64, needle: *u8) -> i64 {
37 let m: i64 = csg_len(needle)
38 if m <= 0 { return 0 }
39 var c: i64 = 0
40 var i: i64 = 0
41 while i + m <= n {
42 var k: i64 = 0
43 var hit: i64 = 1
44 while k < m { if buf[i+k] != needle[k] { hit = 0; k = m } else { k = k + 1 } }
45 if hit == 1 { c = c + 1; i = i + m } else { i = i + 1 }
46 }
47 return c
48}
49func csg_find(buf: *u8, n: i64, needle: *u8) -> i64 {
50 let m: i64 = csg_len(needle)
51 if m <= 0 { return 0 - 1 }
52 var i: i64 = 0
53 while i + m <= n {
54 var k: i64 = 0
55 var hit: i64 = 1
56 while k < m { if buf[i+k] != needle[k] { hit = 0; k = m } else { k = k + 1 } }
57 if hit == 1 { return i }
58 i = i + 1
59 }
60 return 0 - 1
61}
62// scan every plausible segment file of a /tmp/csgate room plane for a needle; returns total hits.
63// This reads the RAW .docs bytes on disk -- the only ruler that can tell hidden from destroyed.
64func csg_seghex(room: *u8, needle: *u8, buf: *u8, cap: i64) -> i64 {
65 var hits: i64 = 0
66 var s: i64 = 0
67 while s < 32 {
68 let p: *u8 = sys_mmap(256)
69 var o: i64 = gv_cat(p, 0, "/tmp/csgate/chat_" as *u8)
70 o = gv_cat(p, o, room)
71 o = gv_cat(p, o, "-seg-" as *u8)
72 o = gv_catn(p, o, s)
73 o = gv_cat(p, o, ".docs" as *u8)
74 p[o] = 0 as u8
75 let n: i64 = csg_read(p, buf, cap)
76 if n > 0 { hits = hits + csg_count(buf, n, needle) }
77 s = s + 1
78 }
79 return hits
80}
81func main(argc: i64, argv: *i64) -> i64 {
82 let ctr: *i64 = gv_ctr()
83 gv_head("nx_chat_store -- store-and-forward delivered byte-identical and in order; budgets refuse loudly; soft-delete is additive-only" as *u8)
84 let ELF: *u8 = "/volume1/homes/elderwesto/nishihost/nx_chat_store.elf" as *u8
85 let CONF: *u8 = "/tmp/csgate/conf" as *u8
86 sys_mkdir("/tmp/csgate" as *u8, 493)
87 csg_write(CONF, "store_root|/tmp/csgate/\nroom_bytes_cliff|300\nroom_msgs_cliff|8\nbody_bytes_max|200\nretention_default_ms|0\n" as *u8)
88 let cchk: *u8 = sys_mmap(4096)
89 var t0: i64 = 0
90 if csg_read(CONF, cchk, 4096) > 0 { t0 = 1 }
91 gv_check("T0 fixture conf on disk (store_root isolated in /tmp/csgate)" as *u8, t0, ctr)
92 // fresh epoch-suffixed rooms so a re-run is a fresh fixture, never a stale one
93 let ms: i64 = sys_now_realtime_ms()
94 let ra: *u8 = sys_mmap(64)
95 var o: i64 = gv_cat(ra, 0, "a" as *u8)
96 o = gv_catn(ra, o, ms)
97 ra[o] = 0 as u8
98 let rb: *u8 = sys_mmap(64)
99 o = gv_cat(rb, 0, "b" as *u8)
100 o = gv_catn(rb, o, ms)
101 rb[o] = 0 as u8
102 let rc0: *u8 = sys_mmap(64)
103 o = gv_cat(rc0, 0, "c" as *u8)
104 o = gv_catn(rc0, o, ms)
105 rc0[o] = 0 as u8
106 let rg: *u8 = sys_mmap(64)
107 o = gv_cat(rg, 0, "g" as *u8)
108 o = gv_catn(rg, o, ms)
109 rg[o] = 0 as u8
110 let out: *u8 = sys_mmap(CSG_CAP)
111 let out2: *u8 = sys_mmap(CSG_CAP)
112 let ol: *i64 = sys_mmap(16) as *i64
113 let av: *i64 = sys_mmap(256) as *i64
114 // ---- T1 open + T2 neg-control-reopen ------------------------------------------------------
115 av[0] = ELF as i64
116 av[1] = "open" as i64
117 av[2] = ra as i64
118 av[3] = "alice" as i64
119 av[4] = CONF as i64
120 av[5] = 0
121 let r1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
122 var t1: i64 = 0
123 if r1 == 0 { if csg_count(out, ol[0], "CHAT-OPEN-OK" as *u8) == 1 { t1 = 1 } }
124 gv_check("T1 BITE: open creates the room and announces seq=1" as *u8, t1, ctr)
125 let r2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
126 var t2: i64 = 0
127 if r2 != 0 { if csg_count(out, ol[0], "room-exists" as *u8) == 1 { t2 = 1 } }
128 gv_check("T2 neg-control-reopen: open is create-only -- a second open REFUSES and changes nothing" as *u8, t2, ctr)
129 // ---- T3 three appends land with ascending seqs --------------------------------------------
130 av[1] = "append" as i64
131 av[2] = ra as i64
132 av[3] = "alice" as i64
133 av[4] = "1" as i64
134 av[5] = "one" as i64
135 av[6] = CONF as i64
136 av[7] = 0
137 let a1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
138 av[5] = "two" as i64
139 let a2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
140 av[5] = "three" as i64
141 let a3: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
142 var t3: i64 = 0
143 if a1 == 0 { if a2 == 0 { if a3 == 0 { if csg_count(out, ol[0], "seq=4" as *u8) == 1 { t3 = 1 } } } }
144 gv_check("T3 appends land and seqs ascend (open=1, third append announces seq=4)" as *u8, t3, ctr)
145 // ---- T4 hex ingest (arbitrary bytes incl newline, tab, pipe) ------------------------------
146 av[1] = "appendhex" as i64
147 av[5] = "000102030405060708090a0b0c0d0e0f0a097c" as i64
148 let a4: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
149 var t4: i64 = 0
150 if a4 == 0 { t4 = 1 }
151 gv_check("T4 a 19-byte binary body (contains newline, tab, pipe) is accepted via hex armor" as *u8, t4, ctr)
152 // ---- T5 byte-identity: the armored body comes back exactly --------------------------------
153 av[1] = "fetch" as i64
154 av[2] = ra as i64
155 av[3] = "0" as i64
156 av[4] = "100" as i64
157 av[5] = CONF as i64
158 av[6] = 0
159 let f1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
160 var t5: i64 = 0
161 if f1 == 0 { if csg_count(out, ol[0], "|alice|000102030405060708090a0b0c0d0e0f0a097c" as *u8) == 1 { t5 = 1 } }
162 gv_check("T5 BYTE-IDENTITY: the stored body replays bit-for-bit (hex armor round-trips)" as *u8, t5, ctr)
163 // ---- T6 THE DONE-RULE: offline member catches up from its cursor, in order ----------------
164 av[1] = "ack" as i64
165 av[3] = "bob" as i64
166 av[4] = "2" as i64
167 av[5] = CONF as i64
168 tr_run_capture(ELF, av, out, CSG_CAP, ol)
169 av[1] = "append" as i64
170 av[3] = "alice" as i64
171 av[4] = "1" as i64
172 av[5] = "later1" as i64
173 av[6] = CONF as i64
174 av[7] = 0
175 tr_run_capture(ELF, av, out, CSG_CAP, ol)
176 av[5] = "later2" as i64
177 tr_run_capture(ELF, av, out, CSG_CAP, ol)
178 av[1] = "cursor" as i64
179 av[3] = "bob" as i64
180 av[4] = CONF as i64
181 av[5] = 0
182 let c1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
183 var t6a: i64 = 0
184 if c1 == 0 { if csg_count(out, ol[0], "member=bob seq=2" as *u8) == 1 { t6a = 1 } }
185 gv_check("T6a the delivery cursor survives process death (every verb here is its own fork)" as *u8, t6a, ctr)
186 av[1] = "fetch" as i64
187 av[3] = "2" as i64
188 av[4] = "100" as i64
189 av[5] = CONF as i64
190 let f2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
191 var t6: i64 = 0
192 if f2 == 0 {
193 if csg_count(out, ol[0], "m|2|" as *u8) == 0 {
194 if csg_count(out, ol[0], "m|3|" as *u8) == 1 {
195 if csg_count(out, ol[0], "returned=5" as *u8) == 1 {
196 if csg_count(out, ol[0], "total=7" as *u8) == 1 {
197 let p3: i64 = csg_find(out, ol[0], "m|3|" as *u8)
198 let p7: i64 = csg_find(out, ol[0], "m|7|" as *u8)
199 if p3 >= 0 { if p7 > p3 { t6 = 1 } }
200 }
201 }
202 }
203 }
204 }
205 gv_check("T6 STORE-AND-FORWARD: fetch-since-cursor replays exactly the missed messages, in order" as *u8, t6, ctr)
206 // ---- T7 neg-control-regress: a late ack cannot move the cursor backwards ------------------
207 av[1] = "ack" as i64
208 av[3] = "bob" as i64
209 av[4] = "4" as i64
210 av[5] = CONF as i64
211 tr_run_capture(ELF, av, out, CSG_CAP, ol)
212 av[4] = "3" as i64
213 let k2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
214 var t7: i64 = 0
215 if k2 == 0 { if csg_count(out, ol[0], "old=4 new=4 advanced=0" as *u8) == 1 { t7 = 1 } }
216 gv_check("T7 neg-control-regress: cm_advance holds -- a stale ack NEVER regresses the cursor" as *u8, t7, ctr)
217 // ---- T8 partition sums over the full log --------------------------------------------------
218 av[1] = "fetch" as i64
219 av[3] = "0" as i64
220 av[4] = "100" as i64
221 let f3: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
222 var t8: i64 = 0
223 if f3 == 0 { if csg_count(out, ol[0], "returned=7 deleted_hidden=0 remaining=0 total=7" as *u8) == 1 { t8 = 1 } }
224 gv_check("T8 PARTITION: returned + hidden + remaining sums to total, printed and checked" as *u8, t8, ctr)
225 // ---- T9 the byte counter is real (sums the decoded bodies exactly) ------------------------
226 av[1] = "status" as i64
227 av[3] = CONF as i64
228 av[4] = 0
229 let s1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
230 var t9: i64 = 0
231 if s1 == 0 { if csg_count(out, ol[0], "bytes=51 bytes_cliff=300" as *u8) == 1 { t9 = 1 } }
232 gv_check("T9 meta:bytes MOVES and counts DECODED bytes: 9+3+3+5+19+6+6 = 51 exactly (38 hex chars did not inflate it)" as *u8, t9, ctr)
233 // ---- T10 soft-delete hides, retains, and the partition still sums -------------------------
234 av[1] = "del" as i64
235 av[3] = "3" as i64
236 av[4] = "bob" as i64
237 av[5] = CONF as i64
238 av[6] = 0
239 let d1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
240 av[1] = "fetch" as i64
241 av[3] = "0" as i64
242 av[4] = "100" as i64
243 let f4: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
244 var t10: i64 = 0
245 if d1 == 0 { if f4 == 0 {
246 if csg_count(out, ol[0], "m|3|" as *u8) == 0 {
247 if csg_count(out, ol[0], "returned=6 deleted_hidden=1 remaining=0 total=7" as *u8) == 1 { t10 = 1 }
248 }
249 } }
250 gv_check("T10 SOFT-DELETE: the row is hidden from fetch, still counted, bytes retained (rule 13)" as *u8, t10, ctr)
251 av[1] = "del" as i64
252 av[3] = "3" as i64
253 av[4] = "bob" as i64
254 let d2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
255 var t11: i64 = 0
256 if d2 == 0 { if csg_count(out, ol[0], "already=1" as *u8) == 1 { t11 = 1 } }
257 gv_check("T11 neg-control-del-again: deleting a tombstoned row is idempotent, not an error and not a second write" as *u8, t11, ctr)
258 // ---- T12 determinism: same fetch twice is byte-identical ----------------------------------
259 av[1] = "fetch" as i64
260 av[3] = "0" as i64
261 av[4] = "100" as i64
262 tr_run_capture(ELF, av, out, CSG_CAP, ol)
263 let n1: i64 = ol[0]
264 tr_run_capture(ELF, av, out2, CSG_CAP, ol)
265 var t12: i64 = 0
266 if ol[0] == n1 {
267 var same: i64 = 1
268 var q: i64 = 0
269 while q < n1 { if out[q] != out2[q] { same = 0; q = n1 } else { q = q + 1 } }
270 if same == 1 { t12 = 1 }
271 }
272 gv_check("T12 DETERMINISM: the same fetch twice is byte-identical" as *u8, t12, ctr)
273 // ---- T13 neg-control-budget-msgs (room B, cliff 8) ----------------------------------------
274 av[1] = "open" as i64
275 av[2] = rb as i64
276 av[3] = "alice" as i64
277 av[4] = CONF as i64
278 av[5] = 0
279 tr_run_capture(ELF, av, out, CSG_CAP, ol)
280 av[1] = "append" as i64
281 av[3] = "alice" as i64
282 av[4] = "1" as i64
283 av[5] = "x" as i64
284 av[6] = CONF as i64
285 av[7] = 0
286 var ai: i64 = 0
287 var aok: i64 = 1
288 while ai < 7 {
289 let ar: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
290 if ar != 0 { aok = 0 }
291 ai = ai + 1
292 }
293 let a9: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
294 var t13: i64 = 0
295 if aok == 1 { if a9 != 0 { if csg_count(out, ol[0], "conf_row=room_msgs_cliff" as *u8) == 1 { t13 = 1 } } }
296 gv_check("T13 neg-control-budget-msgs: message 9 against a cliff of 8 REFUSES and NAMES the conf row" as *u8, t13, ctr)
297 av[1] = "fetch" as i64
298 av[2] = rb as i64
299 av[3] = "0" as i64
300 av[4] = "100" as i64
301 av[5] = CONF as i64
302 av[6] = 0
303 let f5: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
304 var t14: i64 = 0
305 if f5 == 0 { if csg_count(out, ol[0], "total=8" as *u8) == 1 { t14 = 1 } }
306 gv_check("T14 the refused append wrote NOTHING: the room still holds exactly 8" as *u8, t14, ctr)
307 // ---- T15/T16 neg-control-budget-bytes + body-too-big (room C, cliffs 300/200) -------------
308 let b120: *u8 = sys_mmap(256)
309 var bi: i64 = 0
310 while bi < 120 { b120[bi] = 121 as u8; bi = bi + 1 }
311 b120[120] = 0 as u8
312 let b250: *u8 = sys_mmap(512)
313 bi = 0
314 while bi < 250 { b250[bi] = 121 as u8; bi = bi + 1 }
315 b250[250] = 0 as u8
316 av[1] = "open" as i64
317 av[2] = rc0 as i64
318 av[3] = "alice" as i64
319 av[4] = CONF as i64
320 av[5] = 0
321 tr_run_capture(ELF, av, out, CSG_CAP, ol)
322 av[1] = "append" as i64
323 av[3] = "alice" as i64
324 av[4] = "1" as i64
325 av[5] = b120 as i64
326 av[6] = CONF as i64
327 av[7] = 0
328 tr_run_capture(ELF, av, out, CSG_CAP, ol)
329 let c2r: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
330 var reached: i64 = 0
331 if c2r == 0 { if csg_count(out, ol[0], "bytes_total=249" as *u8) == 1 { reached = 1 } }
332 let c3r: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
333 var t15: i64 = 0
334 if reached == 1 { if c3r != 0 { if csg_count(out, ol[0], "conf_row=room_bytes_cliff" as *u8) == 1 { t15 = 1 } } }
335 gv_check("T15 neg-control-budget-bytes: the fixture provably reached 249 of 300, then the crossing append REFUSES by conf row" as *u8, t15, ctr)
336 av[5] = b250 as i64
337 let c4r: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
338 var t16: i64 = 0
339 if c4r != 0 { if csg_count(out, ol[0], "conf_row=body_bytes_max" as *u8) == 1 { t16 = 1 } }
340 gv_check("T16 neg-control-body-too-big: a 250-byte body against body_bytes_max=200 REFUSES by name" as *u8, t16, ctr)
341 // ---- T17 neg-control-room-absent: absent is refused, and is NOT the same as empty ---------
342 av[1] = "append" as i64
343 av[2] = rg as i64
344 av[3] = "alice" as i64
345 av[4] = "1" as i64
346 av[5] = "hello" as i64
347 av[6] = CONF as i64
348 av[7] = 0
349 let g1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
350 var t17: i64 = 0
351 if g1 != 0 { if csg_count(out, ol[0], "room-absent" as *u8) == 1 { t17 = 1 } }
352 gv_check("T17 neg-control-room-absent: appending to an unopened room REFUSES -- a typo cannot conjure a plane" as *u8, t17, ctr)
353 av[1] = "fetch" as i64
354 av[3] = "0" as i64
355 av[4] = "10" as i64
356 av[5] = CONF as i64
357 av[6] = 0
358 let g2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
359 var t18: i64 = 0
360 if g2 != 0 { if csg_count(out, ol[0], "room-absent" as *u8) == 1 { t18 = 1 } }
361 gv_check("T18 fetch on an absent room says ABSENT, never an empty result -- absence is not observed zero" as *u8, t18, ctr)
362 // ---- T19 neg-control-bad-kind -------------------------------------------------------------
363 av[1] = "append" as i64
364 av[2] = ra as i64
365 av[3] = "alice" as i64
366 av[4] = "9" as i64
367 av[5] = "zz" as i64
368 av[6] = CONF as i64
369 av[7] = 0
370 let b1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
371 var t19: i64 = 0
372 if b1 != 0 { if csg_count(out, ol[0], "bad-kind" as *u8) == 1 { t19 = 1 } }
373 gv_check("T19 neg-control-bad-kind: a kind outside the nx_chat_ring sealed range is refused" as *u8, t19, ctr)
374 // ---- C13 RETENTION (room D): additive expiry, announced, partition summed -----------------
375 let rd: *u8 = sys_mmap(64)
376 o = gv_cat(rd, 0, "d" as *u8)
377 o = gv_catn(rd, o, ms)
378 rd[o] = 0 as u8
379 av[0] = ELF as i64
380 av[1] = "open" as i64
381 av[2] = rd as i64
382 av[3] = "alice" as i64
383 av[4] = CONF as i64
384 av[5] = 0
385 tr_run_capture(ELF, av, out, CSG_CAP, ol)
386 av[1] = "append" as i64
387 av[3] = "alice" as i64
388 av[4] = "1" as i64
389 av[5] = "aa" as i64
390 av[6] = CONF as i64
391 av[7] = 0
392 tr_run_capture(ELF, av, out, CSG_CAP, ol)
393 av[5] = "bb" as i64
394 tr_run_capture(ELF, av, out, CSG_CAP, ol)
395 av[1] = "setretention" as i64
396 av[3] = "1" as i64
397 av[4] = "bob" as i64
398 av[5] = CONF as i64
399 av[6] = 0
400 let sr1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
401 var t20a: i64 = 0
402 if sr1 == 0 { if csg_count(out, ol[0], "CHAT-RETENTION-SET" as *u8) == 1 { if csg_count(out, ol[0], "new_ms=1" as *u8) == 1 { t20a = 1 } } }
403 gv_check("T20a retention policy is per-room DATA: setretention writes the plane key and announces old and new" as *u8, t20a, ctr)
404 av[1] = "retain" as i64
405 av[3] = CONF as i64
406 av[4] = 0
407 let rt1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
408 var t20: i64 = 0
409 if rt1 == 0 { if csg_count(out, ol[0], "expired_now=3" as *u8) == 1 { if csg_count(out, ol[0], "sums=ok" as *u8) == 1 { t20 = 1 } } }
410 gv_check("T20 RETENTION SWEEP: 3 rows older than a 1ms window are tombstoned in one commit and the partition sums" as *u8, t20, ctr)
411 av[1] = "fetch" as i64
412 av[3] = "0" as i64
413 av[4] = "100" as i64
414 av[5] = CONF as i64
415 av[6] = 0
416 let rf1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
417 var t21a: i64 = 0
418 if rf1 == 0 { if csg_count(out, ol[0], "returned=0 deleted_hidden=3" as *u8) == 1 { t21a = 1 } }
419 av[1] = "status" as i64
420 av[3] = CONF as i64
421 av[4] = 0
422 let rs1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
423 var t21: i64 = 0
424 if t21a == 1 { if rs1 == 0 { if csg_count(out, ol[0], "bytes=13 " as *u8) == 1 { if csg_count(out, ol[0], "total=3 visible=0 deleted=3" as *u8) == 1 { t21 = 1 } } } }
425 gv_check("T21 HIDDEN NOT ERASED: fetch shows nothing, status still counts all 3 and the 13 body bytes remain (rule 13) -- erasure is the separate confirmed purge rung, stated not implied" as *u8, t21, ctr)
426 av[1] = "retain" as i64
427 av[3] = CONF as i64
428 av[4] = 0
429 let rt2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
430 var t22: i64 = 0
431 if rt2 == 0 { if csg_count(out, ol[0], "expired_now=0 already_hidden=3" as *u8) == 1 { t22 = 1 } }
432 gv_check("T22 neg-control-retain-again: a second sweep expires NOTHING new -- idempotent, and already-hidden is its own named bucket" as *u8, t22, ctr)
433 av[2] = ra as i64
434 let rt3: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
435 var t23: i64 = 0
436 if rt3 == 0 { if csg_count(out, ol[0], "policy=keep-forever expired_now=0" as *u8) == 1 { t23 = 1 } }
437 gv_check("T23 neg-control-forever: a room with no window (conf default 0) announces keep-forever and hides nothing -- the family archive is the default, disappearing is opt-in" as *u8, t23, ctr)
438 // ---- PURGE (room E): confirm-gated BYTE DESTRUCTION, proven at the raw segment files --------
439 let re: *u8 = sys_mmap(64)
440 o = gv_cat(re, 0, "e" as *u8)
441 o = gv_catn(re, o, ms)
442 re[o] = 0 as u8
443 av[0] = ELF as i64
444 av[1] = "open" as i64
445 av[2] = re as i64
446 av[3] = "alice" as i64
447 av[4] = CONF as i64
448 av[5] = 0
449 tr_run_capture(ELF, av, out, CSG_CAP, ol)
450 av[1] = "append" as i64
451 av[3] = "alice" as i64
452 av[4] = "1" as i64
453 av[5] = "secretsecret" as i64
454 av[6] = CONF as i64
455 av[7] = 0
456 tr_run_capture(ELF, av, out, CSG_CAP, ol)
457 av[5] = "x" as i64
458 tr_run_capture(ELF, av, out, CSG_CAP, ol)
459 av[1] = "del" as i64
460 av[3] = "2" as i64
461 av[4] = "alice" as i64
462 av[5] = CONF as i64
463 av[6] = 0
464 tr_run_capture(ELF, av, out, CSG_CAP, ol)
465 let segbuf: *u8 = sys_mmap(CSG_CAP)
466 let HEXN: *u8 = "736563726574736563726574" as *u8
467 let pre: i64 = csg_seghex(re, HEXN, segbuf, CSG_CAP)
468 av[1] = "purge" as i64
469 av[3] = "alice" as i64
470 av[4] = "nope" as i64
471 av[5] = CONF as i64
472 av[6] = 0
473 let pu1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
474 var t24: i64 = 0
475 if pre > 0 { if pu1 != 0 { if csg_count(out, ol[0], "purge-needs-confirm" as *u8) == 1 {
476 if csg_seghex(re, HEXN, segbuf, CSG_CAP) == pre { t24 = 1 }
477 } } }
478 gv_check("T24 neg-control-confirm: the secret's hex provably sits in the raw segment files (fixture reached the condition), and purge WITHOUT confirm=yes refuses and destroys nothing" as *u8, t24, ctr)
479 av[4] = "confirm=yes" as i64
480 let pu2: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
481 var t25a: i64 = 0
482 if pu2 == 0 { if csg_count(out, ol[0], "erased_rows=1 erased_bytes=12" as *u8) == 1 { if csg_count(out, ol[0], "DESTROYED" as *u8) == 1 { t25a = 1 } } }
483 var t25: i64 = 0
484 if t25a == 1 { if csg_seghex(re, HEXN, segbuf, CSG_CAP) == 0 { t25 = 1 } }
485 gv_check("T25 PURGE DESTROYS: after confirm=yes the secret's hex is ABSENT from every raw segment file on disk -- destroyed, not merely unreachable" as *u8, t25, ctr)
486 av[1] = "fetch" as i64
487 av[3] = "0" as i64
488 av[4] = "100" as i64
489 av[5] = CONF as i64
490 av[6] = 0
491 let pf1: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
492 var t26a: i64 = 0
493 if pf1 == 0 { if csg_count(out, ol[0], "returned=2 deleted_hidden=1" as *u8) == 1 { if csg_count(out, ol[0], "m|3|" as *u8) == 1 { t26a = 1 } } }
494 av[1] = "purge" as i64
495 av[3] = "alice" as i64
496 av[4] = "confirm=yes" as i64
497 av[5] = CONF as i64
498 av[6] = 0
499 let pu3: i64 = tr_run_capture(ELF, av, out, CSG_CAP, ol)
500 var t26: i64 = 0
501 if t26a == 1 { if pu3 == 0 { if csg_count(out, ol[0], "erased_rows=0" as *u8) == 1 { t26 = 1 } } }
502 gv_check("T26 SURVIVORS + idempotence: visible history still fetches (the open row and the kept message, tombstone still hides seq 2), and a second purge erases nothing -- safe to run twice" as *u8, t26, ctr)
503 return gv_verdict("CHAT-STORE-GATE" as *u8, ctr, "store-and-forward proven across process death, byte-identical and in order; budgets, tombstones and absence all refuse loudly by name" as *u8)
504}