code wiki / _hdl_build / nx_meet_http_gate.nx
nx_meet_http_gate.nx source
↩ module page · 76 lines · 5612 B
1// nx_meet_http_gate.nx -- liar-kill gate for P2's live-route brain. Feeds fixture HTTP requests through
2// meet_http_handle and asserts: a clean apply POST is parsed + url-decoded + SCREENED + persisted (200 + thanks),
3// a honeypot-filled POST and an AI-slop POST are FLAGGED, a /request-talent POST routes to hire + SCREENED, a GET
4// is refused (405), and a %0D%0A URL-encoded CRLF injection is stripped in the PERSISTED record. expect_exit: 0
5import "nx_syscalls.nx"
6import "nx_meet_lib.nx"
7import "nx_meet_curate.nx"
8import "nx_meet_http.nx"
9import "nx_meet_store.nx"
10import "nx_gate_verdict.nx"
11
12func has(hay: *u8, n: i64, needle: *u8) -> i64 {
13 let nl: i64 = mlen(needle); if nl == 0 { return 0 }
14 var i: i64 = 0
15 while i + nl <= n { var k: i64=0; var hit: i64=1; while k<nl { if hay[i+k]!=needle[k]{hit=0;k=nl}else{k=k+1} } if hit==1 {return 1} i=i+1 }
16 return 0
17}
18func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
19// 1 if the persisted record for id contains needle.
20func stored_has(id: *u8, needle: *u8) -> i64 {
21 let pq: *i64 = sys_mmap(16) as *i64
22 let lq: *i64 = sys_mmap(16) as *i64
23 if meet_store_get(id, pq, lq) != 1 { return 0 }
24 return has(pq[0] as *u8, lq[0], needle)
25}
26
27func main() -> i64 {
28 mputs("=== nx_meet_http_gate: live-route handler (parse -> urldecode -> screen -> persist -> respond) ===\n" as *u8)
29
30 let clean: *u8 = "POST /apply HTTP/1.1\r\nHost: meet\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\nname=Jane+Doe&email=jane%40example.com&role=Engineer&location=McKinney&resume=Built+payment+service+12000+reqs+jane%40example.com+github&website=&attest=on" as *u8
31 let bot: *u8 = "POST /apply HTTP/1.1\r\nHost: meet\r\n\r\nname=Spammer&email=s%40x.com&resume=Built+12000+jane%40example.com+github&website=http%3A%2F%2Fspam.example" as *u8
32 let slop: *u8 = "POST /apply HTTP/1.1\r\nHost: meet\r\n\r\nname=Bot&email=b%40x.com&resume=As+an+AI+language+model+results-driven+professional+synergy+proven+track+record+detail-oriented&website=" as *u8
33 let hire: *u8 = "POST /request-talent HTTP/1.1\r\nHost: meet\r\n\r\nname=HR&company=Acme+Inc&email=hr%40acme.com&role=Engineer&details=Senior+engineer+at+Acme+https%3A%2F%2Facme.com+salary+150000&website=" as *u8
34 let get: *u8 = "GET /apply HTTP/1.1\r\nHost: meet\r\n\r\n" as *u8
35 let inj: *u8 = "POST /apply HTTP/1.1\r\nHost: meet\r\n\r\nname=Eve%0D%0ABcc:+evil&email=eve%40x.com&resume=Built+12000+jane%40example.com+github&website=" as *u8
36
37 let resp: *u8 = sys_mmap(16384)
38 var pass: i64 = 0; var fail: i64 = 0
39
40 // 1) CLEAN apply
41 let v1: i64 = meet_http_handle(clean, slen(clean), "http-clean" as *u8, resp)
42 if v1 == ST_SCREENED { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-not-screened\n" as *u8) }
43 if has(resp, slen(resp), "200 OK" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-no-200\n" as *u8) }
44 if has(resp, slen(resp), "Thanks" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-no-thanks\n" as *u8) }
45 if stored_has("http-clean" as *u8, "status: SCREENED" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-status-not-persisted\n" as *u8) }
46 // url-decode teeth: + -> space, %40 -> @
47 if stored_has("http-clean" as *u8, "name: Jane Doe" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL name-not-urldecoded\n" as *u8) }
48 if stored_has("http-clean" as *u8, "email: jane@example.com" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL email-not-urldecoded\n" as *u8) }
49
50 // 2) GET -> 405
51 let vg: i64 = meet_http_handle(get, slen(get), "http-get" as *u8, resp)
52 if vg == 0 - 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL get-not-refused\n" as *u8) }
53 if has(resp, slen(resp), "405" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL get-no-405\n" as *u8) }
54
55 // 3) honeypot bot -> FLAGGED
56 if meet_http_handle(bot, slen(bot), "http-bot" as *u8, resp) == ST_FLAGGED { pass=pass+1 } else { fail=fail+1; mputs(" FAIL bot-not-flagged\n" as *u8) }
57 // 4) AI-slop -> FLAGGED
58 if meet_http_handle(slop, slen(slop), "http-slop" as *u8, resp) == ST_FLAGGED { pass=pass+1 } else { fail=fail+1; mputs(" FAIL slop-not-flagged\n" as *u8) }
59 // 5) hire route -> SCREENED + persisted kind:hire
60 if meet_http_handle(hire, slen(hire), "http-hire" as *u8, resp) == ST_SCREENED { pass=pass+1 } else { fail=fail+1; mputs(" FAIL hire-not-screened\n" as *u8) }
61 if stored_has("http-hire" as *u8, "kind: hire" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL hire-kind-not-persisted\n" as *u8) }
62 // 6) URL-encoded CRLF injection -> stripped in the persisted record
63 meet_http_handle(inj, slen(inj), "http-inj" as *u8, resp)
64 if stored_has("http-inj" as *u8, "name: EveBcc: evil" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL injection-not-stripped\n" as *u8) }
65
66 mputs("MEET-HTTP-GATE pass=" as *u8); mnum(pass); mputs(" fail=" as *u8); mnum(fail)
67 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
68 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
69 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
70 let ctr__dry: *i64 = gv_ctr()
71 ctr__dry[0] = pass
72 ctr__dry[1] = pass + fail
73 let rc__dry: i64 = gv_verdict("MEET-HTTP-GATE" as *u8, ctr__dry, "live-route handler: HTTP+form parse, url-decode, screen, persist, respond; injection-safe)" as *u8)
74 sys_exit(rc__dry)
75 return rc__dry
76}