code wiki / _hdl_build / nx_printer_ctl_gate.nx
nx_printer_ctl_gate.nx source
↩ module page · 262 lines · 12748 B
1// nx_printer_ctl_gate.nx -- gate for the sovereign printer-control organ.
2//
3// Proves the composed capability WITHOUT live hardware (the QIDI is offline
4// per the LAN research probe): pure-logic teeth (dotted-IP parse, the
5// NEVER-BRICK safe-endpoint allowlist) + REAL loopback roundtrips through a
6// fork'd fake Moonraker server (bytes over the real kernel TCP stack via the
7// production nx_mr_*_ipv4 path -- the exact code nx_printer_ctl runs).
8//
9// T1 dotted-IPv4 parse -> correct packed value
10// T2 malformed IPs rejected (fail-closed)
11// T3 NEVER-BRICK: every verb maps ONLY to a safe control endpoint; a
12// raw-gcode / script verb has NO route (cannot reach a firmware-write path)
13// T4 GET /printer/info roundtrip -> HTTP 200 over real loopback
14// T5 POST /printer/emergency_stop roundtrip -> HTTP 200 (Content-Length: 0)
15//
16// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
17import "nx_syscalls.nx"
18import "nx_tls13_io.nx"
19import "nx_moonraker_client.nx"
20import "nx_moonraker_io.nx"
21import "nx_printer_ctl_lib.nx"
22import "nx_gate_verdict.nx"
23
24// contiguous-substring check
25func g_contains(buf: *u8, len: i64, needle: *u8) -> i64 {
26 var nlen: i64 = 0
27 while needle[nlen] != (0 as u8) { nlen = nlen + 1 }
28 if nlen == 0 { return 1 }
29 if len < nlen { return 0 }
30 var i: i64 = 0
31 while i <= len - nlen {
32 var j: i64 = 0
33 var matched: i64 = 1
34 while j < nlen {
35 if buf[i + j] != needle[j] { matched = 0; j = nlen }
36 j = j + 1
37 }
38 if matched == 1 { return 1 }
39 i = i + 1
40 }
41 return 0
42}
43
44// one real loopback roundtrip for a verb; returns 1 iff the parent validated
45// the request AND the child (production client path) saw HTTP 200.
46func g_roundtrip(id: i64, port: i64) -> i64 {
47 let listen_fd: i64 = tcp_listen_loopback(port)
48 if listen_fd < 0 { return 0 }
49
50 let pid: i64 = sys_fork()
51 if pid < 0 { return 0 }
52
53 if pid == 0 {
54 // ===== child: the real nx_printer_ctl client path =====
55 var spin: i64 = 0
56 while spin < 80000 { spin = spin + 1 }
57 let ipv4: i64 = ((127 << 24) | (0 << 16) | (0 << 8) | 1)
58 let host: *u8 = sys_mmap(64)
59 let hl: i64 = pctl_build_host("127.0.0.1" as *u8, port, host)
60 let scratch: *u8 = sys_mmap(PCTL_SCRATCH)
61 let resp: *u8 = sys_mmap(PCTL_RESP)
62 let rn: *i64 = sys_mmap(8) as *i64
63 rn[0] = 0
64 let empty: *u8 = "\x00" as *u8
65 let status: i64 = pctl_call(id, ipv4, port, host, hl, empty, 0, scratch, resp, rn)
66 if status == 200 { sys_exit(0) }
67 sys_exit(1)
68 }
69
70 // ===== parent: fake Moonraker =====
71 let cfd: i64 = sys_accept(listen_fd)
72 var req_ok: i64 = 0
73 if cfd >= 0 {
74 let req: *u8 = sys_mmap(4096)
75 let nreq: i64 = sys_read(cfd, req, 4096)
76 if nreq > 0 {
77 let path: *u8 = pctl_verb_path(id)
78 if g_contains(req, nreq, path) == 1 {
79 if pctl_verb_is_get(id) == 1 {
80 if g_contains(req, nreq, "GET " as *u8) == 1 { req_ok = 1 }
81 } else {
82 if g_contains(req, nreq, "POST " as *u8) == 1 {
83 if g_contains(req, nreq, "Content-Length: 0" as *u8) == 1 { req_ok = 1 }
84 }
85 }
86 }
87 }
88 if pctl_verb_is_get(id) == 1 {
89 let rget: *u8 = "HTTP/1.1 200 OK\r\nContent-Length: 78\r\nConnection: close\r\n\r\n{\"result\":{\"state\":\"ready\",\"hostname\":\"qidi-xmax3\",\"software_version\":\"v0.12.0\"}}"
90 var rl: i64 = 0
91 while rget[rl] != (0 as u8) { rl = rl + 1 }
92 sys_write(cfd, rget, rl)
93 } else {
94 let rpost: *u8 = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
95 var rl2: i64 = 0
96 while rpost[rl2] != (0 as u8) { rl2 = rl2 + 1 }
97 sys_write(cfd, rpost, rl2)
98 }
99 sys_close(cfd)
100 }
101 sys_close(listen_fd)
102
103 // reap child, read its exit status
104 let st: *i64 = sys_mmap(8) as *i64
105 st[0] = 0
106 sys_wait4(pid, st, 0)
107 let child_code: i64 = (st[0] >> 8) & 0xff
108 if req_ok == 1 { if child_code == 0 { return 1 } }
109 return 0
110}
111
112func main() -> i64 {
113 let ctr: *i64 = gv_ctr()
114 gv_head("nx_printer_ctl_gate -- sovereign 3D-printer/IoT control (moonraker compose, never-brick allowlist, real loopback)" as *u8)
115
116 // T1: dotted-IPv4 parse
117 let want: i64 = ((192 << 24) | (168 << 16) | (1 << 8) | 42)
118 let got: i64 = pctl_parse_ip("192.168.1.42" as *u8)
119 var t1: i64 = 0
120 if got == want { t1 = 1 }
121 gv_check("T1 parse 192.168.1.42 -> correct packed IPv4" as *u8, t1, ctr)
122
123 // T2: malformed IPs fail-closed
124 let bad1: i64 = pctl_parse_ip("999.1.1.1" as *u8)
125 let bad2: i64 = pctl_parse_ip("1.2.3" as *u8)
126 let bad3: i64 = pctl_parse_ip("1.2.3.4.5" as *u8)
127 var t2: i64 = 0
128 if bad1 < 0 { if bad2 < 0 { if bad3 < 0 { t2 = 1 } } }
129 gv_check("T2 malformed IPs rejected (999-octet, too-few, too-many)" as *u8, t2, ctr)
130
131 // T3: NEVER-BRICK safe-endpoint allowlist
132 var t3: i64 = 1
133 if pctl_streq(pctl_verb_path(PCTL_V_INFO), "/printer/info" as *u8) == 0 { t3 = 0 }
134 if pctl_streq(pctl_verb_path(PCTL_V_ESTOP), "/printer/emergency_stop" as *u8) == 0 { t3 = 0 }
135 if pctl_streq(pctl_verb_path(PCTL_V_PAUSE), "/printer/print/pause" as *u8) == 0 { t3 = 0 }
136 if pctl_streq(pctl_verb_path(PCTL_V_RESUME), "/printer/print/resume" as *u8) == 0 { t3 = 0 }
137 if pctl_streq(pctl_verb_path(PCTL_V_CANCEL), "/printer/print/cancel" as *u8) == 0 { t3 = 0 }
138 if pctl_streq(pctl_verb_path(PCTL_V_READY), "/printer/info" as *u8) == 0 { t3 = 0 }
139 // status + ready are GET (read-only); estop/pause/resume/cancel are POST
140 if pctl_verb_is_get(PCTL_V_STATUS) == 0 { t3 = 0 }
141 if pctl_verb_is_get(PCTL_V_READY) == 0 { t3 = 0 }
142 if pctl_verb_is_get(PCTL_V_ESTOP) != 0 { t3 = 0 }
143 // a raw-gcode / script / eeprom verb has NO route (returns BAD id)
144 if pctl_verb_id("gcode" as *u8) != PCTL_V_BAD { t3 = 0 }
145 if pctl_verb_id("script" as *u8) != PCTL_V_BAD { t3 = 0 }
146 if pctl_verb_id("M500" as *u8) != PCTL_V_BAD { t3 = 0 }
147 gv_check("T3 never-brick: verbs map only to safe endpoints; no raw-gcode/eeprom route" as *u8, t3, ctr)
148
149 // T4: GET /printer/info roundtrip
150 let t4: i64 = g_roundtrip(PCTL_V_INFO, 18471)
151 gv_check("T4 GET /printer/info roundtrip -> HTTP 200 over real loopback" as *u8, t4, ctr)
152
153 // T5: POST /printer/emergency_stop roundtrip
154 let t5: i64 = g_roundtrip(PCTL_V_ESTOP, 18472)
155 gv_check("T5 POST /printer/emergency_stop roundtrip -> HTTP 200 (runtime halt, RAM-only)" as *u8, t5, ctr)
156
157 // T6: telemetry parse (extruder 209/210, heater_bed 59/60) from a real objects/query body
158 let tbody: *u8 = "{\"result\":{\"status\":{\"extruder\":{\"temperature\":209.8,\"target\":210.0},\"heater_bed\":{\"temperature\":59.7,\"target\":60.0}}}}"
159 var tn: i64 = 0
160 while tbody[tn] != (0 as u8) { tn = tn + 1 }
161 let ha: i64 = pctl_temp_in(tbody, tn, "\"extruder\":" as *u8, "\"temperature\":" as *u8)
162 let ht: i64 = pctl_temp_in(tbody, tn, "\"extruder\":" as *u8, "\"target\":" as *u8)
163 let ba: i64 = pctl_temp_in(tbody, tn, "\"heater_bed\":" as *u8, "\"temperature\":" as *u8)
164 let bt: i64 = pctl_temp_in(tbody, tn, "\"heater_bed\":" as *u8, "\"target\":" as *u8)
165 var t6: i64 = 0
166 if ha == 209 { if ht == 210 { if ba == 59 { if bt == 60 { t6 = 1 } } } }
167 gv_check("T6 status parse: extruder 209/210 + heater_bed 59/60 from objects/query body" as *u8, t6, ctr)
168
169 // T7: ready classify -- "ready" -> 1, non-ready -> 0 with correct state
170 let rbody: *u8 = "{\"result\":{\"state\":\"ready\",\"state_message\":\"Printer is ready\"}}"
171 var rn7: i64 = 0
172 while rbody[rn7] != (0 as u8) { rn7 = rn7 + 1 }
173 let sbody: *u8 = "{\"result\":{\"state\":\"shutdown\",\"state_message\":\"MCU shutdown\"}}"
174 var sn7: i64 = 0
175 while sbody[sn7] != (0 as u8) { sn7 = sn7 + 1 }
176 var t7: i64 = 0
177 if pctl_ready_flag(rbody, rn7) == 1 { if pctl_ready_flag(sbody, sn7) == 0 { t7 = 1 } }
178 gv_check("T7 ready classify: ready-body -> 1, shutdown-body -> 0 (preflight gate)" as *u8, t7, ctr)
179
180 // T8: GET /printer/objects/query roundtrip (status verb path emitted correctly)
181 let t8: i64 = g_roundtrip(PCTL_V_STATUS, 18473)
182 gv_check("T8 GET /printer/objects/query (status) roundtrip -> HTTP 200 over real loopback" as *u8, t8, ctr)
183
184 // T9: discover finds a real listener on the loopback /24 (non-blocking connect sweep)
185 let dlfd: i64 = tcp_listen_loopback(19001)
186 var t9: i64 = 0
187 if dlfd >= 0 {
188 let base24: i64 = pctl_parse_prefix("127.0.0" as *u8)
189 let ips: *i64 = sys_mmap(254 * 8) as *i64
190 let cnt: i64 = pctl_discover_scan(base24, 19001, 100, ips, 254)
191 let want1: i64 = ((127 << 24) | 1)
192 if cnt >= 1 { if ips[0] == want1 { t9 = 1 } }
193 sys_close(dlfd)
194 }
195 gv_check("T9 discover sweep finds a real Moonraker listener on 127.0.0.1 (non-blocking connect)" as *u8, t9, ctr)
196
197 // T10: survey classifies a real Moonraker :7125 listener on the loopback /24 as a 3d-printer
198 let slfd: i64 = tcp_listen_loopback(7125)
199 var t10: i64 = 0
200 if slfd >= 0 {
201 let smask: *i64 = sys_mmap(256 * 8) as *i64
202 pctl_survey_scan(pctl_parse_prefix("127.0.0" as *u8), 50, smask)
203 let bits1: i64 = smask[1]
204 if (bits1 & 1) != 0 {
205 if pctl_streq(pctl_survey_kind(bits1), "3d-printer" as *u8) == 1 { t10 = 1 }
206 }
207 sys_close(slfd)
208 }
209 gv_check("T10 survey classifies a Moonraker :7125 listener on 127.0.0.1 as a 3d-printer" as *u8, t10, ctr)
210
211 // T11: monitor aggregates the whole dashboard JSON in ONE sovereign call (no shell)
212 let mbuf: *u8 = sys_mmap(65536)
213 let ml: i64 = pctl_build_monitor(mbuf, "127.0.0" as *u8, pctl_parse_prefix("127.0.0" as *u8))
214 var t11: i64 = 0
215 if g_contains(mbuf, ml, "\"printer_online\":false" as *u8) == 1 {
216 if g_contains(mbuf, ml, "\"survey\":" as *u8) == 1 {
217 if g_contains(mbuf, ml, "\"updated_epoch\":" as *u8) == 1 { t11 = 1 }
218 }
219 }
220 gv_check("T11 monitor aggregates dashboard JSON in one sovereign call (offline: online=false + survey + epoch)" as *u8, t11, ctr)
221
222 // T12: printstart builds a valid body for a safe filename, refuses JSON-injection (quote)
223 let pbuf: *u8 = sys_mmap(512)
224 let pbl: i64 = nx_mr_build_print_start_body("cube.gcode" as *u8, 10, pbuf, 512)
225 let pbuf2: *u8 = sys_mmap(512)
226 let pquote: i64 = nx_mr_build_print_start_body("a\"b.gcode" as *u8, 9, pbuf2, 512)
227 var t12: i64 = 0
228 if pbl > 0 { if pquote <= 0 { t12 = 1 } }
229 gv_check("T12 printstart: valid body for safe filename, refuses quote (no JSON injection)" as *u8, t12, ctr)
230
231 // T13: progress parse -- state=printing + 42% from print_stats/virtual_sdcard
232 let progbody: *u8 = "{\"result\":{\"status\":{\"print_stats\":{\"state\":\"printing\",\"filename\":\"cube.gcode\"},\"virtual_sdcard\":{\"progress\":0.42}}}}"
233 var pn: i64 = 0
234 while progbody[pn] != (0 as u8) { pn = pn + 1 }
235 let sbuf: *u8 = sys_mmap(64)
236 let slen2: i64 = pctl_cat_jsonstr_after(sbuf, 0, progbody, pn, "\"print_stats\"" as *u8, "\"state\":\"" as *u8)
237 sbuf[slen2] = 0 as u8
238 let pct: i64 = pctl_pct_after(progbody, pn, "\"virtual_sdcard\"" as *u8, "\"progress\":" as *u8)
239 var t13: i64 = 0
240 if pct == 42 { if pctl_streq(sbuf, "printing" as *u8) == 1 { t13 = 1 } }
241 gv_check("T13 progress parse: state=printing + 42% from print_stats/virtual_sdcard" as *u8, t13, ctr)
242
243 // T14: multipart upload request builder -- boundary + filename + gcode payload + POST path
244 let ubuf: *u8 = sys_mmap(4096)
245 let gc: *u8 = "G28\nG1 X10 E1\n"
246 var gcn: i64 = 0
247 while gc[gcn] != (0 as u8) { gcn = gcn + 1 }
248 let urlen: i64 = pctl_build_upload_req(ubuf, "127.0.0.1:7125" as *u8, "cube.gcode" as *u8, gc, gcn)
249 var t14: i64 = 0
250 if g_contains(ubuf, urlen, "multipart/form-data; boundary=" as *u8) == 1 {
251 if g_contains(ubuf, urlen, "filename=\"cube.gcode\"" as *u8) == 1 {
252 if g_contains(ubuf, urlen, "G1 X10 E1" as *u8) == 1 {
253 if g_contains(ubuf, urlen, "POST /server/files/upload" as *u8) == 1 { t14 = 1 }
254 }
255 }
256 }
257 gv_check("T14 multipart upload req: boundary + filename + gcode payload + POST /server/files/upload" as *u8, t14, ctr)
258
259 let rc: i64 = gv_verdict("PRINTER-CTL" as *u8, ctr, "sovereign moonraker control+telemetry+preflight+discovery+survey+monitor+FULL print workflow(files/progress/printstart/upload); safe-endpoint allowlist; real loopback roundtrips" as *u8)
260 sys_exit(rc)
261 return rc
262}