code wiki / _hdl_build / nx_site_intake_gate.nx
nx_site_intake_gate.nx source
↩ module page · 160 lines · 8571 B
1// nx_site_intake_gate.nx -- proves the PUBLIC intake route core END-TO-END IN-PROCESS (the
2// nx_fin_route_gate discipline: crafted raw requests -> si_route -> assert response bytes AND plane
3// side-effects), on the nx_gate_verdict base class (L009/D001: new gates inherit, never hand-roll).
4// Fixture paths are per-run epoch-suffixed /tmp files so the gate can never measure its own history
5// (the office-intake T1 state-poisoning lesson). license_tier: ORIGINAL No hw writes (Rule 26).
6import "nx_syscalls.nx"
7import "nx_site_intake.nx"
8import "nx_gate_verdict.nx"
9
10const SIG_BUF: i64 = 16384
11const SIG_BIG: i64 = 5000
12const SIG_B_A: i64 = 97
13
14func sg_has(buf: *u8, n: i64, lit: *u8) -> i64 {
15 let ll: i64 = si_len(lit)
16 if ll == 0 { return 0 }
17 var i: i64 = 0
18 while i + ll <= n { var j: i64 = 0; var ok: i64 = 1; while j < ll { if buf[i+j] != lit[j] { ok = 0; j = ll } else { j = j + 1 } } if ok == 1 { return 1 } i = i + 1 }
19 return 0
20}
21func sg_cnt(buf: *u8, n: i64, b: i64) -> i64 {
22 var c: i64 = 0
23 var i: i64 = 0
24 while i < n { if buf[i] == (b as u8) { c = c + 1 } i = i + 1 }
25 return c
26}
27func sg_read(path: *u8, box: *i64) -> *u8 {
28 box[0] = 0
29 let d: *u8 = sys_read_file(path, box)
30 return d
31}
32
33func main(argc: i64, argv: *i64) -> i64 {
34 let ctr: *i64 = gv_ctr()
35 gv_head("nx_site_intake -- the public contact route: record, refuse, redirect, all proven against per-run fixtures" as *u8)
36
37 let ep: i64 = sys_now_realtime_sec()
38 let plane: *u8 = sys_mmap(SI_SCRATCH)
39 var po: i64 = si_cat(plane, 0, "/tmp/si_gate_plane_" as *u8)
40 po = si_putn(plane, po, ep)
41 plane[po] = 0 as u8
42 let logf: *u8 = sys_mmap(SI_SCRATCH)
43 var lo: i64 = si_cat(logf, 0, "/tmp/si_gate_log_" as *u8)
44 lo = si_putn(logf, lo, ep)
45 logf[lo] = 0 as u8
46 let req: *u8 = sys_mmap(SIG_BUF)
47 let resp: *u8 = sys_mmap(SIG_BUF)
48 let box: *i64 = sys_mmap(16) as *i64
49
50 // ---- T1 real submission -> 303 + safe back + ONE grammar-clean row ----
51 var t1: i64 = 1
52 var rn: i64 = si_cat(req, 0, "POST /intake/gen-law HTTP/1.1\r\nHost: nishifamily.com\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\nname=Jane+Doe&email=jane%40example.com&message=Please+call+about+an+estate&back=%2Ffactory%2Fgen-law%2Fcontact%23sent&website=" as *u8)
53 var rl: i64 = si_route(req, rn, resp, plane, logf)
54 if sg_has(resp, rl, "303 See Other" as *u8) == 0 { t1 = 0 }
55 if sg_has(resp, rl, "Location: /factory/gen-law/contact#sent\r\n" as *u8) == 0 { t1 = 0 }
56 var pd: *u8 = sg_read(plane, box)
57 if sg_has(pd, box[0], "Jane Doe" as *u8) == 0 { t1 = 0 }
58 if sg_has(pd, box[0], "jane@example.com" as *u8) == 0 { t1 = 0 }
59 if sg_has(pd, box[0], "Please call about an estate" as *u8) == 0 { t1 = 0 }
60 if sg_has(pd, box[0], "gen-law" as *u8) == 0 { t1 = 0 }
61 if sg_cnt(pd, box[0], SI_B_LF) != 1 { t1 = 0 }
62 if sg_cnt(pd, box[0], SI_B_TAB) != 4 { t1 = 0 }
63 gv_check("T1 RECORD a real submission 303s to the caller's safe back and appends one grammar-clean row" as *u8, t1, ctr)
64
65 // ---- T2 honeypot -> SAME 303 shape, NOTHING recorded ----
66 var t2: i64 = 1
67 rn = si_cat(req, 0, "POST /intake/gen-law HTTP/1.1\r\n\r\nname=Bot&email=bot%40spam.io&message=buy+now&back=%2Ffactory%2Fgen-law%2Fcontact%23sent&website=spamlink" as *u8)
68 rl = si_route(req, rn, resp, plane, logf)
69 if sg_has(resp, rl, "303 See Other" as *u8) == 0 { t2 = 0 }
70 if sg_has(resp, rl, "Location: /factory/gen-law/contact#sent\r\n" as *u8) == 0 { t2 = 0 }
71 pd = sg_read(plane, box)
72 if sg_cnt(pd, box[0], SI_B_LF) != 1 { t2 = 0 }
73 gv_check("T2 HONEYPOT a filled trap gets a 303 indistinguishable from success and records NOTHING" as *u8, t2, ctr)
74
75 // ---- T3 oversized body -> 413 at the door, nothing recorded ----
76 var t3: i64 = 1
77 rn = si_cat(req, 0, "POST /intake/gen-law HTTP/1.1\r\n\r\n" as *u8)
78 var f3: i64 = 0
79 while f3 < SIG_BIG { req[rn] = SIG_B_A as u8; rn = rn + 1; f3 = f3 + 1 }
80 rl = si_route(req, rn, resp, plane, logf)
81 if sg_has(resp, rl, "413" as *u8) == 0 { t3 = 0 }
82 pd = sg_read(plane, box)
83 if sg_cnt(pd, box[0], SI_B_LF) != 1 { t3 = 0 }
84 gv_check("T3 BODYCAP an oversized body is refused 413 at the door (the oversized-proxied-POST class)" as *u8, t3, ctr)
85
86 // ---- T4 GET -> 405 ----
87 var t4: i64 = 1
88 rn = si_cat(req, 0, "GET /intake/gen-law HTTP/1.1\r\n\r\n" as *u8)
89 rl = si_route(req, rn, resp, plane, logf)
90 if sg_has(resp, rl, "405" as *u8) == 0 { t4 = 0 }
91 gv_check("T4 METHOD a GET on the intake route is 405, never a page" as *u8, t4, ctr)
92
93 // ---- T5 separator injection cannot break the plane grammar ----
94 var t5: i64 = 1
95 rn = si_cat(req, 0, "POST /intake/gen-coffee HTTP/1.1\r\n\r\nname=evil%09col%0Arow&message=hi&back=%2Ffactory%2Fgen-coffee%2Fcontact" as *u8)
96 rl = si_route(req, rn, resp, plane, logf)
97 if sg_has(resp, rl, "303 See Other" as *u8) == 0 { t5 = 0 }
98 pd = sg_read(plane, box)
99 if sg_cnt(pd, box[0], SI_B_LF) != 2 { t5 = 0 }
100 if sg_cnt(pd, box[0], SI_B_TAB) != 8 { t5 = 0 }
101 if sg_has(pd, box[0], "evil col row" as *u8) == 0 { t5 = 0 }
102 gv_check("T5 GRAMMAR TAB/CR/LF in fields become spaces BEFORE the append; separator counts hold" as *u8, t5, ctr)
103
104 // ---- T6 open-redirect attempts collapse to '/' ----
105 var t6: i64 = 1
106 rn = si_cat(req, 0, "POST /intake/gen-law HTTP/1.1\r\n\r\nmessage=hello&back=https%3A%2F%2Fevil.example" as *u8)
107 rl = si_route(req, rn, resp, plane, logf)
108 if sg_has(resp, rl, "Location: /\r\n" as *u8) == 0 { t6 = 0 }
109 rn = si_cat(req, 0, "POST /intake/gen-law HTTP/1.1\r\n\r\nmessage=hello2&back=%2F%2Fevil.example%2Fx" as *u8)
110 rl = si_route(req, rn, resp, plane, logf)
111 if sg_has(resp, rl, "Location: /\r\n" as *u8) == 0 { t6 = 0 }
112 pd = sg_read(plane, box)
113 if sg_cnt(pd, box[0], SI_B_LF) != 4 { t6 = 0 }
114 gv_check("T6 REDIRECT absolute and protocol-relative back targets collapse to '/', submissions still record" as *u8, t6, ctr)
115
116 // ---- T7 all-empty submission -> 400, nothing recorded ----
117 var t7: i64 = 1
118 rn = si_cat(req, 0, "POST /intake/gen-law HTTP/1.1\r\n\r\nname=&email=&message=&back=%2F" as *u8)
119 rl = si_route(req, rn, resp, plane, logf)
120 if sg_has(resp, rl, "400" as *u8) == 0 { t7 = 0 }
121 pd = sg_read(plane, box)
122 if sg_cnt(pd, box[0], SI_B_LF) != 4 { t7 = 0 }
123 gv_check("T7 EMPTY an all-empty submission is 400 and records nothing" as *u8, t7, ctr)
124
125 // ---- T8 malformed slug -> 404; evidence log = exactly the recorded set ----
126 var t8: i64 = 1
127 rn = si_cat(req, 0, "POST /intake/Bad_Slug%21 HTTP/1.1\r\n\r\nmessage=x" as *u8)
128 rl = si_route(req, rn, resp, plane, logf)
129 if sg_has(resp, rl, "404" as *u8) == 0 { t8 = 0 }
130 rn = si_cat(req, 0, "POST /intake/../secret HTTP/1.1\r\n\r\nmessage=x" as *u8)
131 rl = si_route(req, rn, resp, plane, logf)
132 if sg_has(resp, rl, "404" as *u8) == 0 { t8 = 0 }
133 pd = sg_read(plane, box)
134 if sg_cnt(pd, box[0], SI_B_LF) != 4 { t8 = 0 }
135 var ld: *u8 = sg_read(logf, box)
136 var rec: i64 = 0
137 var li: i64 = 0
138 let rlit: *u8 = "recorded=1" as *u8
139 let rl8: i64 = si_len(rlit)
140 while li + rl8 <= box[0] { var j8: i64 = 0; var ok8: i64 = 1; while j8 < rl8 { if ld[li+j8] != rlit[j8] { ok8 = 0; j8 = rl8 } else { j8 = j8 + 1 } } if ok8 == 1 { rec = rec + 1; li = li + rl8 } else { li = li + 1 } }
141 if rec != 4 { t8 = 0 }
142 gv_check("T8 SLUG malformed and traversal slugs are 404, and the evidence log carries exactly the 4 recorded submissions" as *u8, t8, ctr)
143
144 // ---- T9 health surface: GET answers 200 ok for the deploy probe; the slug is reserved ----
145 var t9: i64 = 1
146 rn = si_cat(req, 0, "GET /intake/health HTTP/1.1\r\n\r\n" as *u8)
147 rl = si_route(req, rn, resp, plane, logf)
148 if sg_has(resp, rl, "200 OK" as *u8) == 0 { t9 = 0 }
149 if sg_has(resp, rl, "\r\n\r\nok" as *u8) == 0 { t9 = 0 }
150 rn = si_cat(req, 0, "POST /intake/health HTTP/1.1\r\n\r\nmessage=probe" as *u8)
151 rl = si_route(req, rn, resp, plane, logf)
152 if sg_has(resp, rl, "404" as *u8) == 0 { t9 = 0 }
153 pd = sg_read(plane, box)
154 if sg_cnt(pd, box[0], SI_B_LF) != 4 { t9 = 0 }
155 gv_check("T9 HEALTH GET /intake/health answers 200 ok for the deploy probe; POSTing to the reserved slug records nothing" as *u8, t9, ctr)
156
157 let rc: i64 = gv_verdict("SITE-INTAKE" as *u8, ctr, "the public contact data path is real: record, refuse and redirect proven against per-run fixtures, and the plane grammar cannot be broken from a form" as *u8)
158 sys_exit(rc)
159 return rc
160}