code wiki / (root) / nx_chat_store_gate.nx

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}