code wiki / _hdl_build / nx_apistack_problem_gate.nx

nx_apistack_problem_gate.nx source

↩ module page · 49 lines · 3209 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_apistack_problem_gate.nx -- hermetic gate for CAP-API-PROBLEM (RFC7807). Proves the stable machine-readable 4// error shape (type/title/status/detail), JSON escaping, and well-formedness. expect_exit: 0 5import "nx_syscalls.nx" 6import "nx_apistack_problem.nx" 7import "nx_gate_verdict.nx" 8 9func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 10" as *u8); return ok } 11func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func g_contains(hay: *u8, hlen: i64, needle: *u8) -> i64 { 13 let nl: i64 = g_slen(needle); var i: i64 = 0 14 while i + nl <= hlen { var j: i64=0; var m: i64=1; while j<nl { if hay[i+j]!=needle[j] { m=0; j=nl } else { j=j+1 } } if m==1 { return 1 } i=i+1 } 15 return 0 16} 17 18func main(argc: i64, argv: *i64) -> i64 { 19 gp("=== nx_apistack_problem_gate (RFC7807 application/problem+json) ===\n" as *u8) 20 let out: *u8 = sys_mmap(4096) 21 let n: i64 = pr_build_json(out, "https://nishifamily.com/errors/forbidden" as *u8, "Forbidden" as *u8, 403, "operator level required for this action" as *u8) 22 gp(" BODY: " as *u8); sys_write(1, out, n); gp("\n" as *u8) 23 var pass: i64 = 0; var fail: i64 = 0 24 25 if g_contains(out, n, "\"type\":\"https://nishifamily.com/errors/forbidden\"" as *u8) == 1 { pass=pass+1; gp(" T1 stable type URI PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL\n" as *u8) } 26 if g_contains(out, n, "\"status\":403" as *u8) == 1 { pass=pass+1; gp(" T2 status 403 PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL\n" as *u8) } 27 if g_contains(out, n, "\"title\":\"Forbidden\"" as *u8) == 1 { pass=pass+1; gp(" T3 title PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL\n" as *u8) } 28 if g_contains(out, n, "\"detail\":\"operator level required for this action\"" as *u8) == 1 { pass=pass+1; gp(" T4 detail PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL\n" as *u8) } 29 30 // T5 JSON escaping of an embedded quote 31 let out2: *u8 = sys_mmap(4096) 32 let n2: i64 = pr_build_json(out2, "t" as *u8, "T" as *u8, 400, "he said \"hi\"" as *u8) 33 if g_contains(out2, n2, "\\\"hi\\\"" as *u8) == 1 { pass=pass+1; gp(" T5 embedded quotes JSON-escaped PASS\n" as *u8) } else { fail=fail+1; gp(" T5 FAIL\n" as *u8) } 34 35 // T6 well-formed 36 var wf: i64 = 0; if out[0]==(123 as u8) { if out[n-1]==(125 as u8) { wf=1 } } 37 if wf == 1 { pass=pass+1; gp(" T6 well-formed ({...}) PASS\n" as *u8) } else { fail=fail+1; gp(" T6 FAIL\n" as *u8) } 38 39 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 40 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 41 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 42 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 43 let ctr__dry: *i64 = gv_ctr() 44 ctr__dry[0] = pass 45 ctr__dry[1] = pass + fail 46 let rc__dry: i64 = gv_verdict("APISTACK-PROBLEM-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 47 sys_exit(rc__dry) 48 return rc__dry 49}