code wiki / (root) / nx_extllm_call.nx

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}