nx_extllm_call.nx source
↩ module page · 455 lines · 25515 B
1// nx_extllm_call.nx -- RUNG XL3: the ONLY door through which estate bytes may reach an external model.
2// Every conjunct is checked BEFORE a socket is opened, and each refusal names the rule that fired.
3// 1 TERMS xl_use_verdict on the pinned provider ledger. UNKNOWN refuses. An unpinned row admits nothing.
4// 2 CLASSIFY every prompt byte must come from a file the operator DECLARED public, and whose sha256 still
5// matches that declaration. C by default; a stale hash admits nothing.
6// 3 KEY read from a FILE, never argv -- argv is visible in /proc and in every transcript.
7// 4 CALL our own TLS 1.3 + Mozilla trust store, the same send/recv core the InnerTube POST path uses.
8// 5 LEDGER one appended row per call, so "how much has provider P seen, in total, across all time?" is a
9// read and not an investigation. This is the half a per-call check structurally cannot do.
10// The request sets provider.data_collection=deny and zdr=true, which the router documents as a per-request
11// switch -- belt and braces beside the terms row, never instead of it.
12// license_tier: ORIGINAL No hw writes (Rule 26). exit 0 ALLOW / 1 REFUSE / 3 UNKNOWN / 2 usage / 4 transport
13import "nx_extllm_lib.nx"
14import "nx_estate_path.nx"
15import "nx_sha256.nx"
16import "nx_sovjson_lib.nx"
17import "nx_gate_verdict.nx"
18import "nx_x509_trust_store.nx"
19import "nx_trust_store_load_from_certdata.nx"
20import "nx_tls13_client_validate_certificate.nx"
21import "nx_tls13_client_session_run.nx"
22import "nx_https_url_for_fetch.nx"
23import "nx_https_url_connect.nx"
24import "nx_https_get_complete.nx"
25import "nx_http_response_parse.nx"
26import "nx_syscalls.nx"
27
28const XC_RESP_CAP: i64 = 262144
29const XC_REQ_CAP: i64 = 65536
30const XC_PROMPT_CAP: i64 = 16384
31const XC_KEY_CAP: i64 = 4096
32const XC_PATH_CAP: i64 = 1024
33const XC_DIGEST_BYTES: i64 = 32
34const XC_HEX_PER_BYTE: i64 = 2
35const XC_CERT_ROOTS_MIN: i64 = 300
36const XC_CERT_ARENA: i64 = 4194304
37const XC_SOCK_TIMEOUT_S: i64 = 30
38const XC_TLS_RAND_BYTES: i64 = 32
39const XC_ESC_PROMPT: i64 = 12000
40const XC_ESC_FIELD: i64 = 128
41const XC_USAGE: i64 = 2
42const XC_TRANSPORT: i64 = 4
43const XC_ASCII_0: i64 = 48
44const XC_ASCII_a_MINUS_10: i64 = 87
45const XC_NIBBLE_HI_SHIFT: i64 = 16
46const XC_NIBBLE_MASK: i64 = 15
47// 0644 in decimal, because the estate has been bitten by the same constant written in two bases reading as
48// two different constants to every scanner. Named for its purpose, spelled once.
49const XC_LEDGER_MODE: i64 = 420
50const XC_HDR_SLOTS: i64 = 128
51const XC_BODY_CHUNKED: i64 = 2
52const XC_HTTP_OK: i64 = 200
53// A POLICY refusal and a PROVIDER refusal are NOT the same outcome and must not share an exit code.
54// MEASURED: collapsing both into XL_REFUSE made the caller announce "the bytes left and are on the
55// ledger" for a call that opened no socket and wrote no row -- a FALSE claim, in the audit path, about
56// the one fact the audit exists to establish. A refusal that cannot name its failing conjunct is a
57// false-alarm generator; this one was a false-REASSURANCE generator, which is strictly worse.
58const XC_PROVIDER_REFUSED: i64 = 5
59
60func xc_w(s: *u8) -> i64 { return sj_werr(s) }
61
62// 32 raw digest bytes -> 64 lowercase hex chars, NUL-terminated. Arithmetic, no lookup table.
63func xc_hex(dig: *u8, out: *u8) -> i64 {
64 var i: i64 = 0
65 while i < XC_DIGEST_BYTES {
66 let b: i64 = dig[i] as i64
67 let hi: i64 = b / XC_NIBBLE_HI_SHIFT
68 let lo: i64 = b - hi * XC_NIBBLE_HI_SHIFT
69 if hi < 10 { out[i*XC_HEX_PER_BYTE] = (XC_ASCII_0 + hi) as u8 } else { out[i*XC_HEX_PER_BYTE] = (XC_ASCII_a_MINUS_10 + hi) as u8 }
70 if lo < 10 { out[i*XC_HEX_PER_BYTE+1] = (XC_ASCII_0 + lo) as u8 } else { out[i*XC_HEX_PER_BYTE+1] = (XC_ASCII_a_MINUS_10 + lo) as u8 }
71 i = i + 1
72 }
73 out[XC_DIGEST_BYTES * XC_HEX_PER_BYTE] = 0 as u8
74 return XC_DIGEST_BYTES * XC_HEX_PER_BYTE
75}
76
77// The manifest stores a pin as h<64hex>. Build that form so the comparison is like-for-like.
78func xc_pin_of(buf: *u8, n: i64, out: *u8) -> i64 {
79 let dig: *u8 = sys_mmap(XC_DIGEST_BYTES)
80 sha256_digest(buf, n, dig)
81 out[0] = 104 as u8
82 return xc_hex(dig, out + 1) + 1
83}
84
85// Trailing whitespace on a key file is the classic silent 401. Trim it here, once.
86func xc_trim(buf: *u8, n: i64) -> i64 {
87 var e: i64 = n
88 var go: i64 = 1
89 while go == 1 {
90 if e <= 0 { go = 0 } else {
91 let c: i64 = buf[e-1] as i64
92 if c == 10 { e = e - 1 } else { if c == 13 { e = e - 1 } else { if c == 32 { e = e - 1 } else { if c == 9 { e = e - 1 } else { go = 0 } } } }
93 }
94 }
95 buf[e] = 0 as u8
96 return e
97}
98
99func xc_read_estate(p: *u8, out_len: *i64) -> *u8 {
100 let rp: *u8 = sys_mmap(XC_PATH_CAP)
101 if ep_artifact_path(rp, p) == 0 { out_len[0] = 0; return 0 as *u8 }
102 return sys_read_file(rp, out_len)
103}
104
105// The egress ledger row xl_spent sums: <unix>|<provider>|<tier>|<subsystem>|<bytes>|<class>|<prompt-pin>|<verdict>
106func xc_ledger_row(out: *u8, provider: *u8, tier: *u8, subsystem: *u8, bytes: i64, pin: *u8, verdict: *u8) -> i64 {
107 var o: i64 = 0
108 o = sj_catn(out, o, sys_now_realtime_sec())
109 o = sj_cat(out, o, "|" as *u8); o = sj_cat(out, o, provider)
110 o = sj_cat(out, o, "|" as *u8); o = sj_cat(out, o, tier)
111 o = sj_cat(out, o, "|" as *u8); o = sj_cat(out, o, subsystem)
112 o = sj_cat(out, o, "|" as *u8); o = sj_catn(out, o, bytes)
113 o = sj_cat(out, o, "|U|" as *u8); o = sj_cat(out, o, pin)
114 o = sj_cat(out, o, "|" as *u8); o = sj_cat(out, o, verdict)
115 out[o] = 10 as u8
116 return o + 1
117}
118
119// APPEND, never rewrite: an egress ledger that can shrink is not a ledger.
120func xc_ledger_append(path: *u8, row: *u8, n: i64) -> i64 {
121 let fd: i64 = sys_openat_append(path, XC_LEDGER_MODE)
122 if fd < 0 { return 0 - 1 }
123 let w: i64 = sys_write(fd, row, n)
124 sys_close(fd)
125 if w != n { return 0 - 2 }
126 return w
127}
128
129// A PROVIDER KEY MUST NEVER LIVE INSIDE THE ESTATE. Under the estate root it is reachable by the secret
130// scanner, by a glob, and by the served tree. nx_fs_write already refuses to WRITE one there; this is the
131// same judgement one layer down, at the READ. It makes the transit safe BY CONSTRUCTION rather than safe
132// because the caller happened to be careful -- and a caller who was careless now gets a named refusal
133// instead of a key sitting in a scanned tree.
134// Absolute path required; it must not sit under EP_ROOT, whose value is the incumbent's own constant.
135const XC_BYTE_SLASH: i64 = 47
136func xc_keypath_outside_estate(p: *u8) -> i64 {
137 if (p[0] as i64) != XC_BYTE_SLASH { return 0 }
138 var i: i64 = 0
139 while EP_ROOT[i] != (0 as u8) {
140 if p[i] == (0 as u8) { return 1 }
141 if p[i] != EP_ROOT[i] { return 1 }
142 i = i + 1
143 }
144 return 0
145}
146
147// The provider pads a long generation with whitespace-only keepalive chunks. MEASURED on the first
148// successful ox-alpha call: 102,632 bytes of artifact for a few KB of answer, so dechunking concatenates
149// ~100 KB of spaces and the JSON lands at the very end. A caller then has to go hunting for the thing it
150// asked for. Skip the padding and hand back the answer.
151func xc_skip_ws(b: *u8, n: i64) -> i64 {
152 var i: i64 = 0
153 while i < n {
154 let c: i64 = b[i] as i64
155 if c == 32 { i = i + 1 } else { if c == 10 { i = i + 1 } else { if c == 13 { i = i + 1 } else { if c == 9 { i = i + 1 } else { return i } } } }
156 }
157 return n
158}
159
160// ---- THE ENDPOINT AS DATA (2026-08-25) ----------------------------------------------------------
161// This organ hardcoded https://openrouter.ai/api/v1/chat/completions, so the lane could reach exactly ONE
162// provider and "use other free AI like that" required a source edit and a rebuild. A reachable address is
163// data. An absent row ABSTAINS: a provider we have no address for is not a provider we may guess at.
164const XE_EP_PROVIDER: i64 = 0
165const XE_EP_HOST: i64 = 1
166const XE_EP_PATH: i64 = 2
167const XE_EP_AUTHHDR: i64 = 3
168const XE_EP_AUTHSCHEME: i64 = 4
169const XE_EP_COLS: i64 = 6
170const XE_URL_CAP: i64 = 512
171
172func xc_endpoint_path() -> *u8 { return "knowledge/extllm_endpoint.conf" as *u8 }
173
174func xc_ep_row(q: *u8, n: i64, provider: *u8, out: *i64) -> i64 {
175 let c: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
176 var i: i64 = 0
177 while i < n {
178 let le: i64 = sj_le(q, i, n)
179 if xl_is_comment(q, i, le) == 0 {
180 if xl_ncols(q, i, le) == XE_EP_COLS {
181 if xl_col(q, i, le, XE_EP_PROVIDER, c) == 1 {
182 if sj_lit_eq(q, c[0], c[1], provider) == 1 { out[0] = i; out[1] = le; return 1 }
183 }
184 }
185 }
186 i = le + 1
187 }
188 return 0
189}
190
191// Copy one column out as a NUL-terminated string. Returns its length, 0 when the column is absent.
192func xc_ep_field(q: *u8, ls: i64, le: i64, col: i64, out: *u8) -> i64 {
193 let c: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
194 if xl_col(q, ls, le, col, c) == 0 { out[0] = 0 as u8; return 0 }
195 var k: i64 = 0
196 while c[0] + k < c[1] { out[k] = q[c[0] + k]; k = k + 1 }
197 out[k] = 0 as u8
198 return k
199}
200
201// THE XL3 CONTRACT SYMBOL. Order is the security property: TERMS, then CLASSIFY, then KEY, and only then a
202// socket. A transport failure returns XC_TRANSPORT and NOT a policy code -- a network error that read as a
203// policy verdict would let a dropped connection look like an authorised refusal.
204func xl_call(provider: *u8, tier: *u8, model: *u8, prompt_path: *u8, keypath: *u8,
205 subsystem: *u8, ledger: *u8, out: *u8, outcap: i64) -> i64 {
206 let tn: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
207 let terms: *u8 = xc_read_estate(xl_terms_path(), tn)
208 if tn[0] <= 0 { xc_w("XL3-REFUSE rule=terms-ledger-unreadable\n" as *u8); return XL_UNKNOWN }
209 let tv: i64 = xl_use_verdict(terms, tn[0], provider, tier, XL_USE_WORKER)
210 if tv != XL_ALLOW {
211 xc_w("XL3-REFUSE rule=terms verdict=" as *u8); xc_w(xl_verdict_name(tv)); xc_w("\n" as *u8)
212 return tv
213 }
214 // The privacy switches below are DERIVED FROM THE PINNED TERMS ROW, never hardcoded. MEASURED
215 // 2026-08-25 against the live router: sending zdr=true to a stealth model returns 404 "No endpoints
216 // found matching your data policy (Zero data retention)" -- a provider whose contract collects input
217 // for training cannot also offer zero retention, so asking is a call that CANNOT succeed. The router
218 // enforcing this is independent confirmation of the EULA the terms row already carries.
219 let trains: i64 = xl_trains_on_input(terms, tn[0], provider, tier)
220 let pn: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
221 let prompt: *u8 = xc_read_estate(prompt_path, pn)
222 if pn[0] <= 0 { xc_w("XL3-REFUSE rule=prompt-unreadable\n" as *u8); return XL_UNKNOWN }
223 let pin: *u8 = sys_mmap(XC_PATH_CAP)
224 xc_pin_of(prompt, pn[0], pin)
225 let rn: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
226 let rel: *u8 = xc_read_estate(xl_release_path(), rn)
227 var reln: i64 = 0
228 if rn[0] > 0 { reln = rn[0] }
229 if xl_class_of(rel, reln, prompt_path, pin) != XL_CLASS_U {
230 xc_w("XL3-REFUSE rule=classify class=C path=" as *u8); xc_w(prompt_path)
231 xc_w(" -- not on the operator release manifest, or its hash moved since it was declared\n" as *u8)
232 return XL_REFUSE
233 }
234 if xc_keypath_outside_estate(keypath) == 0 {
235 xc_w("XL3-REFUSE rule=key-inside-estate path=" as *u8); xc_w(keypath)
236 xc_w(" -- a provider key must not live under the estate root, where the secret scanner, a glob and the served tree can all reach it\n" as *u8)
237 return XL_REFUSE
238 }
239 let kraw: *u8 = sys_mmap(XC_KEY_CAP)
240 let kfd: i64 = sys_openat_rd(keypath)
241 if kfd < 0 { xc_w("XL3-REFUSE rule=key-file-unreadable path=" as *u8); xc_w(keypath); xc_w("\n" as *u8); return XL_UNKNOWN }
242 let kn: i64 = sys_read(kfd, kraw, XC_KEY_CAP - 1)
243 sys_close(kfd)
244 let klen: i64 = xc_trim(kraw, kn)
245 if klen <= 0 { xc_w("XL3-REFUSE rule=key-file-empty\n" as *u8); return XL_UNKNOWN }
246 let body: *u8 = sys_mmap(XC_REQ_CAP)
247 var b: i64 = 0
248 b = sj_cat(body, b, "{\"model\":\"" as *u8)
249 b = sj_cat_esc(body, b, model, 0, sj_vlen(model), XC_ESC_FIELD)
250 b = sj_cat(body, b, "\",\"messages\":[{\"role\":\"user\",\"content\":\"" as *u8)
251 b = sj_cat_esc(body, b, prompt, 0, pn[0], XC_ESC_PROMPT)
252 b = sj_cat(body, b, "\"}]" as *u8)
253 // A no-training provider gets belt and braces. A training provider gets neither -- and the call is
254 // recorded as DONATED, so the ledger row says plainly that those bytes are now permanently theirs.
255 var donated: i64 = 0
256 if trains == XL_ALLOW {
257 b = sj_cat(body, b, ",\"provider\":{\"data_collection\":\"deny\",\"zdr\":true}" as *u8)
258 } else { donated = 1 }
259 b = sj_cat(body, b, "}" as *u8)
260 // Resolve WHERE this provider lives, from data. No row means no address, and no address means abstain.
261 let en: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
262 let epb: *u8 = xc_read_estate(xc_endpoint_path(), en)
263 if en[0] <= 0 { xc_w("XL3-REFUSE rule=endpoint-conf-unreadable\n" as *u8); return XL_UNKNOWN }
264 let er: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
265 if xc_ep_row(epb, en[0], provider, er) == 0 {
266 xc_w("XL3-REFUSE rule=no-endpoint-row provider=" as *u8); xc_w(provider)
267 xc_w(" -- knowledge/extllm_endpoint.conf carries no address for this provider, and an address is never guessed\n" as *u8)
268 return XL_UNKNOWN
269 }
270 let ehost: *u8 = sys_mmap(XE_URL_CAP)
271 let epath: *u8 = sys_mmap(XE_URL_CAP)
272 let eahdr: *u8 = sys_mmap(XE_URL_CAP)
273 let eschm: *u8 = sys_mmap(XE_URL_CAP)
274 let hlen0: i64 = xc_ep_field(epb, er[0], er[1], XE_EP_HOST, ehost)
275 let plen0: i64 = xc_ep_field(epb, er[0], er[1], XE_EP_PATH, epath)
276 xc_ep_field(epb, er[0], er[1], XE_EP_AUTHHDR, eahdr)
277 xc_ep_field(epb, er[0], er[1], XE_EP_AUTHSCHEME, eschm)
278 if hlen0 <= 0 { xc_w("XL3-REFUSE rule=endpoint-row-has-no-host\n" as *u8); return XL_UNKNOWN }
279 if plen0 <= 0 { xc_w("XL3-REFUSE rule=endpoint-row-has-no-path\n" as *u8); return XL_UNKNOWN }
280 let cdp: *u8 = sys_mmap(XC_PATH_CAP)
281 if ep_artifact_path(cdp, "data/mozilla_certdata.txt\x00" as *u8) == 0 {
282 xc_w("XL3-TRANSPORT rule=trust-store-absent\n" as *u8); return XC_TRANSPORT
283 }
284 let tr: i64 = nx_trust_store_load_from_certdata(cdp, XC_CERT_ROOTS_MIN, XC_CERT_ARENA)
285 if tr <= 0 { xc_w("XL3-TRANSPORT rule=trust-store-load-failed\n" as *u8); return XC_TRANSPORT }
286 let store: *TrustStore = tr as *TrustStore
287 let url: *u8 = sys_mmap(XE_URL_CAP)
288 var uo: i64 = sj_cat(url, 0, "https://" as *u8)
289 uo = sj_cat(url, uo, ehost)
290 uo = sj_cat(url, uo, epath)
291 url[uo] = 0 as u8
292 let url_p: *NxUrl = nx_url_new()
293 let traw: *u8 = sys_mmap(XL_SPAN_BYTES * 2)
294 let target: *NxHttpsTarget = traw as *NxHttpsTarget
295 target.url = url_p
296 target.port = 0
297 if nx_https_url_for_fetch(url, target) != NX_HTTPS_URL_OK { xc_w("XL3-TRANSPORT rule=url-parse\n" as *u8); return XC_TRANSPORT }
298 let host: *u8 = url + target.url.host_off
299 let hlen: i64 = target.url.host_len
300 let fd_p: *i64 = sys_mmap(XL_SPAN_BYTES) as *i64
301 if nx_https_url_connect(target, url, sys_now_realtime_sec(), fd_p) != NX_HTTPS_CONNECT_OK { xc_w("XL3-TRANSPORT rule=connect\n" as *u8); return XC_TRANSPORT }
302 let fd: i64 = *fd_p
303 sys_set_socket_timeout(fd, XC_SOCK_TIMEOUT_S)
304 let vc_raw: *u8 = sys_mmap(XL_SPAN_BYTES * 4)
305 let vc: *TlsValidationContext = vc_raw as *TlsValidationContext
306 vc.store = store
307 vc.sni_host = host
308 vc.sni_host_len = hlen
309 vc.now_epoch = sys_now_realtime_sec()
310 let cr: *u8 = sys_mmap(XC_TLS_RAND_BYTES)
311 let priv: *u8 = sys_mmap(XC_TLS_RAND_BYTES)
312 var i: i64 = 0
313 while i < XC_TLS_RAND_BYTES { cr[i] = (192 + i) as u8; priv[i] = (160 + i) as u8; i = i + 1 }
314 let sr: i64 = nx_tls13_client_session_run(fd, host, hlen, cr, priv, vc)
315 if sr <= 0 { sys_close(fd); xc_w("XL3-TRANSPORT rule=tls-handshake\n" as *u8); return XC_TRANSPORT }
316 let session: *Tls13ClientSession = sr as *Tls13ClientSession
317 let req: *u8 = sys_mmap(XC_REQ_CAP)
318 var ro: i64 = 0
319 ro = sj_cat(req, ro, "POST " as *u8)
320 ro = sj_cat(req, ro, epath)
321 ro = sj_cat(req, ro, " HTTP/1.1\r\nHost: " as *u8)
322 var hi: i64 = 0
323 while hi < hlen { req[ro] = host[hi]; ro = ro + 1; hi = hi + 1 }
324 ro = sj_cat(req, ro, "\r\n" as *u8)
325 ro = sj_cat(req, ro, eahdr)
326 ro = sj_cat(req, ro, ": " as *u8)
327 ro = sj_cat(req, ro, eschm)
328 ro = sj_cat(req, ro, " " as *u8)
329 ro = sj_cat(req, ro, kraw)
330 ro = sj_cat(req, ro, "\r\nContent-Type: application/json\r\nContent-Length: " as *u8)
331 ro = sj_catn(req, ro, b)
332 ro = sj_cat(req, ro, "\r\nConnection: close\r\n\r\n" as *u8)
333 var bi: i64 = 0
334 while bi < b { req[ro] = body[bi]; ro = ro + 1; bi = bi + 1 }
335 let resp: *u8 = sys_mmap(XC_RESP_CAP)
336 let gc: i64 = nx_https_req_complete(session, fd, req, ro, resp, XC_RESP_CAP)
337 sys_close(fd)
338 if gc < 0 { xc_w("XL3-TRANSPORT rule=send-recv\n" as *u8); return XC_TRANSPORT }
339 // PARSE THE RESPONSE. Handing raw wire bytes back was a real defect, measured on the FIRST live
340 // ox-alpha call: it returned 200 over 679 chunked records and the caller received hex chunk-size
341 // markers instead of the answer. The parser was imported and never called -- a feature absent from
342 // the code path has no failure mode of its own, so only reading the output exposed it.
343 let rp: *i64 = sys_mmap(XC_HDR_SLOTS) as *i64
344 if nx_http_response_parse(resp, gc, rp) != 0 { xc_w("XL3-TRANSPORT rule=response-unparseable\n" as *u8); return XC_TRANSPORT }
345 let status: i64 = rp[1]
346 let body_off: i64 = rp[6]
347 var hl: i64 = 0
348 if rp[8] == XC_BODY_CHUNKED { hl = nx_http_dechunk(resp + body_off, gc - body_off, out, outcap - 1) }
349 else {
350 hl = gc - body_off
351 if hl > outcap - 1 { hl = outcap - 1 }
352 var ci: i64 = 0
353 while ci < hl { out[ci] = resp[body_off + ci]; ci = ci + 1 }
354 }
355 let ws: i64 = xc_skip_ws(out, hl)
356 if ws > 0 {
357 var si: i64 = 0
358 while si < hl - ws { out[si] = out[si + ws]; si = si + 1 }
359 hl = hl - ws
360 }
361 out[hl] = 0 as u8
362 // THE LEDGER CARRIES THE PROVIDER'S STATUS. The bytes left the estate whatever came back, so the
363 // disclosure is recorded either way -- but a row reading ALLOW for a 404 would let a refused call
364 // look served, and the odometer would be right while the audit trail lied.
365 let row: *u8 = sys_mmap(XC_PATH_CAP)
366 let vname: *u8 = sys_mmap(XC_ESC_FIELD)
367 var vo: i64 = 0
368 if donated == 1 { vo = sj_cat(vname, vo, "ALLOW-DONATED-" as *u8) } else { vo = sj_cat(vname, vo, "ALLOW-" as *u8) }
369 vo = sj_catn(vname, vo, status)
370 vname[vo] = 0 as u8
371 let rl: i64 = xc_ledger_row(row, provider, tier, subsystem, pn[0], pin, vname)
372 xc_ledger_append(ledger, row, rl)
373 if status != XC_HTTP_OK { return XC_PROVIDER_REFUSED }
374 return XL_ALLOW
375}
376
377func xc_selftest() -> i64 {
378 let ctr: *i64 = gv_ctr()
379 gv_head("nx_extllm_call selftest -- XL3 gated egress: pin arithmetic, ledger wire, refusal ordering" as *u8)
380 let hx: *u8 = sys_mmap(XC_PATH_CAP)
381 let dig: *u8 = sys_mmap(XC_DIGEST_BYTES)
382 sha256_digest("abc" as *u8, 3, dig)
383 xc_hex(dig, hx)
384 gv_check("T1 FIPS 180-4 KAT: sha256(abc) hex is the published digest" as *u8, sj_lit_eq(hx, 0, 64, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" as *u8), ctr)
385 let pin: *u8 = sys_mmap(XC_PATH_CAP)
386 let pl: i64 = xc_pin_of("abc" as *u8, 3, pin)
387 gv_check("T2 a pin is h then 64 hex, the exact form the manifest stores" as *u8, pl == 65, ctr)
388 gv_check("T3 the pin body equals the digest, so classify compares like for like" as *u8, sj_lit_eq(pin, 0, 65, "hba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" as *u8), ctr)
389 let kb: *u8 = sys_mmap(XC_KEY_CAP)
390 var ko: i64 = sj_cat(kb, 0, "sk-test-key-value\n" as *u8)
391 gv_check("T4 a trailing newline on a key file is trimmed (the classic silent 401)" as *u8, xc_trim(kb, ko) == 17, ctr)
392 ko = sj_cat(kb, 0, " \n" as *u8)
393 gv_check("neg-control-an-all-whitespace-key-trims-to-empty-and-must-refuse" as *u8, xc_trim(kb, ko) == 0, ctr)
394 let row: *u8 = sys_mmap(XC_PATH_CAP)
395 let rl: i64 = xc_ledger_row(row, "groq" as *u8, "free" as *u8, "search" as *u8, 4096, "hbeef" as *u8, "ALLOW" as *u8)
396 gv_check("T5 the emitted row carries the byte count" as *u8, sj_span_has(row, 0, rl, "|4096|U|hbeef|ALLOW" as *u8), ctr)
397 gv_check("T6 THE WIRE ROUND-TRIPS: xl_spent reads back exactly what xc_ledger_row wrote" as *u8, xl_spent(row, rl, "groq" as *u8, "" as *u8, 1) == 4096, ctr)
398 gv_check("T7 and it narrows to the subsystem the row declared" as *u8, xl_spent(row, rl, "groq" as *u8, "search" as *u8, 0) == 4096, ctr)
399 gv_check("neg-control-the-round-trip-does-not-credit-another-provider" as *u8, xl_spent(row, rl, "openrouter" as *u8, "" as *u8, 1) == 0, ctr)
400 let two: *u8 = sys_mmap(XC_REQ_CAP)
401 var t2: i64 = 0
402 t2 = t2 + xc_ledger_row(two + t2, "groq" as *u8, "free" as *u8, "search" as *u8, 3000, "hp1" as *u8, "ALLOW" as *u8)
403 t2 = t2 + xc_ledger_row(two + t2, "groq" as *u8, "free" as *u8, "search" as *u8, 4000, "hp2" as *u8, "ALLOW" as *u8)
404 gv_check("T8 TWO APPENDED CALLS SUM -- the odometer the per-call check cannot compute" as *u8, xl_spent(two, t2, "groq" as *u8, "" as *u8, 1) == 7000, ctr)
405 gv_check("T9 fixture-reached-the-condition: each of those rows alone is under a 5000 bound" as *u8, xl_budget_verdict(0, 4000, 5000) == XL_ALLOW, ctr)
406 gv_check("T10 THE AGGREGATION REFUSAL on the SAME two rows: 7000 over a 5000 bound" as *u8, xl_budget_verdict(xl_spent(two, t2, "groq" as *u8, "" as *u8, 1), 0, 5000) == XL_REFUSE, ctr)
407 gv_check("neg-control-ledger-append-to-an-unwritable-path-reports-failure" as *u8, xc_ledger_append("/proc/nx_extllm_cannot_write\x00" as *u8, row, rl) < 0, ctr)
408 gv_check("T13 an ephemeral absolute path outside the estate is an acceptable key location" as *u8, xc_keypath_outside_estate("/tmp/nx_extllm_bearer.txt\x00" as *u8) == 1, ctr)
409 gv_check("neg-control-a-key-UNDER-THE-ESTATE-ROOT-is-refused (scanner, glob and served tree all reach it)" as *u8, xc_keypath_outside_estate("/volume1/homes/elderwesto/nishihost/knowledge/openrouter.key\x00" as *u8) == 0, ctr)
410 gv_check("neg-control-a-RELATIVE-key-path-is-refused (it resolves by CWD, so it could land inside the estate)" as *u8, xc_keypath_outside_estate("knowledge/openrouter.key\x00" as *u8) == 0, ctr)
411 gv_check("T14 fixture-reached-the-condition: a path sharing a PREFIX with the estate root but leaving it early is accepted" as *u8, xc_keypath_outside_estate("/volume1/homes/elderwesto/other/k.txt\x00" as *u8) == 1, ctr)
412 let pad: *u8 = sys_mmap(XC_ESC_FIELD)
413 var po: i64 = sj_cat(pad, 0, " \n \t {\"choices\":[]}" as *u8)
414 gv_check("T11 whitespace keepalive padding is skipped so the caller gets the answer, not the padding" as *u8, xc_skip_ws(pad, po) == 14, ctr)
415 gv_check("neg-control-a-body-that-is-ALL-padding-reports-its-full-length-not-a-false-offset" as *u8, xc_skip_ws(" " as *u8, 4) == 4, ctr)
416 gv_check("T12 fixture-reached-the-condition: a body with NO padding is not shifted at all" as *u8, xc_skip_ws("{\"ok\":1}" as *u8, 8) == 0, ctr)
417 let rc: i64 = gv_verdict("EXTLLM-CALL-GATE" as *u8, ctr, "XL3 egress: pin arithmetic matches the manifest form, the ledger wire round-trips through xl_spent, and the cumulative bound refuses a sum that every part passes alone" as *u8)
418 return rc
419}
420
421func main(argc: i64, argv: *i64) -> i64 {
422 if argc < 2 {
423 xc_w("usage: nx_extllm_call {call <provider> <tier> <model> <prompt-path> <keyfile> <subsystem> <ledger> | selftest}\n" as *u8)
424 sys_exit(XC_USAGE)
425 return XC_USAGE
426 }
427 let verb: *u8 = argv[1] as *u8
428 if sj_lit_eq(verb, 0, sj_vlen(verb), "selftest" as *u8) == 1 {
429 let rc: i64 = xc_selftest()
430 sys_exit(rc)
431 return rc
432 }
433 if sj_lit_eq(verb, 0, sj_vlen(verb), "call" as *u8) == 1 {
434 if argc < 9 { xc_w("XL3-FAIL call needs <provider> <tier> <model> <prompt-path> <keyfile> <subsystem> <ledger>\n" as *u8); sys_exit(XC_USAGE); return XC_USAGE }
435 let out: *u8 = sys_mmap(XC_RESP_CAP)
436 let rc: i64 = xl_call(argv[2] as *u8, argv[3] as *u8, argv[4] as *u8, argv[5] as *u8,
437 argv[6] as *u8, argv[7] as *u8, argv[8] as *u8, out, XC_RESP_CAP)
438 // A REFUSAL MUST STILL SAY WHY. On a non-200 the provider's own error JSON is the most useful
439 // thing we hold, and signalling REFUSE by exit code alone made this organ commit the exact fault
440 // it exists to prevent: refusing without naming the reason. MEASURED -- a 429 printed nothing at
441 // all, and only the ledger row (ALLOW-DONATED-429) said what had happened.
442 if rc == XL_ALLOW { sys_write(1, out, sj_vlen(out)) }
443 // XL_REFUSE is a POLICY refusal: xl_call has already named the rule and NOTHING left the estate,
444 // so there is no body to show and no ledger row to point at. Saying otherwise was the bug.
445 if rc == XC_PROVIDER_REFUSED {
446 xc_w("XL3-PROVIDER-REFUSED -- the bytes DID leave and are on the ledger; the provider body follows\n" as *u8)
447 sys_write(1, out, sj_vlen(out))
448 }
449 sys_exit(rc)
450 return rc
451 }
452 xc_w("XL3-FAIL unknown verb\n" as *u8)
453 sys_exit(XC_USAGE)
454 return XC_USAGE
455}