code wiki / _hdl_build / nx_apistack_audit_gate.nx

nx_apistack_audit_gate.nx source

↩ module page · 51 lines · 3330 B

1import "nx_gate_gn.nx" 2// nx_apistack_audit_gate.nx -- hermetic gate for CAP-API-AUDIT (tamper-evident hash-chained audit log). Proves 3// records chain, the whole chain verifies intact, last-hash tracks the head, and -- the point -- altering ANY past 4// record is DETECTED. Sovereign: nx_syscalls + nx_apistack_audit. expect_exit: 0 5import "nx_syscalls.nx" 6import "nx_apistack_audit.nx" 7import "nx_gate_verdict.nx" 8 9func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 10func g_app(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){buf[off+i]=s[i];i=i+1} return off+i } 11func g_pl(buf: *u8, a: *u8, b: *u8, c: *u8) -> i64 { var o: i64 = g_app(buf,0,a); buf[o]=9 as u8; o=o+1; o=g_app(buf,o,b); buf[o]=9 as u8; o=o+1; o=g_app(buf,o,c); return o } 12 13func main(argc: i64, argv: *i64) -> i64 { 14 gp("=== nx_apistack_audit_gate (tamper-evident hash-chained audit log) ===\n" as *u8) 15 let L: *u8 = "/tmp/au_log.tsv" as *u8 16 let fd0: i64 = sys_openat_wr(L, 0x1a4); if fd0 >= 0 { sys_close(fd0) } // fresh 17 var pass: i64 = 0; var fail: i64 = 0 18 19 let p1: *u8 = sys_mmap(64); let p1n: i64 = g_pl(p1, "DEPLOY" as *u8, "elderwesto" as *u8, "rc=0" as *u8) 20 let p2: *u8 = sys_mmap(64); let p2n: i64 = g_pl(p2, "RESTART" as *u8, "elderwesto" as *u8, "rc=0" as *u8) 21 let p3: *u8 = sys_mmap(64); let p3n: i64 = g_pl(p3, "RECONCILE" as *u8, "elderwesto" as *u8, "ok" as *u8) 22 let h1: i64 = au_append(L, p1, p1n) 23 let h2: i64 = au_append(L, p2, p2n) 24 let h3: i64 = au_append(L, p3, p3n) 25 26 // T1 records chain (distinct hashes, each folds the prior) 27 if h1 != h2 { if h2 != h3 { pass=pass+1; gp(" T1 records chain (distinct linked hashes) PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL h2==h3\n" as *u8) } } else { fail=fail+1; gp(" T1 FAIL h1==h2\n" as *u8) } 28 29 // T2 whole chain verifies intact 30 if au_verify(L) == 1 { pass=pass+1; gp(" T2 intact chain -> verify=1 PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL\n" as *u8) } 31 32 // T3 last-chain tracks the head 33 if au_last_chain(L) == h3 { pass=pass+1; gp(" T3 last-chain == head hash PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL\n" as *u8) } 34 35 // T4 TAMPER a past record -> detected 36 let buf: *u8 = sys_mmap(65536); let n: i64 = au_read_file(L, buf, 65536) 37 buf[17] = (buf[17] ^ 1) as u8 // flip a bit inside record 1's payload 38 let fw: i64 = sys_openat_wr(L, 0x1a4); if fw >= 0 { sys_write(fw, buf, n); sys_close(fw) } 39 if au_verify(L) == 0 { pass=pass+1; gp(" T4 tampered past record -> DETECTED (verify=0) PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL tamper undetected\n" as *u8) } 40 41 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 42 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 43 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 44 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 45 let ctr__dry: *i64 = gv_ctr() 46 ctr__dry[0] = pass 47 ctr__dry[1] = pass + fail 48 let rc__dry: i64 = gv_verdict("APISTACK-AUDIT-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 49 sys_exit(rc__dry) 50 return rc__dry 51}