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}