nx_bindings_delivery_gate.nx source
↩ module page · 262 lines · 13568 B
1// Complete native HTTPS and staged Compare adapter delivery evidence.
2// Only exclusive caller-named /tmp captures are written; published artifacts are read.
3// license_tier: ORIGINAL; expect_exit: 0
4import "nx_gatekit_lib.nx"
5import "nx_gate_verdict.nx"
6import "nx_estate_path.nx"
7import "nx_json_lib.nx"
8
9const BD_FILE_MODE: i64 = 0x180
10const BD_EXEC_FAILED: i64 = 127
11const BD_CAPTURE_FAILED: i64 = 125
12const BD_EINTR: i64 = 4
13const BD_I64_MAX: i64 = 9223372036854775807
14
15func bd_equal(a: *u8, ao: i64, an: i64, b: *u8, bo: i64, bn: i64) -> i64 {
16 if an != bn { return 0 }
17 var i: i64 = 0
18 while i < an { if a[ao+i] != b[bo+i] { return 0 } i = i+1 }
19 return 1
20}
21func bd_prefix(prefix: *u8) -> i64 {
22 let n: i64 = gk_len(prefix)
23 let root: *u8 = "/tmp/" as *u8
24 let r: i64 = gk_len(root)
25 if n <= r { return 0 }
26 if n+gk_len(".gameengine-manifest.json" as *u8)+1 > SYS_PATH_MAX { return 0 }
27 if bd_equal(prefix, 0, r, root, 0, r) == 0 { return 0 }
28 var i: i64 = r
29 while i < n {
30 let c: i64 = prefix[i] as i64
31 var ok: i64 = 0
32 if c >= 97 { if c <= 122 { ok = 1 } }
33 if c >= 65 { if c <= 90 { ok = 1 } }
34 if c >= 48 { if c <= 57 { ok = 1 } }
35 if c == 95 { ok = 1 }
36 if c == 45 { ok = 1 }
37 if ok == 0 { return 0 }
38 i = i+1
39 }
40 return 1
41}
42func bd_capture(elf: *u8, a1: *u8, a2: *u8, a3: *u8, path: *u8) -> i64 {
43 let argv: *i64 = sys_mmap(5*8) as *i64
44 let env: *i64 = sys_mmap(8) as *i64
45 let status: *i64 = sys_mmap(8) as *i64
46 if (argv as i64) <= 0 { return BD_CAPTURE_FAILED }
47 if (env as i64) <= 0 { return BD_CAPTURE_FAILED }
48 if (status as i64) <= 0 { return BD_CAPTURE_FAILED }
49 argv[0] = elf as i64; argv[1] = a1 as i64; argv[2] = a2 as i64; argv[3] = a3 as i64; argv[4] = 0
50 env[0] = 0; status[0] = 0
51 let fd: i64 = sys_openat_exclusive(path, BD_FILE_MODE)
52 if fd < 0 { return BD_CAPTURE_FAILED }
53 let pid: i64 = sys_fork()
54 if pid < 0 { sys_close(fd); return BD_CAPTURE_FAILED }
55 if pid == 0 {
56 if fd != 1 { if sys_dup3(fd, 1, 0) < 0 { sys_exit(BD_CAPTURE_FAILED) } }
57 sys_execve_clean(elf, argv, env); sys_exit(BD_EXEC_FAILED)
58 }
59 var waited: i64 = sys_wait4(pid, status, 0)
60 while waited == 0-BD_EINTR { waited = sys_wait4(pid, status, 0) }
61 let synced: i64 = sys_fsync(fd)
62 let closed: i64 = sys_close(fd)
63 if waited != pid { return BD_CAPTURE_FAILED }
64 if synced < 0 { return BD_CAPTURE_FAILED }
65 if closed < 0 { return BD_CAPTURE_FAILED }
66 return gk_wait_code(status[0])
67}
68func bd_path(prefix: *u8, suffix: *u8) -> *u8 {
69 let out: *u8 = sys_mmap(SYS_PATH_MAX)
70 if (out as i64) <= 0 { return 0 as *u8 }
71 let n: i64 = gk_cat(out, 0, prefix); gk_cat(out, n, suffix)
72 return out
73}
74func bd_key(buf: *u8, p: i64, end: i64, lower: *u8) -> i64 {
75 let n: i64 = gk_len(lower)
76 if end-p < n { return 0 }
77 var i: i64 = 0
78 while i < n {
79 var c: i64 = buf[p+i] as i64
80 if c >= 65 { if c <= 90 { c = c+32 } }
81 if c != (lower[i] as i64) { return 0 }
82 i = i+1
83 }
84 return 1
85}
86// Narrow framing check for the expected Content-Length response, not a generic HTTP stack.
87// Returns body offset; observed[0]=Content-Length and observed[1]=diagnostic prefix bytes.
88func bd_http(buf: *u8, n: i64, observed: *i64) -> i64 {
89 observed[0] = 0-1; observed[1] = 0-1
90 let start: i64 = jx_find(buf, n, 0, "HTTP/1." as *u8)
91 if start < 0 { return 0-1 }
92 let v1: *u8 = "HTTP/1.1 200 " as *u8
93 let v0: *u8 = "HTTP/1.0 200 " as *u8
94 let sl: i64 = gk_len(v1)
95 if n-start < sl { return 0-1 }
96 var status_ok: i64 = bd_equal(buf, start, sl, v1, 0, sl)
97 if status_ok == 0 { status_ok = bd_equal(buf, start, sl, v0, 0, sl) }
98 if status_ok == 0 { return 0-1 }
99 let first: i64 = jx_find(buf, n, start, "\r\n" as *u8)
100 if first < 0 { return 0-1 }
101 var p: i64 = first+2
102 var count: i64 = 0
103 while p < n {
104 let end: i64 = jx_find(buf, n, p, "\r\n" as *u8)
105 if end < 0 { return 0-1 }
106 if end == p {
107 if count != 1 { return 0-1 }
108 let body: i64 = end+2
109 if n-body != observed[0] { return 0-1 }
110 observed[1] = start; return body
111 }
112 if bd_key(buf, p, end, "transfer-encoding:" as *u8) == 1 { return 0-1 }
113 if bd_key(buf, p, end, "content-length:" as *u8) == 1 {
114 count = count+1
115 if count != 1 { return 0-1 }
116 var q: i64 = p+gk_len("content-length:" as *u8)
117 while q < end { if buf[q] != (32 as u8) { if buf[q] != (9 as u8) { break } } q = q+1 }
118 var value: i64 = 0
119 var digits: i64 = 0
120 while q < end {
121 let d: i64 = (buf[q] as i64)-48
122 if d < 0 { break }
123 if d > 9 { break }
124 if value > (BD_I64_MAX-d)/10 { return 0-1 }
125 value = value*10+d; digits = digits+1; q = q+1
126 }
127 if digits == 0 { return 0-1 }
128 while q < end { if buf[q] != (32 as u8) { if buf[q] != (9 as u8) { return 0-1 } } q = q+1 }
129 observed[0] = value
130 }
131 p = end+2
132 }
133 return 0-1
134}
135func bd_https(elf: *u8, prefix: *u8, suffix: *u8, url: *u8, expected: *u8, ctr: *i64) -> i64 {
136 let out: *u8 = bd_path(prefix, suffix)
137 let rn: *i64 = sys_mmap(8) as *i64
138 let en: *i64 = sys_mmap(8) as *i64
139 let observed: *i64 = sys_mmap(2*8) as *i64
140 var allocated: i64 = 0
141 if (out as i64) > 0 { if (rn as i64) > 0 { if (en as i64) > 0 { if (observed as i64) > 0 { allocated = 1 } } } }
142 gv_check("HTTPS-buffers-allocated" as *u8, allocated, ctr)
143 if allocated == 0 { return 0 }
144 let wanted: *u8 = sys_read_file(expected, en)
145 var ready: i64 = 0
146 if (wanted as i64) > 0 { if en[0] > 0 { ready = 1 } }
147 gv_check("published-complete-file-readable" as *u8, ready, ctr)
148 if ready == 0 { return 0 }
149 let rc: i64 = bd_capture(elf, url, 0 as *u8, 0 as *u8, out)
150 gv_check("native-HTTPS-command-exit-zero" as *u8, rc == 0, ctr)
151 let response: *u8 = sys_read_file(out, rn)
152 var body: i64 = 0-1
153 if (response as i64) > 0 { if rn[0] > 0 { body = bd_http(response, rn[0], observed) } }
154 gv_puts("HTTPS_capture=" as *u8); gv_puts(out); gv_puts(" bytes=" as *u8); gv_num(rn[0]); gv_puts(" body_offset=" as *u8); gv_num(body); gv_puts("\n" as *u8)
155 gv_check("HTTPS-200-single-length-exact-complete-framing" as *u8, body >= 0, ctr)
156 var exact: i64 = 0
157 if body >= 0 {
158 gv_puts("diagnostic_prefix_bytes=" as *u8); gv_num(observed[1]); gv_puts(" Content-Length=" as *u8); gv_num(observed[0]); gv_puts("\n" as *u8)
159 exact = bd_equal(response, body, rn[0]-body, wanted, 0, en[0])
160 }
161 gv_check("entire-HTTPS-body-equals-published-artifact" as *u8, exact, ctr)
162 sys_free_file(response, rn[0]); sys_free_file(wanted, en[0]); return exact
163}
164func bd_manifest(elf: *u8, prefix: *u8, suffix: *u8, domain: *u8, expected: *u8, url: *u8, ctr: *i64) -> i64 {
165 let out: *u8 = bd_path(prefix, suffix)
166 let rn: *i64 = sys_mmap(8) as *i64
167 let en: *i64 = sys_mmap(8) as *i64
168 let number: *i64 = sys_mmap(8) as *i64
169 let text: *u8 = sys_mmap(SYS_PATH_MAX)
170 var allocated: i64 = 0
171 if (out as i64) > 0 { if (rn as i64) > 0 { if (en as i64) > 0 { if (number as i64) > 0 { if (text as i64) > 0 { allocated = 1 } } } } }
172 gv_check("manifest-buffers-allocated" as *u8, allocated, ctr)
173 if allocated == 0 { return 0 }
174 let wanted: *u8 = sys_read_file(expected, en)
175 let rc: i64 = bd_capture(elf, "bindings" as *u8, domain, 0 as *u8, out)
176 gv_check("staged-manifest-exit-zero" as *u8, rc == 0, ctr)
177 let report: *u8 = sys_read_file(out, rn)
178 gv_puts("manifest_capture=" as *u8); gv_puts(out); gv_puts(" bytes=" as *u8); gv_num(rn[0]); gv_puts("\n" as *u8)
179 var ready: i64 = 0
180 if (report as i64) > 0 { if rn[0] > 0 { if (wanted as i64) > 0 { if en[0] > 0 { ready = 1 } } } }
181 gv_check("manifest-and-published-body-readable" as *u8, ready, ctr)
182 if ready == 0 { return 0 }
183 let dn: i64 = jx_get_str(report, rn[0], 0, "domain" as *u8, text, SYS_PATH_MAX)
184 var same: i64 = 0
185 if dn > 0 { same = bd_equal(text, 0, gk_len(text), domain, 0, gk_len(domain)) }
186 gv_check("manifest-domain-exact" as *u8, same, ctr)
187 let bn: i64 = jx_get_int(report, rn[0], 0, "total_bytes" as *u8, number)
188 var length_ok: i64 = 0
189 if bn > 0 { if number[0] == en[0] { length_ok = 1 } }
190 gv_check("manifest-total-bytes-equals-complete-published-file" as *u8, length_ok, ctr)
191 let up: i64 = jx_get_str(report, rn[0], 0, "http_url" as *u8, text, SYS_PATH_MAX)
192 var url_ok: i64 = 0
193 if up > 0 { url_ok = bd_equal(text, 0, gk_len(text), url, 0, gk_len(url)) }
194 gv_check("manifest-HTTP-URL-exact" as *u8, url_ok, ctr)
195 let sp: i64 = jx_get_str(report, rn[0], 0, "source_artifact_path" as *u8, text, SYS_PATH_MAX)
196 var path_ok: i64 = 0
197 if sp > 0 { path_ok = bd_equal(text, 0, gk_len(text), expected, 0, gk_len(expected)) }
198 gv_check("manifest-source-artifact-path-exact" as *u8, path_ok, ctr)
199 var honest: i64 = 0
200 if gk_has(report, "\"complete\":false" as *u8) == 1 { if gk_has(report, "\"artifact_body_included\":false" as *u8) == 1 { honest = 1 } }
201 gv_check("manifest-does-not-claim-complete-body-in-response" as *u8, honest, ctr)
202 sys_free_file(report, rn[0]); sys_free_file(wanted, en[0]); return honest
203}
204func bd_refusal(elf: *u8, prefix: *u8, suffix: *u8, domain: *u8, extra: *u8, code: *u8, expected_rc: i64, ctr: *i64) -> i64 {
205 let out: *u8 = bd_path(prefix, suffix)
206 let rn: *i64 = sys_mmap(8) as *i64
207 let text: *u8 = sys_mmap(SYS_PATH_MAX)
208 var allocated: i64 = 0
209 if (out as i64) > 0 { if (rn as i64) > 0 { if (text as i64) > 0 { allocated = 1 } } }
210 gv_check("refusal-buffers-allocated" as *u8, allocated, ctr)
211 if allocated == 0 { return 0 }
212 let rc: i64 = bd_capture(elf, "bindings" as *u8, domain, extra, out)
213 gv_check("manifest-refusal-exit-exact" as *u8, rc == expected_rc, ctr)
214 let report: *u8 = sys_read_file(out, rn)
215 var correct: i64 = 0
216 if (report as i64) > 0 { if rn[0] > 0 {
217 if jx_get_str(report, rn[0], 0, "code" as *u8, text, SYS_PATH_MAX) > 0 { correct = bd_equal(text, 0, gk_len(text), code, 0, gk_len(code)) }
218 } }
219 gv_check("manifest-refusal-code-exact" as *u8, correct, ctr)
220 sys_free_file(report, rn[0]); return correct
221}
222func bd_legacy(elf: *u8, prefix: *u8, suffix: *u8, command: *u8, expected: *u8, ctr: *i64) -> i64 {
223 let out: *u8 = bd_path(prefix, suffix)
224 let rn: *i64 = sys_mmap(8) as *i64
225 let en: *i64 = sys_mmap(8) as *i64
226 var allocated: i64 = 0
227 if (out as i64) > 0 { if (rn as i64) > 0 { if (en as i64) > 0 { allocated = 1 } } }
228 gv_check("legacy-capture-buffers-allocated" as *u8, allocated, ctr)
229 if allocated == 0 { return 0 }
230 let wanted: *u8 = sys_read_file(expected, en)
231 let rc: i64 = bd_capture(elf, command, 0 as *u8, 0 as *u8, out)
232 gv_check("legacy-command-exit-zero" as *u8, rc == 0, ctr)
233 let got: *u8 = sys_read_file(out, rn)
234 var exact: i64 = 0
235 if (wanted as i64) > 0 { if en[0] > 0 { if (got as i64) > 0 { exact = bd_equal(got, 0, rn[0], wanted, 0, en[0]) } } }
236 gv_check("legacy-complete-output-byte-identical" as *u8, exact, ctr)
237 sys_free_file(got, rn[0]); sys_free_file(wanted, en[0]); return exact
238}
239func main(argc: i64, argv: *i64) -> i64 {
240 if argc != 4 { gv_puts("usage: delivery-gate <HTTPS-CLI-path> <staged-adapter-path> </tmp/unique-basename>\n" as *u8); return 3 }
241 let http: *u8 = argv[1] as *u8
242 let adapter: *u8 = argv[2] as *u8
243 let prefix: *u8 = argv[3] as *u8
244 if bd_prefix(prefix) == 0 { gv_puts("REFUSE unsafe temporary basename\n" as *u8); return 3 }
245 if ep_anchor() < 0 { gv_puts("REFUSE estate anchor unavailable\n" as *u8); return 3 }
246 let ctr: *i64 = gv_ctr(); gv_head("Complete native HTTPS and staged Compare bindings delivery" as *u8)
247 let cp: *u8 = "sites/nishifamily/compare/charsim/bindings.json" as *u8
248 let gp: *u8 = "sites/nishifamily/compare/gameengine/bindings.json" as *u8
249 let cu: *u8 = "https://nishifamily.com/compare/charsim/bindings.json" as *u8
250 let gu: *u8 = "https://nishifamily.com/compare/gameengine/bindings.json" as *u8
251 bd_https(http, prefix, ".charsim-http.txt" as *u8, cu, cp, ctr)
252 bd_https(http, prefix, ".gameengine-http.txt" as *u8, gu, gp, ctr)
253 bd_manifest(adapter, prefix, ".charsim-manifest.json" as *u8, "charsim" as *u8, cp, cu, ctr)
254 bd_manifest(adapter, prefix, ".gameengine-manifest.json" as *u8, "gameengine" as *u8, gp, gu, ctr)
255 bd_refusal(adapter, prefix, ".hidden.json" as *u8, "synthroom" as *u8, 0 as *u8, "not_found" as *u8, 1, ctr)
256 bd_refusal(adapter, prefix, ".traversal.json" as *u8, "../" as *u8, 0 as *u8, "bad_domain" as *u8, 2, ctr)
257 bd_refusal(adapter, prefix, ".missing.json" as *u8, 0 as *u8, 0 as *u8, "usage_bindings_domain" as *u8, 2, ctr)
258 bd_refusal(adapter, prefix, ".extra.json" as *u8, "charsim" as *u8, "extra" as *u8, "usage_bindings_domain" as *u8, 2, ctr)
259 bd_legacy(adapter, prefix, ".index.json" as *u8, "index" as *u8, "sites/nishifamily/compare/api.json" as *u8, ctr)
260 bd_legacy(adapter, prefix, ".legacy-gameengine.json" as *u8, "gameengine" as *u8, "sites/nishifamily/compare/gameengine/api.json" as *u8, ctr)
261 return gv_verdict("NX-BINDINGS-DELIVERY" as *u8, ctr, "captures retained under caller prefix; HTTP body bytes and native manifest contract checked, not visual review or SOTA" as *u8)
262}