code wiki / _hdl_build / nx_inventory_serve.nx
nx_inventory_serve.nx
buildroot/runtime/_hdl_build/nx_inventory_serve.nx
about
nx_inventory_serve.nx -- nishifamily.com/inventory : paste a storefront URL, get a LIVING CHECKLIST
of what in it you already own.
REBUILT 2026-08-07 TO MATCH THE KNOWN GOOD (nx_status_daemon), after the first cut shipped three
defects the template would have prevented outright:
1. it bound INADDR_ANY, so an UNAUTHENTICATED, SSRF-capable fetcher answered from another host on
the LAN the instant it started (measured, then killed). Now: nx_http_server_addr_loopback.
2. it had NO AUTH, and I intended to route it with proxy mode=gated believing that WAS the login
gate. It is not -- `gated` means fail-closed 302 when the BACKEND IS DOWN. Site auth is
nx_sa_validate over X-Nishi-Session, NO cookies (charter C1). Now every route but /health is
validated, so an unauthenticated request cannot make this daemon fetch anything.
3. its handler was welded to a socket, so the only way to test it was curl from a shell script --
the exact break-glass shape rule 29 forbids. Now the router is a PURE FUNCTION
iv_handle(ctx, req, req_n, ...) -> out_n, so a NishiLang gate drives it IN-PROCESS.
THIN BY DESIGN. It orchestrates two binaries already proven rather than reimplementing them:
1. ./nx_https_get_cli2.elf <url> -- the sovereign TLS-1.3 client (own trust store)
2. ./nx_ownlib.elf scan <file> -- the ledger diff, selftest 19/19, match key included
The match key (ol_norm) is the correctness-critical part, and a daemon holding its own copy is how
two components drift into disagreeing about what "the same game" is. So the daemon owns NO matching
logic -- it owns a socket, an auth check, and an HTML wrapper.
SSRF: this fetches an operator-supplied URL from INSIDE the estate, where mgmt (:18098) and the tools
daemon (:18096) sit on loopback. Auth alone is NOT sufficient -- it only means the attacker must be
logged in. So the guard is structural and runs before any socket: https only; loopback/private/
link-local refused by construction.
nx_inventory_serve <port> <keysfile> <storefile> <realm> <budget>
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 4 imports · 1 importers
imports: nx_syscalls.nxnx_http_server.nxnx_site_auth.nxnx_tool_run.nx
imported by: nx_inventory_gate.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 35 | const IV_MAGIC_4096: i64 = 4096 |
| 36 | const IV_MAGIC_8192: i64 = 8192 |
| 37 | const IV_REQCAP: i64 = 65536 |
| 38 | const IV_PAGECAP: i64 = 4194304 // a bundle page measured 719,027 bytes LIVE; 4 MiB is ~5.8x headroom |
| 39 | const IV_OUTCAP: i64 = 262144 |
| 40 | const IV_URLCAP: i64 = 2048 |
| 41 | const IV_PATHCAP: i64 = 512 |
| 42 | const IV_SMALL: i64 = 64 |
| 43 | const IV_FETCH_MS: i64 = 45000 |
| 44 | const IV_SCAN_MS: i64 = 30000 |
| 45 | const IV_SESS_TTL: i64 = 900 |
| 46 | const IV_FETCHER: *u8 = "./nx_https_get_cli2.elf" as *u8 |
| 47 | const IV_OWNLIB: *u8 = "./nx_ownlib.elf" as *u8 |
functions
| 49 | func iv_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } called by 1: main |
| 50 | func iv_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o+i] = s[i]; i = i + 1 } return o + i } |
| 51 | func iv_catb(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { d[o+i] = s[i]; i = i + 1 } return o + n } called by 1: iv_resp |
| 52 | func iv_catn(d: *u8, o: i64, v: i64) -> i64 |
| 68 | func iv_lit_at(buf: *u8, n: i64, i: i64, lit: *u8) -> i64 |
| 80 | func iv_esc(d: *u8, o: i64, s: *u8, n: i64, cap: i64) -> i64 |
| 98 | func iv_hexval(c: i64) -> i64 called by 1: iv_urldec |
| 110 | func iv_urldec(src: *u8, sn: i64, i0: i64, dst: *u8, cap: i64) -> i64 |
| 136 | func iv_host_start(url: *u8, n: i64) -> i64 |
| 144 | func iv_url_ok(url: *u8, n: i64, whyout: *i64) -> i64 |
| 186 | func iv_why(w: i64) -> *u8 |
| 196 | func iv_head(d: *u8, o: i64) -> i64 |
| 207 | func iv_foot(d: *u8, o: i64) -> i64 |
| 211 | func iv_resp(out: *u8, status: *u8, body: *u8, blen: i64) -> i64 |
| 222 | func iv_401(out: *u8) -> i64 |
| 229 | func iv_check_url(url: *u8, un: i64, seq: i64, page: *u8, scan: *u8, body: *u8, out: *u8) -> i64 |
| 288 | func iv_handle(ctx: *NxAuthContext, req: *u8, req_n: i64, seq: i64, page: *u8, scan: *u8, body: *u8, out: *u8) -> i64 |
| 320 | func iv_atoi(s: *u8) -> i64 |
| 330 | func main(argc: i64, argv: *i64) -> i64 |