code wiki / _hdl_build / nx_apistack_ratelimit_gate.nx

nx_apistack_ratelimit_gate.nx source

↩ module page · 53 lines · 3599 B

1import "nx_gate_gn.nx" 2// nx_apistack_ratelimit_gate.nx -- hermetic gate for CAP-API-RATELIMIT. Proves the deterministic token-bucket: 3// burst up to cap then 429, refill over elapsed time, cap ceiling on long idle, data-driven per-key quotas, and 4// bit-identical decisions for identical inputs. Sovereign: nx_syscalls + nx_apistack_ratelimit. expect_exit: 0 5import "nx_syscalls.nx" 6import "nx_apistack_ratelimit.nx" 7 8func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 9func 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 } 10 11func main(argc: i64, argv: *i64) -> i64 { 12 gp("=== nx_apistack_ratelimit_gate (deterministic token-bucket 429) ===\n" as *u8) 13 var pass: i64 = 0; var fail: i64 = 0 14 15 // T1 burst up to cap=5 (rate 1/s), then 429 16 let st: *i64 = sys_mmap(16) as *i64; st[0]=5; st[1]=100 17 var allows: i64 = 0; var i: i64 = 0 18 while i < 5 { allows = allows + rl_step(st, 5, 1, 100, 1); i = i + 1 } 19 let deny6: i64 = rl_step(st, 5, 1, 100, 1) 20 if allows == 5 { if deny6 == 0 { pass=pass+1; gp(" T1 burst 5 allow then 429 PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL 6th not denied\n" as *u8) } } else { fail=fail+1; gp(" T1 FAIL allows=" as *u8); gn(allows); gp("\n" as *u8) } 21 22 // T2 refill over 3s -> allow again 23 let a2: i64 = rl_step(st, 5, 1, 103, 1) 24 if a2 == 1 { pass=pass+1; gp(" T2 refill after 3s -> allow PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL\n" as *u8) } 25 26 // T3 long idle -> tokens cap at cap (not unbounded): after now=1000, exactly cap available 27 let st3: *i64 = sys_mmap(16) as *i64; st3[0]=0; st3[1]=100 28 rl_step(st3, 5, 1, 1000, 0) // cost 0 just refills; elapsed 900*1 capped at 5 29 if st3[0] == 5 { pass=pass+1; gp(" T3 long-idle refill CAPPED at cap=5 PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL tokens=" as *u8); gn(st3[0]); gp("\n" as *u8) } 30 31 // T4 data-driven quota from ratelimits.conf 32 let conf: *u8 = sys_mmap(128); var cn: i64 = 0 33 cn = g_app(conf, cn, "shard-a" as *u8); conf[cn]=9 as u8; cn=cn+1 34 cn = g_app(conf, cn, "10" as *u8); conf[cn]=9 as u8; cn=cn+1 35 cn = g_app(conf, cn, "2" as *u8); conf[cn]=10 as u8; cn=cn+1 36 let cfd: i64 = sys_openat_wr("/tmp/rl_conf.tsv" as *u8, 0x1a4); if cfd >= 0 { sys_write(cfd, conf, cn); sys_close(cfd) } 37 let ocap: *i64 = sys_mmap(8) as *i64; let orate: *i64 = sys_mmap(8) as *i64 38 let found: i64 = rl_config("/tmp/rl_conf.tsv" as *u8, "shard-a" as *u8, 7, ocap, orate) 39 if found == 1 { if ocap[0]==10 { if orate[0]==2 { pass=pass+1; gp(" T4 quota-as-data (shard-a cap=10 rate=2) PASS\n" as *u8) } } } 40 if found != 1 { fail=fail+1; gp(" T4 FAIL config miss\n" as *u8) } 41 else { if ocap[0]!=10 { fail=fail+1; gp(" T4 FAIL cap=" as *u8); gn(ocap[0]); gp("\n" as *u8) } } 42 43 // T5 determinism: identical inputs -> identical decision 44 let sa: *i64 = sys_mmap(16) as *i64; sa[0]=3; sa[1]=50 45 let sb: *i64 = sys_mmap(16) as *i64; sb[0]=3; sb[1]=50 46 let da: i64 = rl_step(sa, 5, 1, 52, 4) 47 let db: i64 = rl_step(sb, 5, 1, 52, 4) 48 if da == db { if sa[0]==sb[0] { pass=pass+1; gp(" T5 identical inputs -> identical decision + state PASS\n" as *u8) } else { fail=fail+1; gp(" T5 FAIL state diverged\n" as *u8) } } else { fail=fail+1; gp(" T5 FAIL decision diverged\n" as *u8) } 49 50 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 51 if fail == 0 { gp(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 52 gp(" verdict=RED\n" as *u8); sys_exit(1); return 1 53}