code wiki / _hdl_build / nx_sites_daemon_v2.nx
nx_sites_daemon_v2.nx source
↩ module page · 1886 lines · 120427 B
1// nx_sites_daemon_v2.nx -- sovereign multi-vhost HTTPS daemon, generation 2.
2//
3// Operator 2026-06-09: "nishi video from the hardware layer up ... hosted
4// again on nishifamily.com/video ... improve anything on the website hosting
5// path to S-class exceed" + "less lag for ukrainians/belarusians" + "record
6// circles like telegram, private/romantic ones auto-archived for review."
7//
8// What changed vs runtime/bin/nx_sites_daemon.nx (v1) and WHY (each is a
9// measured v1 defect, see gates):
10// D1 CHUNKED TLS SEND -- v1's app_send built ONE record for the whole
11// payload; RFC 8446 5.1 caps record plaintext at 16384, so v1 could
12// not serve ANY asset over ~16.3KB (the /video page is 19KB).
13// v2 sends everything through nx_tls13_app_send_fd (gated).
14// D2 RECORD-FRAMED RECEIVE -- v1 assumed one sys_read = one TLS record;
15// v2 reads with nx_tls13_read_record_from_fd and reassembles the
16// request across records until CRLFCRLF (bounded).
17// D3 HOT HOSTING WITH FALLTHROUGH -- v1's hr_serve 404'd on a missing
18// file, so nishifamily.com could not live in sites.conf without
19// killing /wiki. v2 uses hr_serve2: file hit = hot serve (keep-alive,
20// bounds-checked); MISS = fall through to the legacy baked routing.
21// andelinwest keeps REAL 404s (no placeholder bleed).
22// D4 WSS -- /signal/* upgrade requests become a TLS-terminating pump to
23// the loopback N-party signaling daemon (nx_signaling_v2 on
24// 127.0.0.1:8445). wss://nishifamily.com/signal/<room> on :8443 --
25// no new public port, secure-origin so getUserMedia works (the root
26// cause the old :8282 HTTP video room died).
27// D5 CIRCLES -- POST /video/circle?room=R&from=F&priv=0|1 streams the
28// browser-recorded webm body (record by record) to the circles store;
29// priv=1 -> circles/private (auto-archive for later review),
30// else circles/public. GET /video/circles?room=R lists a room's
31// public circles as JSON; GET /video/circle/<name> plays one back
32// (8MB serve buffer). Storage is OUTSIDE the doc root.
33//
34// Composes (all KAT'd/gated): nx_tls13_* session + record stack,
35// nx_tls13_app_send_fd (gate: 10/10), nx_host_router v2 (gate: 14/14),
36// nx_poll, nx_sites_telemetry, wiki engine handles.
37// license_tier: ORIGINAL
38
39import "nx_syscalls.nx"
40import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
41import "nx_csprng.nx"
42import "nx_http_server.nx"
43import "nx_tls13_server_session.nx"
44import "nx_tls13_server_session_run.nx"
45import "nx_tls13_server_session_app_data.nx"
46import "nx_tls13_read_record_from_fd.nx"
47import "nx_sites_telemetry.nx"
48import "nx_poll.nx"
49import "wiki/nx_wiki_status.nx"
50import "wiki/nx_wiki_article.nx"
51import "wiki/nx_wiki_queue.nx"
52import "_hdl_build/nx_host_router.nx"
53import "_hdl_build/nx_proxy_route.nx"
54import "_hdl_build/nx_adnet_slot.nx"
55import "_hdl_build/nx_adnet_view.nx"
56import "_hdl_build/nx_adnet_dash.nx"
57import "_hdl_build/nx_adnet_submit.nx"
58import "_hdl_build/nx_tls13_app_send_fd.nx"
59import "_hdl_build/nx_nv1.nx"
60// Route B (SNI-aware TLS, ported from the gated runtime/bin/nx_sites_daemon.nx): peek the
61// cleartext ClientHello SNI, present the matching per-domain wildcard chain. Composes the
62// gated scs_pick_from_clienthello (nx_sites_sni_cert_gate 12/12 unit + 4/4 e2e).
63import "nx_sni_cert_select.nx"
64const NX_MAGIC_8192: i64 = 8192
65const NX_MAGIC_8445: i64 = 8445
66const NX_MAGIC_16000: i64 = 16000
67const NX_MAGIC_65536: i64 = 65536
68const NX_MAGIC_16384: i64 = 16384
69const NX_MAGIC_60000: i64 = 60000
70const NX_MAGIC_51850: i64 = 51850
71const NX_MAGIC_4096: i64 = 4096
72const NX_MAGIC_1048576: i64 = 1048576
73const NX_MAGIC_262144: i64 = 262144
74const NX_MAGIC_131072: i64 = 131072
75const NX_MAGIC_9091: i64 = 9091
76const NX_MAGIC_18190: i64 = 18190
77const NX_MAGIC_18791: i64 = 18791
78const NX_MAGIC_18792: i64 = 18792
79const NX_MAGIC_18794: i64 = 18794
80const NX_MAGIC_18793: i64 = 18793
81const NX_MAGIC_18099: i64 = 18099
82const NX_MAGIC_8791: i64 = 8791
83
84const NX_SD2_PORT: i64 = 8443
85const NX_SD2_BUDGET: i64 = 100000000
86const NX_SD2_MAX_CHILDREN: i64 = 64
87const NX_SD2_CERT_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_fullchain.der" as *u8
88const NX_SD2_PRIV_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_ecdsa_key.bin" as *u8
89// Route B: per-domain wildcard chains (leaf-first concat-DER + 32-byte P-256 scalar), the SAME
90// files nx_cert_autorenew writes on every renewal (le_<label>_*) -- loading them here RECONNECTS
91// the renewal outputs to the live edge. PAIRED fail-safe: if EITHER file of a pair is absent or
92// malformed, that domain serves the legacy generic pair (never a mismatched cert/key).
93const NX_SD2_CERT_NISHI: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_nishifamily_fullchain.der" as *u8
94const NX_SD2_PRIV_NISHI: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_nishifamily_ecdsa_key.bin" as *u8
95const NX_SD2_CERT_ANDELIN: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_andelinwest_fullchain.der" as *u8
96const NX_SD2_PRIV_ANDELIN: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_andelinwest_ecdsa_key.bin" as *u8
97// MSG_PEEK (recvfrom flag 0x2): read the cleartext ClientHello WITHOUT consuming it, so the
98// proven handshake re-reads the same bytes -> the SNI peek is invisible to nx_tls13_server_session_run.
99const NX_SD2_MSG_PEEK: i64 = 2
100const NX_SD2_SNI_PEEK_CAP: i64 = 8192
101const NX_SD2_SITES_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/sites.conf" as *u8
102// data-driven PROXY route table (nx_proxy_route): app routes are config rows, no recompile.
103const NX_SD2_PROXY_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/proxy_routes.conf" as *u8
104// data-driven ADNET inventory (universal ad slot; nx_adnet_slot): rows id/advertiser/img/click/
105// section/weight + @host directives. ABSENT FILE = ads OFF everywhere (kill-switch by construction);
106// a vhost without an @host row NEVER gets a slot (fail-closed). Counters are per-AD only (no visitor
107// id/cookie/IP -- the nx_ad privacy law). Rotation is TIME-based: no per-user frequency state.
108// (docroot-resident so it lands via the EXISTING /api/upload -> /api/promote_content content lane --
109// zero mgmt-allowlist changes; public-readable is fine: it is the same data every served ad exposes)
110const NX_SD2_ADNET_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/synth/adnet_inventory.txt" as *u8
111const NX_SD2_ADNET_IMPLOG: *u8 = "/volume1/homes/elderwesto/nishihost/adnet_impressions.log" as *u8
112const NX_SD2_ADNET_CLKLOG: *u8 = "/volume1/homes/elderwesto/nishihost/adnet_clicks.log" as *u8
113// served-slot rotation window (us). NAMED code-default tier; store migration = follow-on.
114const NX_SD2_ADNET_ROT_US: i64 = 60000000
115const NX_SD2_TELEMETRY_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/sites_telemetry.log" as *u8
116const NX_SD2_CIRCLES_DIR: *u8 = "/volume1/homes/elderwesto/nishihost/circles" as *u8
117const NX_SD2_MAX_REQ_PER_CONN: i64 = 64
118// KEEP-ALIVE IDLE BUDGET -- deliberately SEPARATE from the 10s handshake/first-request timeout.
119// THE BUG THIS FIXES (2026-07-31): the child set ONE 10s SO_RCVTIMEO before the handshake and then
120// reused it as the keep-alive idle budget. Every response advertises `Connection: keep-alive` with no
121// timeout hint, so a browser parks the socket for minutes -- but the server dropped it after 10s of
122// silence and tore it down with a bare close. Read any page for >10s, click a link, and the browser
123// writes the request into a connection the server already abandoned, then eats a timeout before
124// retrying on a fresh one. Opening in a NEW TAB was instant because that took a fresh connection.
125// 65s matches the nginx default idle window and is advertised to the client in hr_emit_b, so the
126// client retires the socket BEFORE the server does -- which is what actually closes the race.
127const NX_SD2_KA_IDLE_S: i64 = 65
128// VIEWABLE-impression journal, deliberately SEPARATE from the served-impression journal. Both are kept:
129// served/viewable is the honest delivery ratio for an advertiser, and collapsing them would destroy it.
130const NX_SD2_ADNET_VIEWLOG: *u8 = "/volume1/homes/elderwesto/nishihost/knowledge/status/adnet_viewable.log" as *u8
131// One TLS record (max 16384 payload + header/tag slack) for reads + sends.
132const NX_SD2_RECCAP: i64 = 20480
133// Request plaintext reassembly cap (headers + POST bodies). 2MiB (was 64KB): the PROXIED-route body fill
134// (sd2_fill_body) buffers a full upload chunk here before forwarding, so API clients can send ~1MB chunks
135// instead of 8KB (80MB tree sync: ~10k requests -> ~80). mmap = virtual; only touched pages cost RAM.
136// Mirrors the mgmt daemon's MA_UPLOAD_REQCAP=2MiB so edge and backend agree on the per-request ceiling.
137const NX_SD2_PLAINCAP: i64 = 2097152
138// Out-record scratch for the chunked sender (one wire record).
139const NX_SD2_OUTREC: i64 = 17408
140// Dynamic/file serve buffer: 8MB so a 60s circle webm can be played back.
141const NX_SD2_DYN_CAP: i64 = 8388608 // assembled-response buffer (dynamic pages). Oversize STATICS no longer bound by this: they take the HR_S2_STREAM zero-ceiling path (debt 1785879638 root fix; the interim 32MiB bump is REVERTED -- no magic ceilings)
142const NX_SD2_HDR_RESERVE: i64 = 1024 // baked-page buffer header reserve: must exceed sd2_build_resp's header size (status+ctype+len+SOTA security-header set)
143// SOTA response security headers (OWASP secure-headers set), shared by every sd2-emitted page. Held as a
144// named const so the HSTS max-age is config, not an inline magic (rule 11). Mirrors the hr_emit_b file-serve path.
145const NX_SD2_SEC_HDRS: *u8 = "\r\nX-Content-Type-Options: nosniff\r\nX-Frame-Options: SAMEORIGIN\r\nReferrer-Policy: strict-origin-when-cross-origin\r\nStrict-Transport-Security: max-age=63072000; includeSubDomains\r\nContent-Security-Policy: default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self'; media-src 'self'; frame-ancestors 'self'; base-uri 'none'; object-src 'none'"
146const NX_SD2_STREAM_CHUNK: i64 = 262144 // 256KB read/encrypt window for the streaming reverse-proxy (media)
147// Circle upload hard cap (policy; keep in sync with client MAX_CIRCLE_SECS).
148const NX_SD2_CIRCLE_MAX: i64 = 33554432
149// seq332 edge-DoS guard: a proxied body larger than the reassembly cap CANNOT be buffered whole, so the old
150// path truncated it + forwarded a partial body -> the backend blocked on bytes that never came, each child
151// pinned ~10MB for its 30s upstream timeout, and repeated oversize POSTs saturated MAX_CHILDREN -> OOM crash
152// loop (sig=9 reaps). Reject beyond-capacity bodies fast with 413 + close. Bodies <= PLAINCAP are unchanged;
153// bodies > PLAINCAP were already broken (truncated), so no legitimate upload regresses.
154const RESP2_413: *u8 = "HTTP/1.1 413 Payload Too Large\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
155// WS pump idle cap (ms): no traffic either direction for this long -> close.
156const NX_SD2_WS_IDLE_MS: i64 = 180000
157const NX_SD2_STATUS_CAP: i64 = 65536
158const NX_SD2_ART_CAP: i64 = 65536
159const RESP2_FAVICON: *u8 = "HTTP/1.1 204 No Content\r\nConnection: keep-alive\r\n\r\n" as *u8
160// Bare /video (no trailing slash) -> /video/ so hr_resolve serves index.html.
161const RESP2_VIDEO_301: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /video/index.html\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8
162// top-level /advertising -> 301 to the OPAQUE-gated census page (operator-only; never a public byte -- the
163// target lives behind the wiki OPAQUE wall). Added 2026-06-20.
164const RESP2_ADV_301: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /wiki/advertising.html\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8
165// FAIL-CLOSED bounce for gated branches (/wiki, /hub) when their OPAQUE gateway is unreachable: redirect to the
166// login page rather than EVER falling through to the unguarded :51850 wiki engine or static wiki files. Operator
167// law: a gated area must never leak content without the OPAQUE gate, even when the backend is momentarily down.
168const RESP2_GATE_LOGIN: *u8 = "HTTP/1.1 302 Found\r\nLocation: /login\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8
169// bare /status and /status/ -> the live status dashboard (the supervisor emits status.html every poll).
170const RESP2_STATUS_301: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /status.html\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8
171
172const BODY2_ANDELIN: *u8 = "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Andelin West Law - Coming Soon</title><style>body{font-family:Georgia,serif;max-width:680px;margin:8vh auto;padding:0 24px;color:#1a1a2e;line-height:1.6}h1{font-size:2rem}.tag{color:#555}.note{margin-top:2rem;padding:16px 20px;background:#f4f4f8;border-left:4px solid #2a4d8f;font-size:.95rem}.foot{margin-top:3rem;font-size:.8rem;color:#888}</style></head><body><h1>Andelin West Law</h1><p class=\"tag\">A modern legal practice. Site launching soon.</p><div class=\"note\"><strong>Placeholder page.</strong> Served by the sovereign Nishi substrate. The full site is pending attorney review of state-bar advertising rules, ADA accessibility conformance, and the privacy notice before any client-facing or intake content goes live.</div><p class=\"foot\">Served bits-up by the Nishi stack — TLS 1.3, no third-party web server.</p></body></html>\n" as *u8
173
174const BODY2_WIKI: *u8 = "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Nishi Ecosystem Wiki</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:760px;margin:6vh auto;padding:0 24px;color:#161622;line-height:1.65}h1{font-size:2.1rem}h2{font-size:1.1rem;margin-top:2rem;color:#2a4d8f}ul{padding-left:1.2rem}li{margin:.35rem 0}.note{padding:14px 18px;background:#eef2fb;border-left:4px solid #2a4d8f;border-radius:4px;font-size:.95rem}code{background:#f0f0f4;padding:1px 5px;border-radius:3px;font-size:.9em}.foot{margin-top:3rem;font-size:.8rem;color:#888}</style></head><body><h1>Nishi Ecosystem Wiki</h1><p class=\"note\"><strong>Launch placeholder — the live wiki engine is coming online.</strong> What you are reading is itself served bits-up by the substrate below: no nginx, no OpenSSL, no libc.</p><p style=\"margin:1.2rem 0\"><a href=\"/wiki/status\"><strong>▸ Live stack scorecard →</strong></a> <a href=\"/wiki/components\"><strong>▸ Component articles (Gitea×Wikipedia) →</strong></a></p><h2>Shipped substrate</h2><ul><li>Self-hosting NishiLang compiler (RV64 + x86_64), bits-up from C bootstrap</li><li>TLS 1.3 server — serving this page now</li><li>SHA-256/512, ChaCha20-Poly1305, AES-GCM, HKDF, Argon2id — all KAT-verified</li><li>Sovereign secrets vault (HashiCorp-class, ChaCha20-Poly1305 at rest)</li><li>Multi-vhost HTTPS daemon + N-party video signaling (wss) + circles store</li></ul><h2>In progress</h2><ul><li>Full wiki engine (search index, doc store, markdown render)</li><li>Modern auth (OPAQUE PAKE + BIP39 recovery, no cookies)</li><li>Multi-agent concurrent editing (CRDT, sovereign)</li></ul><p class=\"foot\">nishifamily.com/wiki — bits-up sovereign hosting on the west NAS.</p></body></html>\n" as *u8
175
176// Return-aware bootstrap for a TOP-LEVEL /wiki navigation with NO session header (no-cookie model: a nav
177// never carries X-Nishi-Session). If a token is in sessionStorage -> fetch the same path WITH the header
178// (-> proxied to the wiki gateway -> renders content in place); else -> /login?return=<path> so the fixed
179// login() lands the member back EXACTLY where they were. Replaces the wiki gateway's stale board()->hub login.
180const BODY2_WIKI_BOOTSTRAP: *u8 = "<!doctype html><html><head><meta charset=utf-8><meta name=viewport content='width=device-width,initial-scale=1'><title>Nishi</title></head><body><script>var t=sessionStorage.getItem('nsess');function go(){location='/login?return='+encodeURIComponent(location.pathname+location.search)}function R(h){document.open();document.write(h);document.close()}function F(p,nx){fetch(p,{headers:{'X-Nishi-Session':t}}).then(function(r){return r.ok?r.text():null}).then(function(h){if(h){R(h)}else{nx()}}).catch(go)}if(t){var p=location.pathname,s=location.search;F(p+s,function(){F(p+'.html'+s,go)})}else{go()}</script></body></html>" as *u8
181
182const BODY2_FAMILY: *u8 = "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Nishi Family</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:680px;margin:8vh auto;padding:0 24px;color:#161622;line-height:1.65;text-align:center}h1{font-size:2.3rem}.tag{color:#555;font-size:1.05rem}a{color:#2a4d8f}.links a{display:inline-block;margin:8px 14px;font-size:1.1rem}.foot{margin-top:3rem;font-size:.8rem;color:#888}</style></head><body><h1>Nishi Family</h1><p class=\"tag\">The family hub — home of the Nishi sovereign ecosystem.</p><p class=\"links\"><a href=\"/video\">🎥 Family Video →</a> <a href=\"/wiki\">Wiki →</a></p><p class=\"foot\">Served bits-up by the Nishi stack — TLS 1.3, no third-party web server.</p></body></html>\n" as *u8
183
184func sd2_strlen(s: *u8) -> i64 {
185 var n: i64 = 0
186 while s[n] != 0 { n = n + 1 }
187 return n
188}
189
190// Load a concat-DER fullchain; 0 if absent or implausibly short (mirrors the gated sd_load_chain).
191func sd2_load_chain(path: *u8, len_box: *i64) -> *u8 {
192 len_box[0] = 0
193 let p: *u8 = sys_read_file(path, len_box)
194 if (p as i64) == 0 { return 0 as *u8 }
195 if len_box[0] < 100 { return 0 as *u8 }
196 return p
197}
198
199// Load a 32-byte P-256 ECDSA private scalar; 0 if absent / wrong size (mirrors sd_load_key).
200func sd2_load_key(path: *u8) -> *u8 {
201 let lb: *i64 = (sys_mmap(8)) as *i64
202 lb[0] = 0
203 let p: *u8 = sys_read_file(path, lb)
204 if (p as i64) == 0 { return 0 as *u8 }
205 if lb[0] != 32 { return 0 as *u8 }
206 return p
207}
208
209// ---- DATA-DRIVEN SNI cert table (R1b 2026-07-15) -------------------------------------------------
210// Every HTTPS domain = one manifest row (suffix + fullchain-der + ecdsa-key). Add a domain = drop its
211// le_<domain>_* + a manifest line; NEVER an edge recompile. Row 0 = the DEFAULT cert.
212const NX_SD2_CERT_MANIFEST: *u8 = "/volume1/homes/elderwesto/nishihost/certs/sni_certs.manifest" as *u8
213const NX_SD2_CERT_MAX: i64 = 32
214
215// Copy one whitespace-delimited field from buf[pos..end) into out (NUL-terminated). Skips leading
216// spaces/tabs. Returns the position past the field, or -1 if the line has no field (blank/'#'/EOL).
217func sd2_field(buf: *u8, pos: i64, end: i64, out: *u8, out_cap: i64) -> i64 {
218 var p: i64 = pos
219 var skip: i64 = 1
220 while skip == 1 {
221 if p >= end { skip = 0 }
222 else {
223 let c: i64 = buf[p] as i64
224 if c == 32 { p = p + 1 }
225 else { if c == 9 { p = p + 1 } else { skip = 0 } }
226 }
227 }
228 if p >= end { return 0 - 1 }
229 let c0: i64 = buf[p] as i64
230 if c0 == 10 { return 0 - 1 }
231 if c0 == 13 { return 0 - 1 }
232 if c0 == 35 { return 0 - 1 }
233 var o: i64 = 0
234 var cp: i64 = 1
235 while cp == 1 {
236 if p >= end { cp = 0 }
237 else {
238 let c: i64 = buf[p] as i64
239 if c == 32 { cp = 0 }
240 else { if c == 9 { cp = 0 }
241 else { if c == 10 { cp = 0 }
242 else { if c == 13 { cp = 0 }
243 else {
244 if o < out_cap - 1 { out[o] = buf[p] as u8; o = o + 1 }
245 p = p + 1
246 } } } }
247 }
248 }
249 out[o] = 0 as u8
250 return p
251}
252
253// Advance past the current line (to the byte after the next '\n', or to end).
254func sd2_next_line(buf: *u8, pos: i64, end: i64) -> i64 {
255 var p: i64 = pos
256 var go: i64 = 1
257 while go == 1 {
258 if p >= end { go = 0 }
259 else { if (buf[p] as i64) == 10 { p = p + 1; go = 0 } else { p = p + 1 } }
260 }
261 return p
262}
263
264// Parse the manifest into parallel arrays; load each row's cert+key. Rows whose cert/key fail to load
265// are skipped (fail-safe). Returns rows loaded (0 => caller uses the legacy fallback).
266func sd2_load_cert_table(man: *u8, man_n: i64,
267 suf_ptrs: *i64, suf_lens: *i64,
268 cert_ptrs: *i64, cert_lens: *i64, key_ptrs: *i64,
269 max: i64) -> i64 {
270 var count: i64 = 0
271 var pos: i64 = 0
272 while pos < man_n {
273 if count >= max { pos = man_n }
274 else {
275 let sufb: *u8 = sys_mmap(256)
276 let p1: i64 = sd2_field(man, pos, man_n, sufb, 256)
277 if p1 < 0 { pos = sd2_next_line(man, pos, man_n) }
278 else {
279 let certp: *u8 = sys_mmap(512)
280 let p2: i64 = sd2_field(man, p1, man_n, certp, 512)
281 if p2 < 0 { pos = sd2_next_line(man, pos, man_n) }
282 else {
283 let keyp: *u8 = sys_mmap(512)
284 let p3: i64 = sd2_field(man, p2, man_n, keyp, 512)
285 if p3 < 0 { pos = sd2_next_line(man, pos, man_n) }
286 else {
287 let clb: *i64 = (sys_mmap(8)) as *i64
288 clb[0] = 0
289 let cbuf: *u8 = sd2_load_chain(certp, clb)
290 let kbuf: *u8 = sd2_load_key(keyp)
291 if (cbuf as i64) == 0 { pos = sd2_next_line(man, pos, man_n) }
292 else { if (kbuf as i64) == 0 { pos = sd2_next_line(man, pos, man_n) }
293 else {
294 var sl: i64 = 0
295 while sufb[sl] != (0 as u8) { sl = sl + 1 }
296 suf_ptrs[count] = sufb as i64
297 suf_lens[count] = sl
298 cert_ptrs[count] = cbuf as i64
299 cert_lens[count] = clb[0]
300 key_ptrs[count] = kbuf as i64
301 count = count + 1
302 pos = sd2_next_line(man, pos, man_n)
303 } }
304 }
305 }
306 }
307 }
308 }
309 return count
310}
311
312// (mtime,size) signature for HOT-RELOAD change detection. out2[0]=st_mtime out2[1]=st_size
313// (x86_64 struct stat: mtime byte 88 = i64[11], size byte 48 = i64[6] -- same convention as
314// nx_torrent_up/nx_torrent_daemon). Returns 0 ok / -1 stat-fail. Comparing BOTH catches a
315// same-second rewrite (mtime granularity) via the size delta.
316func sd2_statsig(path: *u8, statb: *u8, out2: *i64) -> i64 {
317 if sys_fstatat(path, statb) != 0 { out2[0] = 0 - 1; out2[1] = 0 - 1; return 0 - 1 }
318 let sb: *i64 = statb as *i64
319 out2[0] = sb[11]
320 out2[1] = sb[6]
321 return 0
322}
323
324func sd2_contains(hay: *u8, hlen: i64, needle: *u8, nlen: i64) -> i64 {
325 if nlen <= 0 { return 0 }
326 if hlen < nlen { return 0 }
327 var i: i64 = 0
328 let last: i64 = hlen - nlen
329 while i <= last {
330 var j: i64 = 0
331 var ok: i64 = 1
332 while j < nlen {
333 if hay[i + j] != needle[j] { ok = 0; j = nlen } else { j = j + 1 }
334 }
335 if ok == 1 { return 1 }
336 i = i + 1
337 }
338 return 0
339}
340
341func sd2_lower(c: u8) -> u8 {
342 if c >= (65 as u8) { if c <= (90 as u8) { return (c + (32 as u8)) } }
343 return c
344}
345
346// case-insensitive contains (Upgrade/upgrade, WebSocket/websocket...)
347func sd2_contains_ci(hay: *u8, hlen: i64, needle: *u8, nlen: i64) -> i64 {
348 if nlen <= 0 { return 0 }
349 if hlen < nlen { return 0 }
350 var i: i64 = 0
351 let last: i64 = hlen - nlen
352 while i <= last {
353 var j: i64 = 0
354 var ok: i64 = 1
355 while j < nlen {
356 if sd2_lower(hay[i + j]) != sd2_lower(needle[j]) { ok = 0; j = nlen } else { j = j + 1 }
357 }
358 if ok == 1 { return 1 }
359 i = i + 1
360 }
361 return 0
362}
363
364func sd2_body_start(hay: *u8, hlen: i64) -> i64 {
365 if hlen < 4 { return hlen }
366 var i: i64 = 0
367 let last: i64 = hlen - 4
368 while i <= last {
369 if hay[i] == (0x0D as u8) { if hay[i + 1] == (0x0A as u8) { if hay[i + 2] == (0x0D as u8) { if hay[i + 3] == (0x0A as u8) {
370 return i + 4
371 } } } }
372 i = i + 1
373 }
374 return hlen
375}
376
377func sd2_u64_to_dec(n: i64, buf: *u8) -> i64 {
378 if n == 0 { buf[0] = 48; return 1 }
379 var d: i64 = 0
380 var x: i64 = n
381 while x > 0 { d = d + 1; x = x / 10 }
382 var i: i64 = d - 1
383 x = n
384 while i >= 0 {
385 buf[i] = (48 + (x % 10)) as u8
386 x = x / 10
387 i = i - 1
388 }
389 return d
390}
391
392func sd2_append(dst: *u8, off: i64, src: *u8, n: i64) -> i64 {
393 var i: i64 = 0
394 while i < n { dst[off + i] = src[i]; i = i + 1 }
395 return off + n
396}
397
398func sd2_append_str(dst: *u8, off: i64, s: *u8) -> i64 {
399 return sd2_append(dst, off, s, sd2_strlen(s))
400}
401
402// Full HTTP/1.1 keep-alive response into out (baked pages, built at startup).
403func sd2_build_resp(out: *u8, ctype: *u8, body: *u8, body_len: i64) -> i64 {
404 var w: i64 = 0
405 w = sd2_append_str(out, w, "HTTP/1.1 200 OK\r\nContent-Type: " as *u8)
406 w = sd2_append_str(out, w, ctype)
407 w = sd2_append_str(out, w, "\r\nContent-Length: " as *u8)
408 let dbuf: *u8 = sys_mmap(24)
409 let dn: i64 = sd2_u64_to_dec(body_len, dbuf)
410 w = sd2_append(out, w, dbuf, dn)
411 w = sd2_append_str(out, w, "\r\nConnection: keep-alive" as *u8)
412 w = sd2_append_str(out, w, NX_SD2_SEC_HDRS)
413 w = sd2_append_str(out, w, "\r\nX-Served-By: nishi-substrate-v2\r\n\r\n" as *u8)
414 w = sd2_append(out, w, body, body_len)
415 return w
416}
417
418// Parse "Content-Length:" value from the request headers; -1 if absent.
419func sd2_content_length(req: *u8, reqn: i64) -> i64 {
420 let key: *u8 = "content-length:" as *u8
421 var i: i64 = 0
422 while i + 15 <= reqn {
423 var j: i64 = 0
424 var ok: i64 = 1
425 while j < 15 {
426 if sd2_lower(req[i + j]) != key[j] { ok = 0; j = 15 } else { j = j + 1 }
427 }
428 if ok == 1 {
429 var k: i64 = i + 15
430 while k < reqn { if req[k] == (32 as u8) { k = k + 1 } else { break } }
431 var v: i64 = 0
432 var got: i64 = 0
433 // flag-style digit loop (NO continue-in-nested-if -- that
434 // construct miscompiles under the 2026-06-09 compiler, child hangs)
435 var run: i64 = 1
436 while run == 1 {
437 if k >= reqn { run = 0 }
438 else {
439 let c: i64 = req[k] as i64
440 var dig: i64 = 0
441 if c >= 48 { if c <= 57 { dig = 1 } }
442 if dig == 1 { v = v * 10 + (c - 48); got = 1; k = k + 1 }
443 else { run = 0 }
444 }
445 }
446 if got == 1 { return v }
447 return 0 - 1
448 }
449 i = i + 1
450 }
451 return 0 - 1
452}
453
454// Extract a query parameter value (sanitized to [a-z0-9-], lowercased,
455// max 32 bytes) from the request line. key like "room=". Returns length.
456// Written in strict flag style throughout -- break/continue inside nested
457// ifs miscompile under the 2026-06-09 compiler (child hangs; see the
458// wsupgrade-miscompile repro note).
459func sd2_query_param(req: *u8, reqn: i64, key: *u8, keyn: i64, out: *u8) -> i64 {
460 // only scan the first line (request line)
461 var lim: i64 = 0
462 var scanning: i64 = 1
463 while scanning == 1 {
464 if lim >= reqn { scanning = 0 }
465 else {
466 if req[lim] == (13 as u8) { scanning = 0 }
467 else { lim = lim + 1 }
468 }
469 }
470 // find "key" in the request line
471 var found: i64 = 0 - 1
472 var i: i64 = 0
473 while i + keyn <= lim {
474 if found < 0 {
475 var j: i64 = 0
476 var ok: i64 = 1
477 while j < keyn {
478 if req[i + j] != key[j] { ok = 0; j = keyn } else { j = j + 1 }
479 }
480 if ok == 1 { found = i + keyn }
481 }
482 i = i + 1
483 }
484 if found < 0 { return 0 }
485 // copy sanitized value
486 var k: i64 = found
487 var w: i64 = 0
488 var run: i64 = 1
489 while run == 1 {
490 if k >= lim { run = 0 }
491 else {
492 if w >= 32 { run = 0 }
493 else {
494 let c: u8 = sd2_lower(req[k])
495 var keepc: i64 = 0
496 if c >= (97 as u8) { if c <= (122 as u8) { keepc = 1 } }
497 if c >= (48 as u8) { if c <= (57 as u8) { keepc = 1 } }
498 if c == (45 as u8) { keepc = 1 }
499 if keepc == 0 { run = 0 }
500 else { out[w] = c; w = w + 1; k = k + 1 }
501 }
502 }
503 }
504 return w
505}
506
507// Receive one HTTP request: read TLS records and reassemble plaintext until the headers (CRLFCRLF) AND, for a
508// POST/PUT carrying a Content-Length, the FULL body. v1 returned at CRLFCRLF and NEVER read the body -- so a
509// client that put the POST body in a separate TLS record (HttpWebRequest, and some mobile browsers) had its
510// body DROPPED: the OPAQUE login daemon then saw an empty handle+pw -> 400/401, making login impossible for
511// EVERY gated service (gallery/wiki/hub/torrent). GETs (no body) still return at the headers. SMALL bodies
512// (login/register/forms) are completed here; LARGE bodies (uploads) are left for their streaming handler so
513// we never force-buffer a multi-MB upload. Returns plaintext length, <=0 on error/EOF.
514func sd2_recv_request(s: *Tls13ServerSession, cfd: i64, rec_buf: *u8, plain: *u8, plain_cap: i64) -> i64 {
515 var total: i64 = 0
516 var recs: i64 = 0
517 var need: i64 = 0 // 0 until headers seen; then = body_start + Content-Length (the full-request byte target)
518 while recs < 8 {
519 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP)
520 if rn <= 0 { if total > 0 { return total } return 0 - 1 }
521 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, (plain as i64 + total) as *u8, plain_cap - total)
522 if pn <= 0 { if total > 0 { return total } return 0 - 1 }
523 total = total + pn
524 if need == 0 {
525 // headers complete yet? (CRLFCRLF present)
526 if sd2_contains(plain, total, "\r\n\r\n" as *u8, 4) == 1 {
527 let bs: i64 = sd2_body_start(plain, total)
528 let cl: i64 = sd2_content_length(plain, total)
529 if cl <= 0 { return total } // GET / no body -> done at the headers
530 if cl > NX_MAGIC_8192 { return total } // large body (upload) -> its streaming handler reads the rest
531 need = bs + cl // small body -> keep reading until the whole body arrives
532 if total >= need { return total } // ... already fully present in this record
533 }
534 } else {
535 if total >= need { return total } // small body now complete across records
536 }
537 recs = recs + 1
538 }
539 return total
540}
541
542// Complete a PROXIED request's body in `plain` before forwarding: sd2_recv_request stops at the headers for
543// bodies >8KB (streaming handlers read their own body), but the buffered reverse-proxy is NOT such a handler --
544// it forwarded whatever was buffered, TRUNCATING any body spanning >1 TLS record (the hard 8KB upload-chunk cap;
545// backends then waited on bytes that never came). This reads TLS records until body_start+Content-Length, bounded
546// by plain_cap and a record budget. FAIL-SAFE BY CONSTRUCTION: on any error/timeout/oversize it returns what is
547// buffered -- exactly the old forward-partial behavior, so no failure mode is NEW; the backend's own
548// Content-Length handling still applies. Pump pattern mirrors the proven sd2_circle_upload reader.
549func sd2_fill_body(s: *Tls13ServerSession, cfd: i64, rec_buf: *u8, plain: *u8, have: i64, plain_cap: i64) -> i64 {
550 if sd2_contains(plain, have, "\r\n\r\n" as *u8, 4) == 0 { return have } // headers incomplete -> old behavior
551 let cl: i64 = sd2_content_length(plain, have)
552 if cl <= 0 { return have } // GET / no declared body -> nothing to fill
553 let bs: i64 = sd2_body_start(plain, have) // CRLFCRLF proven present, so bs is the true body offset
554 var need: i64 = bs + cl
555 if need > plain_cap { need = plain_cap } // oversize: forward the first plain_cap bytes (backend refuses)
556 var total: i64 = have
557 var recs: i64 = 0
558 while total < need {
559 if recs >= 512 { return total } // budget backstop (2MiB / ~4KB-min records)
560 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP)
561 if rn <= 0 { return total }
562 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, (plain as i64 + total) as *u8, plain_cap - total)
563 if pn <= 0 { return total }
564 total = total + pn
565 recs = recs + 1
566 }
567 return total
568}
569
570// ---- D4: TLS-terminating WebSocket pump to loopback nx_signaling_v2 ----
571func sd2_ws_pump(s: *Tls13ServerSession, cfd: i64, first_req: *u8, first_n: i64,
572 rec_buf: *u8, out_rec: *u8, pump: *u8) -> i64 {
573 // connect 127.0.0.1:8445
574 let ufd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
575 if ufd < 0 { return 0 - 1 }
576 let addr: *u8 = sys_mmap(16)
577 addr[0] = 2 as u8; addr[1] = 0 as u8
578 addr[2] = ((NX_MAGIC_8445 >> 8) & 0xff) as u8
579 addr[3] = (NX_MAGIC_8445 & 0xff) as u8
580 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8
581 var zi: i64 = 8
582 while zi < 16 { addr[zi] = 0 as u8; zi = zi + 1 }
583 if nx_connect_bounded(ufd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(ufd); return 0 - 1 }
584
585 // TCP_NODELAY (IPPROTO_TCP=6, TCP_NODELAY=1) on the UPSTREAM pump socket: this hop carries
586 // every live video/audio frame to the relay. Without it, Nagle here x delayed-ACK on the
587 // relay side adds up to ~40ms per frame burst -- MEASURED live by nx_video_qoe_live
588 // 2026-07-03 (an exact ~40ms cycle floor above 25fps that client-side nodelay did NOT fix).
589 // Mirrors the nodelay this daemon already sets on its public accept sockets.
590 let pnd: *u8 = sys_mmap(4)
591 pnd[0] = 1 as u8
592 pnd[1] = 0 as u8
593 pnd[2] = 0 as u8
594 pnd[3] = 0 as u8
595 sys_setsockopt(ufd, 6, 1, pnd, 4)
596
597 // forward the decrypted upgrade request; the signaling daemon answers 101
598 if nx_tls13_sendfd_write_all(ufd, first_req, first_n) < 0 { sys_close(ufd); return 0 - 1 }
599
600 // long-lived call: lift the 10s accept-time read timeout (poll bounds idle)
601 sys_set_socket_timeout(cfd, 600)
602 let pfds: *u8 = sys_mmap(2 * NX_POLLFD_BYTES)
603 var alive: i64 = 1
604 while alive == 1 {
605 nx_pollfd_set(pfds, 0, cfd, NX_POLLIN)
606 nx_pollfd_set(pfds, 1, ufd, NX_POLLIN)
607 let nr: i64 = nx_poll(pfds, 2, NX_SD2_WS_IDLE_MS)
608 if nr <= 0 { alive = 0 } // idle cap or error -> close
609 if alive == 1 {
610 if (nx_pollfd_revents(pfds, 0) & NX_POLLIN) != 0 {
611 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP)
612 if rn <= 0 { alive = 0 }
613 else {
614 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, pump, NX_SD2_RECCAP)
615 if pn <= 0 { alive = 0 }
616 else {
617 if nx_tls13_sendfd_write_all(ufd, pump, pn) < 0 { alive = 0 }
618 }
619 }
620 }
621 }
622 if alive == 1 {
623 if (nx_pollfd_revents(pfds, 1) & NX_POLLIN) != 0 {
624 let un: i64 = sys_read(ufd, pump, NX_MAGIC_16000)
625 if un <= 0 { alive = 0 }
626 else {
627 if nx_tls13_app_send_fd(s, pump, un, cfd, out_rec, NX_SD2_OUTREC) < 0 { alive = 0 }
628 }
629 }
630 }
631 }
632 sys_close(ufd)
633 return 0
634}
635
636// ---- D5: circles ----
637
638// Build "<dir>/<sub>/<room>_<from>_<usec>.<ext>" into out; returns len.
639// ext_nv1=1 -> ".nv1" (NishiLossless v1 circles, see nx_nv1.nx); else ".webm"
640// (legacy MediaRecorder circles -- still served for back-compat playback).
641func sd2_circle_path(out: *u8, priv: i64, room: *u8, room_n: i64,
642 from: *u8, from_n: i64, usec: i64, ext_nv1: i64) -> i64 {
643 var w: i64 = 0
644 w = sd2_append_str(out, w, NX_SD2_CIRCLES_DIR)
645 if priv == 1 { w = sd2_append_str(out, w, "/private/" as *u8) }
646 else { w = sd2_append_str(out, w, "/public/" as *u8) }
647 w = sd2_append(out, w, room, room_n)
648 out[w] = 95; w = w + 1 // '_'
649 w = sd2_append(out, w, from, from_n)
650 out[w] = 95; w = w + 1
651 let dbuf: *u8 = sys_mmap(24)
652 let dn: i64 = sd2_u64_to_dec(usec, dbuf)
653 w = sd2_append(out, w, dbuf, dn)
654 if ext_nv1 == 1 { w = sd2_append_str(out, w, ".nv1" as *u8) }
655 else { w = sd2_append_str(out, w, ".webm" as *u8) }
656 out[w] = 0
657 return w
658}
659
660// bounded append of pn received bytes into the body buffer (clamped at the
661// declared content-length); hoisted to a helper to keep the receive loop's
662// nesting shallow (the nested-if miscompile landmine). Returns new got.
663func sd2_body_copy(body: *u8, got: i64, cl: i64, src: *u8, pn: i64) -> i64 {
664 var wn: i64 = pn
665 if got + wn > cl { wn = cl - got }
666 var pi: i64 = 0
667 while pi < wn { body[got + pi] = src[pi]; pi = pi + 1 }
668 return got + pn
669}
670
671// POST /video/circle?room=R&from=F&priv=0|1 -- stream the webm body to the
672// circles store. Response written into dyn (small JSON). Returns resp len.
673func sd2_circle_upload(s: *Tls13ServerSession, cfd: i64, plain: *u8, plain_n: i64,
674 rec_buf: *u8, pump: *u8, dyn: *u8) -> i64 {
675 let cl: i64 = sd2_content_length(plain, plain_n)
676 var bad: i64 = 0
677 if cl <= 0 { bad = 1 }
678 if cl > NX_SD2_CIRCLE_MAX { bad = 1 }
679 let room: *u8 = sys_mmap(40)
680 let from: *u8 = sys_mmap(40)
681 let pv: *u8 = sys_mmap(40)
682 let room_n: i64 = sd2_query_param(plain, plain_n, "room=" as *u8, 5, room)
683 var from_n: i64 = sd2_query_param(plain, plain_n, "from=" as *u8, 5, from)
684 let pv_n: i64 = sd2_query_param(plain, plain_n, "priv=" as *u8, 5, pv)
685 if room_n == 0 { bad = 1 }
686 if from_n == 0 { from[0] = 120; from_n = 1 } // 'x'
687 var priv: i64 = 0
688 if pv_n == 1 { if pv[0] == (49 as u8) { priv = 1 } }
689 // ext=nv1 -> NishiLossless container suffix (allowlist, not pass-through:
690 // the suffix is the ONLY client-controlled byte sequence in the path)
691 let ex: *u8 = sys_mmap(40)
692 let ex_n: i64 = sd2_query_param(plain, plain_n, "ext=" as *u8, 4, ex)
693 var ext_nv1: i64 = 0
694 if ex_n == 3 {
695 var exm: i64 = 1
696 if ex[0] != (110 as u8) { exm = 0 } // 'n'
697 if ex[1] != (118 as u8) { exm = 0 } // 'v'
698 if ex[2] != (49 as u8) { exm = 0 } // '1'
699 ext_nv1 = exm
700 }
701 if bad == 1 {
702 let b: *u8 = "{\"ok\":0,\"err\":\"bad request\"}" as *u8
703 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 400 Bad Request" as *u8, "application/json" as *u8, b, sd2_strlen(b))
704 }
705
706 // Receive the FULL body into memory first (cl capped at
707 // NX_SD2_CIRCLE_MAX; anonymous mmap is lazy so only received pages
708 // cost RAM), VALIDATE, and only then touch the circles store: a
709 // truncated or corrupt upload never lands as a stored circle (the
710 // old stream-to-file path left truncated files behind on failure).
711 let body: *u8 = sys_mmap(cl + 64)
712 let bs: i64 = sd2_body_start(plain, plain_n)
713 var got: i64 = plain_n - bs
714 if got > 0 { sd2_body_copy(body, 0, cl, (plain as i64 + bs) as *u8, got) }
715 var fail: i64 = 0
716 while got < cl {
717 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP)
718 if rn <= 0 { fail = 1; got = cl }
719 else {
720 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, pump, NX_SD2_RECCAP)
721 if pn <= 0 { fail = 1; got = cl }
722 else {
723 got = sd2_body_copy(body, got, cl, pump, pn)
724 }
725 }
726 }
727 if fail == 1 {
728 sys_write(2, "circle upload TRUNCATED, nothing stored\n" as *u8, 40)
729 let b3: *u8 = "{\"ok\":0,\"err\":\"upload truncated\"}" as *u8
730 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 400 Bad Request" as *u8, "application/json" as *u8, b3, sd2_strlen(b3))
731 }
732
733 // Server-side NV1 validation (the named rung from the NV1 spec):
734 // ext=nv1 uploads must be a well-formed NLC1 container (raw 'A' or
735 // LPC 'L' audio) or they are REJECTED at the door. Legacy .webm
736 // bodies stay opaque (back-compat playback only).
737 if ext_nv1 == 1 {
738 let vinfo: *i64 = sys_mmap(64) as *i64
739 let vrc: i64 = nv1_validate(body, cl, vinfo)
740 if vrc != 0 {
741 sys_write(2, "circle nv1-invalid rc=-" as *u8, 23)
742 let vd: *u8 = sys_mmap(8)
743 vd[0] = (48 - vrc) as u8
744 sys_write(2, vd, 1)
745 sys_write(2, " rejected, nothing stored\n" as *u8, 26)
746 let b5: *u8 = "{\"ok\":0,\"err\":\"nv1 invalid\"}" as *u8
747 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 400 Bad Request" as *u8, "application/json" as *u8, b5, sd2_strlen(b5))
748 }
749 }
750
751 // Store dirs are DEPLOY-OWNED (created once by _deploy_content, 0700 on
752 // private). No per-request sys_mkdir: that helper hardcodes rv64 34
753 // (mkdirat) and under the C-bootstrap compiler there is NO rv64->x86
754 // translation -- syscall 34 on x86_64 is pause(), which blocked the
755 // upload child forever (found live 2026-06-10 via CU breadcrumbs).
756 let path: *u8 = sys_mmap(512)
757 let path_n: i64 = sd2_circle_path(path, priv, room, room_n, from, from_n, sys_now_us(), ext_nv1)
758 let ffd: i64 = sys_openat_wr(path, 0x1a4)
759 if ffd < 0 {
760 let b2: *u8 = "{\"ok\":0,\"err\":\"store open failed\"}" as *u8
761 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 500 Internal Server Error" as *u8, "application/json" as *u8, b2, sd2_strlen(b2))
762 }
763 nx_tls13_sendfd_write_all(ffd, body, cl)
764 sys_close(ffd)
765 // Cardinal 18: one meaningful line per stored circle (path + outcome).
766 sys_write(2, "circle stored " as *u8, 14)
767 sys_write(2, path, path_n)
768 sys_write(2, " ok\n" as *u8, 4)
769 let b4: *u8 = "{\"ok\":1}" as *u8
770 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "application/json" as *u8, b4, sd2_strlen(b4))
771}
772
773// GET /video/circles?room=R[&priv=1] -- JSON list of the room's circles,
774// newest unsorted (client sorts by the embedded usec). priv=1 lists the
775// private archive (review-later view).
776func sd2_circle_list(plain: *u8, plain_n: i64, dyn: *u8) -> i64 {
777 let room: *u8 = sys_mmap(40)
778 let pv: *u8 = sys_mmap(40)
779 let room_n: i64 = sd2_query_param(plain, plain_n, "room=" as *u8, 5, room)
780 let pv_n: i64 = sd2_query_param(plain, plain_n, "priv=" as *u8, 5, pv)
781 var priv: i64 = 0
782 if pv_n == 1 { if pv[0] == (49 as u8) { priv = 1 } }
783 let dirp: *u8 = sys_mmap(256)
784 var dw: i64 = sd2_append_str(dirp, 0, NX_SD2_CIRCLES_DIR)
785 if priv == 1 { dw = sd2_append_str(dirp, dw, "/private" as *u8) }
786 else { dw = sd2_append_str(dirp, dw, "/public" as *u8) }
787 dirp[dw] = 0
788
789 let body: *u8 = sys_mmap(NX_MAGIC_65536)
790 var bw: i64 = 0
791 body[bw] = 91; bw = bw + 1 // '['
792 var first: i64 = 1
793 let dfd: i64 = sys_openat_rd(dirp)
794 if dfd >= 0 {
795 let dbuf: *u8 = sys_mmap(NX_MAGIC_16384)
796 var more: i64 = 1
797 while more == 1 {
798 let nread: i64 = sys_getdents64(dfd, dbuf, NX_MAGIC_16384)
799 if nread <= 0 { more = 0 }
800 else {
801 var off: i64 = 0
802 while off < nread {
803 // linux_dirent64: u64 ino, i64 off, u16 reclen, u8 type, name...
804 let reclen: i64 = ((dbuf[off + 16] as i64) | ((dbuf[off + 17] as i64) << 8))
805 let namep: i64 = off + 19
806 var nl: i64 = 0
807 while dbuf[namep + nl] != 0 { nl = nl + 1 }
808 // match "<room>_" prefix + ".webm" suffix; skip . / ..
809 var want: i64 = 0
810 if room_n > 0 { if nl > room_n {
811 var m: i64 = 1
812 var q: i64 = 0
813 while q < room_n {
814 if dbuf[namep + q] != room[q] { m = 0; q = room_n } else { q = q + 1 }
815 }
816 if m == 1 { if dbuf[namep + room_n] == (95 as u8) { want = 1 } }
817 } }
818 if want == 1 { if bw < NX_MAGIC_60000 {
819 if first == 0 { body[bw] = 44; bw = bw + 1 } // ','
820 body[bw] = 34; bw = bw + 1 // '"'
821 var c2: i64 = 0
822 while c2 < nl { body[bw] = dbuf[namep + c2]; bw = bw + 1; c2 = c2 + 1 }
823 body[bw] = 34; bw = bw + 1
824 first = 0
825 } }
826 if reclen <= 0 { off = nread } else { off = off + reclen }
827 }
828 }
829 }
830 sys_close(dfd)
831 }
832 body[bw] = 93; bw = bw + 1 // ']'
833 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "application/json" as *u8, body, bw)
834}
835
836// GET /video/circle/<name> -- play one circle back. Name is taken from the
837// path, sanitized (no '/', no '..'); public first, then private (the
838// review-later view; honest residual: room-name capability is the only
839// auth until OPAQUE lands -- flagged in the deploy log, not hidden).
840func sd2_circle_play(plain: *u8, plain_n: i64, dyn: *u8) -> i64 {
841 // path starts after "GET /video/circle/"
842 let pfx: *u8 = "GET /video/circle/" as *u8
843 let pfxn: i64 = 18
844 var st: i64 = 0 - 1
845 var i: i64 = 0
846 while i + pfxn <= plain_n {
847 var j: i64 = 0
848 var ok: i64 = 1
849 while j < pfxn {
850 if plain[i + j] != pfx[j] { ok = 0; j = pfxn } else { j = j + 1 }
851 }
852 if ok == 1 { st = i + pfxn; i = plain_n } else { i = i + 1 }
853 }
854 if st < 0 { return hr_emit_404(dyn, NX_SD2_DYN_CAP) }
855 let name: *u8 = sys_mmap(256)
856 var nl: i64 = 0
857 while st < plain_n {
858 let c: u8 = plain[st]
859 if c == (32 as u8) { break }
860 if c == (63 as u8) { break }
861 if c == (13 as u8) { break }
862 if c == (47 as u8) { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } // '/'
863 if c == (46 as u8) { if st + 1 < plain_n { if plain[st + 1] == (46 as u8) { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } } }
864 if nl < 250 { name[nl] = c; nl = nl + 1 }
865 st = st + 1
866 }
867 if nl == 0 { return hr_emit_404(dyn, NX_SD2_DYN_CAP) }
868 name[nl] = 0
869
870 let path: *u8 = sys_mmap(512)
871 var w: i64 = sd2_append_str(path, 0, NX_SD2_CIRCLES_DIR)
872 w = sd2_append_str(path, w, "/public/" as *u8)
873 w = sd2_append(path, w, name, nl)
874 path[w] = 0
875 let lenbox: *i64 = (sys_mmap(8)) as *i64
876 lenbox[0] = 0
877 var data: *u8 = sys_read_file(path, lenbox)
878 if (data as i64) == 0 {
879 w = sd2_append_str(path, 0, NX_SD2_CIRCLES_DIR)
880 w = sd2_append_str(path, w, "/private/" as *u8)
881 w = sd2_append(path, w, name, nl)
882 path[w] = 0
883 lenbox[0] = 0
884 data = sys_read_file(path, lenbox)
885 }
886 if (data as i64) == 0 { return hr_emit_404(dyn, NX_SD2_DYN_CAP) }
887 let body_n: i64 = lenbox[0]
888 let w2: i64 = hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "video/webm" as *u8, data, body_n)
889 if w2 < 0 {
890 let b: *u8 = "<!doctype html><h1>500 - circle exceeds serve buffer</h1>" as *u8
891 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 500 Internal Server Error" as *u8, "text/html; charset=utf-8" as *u8, b, sd2_strlen(b))
892 }
893 return w2
894}
895
896// HTTP reverse-proxy to a loopback backend on 127.0.0.1:<port>. Forwards the already TLS-decrypted
897// request `plain` and reads the backend's full HTTP response into `dyn` (backend MUST close after its
898// response -- both the wiki engine :51850 and the OPAQUE login daemon :9091 send Connection: close +
899// close the fd -> read to EOF). A 15s upstream read timeout guarantees the child can never hang on a
900// stuck backend. Returns response length, or <=0 on failure (caller falls through -- ADDITIVE: a proxy
901// miss never breaks the site). license_tier: ORIGINAL (sovereign reverse proxy -- replaces nginx).
902func sd2_lc(c: i64) -> i64 { if c>=65 { if c<=90 { return c+32 } } return c }
903func sd2_is_conn_line(plain: *u8, p: i64, n: i64) -> i64 {
904 let key: *u8 = "connection:" as *u8
905 var i: i64 = 0
906 while i < 11 { if p+i >= n { return 0 } if sd2_lc(plain[p+i] as i64) != (key[i] as i64) { return 0 } i = i + 1 }
907 return 1
908}
909// Rewrite the upstream request: drop any Connection: header line + insert "Connection: close", keep the body
910// verbatim. ROOT-CAUSE FIX (galxauthprobe proved the gateway answers in 0ms; the hang is here): a keep-alive POST
911// made the backend hold the socket open, so the proxy relay below BLOCKED waiting for a close that never came ->
912// the client timed out (~10s) = "Failed to fetch". Forcing close => the backend closes after replying => clean EOF.
913func sd2_force_close(plain: *u8, n: i64, out: *u8) -> i64 {
914 var he: i64 = 0 - 1
915 var i: i64 = 0
916 while i + 3 < n {
917 if (plain[i] as i64)==13 { if (plain[i+1] as i64)==10 { if (plain[i+2] as i64)==13 { if (plain[i+3] as i64)==10 { he = i + 4 } } } }
918 if he >= 0 { i = n } else { i = i + 1 }
919 }
920 if he < 0 { var k: i64 = 0; while k < n { out[k] = plain[k]; k = k + 1 } return n }
921 var o: i64 = 0
922 var p: i64 = 0
923 let hend: i64 = he - 2
924 while p < hend {
925 var le: i64 = p
926 var found: i64 = 0
927 while found == 0 {
928 if le + 1 >= hend { le = hend; found = 1 }
929 else { if (plain[le] as i64)==13 { if (plain[le+1] as i64)==10 { found = 1 } else { le = le + 1 } } else { le = le + 1 } }
930 }
931 if sd2_is_conn_line(plain, p, n) == 0 {
932 var c: i64 = p
933 var cend: i64 = le + 2
934 if cend > hend { cend = hend }
935 while c < cend { out[o] = plain[c]; o = o + 1; c = c + 1 }
936 }
937 p = le + 2
938 }
939 let cc: *u8 = "Connection: close\r\n\r\n" as *u8
940 var ci: i64 = 0
941 while cc[ci] != (0 as u8) { out[o] = cc[ci]; o = o + 1; ci = ci + 1 }
942 var b: i64 = he
943 while b < n { out[o] = plain[b]; o = o + 1; b = b + 1 }
944 return o
945}
946func sd2_proxy_to(plain: *u8, plain_n: i64, dyn: *u8, port: i64) -> i64 {
947 let ufd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
948 if ufd < 0 { return 0 - 1 }
949 let addr: *u8 = sys_mmap(16)
950 addr[0] = 2 as u8; addr[1] = 0 as u8
951 addr[2] = ((port >> 8) & 0xff) as u8
952 addr[3] = (port & 0xff) as u8
953 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8
954 var zi: i64 = 8
955 while zi < 16 { addr[zi] = 0 as u8; zi = zi + 1 }
956 if nx_connect_bounded(ufd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(ufd); return 0 - 1 }
957 sys_set_socket_timeout(ufd, 15)
958 let fcbuf: *u8 = sys_mmap(NX_SD2_PLAINCAP)
959 let fcn: i64 = sd2_force_close(plain, plain_n, fcbuf)
960 var wo: i64 = 0
961 while wo < fcn { let w: i64 = sys_write(ufd, ((fcbuf as i64) + wo) as *u8, fcn - wo); if w <= 0 { sys_close(ufd); return 0 - 1 } wo = wo + w }
962 var off: i64 = 0
963 var reading: i64 = 1
964 while reading == 1 {
965 if off >= NX_SD2_DYN_CAP { reading = 0 }
966 else {
967 let r: i64 = sys_read(ufd, ((dyn as i64) + off) as *u8, NX_SD2_DYN_CAP - off)
968 if r <= 0 { reading = 0 } else { off = off + r }
969 }
970 }
971 sys_close(ufd)
972 return off
973}
974
975// STREAMING reverse-proxy (S-class media: NO 8MB buffer). Connect 127.0.0.1:port, forward the decrypted
976// request, then read the backend response in 256KB windows and TLS-encrypt each straight to the client --
977// the file is NEVER buffered whole (the way real media servers serve byte-range video: read-chunk ->
978// send-chunk, TCP backpressure paces it; cf. MDN HTTP Range requests / Media Source Extensions). Returns
979// total bytes streamed, or -1 if the backend was unreachable (nothing sent yet -> caller may fall through).
980// license_tier: ORIGINAL (loopback spine from sd2_proxy_to; TLS app-send from sd2_ws_pump).
981func sd2_proxy_stream(s: *Tls13ServerSession, cfd: i64, plain: *u8, plain_n: i64, port: i64, out_rec: *u8) -> i64 {
982 let ufd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
983 if ufd < 0 { return 0 - 1 }
984 let addr: *u8 = sys_mmap(16)
985 addr[0] = 2 as u8; addr[1] = 0 as u8
986 addr[2] = ((port >> 8) & 0xff) as u8
987 addr[3] = (port & 0xff) as u8
988 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8
989 var zi: i64 = 8
990 while zi < 16 { addr[zi] = 0 as u8; zi = zi + 1 }
991 if nx_connect_bounded(ufd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(ufd); return 0 - 1 }
992 sys_set_socket_timeout(ufd, 30)
993 let fcbuf: *u8 = sys_mmap(NX_SD2_PLAINCAP)
994 let fcn: i64 = sd2_force_close(plain, plain_n, fcbuf)
995 var wo: i64 = 0
996 while wo < fcn { let w: i64 = sys_write(ufd, ((fcbuf as i64) + wo) as *u8, fcn - wo); if w <= 0 { sys_close(ufd); return 0 - 1 } wo = wo + w }
997 sys_write(1, "PXY-FWD\n" as *u8, 8)
998 sys_set_socket_timeout(cfd, 600) // long-lived media stream: lift the accept-time client read timeout
999 let chunk: *u8 = sys_mmap(NX_SD2_STREAM_CHUNK)
1000 var total: i64 = 0
1001 var go: i64 = 1
1002 var first: i64 = 1
1003 while go == 1 {
1004 let rn: i64 = sys_read(ufd, chunk, NX_SD2_STREAM_CHUNK)
1005 if first == 1 { if rn > 0 { sys_write(1, "PXY-GOT\n" as *u8, 8) } else { sys_write(1, "PXY-EOF0\n" as *u8, 9) } first = 0 }
1006 if rn <= 0 { go = 0 } else {
1007 if nx_tls13_app_send_fd(s, chunk, rn, cfd, out_rec, NX_SD2_OUTREC) < 0 { go = 0 } else { total = total + rn }
1008 }
1009 }
1010 sys_close(ufd)
1011 sys_write(1, "PXY-RET\n" as *u8, 8)
1012 return total
1013}
1014
1015// Wiki engine reverse-proxy (loopback 127.0.0.1:51850).
1016func sd2_wiki_proxy(plain: *u8, plain_n: i64, dyn: *u8) -> i64 {
1017 return sd2_proxy_to(plain, plain_n, dyn, NX_MAGIC_51850)
1018}
1019
1020// seq1306 (sev9, MEASURED 2026-07-30): route matching MUST NOT see the body. Every dispatcher match in
1021// this daemon scanned the WHOLE buffer, so a request whose BODY merely quoted a real route+query was
1022// HIJACKED by that handler (reproducer: uploading this daemon's own source 400'd, deterministic 6/6 --
1023// the edge could not ship its own fix). It also let a body spoof header checks (X-Nishi-Session, Host,
1024// Accept). Fix: compute the header span ONCE per request and match only within it. Forwarding calls
1025// (sd2_proxy_to / sd2_fill_body) still get the FULL length -- bodies must still be proxied whole.
1026// Returns bytes up to and including the CRLFCRLF terminator, or n when no terminator is present.
1027func sd2_hdr_span(p: *u8, n: i64) -> i64 {
1028 var i: i64 = 0
1029 while i + 3 < n {
1030 if p[i] == (13 as u8) { if p[i+1] == (10 as u8) { if p[i+2] == (13 as u8) { if p[i+3] == (10 as u8) { return i + 4 } } } }
1031 i = i + 1
1032 }
1033 return n
1034}
1035// Is this request one of the OPAQUE login routes (/login, /register, /whoami, /audio)? Matched with a
1036// leading space so it fires only on the request-line path -- âš the leading space does NOT bound it to the
1037// request line (seq1306): callers MUST pass the header span, never the full request length.
1038func sd2_is_login_route(plain: *u8, plain_n: i64) -> i64 {
1039 if sd2_contains(plain, plain_n, " /login" as *u8, 7) == 1 { return 1 }
1040 if sd2_contains(plain, plain_n, " /register" as *u8, 10) == 1 { return 1 }
1041 if sd2_contains(plain, plain_n, " /whoami" as *u8, 8) == 1 { return 1 }
1042 if sd2_contains(plain, plain_n, " /audio" as *u8, 7) == 1 { return 1 }
1043 if sd2_contains(plain, plain_n, " /access" as *u8, 8) == 1 { return 1 }
1044 if sd2_contains(plain, plain_n, " /welcome" as *u8, 9) == 1 { return 1 }
1045 return 0
1046}
1047
1048// PUBLIC CARVE-OUT under the otherwise fully-gated /wiki tree (operator 2026-08-01: product strategy
1049// stays behind the gate, "code can exist without a gate as its fine to share that information and
1050// research as its public"). /wiki/research is the research OCEAN -- the index over every research
1051// river -- and is deliberately readable without a session. Nothing else under /wiki is affected.
1052// BOUNDARY-SAFE BY CONSTRUCTION: only the exact page and its .html / query forms are public, so a
1053// sibling file whose name merely STARTS with "research" (e.g. /wiki/research_private.html) can NOT
1054// ride this carve-out. A prefix match here would be an escape hatch, not a carve-out.
1055func sd2_wiki_public(p: *u8, n: i64) -> i64 {
1056 if sd2_contains(p, n, " /wiki/research " as *u8, 16) == 1 { return 1 }
1057 if sd2_contains(p, n, " /wiki/research.html" as *u8, 20) == 1 { return 1 }
1058 if sd2_contains(p, n, " /wiki/research?" as *u8, 16) == 1 { return 1 }
1059 return 0
1060}
1061// 1 = this request must go through the OPAQUE wiki gate; 0 = not a /wiki path at all, OR an explicitly
1062// public one, which then falls through to normal static routing. Replaces a bare /wiki substring test
1063// at the gate call site so the allowlist lives in ONE named place instead of inline at the branch.
1064func sd2_wiki_gated(p: *u8, n: i64) -> i64 {
1065 if sd2_contains(p, n, " /wiki" as *u8, 6) == 0 { return 0 }
1066 if sd2_wiki_public(p, n) == 1 { return 0 }
1067 return 1
1068}
1069
1070func sd2_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c<48{return v} if c>57{return v} v=v*10+(c-48); i=i+1 } return v }
1071
1072func main(argc: i64, argv: *i64) -> i64 {
1073 // listen port: argv[1] overrides NX_SD2_PORT (default 8443). Lets a fresh build be
1074 // scratch-tested on a spare port without disturbing the live :8443 daemon.
1075 var listen_port: i64 = NX_SD2_PORT
1076 if argc > 1 { listen_port = sd2_atoi(argv[1] as *u8) }
1077 // ---- Route B: load the per-domain wildcard pairs; PAIRED fail-safe to the generic pair ----
1078 // NISHI (index 0) = the default for absent/garbled/unknown SNI. If its per-domain pair is
1079 // incomplete, the legacy generic both-SAN pair serves it (exactly today's behavior).
1080 let cert_len_box: *i64 = (sys_mmap(8)) as *i64
1081 var cert_nishi: *u8 = sd2_load_chain(NX_SD2_CERT_NISHI, cert_len_box)
1082 var cert_nishi_len: i64 = cert_len_box[0]
1083 var ecdsa_nishi: *u8 = sd2_load_key(NX_SD2_PRIV_NISHI)
1084 var nishi_src: i64 = 1 // 1 = per-domain files, 0 = generic fallback
1085 if (cert_nishi as i64) == 0 { nishi_src = 0 }
1086 if (ecdsa_nishi as i64) == 0 { nishi_src = 0 }
1087 if nishi_src == 0 {
1088 cert_nishi = sd2_load_chain(NX_SD2_CERT_PATH, cert_len_box)
1089 cert_nishi_len = cert_len_box[0]
1090 ecdsa_nishi = sd2_load_key(NX_SD2_PRIV_PATH)
1091 }
1092 if (cert_nishi as i64) == 0 { return 2 }
1093 if (ecdsa_nishi as i64) == 0 { return 3 }
1094
1095 // ANDELIN (index 1). PAIRED fail-safe: any missing/short file -> serve the NISHI pair for
1096 // andelinwest hosts (a valid handshake still completes; never a mismatched cert/key).
1097 let andelin_len_box: *i64 = (sys_mmap(8)) as *i64
1098 var cert_andelin: *u8 = sd2_load_chain(NX_SD2_CERT_ANDELIN, andelin_len_box)
1099 var cert_andelin_len: i64 = andelin_len_box[0]
1100 var ecdsa_andelin: *u8 = sd2_load_key(NX_SD2_PRIV_ANDELIN)
1101 var andelin_src: i64 = 1
1102 if (cert_andelin as i64) == 0 { andelin_src = 0 }
1103 if (ecdsa_andelin as i64) == 0 { andelin_src = 0 }
1104 if andelin_src == 0 {
1105 cert_andelin = cert_nishi
1106 cert_andelin_len = cert_nishi_len
1107 ecdsa_andelin = ecdsa_nishi
1108 }
1109
1110 // ---- DATA-DRIVEN cert table: load the manifest (row 0 = default). Fall back to the legacy
1111 // nishi+andelin pair if the manifest is absent/empty so nothing regresses (rule 20 fail-safe). ----
1112 let cert_suf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1113 let cert_suf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1114 let cert_buf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1115 let cert_buf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1116 let cert_key_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1117 let man_box: *i64 = (sys_mmap(8)) as *i64
1118 man_box[0] = 0
1119 let man_buf: *u8 = sys_read_file(NX_SD2_CERT_MANIFEST, man_box)
1120 var cert_count: i64 = 0
1121 if (man_buf as i64) != 0 {
1122 cert_count = sd2_load_cert_table(man_buf, man_box[0], cert_suf_ptrs, cert_suf_lens, cert_buf_ptrs, cert_buf_lens, cert_key_ptrs, NX_SD2_CERT_MAX)
1123 }
1124 if cert_count == 0 {
1125 cert_suf_ptrs[0] = ("nishifamily.com" as *u8) as i64
1126 cert_suf_lens[0] = 15
1127 cert_buf_ptrs[0] = cert_nishi as i64
1128 cert_buf_lens[0] = cert_nishi_len
1129 cert_key_ptrs[0] = ecdsa_nishi as i64
1130 cert_suf_ptrs[1] = ("andelinwest.com" as *u8) as i64
1131 cert_suf_lens[1] = 15
1132 cert_buf_ptrs[1] = cert_andelin as i64
1133 cert_buf_lens[1] = cert_andelin_len
1134 cert_key_ptrs[1] = ecdsa_andelin as i64
1135 cert_count = 2
1136 }
1137 sys_write(1, "nishi sites daemon v2: SNI cert table rows=" as *u8, 43)
1138 let ccb2: *u8 = sys_mmap(24)
1139 let ccn2: i64 = sd2_u64_to_dec(cert_count, ccb2)
1140 sys_write(1, ccb2, ccn2)
1141 sys_write(1, "\n" as *u8, 1)
1142
1143 let sd_cfg_box: *i64 = (sys_mmap(8)) as *i64
1144 sd_cfg_box[0] = 0
1145 var sites_cfg: *u8 = sys_read_file(NX_SD2_SITES_CONF, sd_cfg_box)
1146 var sites_cfg_n: i64 = 0
1147 if (sites_cfg as i64) != 0 { sites_cfg_n = sd_cfg_box[0] }
1148 // load the data-driven proxy route table (absent file -> proxy_cfg_n=0 -> legacy cascade only)
1149 let pr_cfg_box: *i64 = (sys_mmap(8)) as *i64
1150 pr_cfg_box[0] = 0
1151 var proxy_cfg: *u8 = sys_read_file(NX_SD2_PROXY_CONF, pr_cfg_box)
1152 var proxy_cfg_n: i64 = 0
1153 if (proxy_cfg as i64) != 0 { proxy_cfg_n = pr_cfg_box[0] }
1154 // load the data-driven ADNET inventory (absent -> adnet_cfg_n=0 -> slots OFF + no click route)
1155 let ad_cfg_box: *i64 = (sys_mmap(8)) as *i64
1156 ad_cfg_box[0] = 0
1157 let adnet_cfg: *u8 = sys_read_file(NX_SD2_ADNET_CONF, ad_cfg_box)
1158 var adnet_cfg_n: i64 = 0
1159 if (adnet_cfg as i64) != 0 { adnet_cfg_n = ad_cfg_box[0] }
1160 var ad_imp_fd: i64 = 0 - 1
1161 var ad_clk_fd: i64 = 0 - 1
1162 if adnet_cfg_n > 0 { ad_imp_fd = sys_openat_append(NX_SD2_ADNET_IMPLOG, 420) }
1163 if adnet_cfg_n > 0 { ad_clk_fd = sys_openat_append(NX_SD2_ADNET_CLKLOG, 420) }
1164 var ad_view_fd: i64 = 0 - 1
1165 if adnet_cfg_n > 0 { ad_view_fd = sys_openat_append(NX_SD2_ADNET_VIEWLOG, 420) }
1166 if adnet_cfg_n > 0 {
1167 let adr1: *u8 = "adnet: inventory loaded, slots ON\n" as *u8
1168 sys_write(1, adr1, sd2_strlen(adr1))
1169 } else {
1170 let adr0: *u8 = "adnet: no inventory, slots OFF\n" as *u8
1171 sys_write(1, adr0, sd2_strlen(adr0))
1172 }
1173
1174 let addr_buf: *u8 = sys_mmap(16)
1175 nx_http_server_addr_any(addr_buf, listen_port)
1176 let lv: *i64 = (sys_mmap(8)) as *i64
1177 let lfd: i64 = nx_http_server_listen(addr_buf, 16, lv)
1178 if lfd < 0 { return 4 }
1179 // ZOMBIE-REAP (2026-07-15): SO_RCVTIMEO on the listen socket -> accept() returns EAGAIN every 5s when
1180 // idle, so the wait4(WNOHANG) reap at the loop top runs promptly (not only when the next connection
1181 // arrives). Keeps the graceful fork-bomb cap intact; a real connection still returns immediately.
1182 sys_set_socket_timeout(lfd, 5)
1183 sys_write(1, "nishi sites daemon v2: vhosts + wss/video + circles on 0.0.0.0:8443\n" as *u8, 69)
1184 // Route B receipt: WHICH pair each domain serves (visible in sitetest / sites_run.log).
1185 if nishi_src == 1 { sys_write(1, "sni-cert nishi=per-domain\n" as *u8, 26) } else { sys_write(1, "sni-cert nishi=generic\n" as *u8, 23) }
1186 if andelin_src == 1 { sys_write(1, "sni-cert andelin=per-domain\n" as *u8, 28) } else { sys_write(1, "sni-cert andelin=nishi-fallback\n" as *u8, 32) }
1187
1188 let ctype_html: *u8 = "text/html; charset=utf-8" as *u8
1189 let nb_andelin: i64 = sd2_strlen(BODY2_ANDELIN)
1190 let nb_wiki: i64 = sd2_strlen(BODY2_WIKI)
1191 let nb_family: i64 = sd2_strlen(BODY2_FAMILY)
1192 let resp_andelin: *u8 = sys_mmap(nb_andelin + NX_SD2_HDR_RESERVE)
1193 let resp_wiki: *u8 = sys_mmap(nb_wiki + NX_SD2_HDR_RESERVE)
1194 let resp_family: *u8 = sys_mmap(nb_family + NX_SD2_HDR_RESERVE)
1195 let n_andelin: i64 = sd2_build_resp(resp_andelin, ctype_html, BODY2_ANDELIN, nb_andelin)
1196 let n_wiki: i64 = sd2_build_resp(resp_wiki, ctype_html, BODY2_WIKI, nb_wiki)
1197 let n_family: i64 = sd2_build_resp(resp_family, ctype_html, BODY2_FAMILY, nb_family)
1198 let n_favicon: i64 = sd2_strlen(RESP2_FAVICON)
1199
1200 var resp_wstatus: *u8 = sys_mmap(NX_SD2_STATUS_CAP)
1201 let wstatus_box: *i64 = (sys_mmap(8)) as *i64
1202 wstatus_box[0] = 0
1203 let wstatus_rc: i64 = nx_wiki_status_handle(resp_wstatus, NX_SD2_STATUS_CAP, wstatus_box)
1204 var n_wstatus: i64 = wstatus_box[0]
1205 if wstatus_rc != 0 { resp_wstatus = resp_wiki; n_wstatus = n_wiki }
1206 if n_wstatus <= 0 { resp_wstatus = resp_wiki; n_wstatus = n_wiki }
1207
1208 var resp_art_crawler: *u8 = sys_mmap(NX_SD2_ART_CAP)
1209 let acr_box: *i64 = (sys_mmap(8)) as *i64
1210 acr_box[0] = 0
1211 let acr_rc: i64 = nx_wiki_article_handle("crawler" as *u8, 7, resp_art_crawler, NX_SD2_ART_CAP, acr_box)
1212 var n_art_crawler: i64 = acr_box[0]
1213 if acr_rc != 0 { resp_art_crawler = resp_wiki; n_art_crawler = n_wiki }
1214 if n_art_crawler <= 0 { resp_art_crawler = resp_wiki; n_art_crawler = n_wiki }
1215
1216 var resp_art_x25519: *u8 = sys_mmap(NX_SD2_ART_CAP)
1217 let axx_box: *i64 = (sys_mmap(8)) as *i64
1218 axx_box[0] = 0
1219 let axx_rc: i64 = nx_wiki_article_handle("x25519" as *u8, 6, resp_art_x25519, NX_SD2_ART_CAP, axx_box)
1220 var n_art_x25519: i64 = axx_box[0]
1221 if axx_rc != 0 { resp_art_x25519 = resp_wiki; n_art_x25519 = n_wiki }
1222 if n_art_x25519 <= 0 { resp_art_x25519 = resp_wiki; n_art_x25519 = n_wiki }
1223
1224 var resp_art_ranking: *u8 = sys_mmap(NX_SD2_ART_CAP)
1225 let ark_box: *i64 = (sys_mmap(8)) as *i64
1226 ark_box[0] = 0
1227 let ark_rc: i64 = nx_wiki_article_handle("ranking-math" as *u8, 12, resp_art_ranking, NX_SD2_ART_CAP, ark_box)
1228 var n_art_ranking: i64 = ark_box[0]
1229 if ark_rc != 0 { resp_art_ranking = resp_wiki; n_art_ranking = n_wiki }
1230 if n_art_ranking <= 0 { resp_art_ranking = resp_wiki; n_art_ranking = n_wiki }
1231
1232 var resp_art_wiki: *u8 = sys_mmap(NX_SD2_ART_CAP)
1233 let awe_box: *i64 = (sys_mmap(8)) as *i64
1234 awe_box[0] = 0
1235 let awe_rc: i64 = nx_wiki_article_handle("wiki-engine" as *u8, 11, resp_art_wiki, NX_SD2_ART_CAP, awe_box)
1236 var n_art_wiki: i64 = awe_box[0]
1237 if awe_rc != 0 { resp_art_wiki = resp_wiki; n_art_wiki = n_wiki }
1238 if n_art_wiki <= 0 { resp_art_wiki = resp_wiki; n_art_wiki = n_wiki }
1239
1240 var resp_components: *u8 = sys_mmap(NX_SD2_ART_CAP)
1241 let aci_box: *i64 = (sys_mmap(8)) as *i64
1242 aci_box[0] = 0
1243 let aci_rc: i64 = nx_wiki_components_handle(resp_components, NX_SD2_ART_CAP, aci_box)
1244 var n_components: i64 = aci_box[0]
1245 if aci_rc != 0 { resp_components = resp_wiki; n_components = n_wiki }
1246 if n_components <= 0 { resp_components = resp_wiki; n_components = n_wiki }
1247
1248 var resp_projects: *u8 = resp_wiki
1249 var n_projects: i64 = n_wiki
1250
1251 // CONSTANT MEMORY: hoisted per-connection buffers (see v1 rationale).
1252 let server_random: *u8 = sys_mmap(32)
1253 let server_x25519_priv: *u8 = sys_mmap(32)
1254 let rec_buf: *u8 = sys_mmap(NX_SD2_RECCAP)
1255 let plain: *u8 = sys_mmap(NX_SD2_PLAINCAP)
1256 let out_rec: *u8 = sys_mmap(NX_SD2_OUTREC)
1257 let pump: *u8 = sys_mmap(NX_SD2_RECCAP)
1258 let dyn_buf: *u8 = sys_mmap(NX_SD2_DYN_CAP)
1259 let sock_addr: *u8 = sys_mmap(64)
1260 let sock_len: *i64 = (sys_mmap(8)) as *i64
1261 let tel_buf: *u8 = sys_mmap(256)
1262 let tel_fd: i64 = sys_openat_append(NX_SD2_TELEMETRY_PATH, 420)
1263 // Route B: hoisted SNI-peek buffers (constant memory; children get a COW copy on write).
1264 let sni_peek: *u8 = sys_mmap(NX_SD2_SNI_PEEK_CAP)
1265 let sni_host: *u8 = sys_mmap(256)
1266
1267 sys_set_socket_timeout(lfd, 5)
1268 let reap_status: *i64 = (sys_mmap(8)) as *i64
1269 var served: i64 = 0
1270 var live: i64 = 0
1271
1272 // ---- HOT-RELOAD (2026-07-15): config changes go LIVE on the NEXT CONNECTION, no restart. On each
1273 // accepted connection the PARENT (single-threaded between accepts; forked children snapshot a
1274 // consistent copy) compares (mtime,size) of cert-manifest / sites.conf / proxy_routes.conf and
1275 // re-reads on change. The cert table loads into TEMP arrays and copies over ONLY on a non-empty
1276 // parse, so a half-written/broken manifest can never wipe the live table (fail-safe, rule 14/20).
1277 let hr_statb: *u8 = sys_mmap(160)
1278 let hr_sig: *i64 = (sys_mmap(16)) as *i64
1279 var man_mt: i64 = 0 - 1
1280 var man_sz: i64 = 0 - 1
1281 if sd2_statsig(NX_SD2_CERT_MANIFEST, hr_statb, hr_sig) == 0 { man_mt = hr_sig[0]; man_sz = hr_sig[1] }
1282 var sc_mt: i64 = 0 - 1
1283 var sc_sz: i64 = 0 - 1
1284 if sd2_statsig(NX_SD2_SITES_CONF, hr_statb, hr_sig) == 0 { sc_mt = hr_sig[0]; sc_sz = hr_sig[1] }
1285 var prc_mt: i64 = 0 - 1
1286 var prc_sz: i64 = 0 - 1
1287 if sd2_statsig(NX_SD2_PROXY_CONF, hr_statb, hr_sig) == 0 { prc_mt = hr_sig[0]; prc_sz = hr_sig[1] }
1288 let tmp_suf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1289 let tmp_suf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1290 let tmp_buf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1291 let tmp_buf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1292 let tmp_key_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64
1293
1294 while served < NX_SD2_BUDGET {
1295 while sys_wait4(0 - 1, reap_status, 1) > 0 { live = live - 1 }
1296
1297 sock_len[0] = 16
1298 let cfd: i64 = sys_accept_with_addr(lfd, sock_addr, sock_len)
1299 if cfd < 0 { continue }
1300
1301 // hot-reload check (parent, pre-fork): the connection just accepted already sees fresh config.
1302 if sd2_statsig(NX_SD2_CERT_MANIFEST, hr_statb, hr_sig) == 0 {
1303 if hr_sig[0] != man_mt || hr_sig[1] != man_sz {
1304 man_mt = hr_sig[0]
1305 man_sz = hr_sig[1]
1306 let mb2: *i64 = (sys_mmap(8)) as *i64
1307 mb2[0] = 0
1308 let mbuf2: *u8 = sys_read_file(NX_SD2_CERT_MANIFEST, mb2)
1309 if (mbuf2 as i64) != 0 {
1310 let nc2: i64 = sd2_load_cert_table(mbuf2, mb2[0], tmp_suf_ptrs, tmp_suf_lens, tmp_buf_ptrs, tmp_buf_lens, tmp_key_ptrs, NX_SD2_CERT_MAX)
1311 if nc2 > 0 {
1312 var ci2: i64 = 0
1313 while ci2 < nc2 {
1314 cert_suf_ptrs[ci2] = tmp_suf_ptrs[ci2]
1315 cert_suf_lens[ci2] = tmp_suf_lens[ci2]
1316 cert_buf_ptrs[ci2] = tmp_buf_ptrs[ci2]
1317 cert_buf_lens[ci2] = tmp_buf_lens[ci2]
1318 cert_key_ptrs[ci2] = tmp_key_ptrs[ci2]
1319 ci2 = ci2 + 1
1320 }
1321 cert_count = nc2
1322 sys_write(1, "hot-reload: cert table\n" as *u8, 23)
1323 }
1324 }
1325 }
1326 }
1327 if sd2_statsig(NX_SD2_SITES_CONF, hr_statb, hr_sig) == 0 {
1328 if hr_sig[0] != sc_mt || hr_sig[1] != sc_sz {
1329 sc_mt = hr_sig[0]
1330 sc_sz = hr_sig[1]
1331 let scb2: *i64 = (sys_mmap(8)) as *i64
1332 scb2[0] = 0
1333 let scfg2: *u8 = sys_read_file(NX_SD2_SITES_CONF, scb2)
1334 if (scfg2 as i64) != 0 {
1335 sites_cfg = scfg2
1336 sites_cfg_n = scb2[0]
1337 sys_write(1, "hot-reload: sites.conf\n" as *u8, 23)
1338 }
1339 }
1340 }
1341 if sd2_statsig(NX_SD2_PROXY_CONF, hr_statb, hr_sig) == 0 {
1342 if hr_sig[0] != prc_mt || hr_sig[1] != prc_sz {
1343 prc_mt = hr_sig[0]
1344 prc_sz = hr_sig[1]
1345 let pcb2: *i64 = (sys_mmap(8)) as *i64
1346 pcb2[0] = 0
1347 let pcfg2: *u8 = sys_read_file(NX_SD2_PROXY_CONF, pcb2)
1348 if (pcfg2 as i64) != 0 {
1349 proxy_cfg = pcfg2
1350 proxy_cfg_n = pcb2[0]
1351 sys_write(1, "hot-reload: proxy_routes.conf\n" as *u8, 30)
1352 }
1353 }
1354 }
1355
1356 if live >= NX_SD2_MAX_CHILDREN {
1357 if sys_wait4(0 - 1, reap_status, 0) > 0 { live = live - 1 }
1358 }
1359
1360 let pid: i64 = sys_fork()
1361 if pid == 0 {
1362 // ---- CHILD ----
1363 sys_close(lfd)
1364 let acc_lan: i64 = nx_access_is_lan(sock_addr)
1365 sys_set_socket_timeout(cfd, 10)
1366 let nodelay: *u8 = sys_mmap(4)
1367 nodelay[0] = 1 as u8; nodelay[1] = 0 as u8; nodelay[2] = 0 as u8; nodelay[3] = 0 as u8
1368 sys_setsockopt(cfd, 6, 1, nodelay, 4)
1369 nx_csprng_fill(server_random, 32)
1370 nx_csprng_fill(server_x25519_priv, 32)
1371 // ---- Route B: SNI-aware cert selection ----
1372 // MSG_PEEK the cleartext ClientHello (non-consuming), pick the per-domain wildcard
1373 // pair by the SNI, then run the UNCHANGED handshake serving that pair. Any peek
1374 // failure / absent / unknown SNI -> the default (nishifamily) pair.
1375 let pk_n: i64 = sys_recvfrom(cfd, sni_peek, NX_SD2_SNI_PEEK_CAP, NX_SD2_MSG_PEEK, 0 as *u8, 0 as *i64)
1376 // DATA-DRIVEN: pick the cert-table row from the SNI (row 0 = default; unknown/absent -> 0).
1377 var cert_idx: i64 = 0
1378 if pk_n > 0 { cert_idx = scs_pick_from_clienthello_table(sni_peek, pk_n, sni_host, 256, cert_suf_ptrs, cert_suf_lens, cert_count) }
1379 if cert_idx < 0 { cert_idx = 0 }
1380 if cert_idx >= cert_count { cert_idx = 0 }
1381 var use_cert: *u8 = cert_buf_ptrs[cert_idx] as *u8
1382 var use_cert_len: i64 = cert_buf_lens[cert_idx]
1383 var use_priv: *u8 = cert_key_ptrs[cert_idx] as *u8
1384 let t_hs0: i64 = sys_now_us()
1385 let hs_rc: i64 = nx_tls13_server_session_run(
1386 cfd, server_random, server_x25519_priv,
1387 use_cert, use_cert_len, use_priv)
1388 let hs_us: i64 = sys_now_us() - t_hs0
1389 // hs_rc carries TWO meanings: >0 it is a Tls13ServerSession HANDLE (cast below), <=0 it is a
1390 // failure status. Telemetry wants only the status. Passing the handle into a parameter named
1391 // `rc` conflated the two -- nx_telemetry_emit already had to defend itself with `if rc > 0 { rc = 0 }`,
1392 // which is the tell that a pointer was arriving where a status was declared. Narrow it ONCE, here,
1393 // so the serving path never hands an address to something that will report it as a number.
1394 var hs_stat: i64 = hs_rc
1395 if hs_stat > 0 { hs_stat = 0 }
1396 var vhost_id: i64 = 0
1397 var served_bytes: i64 = 0
1398 if hs_rc > 0 {
1399 let s: *Tls13ServerSession = hs_rc as *Tls13ServerSession
1400 var keep: i64 = 1
1401 var nreq: i64 = 0
1402 while keep == 1 {
1403 if nreq >= NX_SD2_MAX_REQ_PER_CONN {
1404 keep = 0
1405 } else {
1406 let plain_n: i64 = sd2_recv_request(s, cfd, rec_buf, plain, NX_SD2_PLAINCAP)
1407 let hdr_n: i64 = sd2_hdr_span(plain, plain_n) // seq1306: routes match HEADERS ONLY
1408 if plain_n <= 0 {
1409 keep = 0
1410 } else {
1411 // ---- D4: wss upgrade? consumes the connection ----
1412 var is_ws: i64 = 0
1413 if sd2_contains(plain, hdr_n, "GET /signal/" as *u8, 12) == 1 {
1414 if sd2_contains_ci(plain, plain_n, "upgrade: websocket" as *u8, 18) == 1 { is_ws = 1 }
1415 if sd2_contains_ci(plain, plain_n, "upgrade:websocket" as *u8, 17) == 1 { is_ws = 1 }
1416 }
1417 if is_ws == 1 {
1418 vhost_id = 21
1419 sd2_ws_pump(s, cfd, plain, plain_n, rec_buf, out_rec, pump)
1420 keep = 0
1421 } else {
1422 var resp: *u8 = resp_family
1423 var resp_n: i64 = n_family
1424 let is_favicon: i64 = sd2_contains(plain, hdr_n, "favicon" as *u8, 7)
1425 if is_favicon == 1 {
1426 resp = RESP2_FAVICON; resp_n = n_favicon; vhost_id = 9
1427 } else {
1428 var dyn_done: i64 = 0
1429 // ---- DEBRIS REFUSAL (2026-07-30). Rollback/backup/temp artifacts sitting in a
1430 // docroot were being SERVED 200: measured https://andelinwest.com/index.html.bak-v1
1431 // returning a whole previous CLIENT homepage, plus 65 .prev/.bak/.nxw artifacts on
1432 // nishifamily. Every one is a public duplicate-content + information-disclosure
1433 // surface. Refused FIRST, before any handler can serve them, so the guarantee does
1434 // not depend on which route would have won. Path-bounded (hr_req_path), never a
1435 // whole-header scan -- a Referer carrying .bak must not 404 a real page.
1436 let dbz: *u8 = sys_mmap(NX_MAGIC_4096)
1437 let dbn: i64 = hr_req_path(plain, hdr_n, dbz, NX_MAGIC_4096)
1438 var dbg: i64 = 0
1439 if sd2_contains(dbz, dbn, ".prev" as *u8, 5) == 1 { dbg = 1 }
1440 if sd2_contains(dbz, dbn, ".bak" as *u8, 4) == 1 { dbg = 1 }
1441 if sd2_contains(dbz, dbn, ".nxw" as *u8, 4) == 1 { dbg = 1 }
1442 if sd2_contains(dbz, dbn, ".nxtmp" as *u8, 6) == 1 { dbg = 1 }
1443 if sd2_contains(dbz, dbn, ".nxpub" as *u8, 6) == 1 { dbg = 1 }
1444 if dbg == 1 { resp_n = hr_emit_404(dyn_buf, NX_SD2_DYN_CAP); resp = dyn_buf; vhost_id = 23; dyn_done = 1 }
1445 // ---- VIEWABLE-IMPRESSION BEACON: /ad/view/<id> (MRC 50pct for 1 continuous second).
1446 // Journalled SEPARATELY from served impressions so served/viewable stays a visible,
1447 // honest delivery ratio. FAIL-CLOSED: aview_resp only fills av_id for a well-formed
1448 // inventory id, so a forged or replayed path answers 204 and journals NOTHING.
1449 if dyn_done == 0 { if aview_is_path(dbz, dbn) == 1 {
1450 let av_id: *u8 = sys_mmap(128)
1451 let avr: i64 = aview_resp(dbz, dbn, dyn_buf, NX_SD2_DYN_CAP, av_id)
1452 if avr > 0 {
1453 resp = dyn_buf; resp_n = avr; vhost_id = 26; dyn_done = 1
1454 if ad_view_fd >= 0 { if av_id[0] != (0 as u8) {
1455 let avl: *u8 = sys_mmap(160)
1456 var avn: i64 = 0
1457 while av_id[avn] != (0 as u8) { avl[avn] = av_id[avn]; avn = avn + 1 }
1458 avl[avn] = 10 as u8
1459 avn = avn + 1
1460 sys_write(ad_view_fd, avl, avn)
1461 } }
1462 }
1463 } }
1464 // ---- HOT HOME: nishifamily root ("GET / HTTP") served from a LIVING FILE
1465 // (sites/nishifamily/home.html) so the front door updates via a file push, no
1466 // recompile -- the sovereign nav landing (nx_site_chrome home). NEVER-BRICK:
1467 // an absent/empty/unreadable file leaves dyn_done=0 -> the baked resp_family
1468 // (BODY2_FAMILY) serves EXACTLY as before. Guarded to nishifamily: skip if the
1469 // andelinwest host header is present (its root is served on its own vhost).
1470 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET / HTTP" as *u8, 10) == 1 {
1471 // Nishifamily hot-home for the nishifamily apex + the DEFAULT (unknown) host ONLY.
1472 // Any OTHER registered vhost (andelinwest, b2b.loans, ...) skips this and serves its
1473 // OWN sites.conf docroot below -- data-driven, no per-domain hardcode.
1474 let hh_known: i64 = hr_known_host(sites_cfg, sites_cfg_n, plain, plain_n)
1475 let hh_nishi: i64 = sd2_contains(plain, hdr_n, "nishifamily" as *u8, 11)
1476 var hh_ok: i64 = 0
1477 if hh_known == 0 { hh_ok = 1 }
1478 else { if hh_nishi == 1 { hh_ok = 1 } }
1479 if hh_ok == 1 {
1480 let hm_box: *i64 = (sys_mmap(8)) as *i64; hm_box[0] = 0
1481 let hm_buf: *u8 = sys_read_file("/volume1/homes/elderwesto/nishihost/sites/nishifamily/home.html" as *u8, hm_box)
1482 if (hm_buf as i64) != 0 { if hm_box[0] > 0 { resp = dyn_buf; resp_n = sd2_build_resp(dyn_buf, ctype_html, hm_buf, hm_box[0]); vhost_id = 33; dyn_done = 1 } }
1483 }
1484 } }
1485 // ---- DATA-DRIVEN PROXY ROUTES (nx_proxy_route): app routes are CONFIG ROWS, no
1486 // recompile. Matched BEFORE the legacy hardcoded cascade. ADDITIVE + SAFE: no match
1487 // (or proxy_routes.conf absent -> proxy_cfg_n=0) leaves dyn_done=0 -> the legacy
1488 // cascade serves exactly as before. mode buffered(0)=sd2_proxy_to, stream(1)=
1489 // sd2_proxy_stream, gated(2)=proxy + fail-closed 302 /login. Same ports/semantics as
1490 // the cascade -> a config "match" is byte-identical to the hardcoded route it shadows.
1491 if dyn_done == 0 { if proxy_cfg_n > 0 {
1492 let pr_host: *u8 = sys_mmap(256)
1493 let pr_path: *u8 = sys_mmap(NX_MAGIC_4096)
1494 let pr_hn: i64 = hr_req_host(plain, plain_n, pr_host, 256)
1495 let pr_pn: i64 = hr_req_path(plain, hdr_n, pr_path, NX_MAGIC_4096)
1496 let pr_portb: *i64 = (sys_mmap(8)) as *i64
1497 let pr_modeb: *i64 = (sys_mmap(8)) as *i64
1498 if pr_lookup(proxy_cfg, proxy_cfg_n, pr_host, pr_hn, pr_path, pr_pn, pr_portb, pr_modeb) == 1 {
1499 if pr_modeb[0] == 1 {
1500 let pst: i64 = sd2_proxy_stream(s, cfd, plain, plain_n, pr_portb[0], out_rec)
1501 if pst >= 0 { served_bytes = served_bytes + pst; resp_n = 0; vhost_id = 70; dyn_done = 1; keep = 0 }
1502 } else {
1503 // buffered/gated: complete the request body FIRST (sd2_fill_body;
1504 // fail-safe no-op for GETs/complete bodies) so >8KB POST chunks
1505 // reach the backend whole -- the API bulk-upload unlock.
1506 if sd2_content_length(plain, plain_n) > NX_SD2_PLAINCAP {
1507 resp = RESP2_413; resp_n = sd2_strlen(RESP2_413); vhost_id = 13; dyn_done = 1; keep = 0
1508 } else {
1509 let pfn: i64 = sd2_fill_body(s, cfd, rec_buf, plain, plain_n, NX_SD2_PLAINCAP)
1510 let pbr: i64 = sd2_proxy_to(plain, pfn, dyn_buf, pr_portb[0])
1511 if pbr > 0 { resp = dyn_buf; resp_n = pbr; vhost_id = 70; dyn_done = 1 }
1512 else { if pr_modeb[0] == 2 { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 70; dyn_done = 1 } else {
1513 // seq1294 (both edge outages, 07-20 + 07-29): a PROXIED route whose backend
1514 // yielded NO bytes is an ERROR -- falling through to the static cascade served
1515 // the HOMEPAGE as a 200, and that HTML-to-a-machine-client is the retry-storm
1516 // trigger. Content-negotiated honest 503 + Retry-After instead: machines (no
1517 // text/html in Accept) get RFC-9457 problem+json; browsers get a real 503 page.
1518 var e_w: i64 = 0
1519 if sd2_contains(plain, hdr_n, "text/html" as *u8, 9) == 1 {
1520 let eb: *u8 = "<!doctype html><h1>503 backend unavailable</h1><p>The service behind this route did not answer inside the edge window. Retry shortly.</p>" as *u8
1521 e_w = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 503 Service Unavailable\r\nRetry-After: 5" as *u8, "text/html; charset=utf-8" as *u8, eb, sd2_strlen(eb))
1522 } else {
1523 let ej: *u8 = "{\"type\":\"about:blank\",\"title\":\"Service Unavailable\",\"status\":503,\"detail\":\"upstream backend gave no response inside the edge window; retry after 5s\"}" as *u8
1524 e_w = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 503 Service Unavailable\r\nRetry-After: 5" as *u8, "application/problem+json" as *u8, ej, sd2_strlen(ej))
1525 }
1526 if e_w > 0 { resp = dyn_buf; resp_n = e_w; vhost_id = 71; dyn_done = 1; keep = 0 }
1527 } }
1528 }
1529 }
1530 }
1531 } }
1532 // ---- ADNET first-party click redirect (/ad/click/<id>) + per-AD click counter.
1533 // No visitor id/cookie ever; unknown/invalid id -> 302 / (fail-closed). Only alive
1534 // when the inventory conf exists (adnet_cfg_n>0) -> zero behavior change otherwise.
1535 if dyn_done == 0 { if adnet_cfg_n > 0 {
1536 if sd2_contains(plain, hdr_n, "GET /ad/click/" as *u8, 14) == 1 {
1537 let ac_path: *u8 = sys_mmap(NX_MAGIC_4096)
1538 let ac_pn: i64 = hr_req_path(plain, hdr_n, ac_path, NX_MAGIC_4096)
1539 let ac_id: *u8 = sys_mmap(128)
1540 let ac_w: i64 = aslot_click_resp(adnet_cfg, adnet_cfg_n, ac_path, ac_pn, dyn_buf, NX_SD2_DYN_CAP, ac_id)
1541 if ac_w > 0 {
1542 resp = dyn_buf; resp_n = ac_w; vhost_id = 28; dyn_done = 1
1543 if ad_clk_fd >= 0 { if ac_id[0] != (0 as u8) {
1544 let ac_line: *u8 = sys_mmap(160)
1545 var ac_ln: i64 = 0
1546 while ac_id[ac_ln] != (0 as u8) { ac_line[ac_ln] = ac_id[ac_ln]; ac_ln = ac_ln + 1 }
1547 ac_line[ac_ln] = 10 as u8
1548 ac_ln = ac_ln + 1
1549 sys_write(ad_clk_fd, ac_line, ac_ln)
1550 } }
1551 }
1552 }
1553 } }
1554 // ---- ADNET public aggregate dashboard (/ad/dash): per-AD served/click counters
1555 // rendered LIVE from the append-only logs each request (BOUNDED reads, rule 21).
1556 // Aggregate-only by construction (logs carry ad ids, never visitor identity) ->
1557 // public transparency is safe; the page self-opts-out of slot injection.
1558 if dyn_done == 0 { if adnet_cfg_n > 0 {
1559 if sd2_contains(plain, hdr_n, "GET /ad/dash" as *u8, 12) == 1 {
1560 let dd_il: *u8 = sys_mmap(NX_MAGIC_1048576)
1561 let dd_iln: i64 = and_read_bounded(NX_SD2_ADNET_IMPLOG, dd_il, NX_MAGIC_1048576)
1562 let dd_cl: *u8 = sys_mmap(NX_MAGIC_1048576)
1563 let dd_cln: i64 = and_read_bounded(NX_SD2_ADNET_CLKLOG, dd_cl, NX_MAGIC_1048576)
1564 let dd_page: *u8 = sys_mmap(NX_MAGIC_262144)
1565 let dd_pn: i64 = and_page(adnet_cfg, adnet_cfg_n, dd_il, dd_iln, dd_cl, dd_cln, dd_page, NX_MAGIC_262144)
1566 if dd_pn > 0 {
1567 let dd_w: i64 = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "text/html; charset=utf-8" as *u8, dd_page, dd_pn)
1568 if dd_w > 0 { resp = dyn_buf; resp_n = dd_w; vhost_id = 29; dyn_done = 1 }
1569 }
1570 }
1571 } }
1572 // ---- SELF-SERVE advertiser intake (/ad/submit): GET renders the zero-JS form,
1573 // POST validates (fail-closed, same validators as serving) + stages to a NON-public
1574 // operator-review journal (nishihost/adnet_submissions.log). STAGED IS NOT LIVE.
1575 if dyn_done == 0 { if adnet_cfg_n > 0 {
1576 if sd2_contains(plain, hdr_n, " /ad/submit" as *u8, 11) == 1 {
1577 let su_page: *u8 = sys_mmap(NX_MAGIC_131072)
1578 var su_pn: i64 = 0
1579 if sd2_contains(plain, hdr_n, "POST /ad/submit" as *u8, 15) == 1 {
1580 let su_bs: i64 = sd2_body_start(plain, plain_n)
1581 let su_body: *u8 = ((plain as i64) + su_bs) as *u8
1582 let su_bn: i64 = plain_n - su_bs
1583 su_pn = asf_post(su_body, su_bn, "adnet_submissions.log" as *u8, su_page, NX_MAGIC_131072)
1584 } else {
1585 su_pn = asf_form_page(su_page, NX_MAGIC_131072)
1586 }
1587 if su_pn > 0 {
1588 let su_w: i64 = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "text/html; charset=utf-8" as *u8, su_page, su_pn)
1589 if su_w > 0 { resp = dyn_buf; resp_n = su_w; vhost_id = 31; dyn_done = 1 }
1590 }
1591 }
1592 } }
1593 // RACI: /video is OWNED solely by hr_resolve (clean URL -> video/index.html),
1594 // exactly like /games. The old bare-/video -> 301 /video/ rule here was a SECOND,
1595 // competing owner; colliding with the file server's slash handling it produced
1596 // "too many redirects". Removed per the single-owner principle -> /video falls
1597 // through to the file server (hr_serve2), which serves video/index.html directly.
1598 // /advertising (top-level, operator-only) -> 301 to the OPAQUE-gated census page
1599 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /advertising HTTP" as *u8, 21) == 1 {
1600 resp = RESP2_ADV_301; resp_n = sd2_strlen(RESP2_ADV_301); vhost_id = 26; dyn_done = 1
1601 } }
1602 // bare /status and /status/ -> /status.html (the live supervisor-emitted dashboard).
1603 // "GET /status HTTP"(16) matches ONLY exact /status (not /status.html -> ".html"!=" ").
1604 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /status HTTP" as *u8, 16) == 1 {
1605 resp = RESP2_STATUS_301; resp_n = sd2_strlen(RESP2_STATUS_301); vhost_id = 27; dyn_done = 1
1606 } }
1607 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /status/ HTTP" as *u8, 17) == 1 {
1608 resp = RESP2_STATUS_301; resp_n = sd2_strlen(RESP2_STATUS_301); vhost_id = 27; dyn_done = 1
1609 } }
1610 // ---- OPAQUE no-cookie login (sovereign): reverse-proxy /login,/register,
1611 // /whoami,/audio to the loopback login daemon (127.0.0.1:9091). This serves
1612 // nishifamily.com/login from the Nishi substrate itself -- NO nginx, NO third
1613 // party. ADDITIVE: a proxy miss leaves dyn_done=0 -> normal routing serves.
1614 if dyn_done == 0 { if sd2_is_login_route(plain, hdr_n) == 1 {
1615 let lpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_9091)
1616 if lpr > 0 { resp = dyn_buf; resp_n = lpr; vhost_id = 50; dyn_done = 1 }
1617 } }
1618 // ---- GALLERY (OPAQUE-gated, NSFW): reverse-proxy /gallery -> bridge
1619 // (127.0.0.1:18190) -> reverse-tunnel -> workstation gateway:18091 (OPAQUE
1620 // session check) -> gallery:18090. ADDITIVE: a proxy miss (bridge down)
1621 // leaves dyn_done=0 -> normal routing serves; /gallery is never a public byte
1622 // unless the OPAQUE gateway authorized it.
1623 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /gallery" as *u8, 9) == 1 {
1624 // STREAM /gallery (large video + images) chunk-by-chunk to the client --
1625 // NO 8MB dyn_buf cap, NO buffer-then-send latency. gst>=0 => already sent
1626 // (resp_n=0 skips the buffered D1 send); gst<0 => backend down, fall through.
1627 let gst: i64 = sd2_proxy_stream(s, cfd, plain, plain_n, NX_MAGIC_18190, out_rec)
1628 if gst >= 0 { served_bytes = served_bytes + gst; resp_n = 0; vhost_id = 60; dyn_done = 1; keep = 0 }
1629 } }
1630 // ---- WIKI (OPAQUE-gated, Nishi Family): reverse-proxy /wiki -> the wiki
1631 // gateway (127.0.0.1:18791; OPAQUE session check, no session -> login page).
1632 // ADDITIVE: a proxy miss (gateway down) leaves dyn_done=0 -> normal routing serves.
1633 if dyn_done == 0 { if sd2_wiki_gated(plain, hdr_n) == 1 {
1634 // no-cookie redirect fix: a TOP-LEVEL nav (Accept: text/html, NO X-Nishi-Session) gets the
1635 // return-aware bootstrap, not the wiki gateway's stale board()->hub login. Session-fetches +
1636 // assets (no text/html) still proxy unchanged -> no asset/content regression.
1637 var wiki_done: i64 = 0
1638 if sd2_contains(plain, hdr_n, "X-Nishi-Session" as *u8, 15) == 0 { if sd2_contains(plain, hdr_n, "text/html" as *u8, 9) == 1 {
1639 resp = dyn_buf; resp_n = sd2_build_resp(dyn_buf, ctype_html, BODY2_WIKI_BOOTSTRAP, sd2_strlen(BODY2_WIKI_BOOTSTRAP)); vhost_id = 61; dyn_done = 1; wiki_done = 1
1640 } }
1641 if wiki_done == 0 {
1642 let wgpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18791)
1643 if wgpr > 0 { resp = dyn_buf; resp_n = wgpr; vhost_id = 61; dyn_done = 1 }
1644 else { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 61; dyn_done = 1 }
1645 }
1646 } }
1647 // ---- HUB (OPAQUE-gated, maturity-flag leveled): reverse-proxy /hub -> the hub gateway
1648 // (127.0.0.1:18792; mr_route over the maturity registry; OPAQUE session -> level).
1649 // FAIL-CLOSED: a proxy miss -> 302 /login (never a public byte), mirroring /wiki.
1650 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /hub" as *u8, 5) == 1 {
1651 let hgpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18792)
1652 if hgpr > 0 { resp = dyn_buf; resp_n = hgpr; vhost_id = 62; dyn_done = 1 }
1653 else { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 62; dyn_done = 1 }
1654 } }
1655 // ---- GEN (Elder AI image generation, OPAQUE-gated owner): reverse-proxy /gen ->
1656 // the gen gateway (127.0.0.1:18794; family OPAQUE session + he_has_access(/gen) ->
1657 // orchestrator :18795 -> laptop 5080). FAIL-CLOSED: a proxy miss (gateway down) ->
1658 // 302 /login (never a public byte), mirroring /wiki,/hub. ADDITIVE: the leading-space
1659 // " /gen" matches only the request-line path, never a header, so other sites are untouched.
1660 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /gen" as *u8, 5) == 1 {
1661 let ggpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18794)
1662 if ggpr > 0 { resp = dyn_buf; resp_n = ggpr; vhost_id = 64; dyn_done = 1 }
1663 else { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 64; dyn_done = 1 }
1664 } }
1665 // ---- TORRENT/MEDIA acquirer (OPAQUE-gated, owner): reverse-proxy /torrent -> the
1666 // torrent gateway (127.0.0.1:18793; OPAQUE session -> X-Nishi-Level:OWNER -> daemon :8097).
1667 // STREAMED (the acquirer serves video). ADDITIVE: a proxy miss leaves dyn_done=0 -> normal routing.
1668 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /torrent" as *u8, 9) == 1 {
1669 let tst: i64 = sd2_proxy_stream(s, cfd, plain, plain_n, NX_MAGIC_18793, out_rec)
1670 if tst >= 0 { served_bytes = served_bytes + tst; resp_n = 0; vhost_id = 63; dyn_done = 1 }
1671 } }
1672 // ---- STUDIO (OPAQUE-gated, operator-only): reverse-proxy /studio -> NAS-local
1673 // gated daemon (127.0.0.1:18099; OPAQUE session check, no token -> 401). ADDITIVE:
1674 // a proxy miss leaves dyn_done=0 -> normal routing serves; /studio is never a
1675 // public byte unless the OPAQUE gate authorized it. [[project-image-stack-ownership-2026-06-17]]
1676 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /studio" as *u8, 8) == 1 {
1677 let spr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18099)
1678 if spr > 0 { resp = dyn_buf; resp_n = spr; vhost_id = 61; dyn_done = 1 }
1679 } }
1680 // ---- LIBRARY (nishifamily.com/library): reverse-proxy /library -> the
1681 // auth-walled Calibre reader (127.0.0.1:8791, keeper-supervised). The reader
1682 // is /library-prefix-aware (input-strips /library, serves <base href=/library/>).
1683 // ADDITIVE: a proxy miss (reader down) leaves dyn_done=0 -> normal routing serves.
1684 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /library" as *u8, 9) == 1 {
1685 let lipr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_8791)
1686 if lipr > 0 { resp = dyn_buf; resp_n = lipr; vhost_id = 61; dyn_done = 1 }
1687 } }
1688 // ---- MEDIA (nishifamily.com/media): the FAMILY-facing SFW library -> the SAME
1689 // auth-walled media reader (127.0.0.1:8791). The reader is /media-prefix-aware +
1690 // denies the owner-only /mnt/nas_logging (galx_media_path_ok) so family gets SFW
1691 // only; the owner-only recordings/NSFW are /gallery. ADDITIVE: a miss falls through.
1692 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /media" as *u8, 7) == 1 {
1693 let mepr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_8791)
1694 if mepr > 0 { resp = dyn_buf; resp_n = mepr; vhost_id = 61; dyn_done = 1 }
1695 } }
1696 // ---- D5: circles ----
1697 if sd2_contains(plain, hdr_n, "POST /video/circle?" as *u8, 19) == 1 {
1698 resp_n = sd2_circle_upload(s, cfd, plain, plain_n, rec_buf, pump, dyn_buf)
1699 resp = dyn_buf; vhost_id = 22; dyn_done = 1
1700 }
1701 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /video/circles" as *u8, 18) == 1 {
1702 resp_n = sd2_circle_list(plain, plain_n, dyn_buf)
1703 resp = dyn_buf; vhost_id = 23; dyn_done = 1
1704 } }
1705 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /video/circle/" as *u8, 18) == 1 {
1706 resp_n = sd2_circle_play(plain, plain_n, dyn_buf)
1707 resp = dyn_buf; vhost_id = 24; dyn_done = 1
1708 } }
1709 // ---- wiki dynamic routes (v1 behaviour) ----
1710 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "POST /wiki/request" as *u8, 18) == 1 {
1711 let bstart: i64 = sd2_body_start(plain, plain_n)
1712 let dnq: *i64 = (sys_mmap(8)) as *i64
1713 dnq[0] = 0
1714 let prc: i64 = nx_wiki_request_handle((plain as i64 + bstart) as *u8, plain_n - bstart, dyn_buf, NX_SD2_DYN_CAP, dnq)
1715 if prc == 0 { resp = dyn_buf; resp_n = dnq[0]; vhost_id = 10; dyn_done = 1 }
1716 } }
1717 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "/wiki/queue" as *u8, 11) == 1 {
1718 let dnq2: *i64 = (sys_mmap(8)) as *i64
1719 dnq2[0] = 0
1720 let qrc: i64 = nx_wiki_queue_handle(dyn_buf, NX_SD2_DYN_CAP, dnq2)
1721 if qrc == 0 { resp = dyn_buf; resp_n = dnq2[0]; vhost_id = 11; dyn_done = 1 }
1722 } }
1723 // ---- D3: hot file hosting with fallthrough (+ universal ADNET slot injection).
1724 // adnet_cfg_n==0 OR host not @host-enabled -> slot_n=0 -> hr_serve3_slot is
1725 // BYTE-IDENTICAL to hr_serve3 (gated do-no-harm law) -> zero behavior change.
1726 if dyn_done == 0 {
1727 let nbox: *i64 = (sys_mmap(8)) as *i64
1728 var ad_slot_n: i64 = 0
1729 let ad_slotb: *u8 = sys_mmap(NX_MAGIC_8192)
1730 let ad_sid: *u8 = sys_mmap(128)
1731 let ad_injb: *i64 = (sys_mmap(8)) as *i64
1732 ad_injb[0] = 0
1733 if adnet_cfg_n > 0 {
1734 let ad_host: *u8 = sys_mmap(256)
1735 hr_req_host(plain, plain_n, ad_host, 256)
1736 let ad_hok: i64 = aslot_host_ok(adnet_cfg, adnet_cfg_n, ad_host)
1737 if ad_hok == 1 {
1738 let ad_path: *u8 = sys_mmap(NX_MAGIC_4096)
1739 let ad_pn: i64 = hr_req_path(plain, hdr_n, ad_path, NX_MAGIC_4096)
1740 let ad_now: i64 = sys_now_us()
1741 let ad_rot: i64 = ad_now / NX_SD2_ADNET_ROT_US
1742 ad_slot_n = aslot_html(adnet_cfg, adnet_cfg_n, ad_path, ad_pn, ad_rot, ad_slotb, NX_MAGIC_8192, ad_sid)
1743 // WIRE THE VIEWABILITY OBSERVER (debt 1785512185). Appended to the slot bytes BEFORE
1744 // hr_serve3_slot merges them, so Content-Length stays correct by construction. A refused
1745 // emit (bad id / no room) leaves ad_slot_n untouched -> the slot serves exactly as before.
1746 if ad_slot_n > 0 { if ad_sid[0] != (0 as u8) {
1747 let av_n: i64 = aview_script(((ad_slotb as i64) + ad_slot_n) as *u8, NX_MAGIC_8192 - ad_slot_n, ad_sid)
1748 if av_n > 0 { ad_slot_n = ad_slot_n + av_n }
1749 } }
1750 }
1751 }
1752 let sv: i64 = hr_serve3_slot(sites_cfg, sites_cfg_n, plain, plain_n, dyn_buf, NX_SD2_DYN_CAP, nbox, ad_slotb, ad_slot_n, ad_injb)
1753 if sv == HR_S2_OK { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 }
1754 if sv == HR_S2_OK { if ad_injb[0] == 1 { if ad_imp_fd >= 0 { if ad_sid[0] != (0 as u8) {
1755 let ai_line: *u8 = sys_mmap(160)
1756 var ai_ln: i64 = 0
1757 while ad_sid[ai_ln] != (0 as u8) { ai_line[ai_ln] = ad_sid[ai_ln]; ai_ln = ai_ln + 1 }
1758 ai_line[ai_ln] = 10 as u8
1759 ai_ln = ai_ln + 1
1760 sys_write(ad_imp_fd, ai_line, ai_ln)
1761 } } } }
1762 if sv == HR_S2_REDIR { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 }
1763 if sv == HR_S2_BAD { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 }
1764 if sv == HR_S2_TOOBIG { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 }
1765 if sv == HR_S2_STREAM {
1766 // ZERO-CEILING STREAM (debt 1785879638): headers then the oversize body through
1767 // the SAME chunked TLS send that carries every response -- no size constant on
1768 // this path; anything the host can mmap serves. Connection closes after (exact
1769 // Content-Length + close = valid HTTP; keep-alive resumes on the next connect).
1770 let sh: i64 = nx_tls13_app_send_fd(s, dyn_buf, nbox[0], cfd, out_rec, NX_SD2_OUTREC)
1771 if sh >= 0 {
1772 let sb: i64 = nx_tls13_app_send_fd(s, hr_stream_body() as *u8, hr_stream_bodyn(), cfd, out_rec, NX_SD2_OUTREC)
1773 if sb >= 0 { served_bytes = served_bytes + nbox[0] + hr_stream_bodyn(); nreq = nreq + 1 }
1774 }
1775 resp = dyn_buf
1776 resp_n = 0
1777 vhost_id = 20
1778 dyn_done = 1
1779 }
1780 // MISS on andelinwest = REAL 404 (its real site is file-based;
1781 // never bleed the family placeholder onto it)
1782 if sv == HR_S2_MISS {
1783 if sd2_contains(plain, hdr_n, "andelinwest" as *u8, 11) == 1 {
1784 if sd2_contains(plain, hdr_n, "GET / HTTP" as *u8, 10) == 0 {
1785 resp_n = hr_emit_404(dyn_buf, NX_SD2_DYN_CAP)
1786 resp = dyn_buf; vhost_id = 20; dyn_done = 1
1787 }
1788 }
1789 }
1790 }
1791 // ---- live wiki engine proxy (imported corpus + search) ----
1792 // GET /wiki/<slug> that hr_serve2 MISSED, isn't a .html hot file,
1793 // and isn't a baked route -> reverse-proxy to the loopback wiki
1794 // engine (127.0.0.1:51850). ADDITIVE: on any failure dyn_done stays
1795 // 0 and the existing baked placeholder serves (never breaks the site).
1796 if dyn_done == 0 {
1797 if sd2_contains(plain, hdr_n, "GET /wiki/" as *u8, 10) == 1 {
1798 var wbaked: i64 = 0
1799 if sd2_contains(plain, hdr_n, ".html" as *u8, 5) == 1 { wbaked = 1 }
1800 if sd2_contains(plain, hdr_n, "/wiki/roadmap" as *u8, 13) == 1 { wbaked = 1 }
1801 if sd2_contains(plain, hdr_n, "/wiki/status" as *u8, 12) == 1 { wbaked = 1 }
1802 if sd2_contains(plain, hdr_n, "/wiki/components" as *u8, 16) == 1 { wbaked = 1 }
1803 if sd2_contains(plain, hdr_n, "/wiki/component/" as *u8, 16) == 1 { wbaked = 1 }
1804 if sd2_contains(plain, hdr_n, "/wiki/projects" as *u8, 14) == 1 { wbaked = 1 }
1805 if sd2_contains(plain, hdr_n, "/wiki/request" as *u8, 13) == 1 { wbaked = 1 }
1806 if sd2_contains(plain, hdr_n, "/wiki/queue" as *u8, 11) == 1 { wbaked = 1 }
1807 if wbaked == 0 {
1808 let wpr: i64 = sd2_wiki_proxy(plain, plain_n, dyn_buf)
1809 if wpr > 0 { resp = dyn_buf; resp_n = wpr; vhost_id = 40; dyn_done = 1 }
1810 }
1811 }
1812 }
1813 // ---- legacy hot roadmap + baked routes (v1) ----
1814 if dyn_done == 0 {
1815 if sd2_contains(plain, hdr_n, "/wiki/roadmap" as *u8, 13) == 1 {
1816 let rlb: *i64 = (sys_mmap(8)) as *i64
1817 rlb[0] = 0
1818 let rbuf: *u8 = sys_read_file("/volume1/homes/elderwesto/nishihost/wiki/roadmap.html" as *u8, rlb)
1819 if (rbuf as i64) != 0 { resp = dyn_buf; resp_n = sd2_build_resp(dyn_buf, ctype_html, rbuf, rlb[0]); vhost_id = 30; dyn_done = 1 }
1820 }
1821 }
1822 if dyn_done == 0 {
1823 let is_andelin: i64 = sd2_contains(plain, hdr_n, "andelinwest" as *u8, 11)
1824 let is_wiki: i64 = sd2_contains(plain, hdr_n, "/wiki" as *u8, 5)
1825 let is_wstatus: i64 = sd2_contains(plain, hdr_n, "/wiki/status" as *u8, 12)
1826 let is_cidx: i64 = sd2_contains(plain, hdr_n, "/wiki/components" as *u8, 16)
1827 let is_proj: i64 = sd2_contains(plain, hdr_n, "/wiki/projects" as *u8, 14)
1828 let is_cr: i64 = sd2_contains(plain, hdr_n, "/wiki/component/crawler" as *u8, 23)
1829 let is_xx: i64 = sd2_contains(plain, hdr_n, "/wiki/component/x25519" as *u8, 22)
1830 let is_rk: i64 = sd2_contains(plain, hdr_n, "/wiki/component/ranking-math" as *u8, 28)
1831 let is_we: i64 = sd2_contains(plain, hdr_n, "/wiki/component/wiki-engine" as *u8, 27)
1832 if is_andelin == 1 {
1833 resp = resp_andelin; resp_n = n_andelin; vhost_id = 1
1834 } else {
1835 if is_wiki == 1 { resp = resp_wiki; resp_n = n_wiki; vhost_id = 2 }
1836 if is_wstatus == 1 { resp = resp_wstatus; resp_n = n_wstatus; vhost_id = 3 }
1837 if is_cidx == 1 { resp = resp_components; resp_n = n_components; vhost_id = 8 }
1838 if is_proj == 1 { resp = resp_projects; resp_n = n_projects; vhost_id = 12 }
1839 if is_cr == 1 { resp = resp_art_crawler; resp_n = n_art_crawler; vhost_id = 4 }
1840 if is_xx == 1 { resp = resp_art_x25519; resp_n = n_art_x25519; vhost_id = 5 }
1841 if is_rk == 1 { resp = resp_art_ranking; resp_n = n_art_ranking; vhost_id = 6 }
1842 if is_we == 1 { resp = resp_art_wiki; resp_n = n_art_wiki; vhost_id = 7 }
1843 }
1844 }
1845 }
1846 // ---- SOFT-404 ROOT FIX (2026-07-30) ------------------------------------------
1847 // MEASURED: GET /zzz-not-a-page-12345 on nishifamily.com returned 200 with the
1848 // baked 835-byte family stub. Every unmatched path did. That burns crawl budget on
1849 // infinite phantom URLs AND makes a publishing-registry status of `withdrawn`
1850 // structurally unenforceable -- the page keeps answering 200 forever.
1851 // The test is `resp is STILL the family stub`, not `dyn_done == 0`: the baked-route
1852 // block below assigns resp WITHOUT setting dyn_done, so keying on dyn_done would
1853 // 404 legitimately-served pages. Pointer identity is exact -- the ONLY state that
1854 // changes is `nothing matched at all, for a non-root path`.
1855 // The root keeps the stub: that is the never-brick fallback for an absent home.html.
1856 if (resp as i64) == (resp_family as i64) {
1857 if sd2_contains(plain, hdr_n, "GET / HTTP" as *u8, 10) == 0 {
1858 resp_n = hr_emit_404(dyn_buf, NX_SD2_DYN_CAP)
1859 resp = dyn_buf
1860 vhost_id = 22
1861 }
1862 }
1863 // ---- D1: chunked send (any size up to DYN_CAP) ----
1864 if resp_n > 0 {
1865 let sent: i64 = nx_tls13_app_send_fd(s, resp, resp_n, cfd, out_rec, NX_SD2_OUTREC)
1866 if sent < 0 { keep = 0 }
1867 else { served_bytes = served_bytes + resp_n; nreq = nreq + 1; sys_set_socket_timeout(cfd, NX_SD2_KA_IDLE_S) }
1868 } else { keep = 0 }
1869 }
1870 }
1871 }
1872 }
1873 }
1874 sys_close(cfd)
1875 nx_telemetry_emit(tel_fd, tel_buf, sys_now_us(), acc_lan, vhost_id,
1876 hs_us, served_bytes, hs_stat)
1877 sys_exit(0)
1878 }
1879
1880 sys_close(cfd)
1881 if pid > 0 { live = live + 1 }
1882 served = served + 1
1883 }
1884 sys_close(lfd)
1885 return 0
1886}