code wiki / (root) / nx_content_get_client.nx

nx_content_get_client.nx

buildroot/runtime/nx_content_get_client.nx

18328 B383 linesdepth 23pulls 155 transitivereach 0 importersview sourcekind tooltopic content
docsdependenciesstructsconstsfunctions

about

nx_content_get_client.nx -- THE SOVEREIGN NAS->laptop DOWNLOAD CLIENT. Retires nx_content_get_client.py. WHY THIS EXISTS (operator standing order, restated 2026-09-04: "we shouldnt be using ps1 or py or anything else in our build path only as external tooling being liar killers and validators etc"). nx_content_get has been the sovereign SOURCE since 2026-09-03 and its only driver was a Python script written on 2026-09-04 that shells out to a Python MCP wire. A SHIPPER IS THE BUILD PATH BY DEFINITION, so it can never be one of the external oracles that order permits. This is the NishiLang driver. Its outbound sibling nx_content_put_client.nx made exactly this move for the write direction and its own first line says so; this file is the half that was missing. nx_content_get_client [dryrun] <remote_src> <local_dest> <capfile> <url> MEASURED COST OF THE GAP IT CLOSES (hostops debt 1788534921, 2026-09-04): with the NAS array degraded and every NAS build refused, the laptop farm could compile and SHIP but could not BITE, because its nx_gate_bite.nx was 39,842 bytes against the NAS 98,879 and nothing could refresh it without a human copy or retyping bytes through an agent transcript. An outbound-only lane is a fallback that works only until the thing you need is on the other side. THE PROTOCOL IS THE SERVER OWN AND IT IS STATELESS, WHICH CHANGES THIS CLIENT SHAPE: begin <src> -> CG-BEGIN src= total_bytes= sha256= chunk_raw= nchunks= chunk <src> <index> -> CG-CHUNK OK ... chunk_sha256= b64=<data> There is no transfer id and no commit: in a get the bytes accumulate on the CLIENT, so there is no server-side state to open, resume or close. The put client id-threading and commit-unknown handling are therefore ABSENT rather than mirrored -- carrying them would be machinery with no invariant to protect, which the server own header names as the asymmetry a symmetric copy gets wrong. NOTHING IS WRITTEN TO <local_dest> UNTIL THE WHOLE-FILE DIGEST MATCHES. The server header states the exposure precisely: the SOURCE can change under a multi-call read, so chunks reassembled from two generations give a franken-file that is byte-valid and semantically nonsense. The per-chunk digest catches a CORRUPTED chunk and CANNOT catch a consistent read of a CHANGED file; only the whole-file sha256 declared by begin can. So this client assembles in memory, verifies, then writes ONCE. A partial or franken download must never be able to masquerade as a refreshed source -- and a size check would not do, because a same-size rewrite passes it. THE CHUNK SIZE IS READ FROM THE SERVER RECEIPT, NEVER COMPUTED HERE. nx_content_get derives it from the RESPONSE capture cap (163,840) rather than the request cap, which is the one term a symmetric copy of the upload client would get wrong. Recomputing it here would install a second ruler that drifts the moment the server reserve changes, and the drift would surface as truncated downloads. A SERVER DECISION IS NEVER RETRIED, AND IT HAS TWO VOCABULARIES.

dependencies 5 imports · 0 importers

nx_syscalls.nx nx_base64.nx nx_sha256.nx nx_https_post_lib.nx nx_jobfollow_lib.nx nx_content_get_client.nx

imports: nx_syscalls.nxnx_base64.nxnx_sha256.nxnx_https_post_lib.nxnx_jobfollow_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main cg_streq cg_eo sys_write cg_slen cg_is_readcap sys_mmap nxa_die sys_write ↻ sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_munmap sys_close cg_json_safe hf_store_load nx_trust_store_load_from_c sys_mmap ↻ sys_read_file ↻ nx_nss_certdata_parse sys_mmap ↻ _pat_class_cert _pat_value_octal _pat_end _find_newline _starts_with

structs

none

consts

62const CG_DIGEST: i64 = 32
63const CG_SHAHEX: i64 = 64
64const CG_RESP: i64 = 262144
65const CG_REQ: i64 = 262144
66const CG_NUMBUF: i64 = 32
67const CG_MODE_RW: i64 = 420
70const CG_POLLS: i64 = 40
71const CG_POLL_MS: i64 = 3000
76const CG_PRE: *u8 = "{\x22jsonrpc\x22:\x222.0\x22,\x22id\x22:1,\x22method\x22:\x22tools/call\x22,\x22params\x22:{\x22name\x22:\x22nx_content_get\x22,\x22arguments\x22:{\x22argv\x22:["
77const CG_TAIL: *u8 = "}}}"
78const CG_QUOTE: i64 = 34
79const CG_BACKSLASH: i64 = 92
80const CG_SPACE: i64 = 32
81const CG_DEL: i64 = 127

functions

83func cg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
84func cg_out(s: *u8) -> i64 { sys_write(1, s, cg_slen(s)); return 0 }
called by 1: main calls 2: sys_writecg_slen
85func cg_eo(s: *u8) -> i64 { sys_write(2, s, cg_slen(s)); return 0 }
called by 1: main calls 2: sys_writecg_slen
86func cg_num(v: i64) -> i64
called by 1: main calls 2: sys_mmapsys_write
95func cg_itoa(v: i64, out: *u8) -> i64
called by 1: main calls 1: sys_mmap
105func cg_hex_into(d: *u8, out: *u8) -> i64
called by 1: main
118func cg_json_safe(s: *u8, n: i64) -> i64
called by 2: cg_put_argmain
132func cg_find(buf: *u8, n: i64, needle: *u8) -> i64
called by 3: cg_int_aftercg_decidedmain calls 1: cg_slen
146func cg_int_after(buf: *u8, n: i64, key: *u8) -> i64
called by 1: main calls 1: cg_find
165func cg_b64ch(c: i64) -> i64
called by 1: main
174func cg_put_arg(req: *u8, off: i64, val: *u8, vlen: i64, first: i64) -> i64
called by 1: main calls 1: cg_json_safe
185func cg_put_lit(req: *u8, off: i64, lit: *u8) -> i64
called by 1: main calls 1: cg_slen
192func cg_streq(a: *u8, b: *u8) -> i64
called by 1: main
202func cg_decided(buf: *u8, n: i64) -> i64
called by 1: main calls 1: cg_find
211func cg_is_readcap(a: *u8) -> i64
called by 1: main
221func main(argc: i64, argv: *i64) -> i64