nx_toolcall_idem_gate.nx source
↩ module page · 91 lines · 6304 B
1// nx_toolcall_idem_gate.nx -- IN-PROCESS gate over nx_toolcall_idem_lib (/compare/dataio DI4 ta_idempotency_key).
2// Fixtures under /tmp/<gate>/ (never a production plane). Proves: the decision states, the reservation, the replay,
3// the release, the row grammar, the digest naming -- and named negatives (a key with whitespace is refused before
4// anything executes; a second key never sees the first's outcome; two keys never share a digest name).
5// exit: 0 GREEN / 1 RED (gv_verdict law).
6import "nx_syscalls.nx"
7import "nx_gate_verdict.nx"
8import "nx_gatekit_lib.nx"
9import "nx_toolcall_idem_lib.nx"
10
11const TG_DIR: *u8 = "/tmp/nx_toolcall_idem_gate" as *u8
12const TG_LEDGER: *u8 = "/tmp/nx_toolcall_idem_gate/toolcall_idem.jrnl" as *u8
13const TG_NOW: i64 = 1788640000
14
15func tg_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 }
16func tg_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] == b[i] { if a[i] == (0 as u8) { return 1 } i = i + 1 } return 0 }
17
18func main() -> i64 {
19 let ctr: *i64 = gv_ctr()
20 gv_head("nx_toolcall_idem_gate -- a keyed tools/call is reserved, applied once, replayed, or released" as *u8)
21 gk_mkdir(TG_DIR)
22 gk_rm(TG_LEDGER)
23 let hex: *u8 = sys_mmap(TI_HEX_CH + 8)
24 let row: *u8 = sys_mmap(TI_ROW_CAP)
25 let k1: *u8 = "seat-a/write-42" as *u8
26 let k2: *u8 = "seat-a/write-43" as *u8
27 let kbad: *u8 = "has space" as *u8
28 let ktab: *u8 = sys_mmap(16)
29 ktab[0] = 104 as u8
30 ktab[1] = 97 as u8
31 ktab[2] = 115 as u8
32 ktab[3] = 9 as u8
33 ktab[4] = 116 as u8
34 ktab[5] = 0 as u8
35 // the fixture must start clean: no claims for the keys used here
36 ti_key_hex(k1, ti_slen(k1), hex)
37 ti_release(TG_DIR, hex)
38 ti_key_hex(k2, ti_slen(k2), hex)
39 ti_release(TG_DIR, hex)
40
41 gv_check_eq("T1 no key present (pointer 0) is NOKEY: the call behaves exactly as before" as *u8, ti_classify(TG_LEDGER, TG_DIR, 0 as *u8, 0, hex, row, TI_ROW_CAP, TG_NOW), TI_NOKEY, ctr)
42 gv_check_eq("neg-control-T2 a key with a SPACE is BADKEY before anything executes" as *u8, ti_classify(TG_LEDGER, TG_DIR, kbad, ti_slen(kbad), hex, row, TI_ROW_CAP, TG_NOW), TI_BADKEY, ctr)
43 gv_check_eq("neg-control-T3 a key with a TAB is BADKEY (it would corrupt the ledger row)" as *u8, ti_classify(TG_LEDGER, TG_DIR, ktab, ti_slen(ktab), hex, row, TI_ROW_CAP, TG_NOW), TI_BADKEY, ctr)
44 gv_check_eq("T4 an empty-but-present key is BADKEY, not NOKEY" as *u8, ti_classify(TG_LEDGER, TG_DIR, k1, 0, hex, row, TI_ROW_CAP, TG_NOW), TI_BADKEY, ctr)
45
46 let st1: i64 = ti_classify(TG_LEDGER, TG_DIR, k1, ti_slen(k1), hex, row, TI_ROW_CAP, TG_NOW)
47 gv_check_eq("T5 a fresh key is NEW (reserved by this call)" as *u8, st1, TI_NEW, ctr)
48 let cp: *u8 = sys_mmap(TI_PATH_CAP)
49 ti_claim_path(TG_DIR, hex, cp)
50 gv_check("T5b fixture reached the condition: the claim file exists after NEW" as *u8, tg_exists(cp), ctr)
51 gv_check_eq("T5c the claim carries its reservation time (age 0 s at the same clock)" as *u8, ti_claim_age(TG_DIR, hex, TG_NOW), 0, ctr)
52 gv_check_eq("T6 the same key again, before any outcome is recorded, is INFLIGHT (never executed twice)" as *u8, ti_classify(TG_LEDGER, TG_DIR, k1, ti_slen(k1), hex, row, TI_ROW_CAP, TG_NOW), TI_INFLIGHT, ctr)
53
54 let arow: *u8 = sys_mmap(TI_ROW_CAP)
55 let arl: i64 = ti_row_job(arow, TI_ROW_CAP, "async" as *u8, "nx_fs_write" as *u8, 11, 1788640077)
56 gv_check("T7 the async outcome row reads lane=async tool=nx_fs_write job=1788640077" as *u8, tg_streq(arow, "lane=async tool=nx_fs_write job=1788640077" as *u8), ctr)
57 gv_check_eq("T7b the row records under the key (first-write-wins ledger)" as *u8, ti_record(TG_LEDGER, k1, ti_slen(k1), arow, arl), 1, ctr)
58 let st2: i64 = ti_classify(TG_LEDGER, TG_DIR, k1, ti_slen(k1), hex, row, TI_ROW_CAP, TG_NOW)
59 gv_check_eq("T8 the same key after the record is REPLAY (the first outcome, never a second execution)" as *u8, st2, TI_REPLAY, ctr)
60 gv_check_eq("T8b the replayed row hands back the job id" as *u8, ti_row_int(row, "job=" as *u8), 1788640077, ctr)
61 gv_check("T8c the replayed row is the recorded row, byte for byte" as *u8, tg_streq(row, arow), ctr)
62
63 let st3: i64 = ti_classify(TG_LEDGER, TG_DIR, k2, ti_slen(k2), hex, row, TI_ROW_CAP, TG_NOW)
64 gv_check_eq("neg-control-T9 a DIFFERENT key never sees the first key's outcome: NEW" as *u8, st3, TI_NEW, ctr)
65 gv_check_eq("T10 releasing an unrecorded key makes it NEW again (a refusal must be judged afresh)" as *u8, ti_release(TG_DIR, hex), 1, ctr)
66 gv_check_eq("T10b after release the key reserves again" as *u8, ti_classify(TG_LEDGER, TG_DIR, k2, ti_slen(k2), hex, row, TI_ROW_CAP, TG_NOW), TI_NEW, ctr)
67
68 let srow: *u8 = sys_mmap(TI_ROW_CAP)
69 ti_row_sync(srow, TI_ROW_CAP, "sync" as *u8, "nx_fs" as *u8, 5, 3, 12, TG_DIR, hex)
70 gv_check("T11 the sync outcome row carries exit, bytes and the replay artifact path" as *u8, ti_row_has(srow, "lane=sync tool=nx_fs exit=3 bytes=12 out=/tmp/nx_toolcall_idem_gate/idem_" as *u8), ctr)
71 gv_check_eq("T11b the sync row's exit parses back" as *u8, ti_row_int(srow, "exit=" as *u8), 3, ctr)
72
73 let h1: *u8 = sys_mmap(TI_HEX_CH + 8)
74 let h1b: *u8 = sys_mmap(TI_HEX_CH + 8)
75 let h2: *u8 = sys_mmap(TI_HEX_CH + 8)
76 ti_key_hex(k1, ti_slen(k1), h1)
77 ti_key_hex(k1, ti_slen(k1), h1b)
78 ti_key_hex(k2, ti_slen(k2), h2)
79 gv_check_eq("T12 the digest name is 16 hex chars" as *u8, ti_slen(h1), TI_HEX_CH, ctr)
80 gv_check("T12b the digest name is deterministic for one key" as *u8, tg_streq(h1, h1b), ctr)
81 gv_check("neg-control-T12c two keys never share a digest name" as *u8, (tg_streq(h1, h2) == 0) as i64, ctr)
82 gv_check_eq("T13 an absent claim has no age (-1), so a caller is never told a fake age" as *u8, ti_claim_age(TG_DIR, "0000000000000000" as *u8, TG_NOW), 0 - 1, ctr)
83
84 // leave the fixture clean for the next run
85 ti_key_hex(k1, ti_slen(k1), hex)
86 ti_release(TG_DIR, hex)
87 ti_key_hex(k2, ti_slen(k2), hex)
88 ti_release(TG_DIR, hex)
89 gk_rm(TG_LEDGER)
90 return gv_verdict("nx_toolcall_idem_gate" as *u8, ctr, "a keyed call is reserved before it executes, applied once, replayed from its recorded outcome, released when nothing was applied, and refused when the key is not a token" as *u8)
91}