code wiki / _hdl_build / _galx_serve_gate.nx

_galx_serve_gate.nx source

↩ module page · 325 lines · 18658 B

1import "nx_gate_gn.nx" 2import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 3// _galx_serve_gate.nx -- NO-FAKE-GREEN gate for the spec2 gallery daemon (X-GALX-SERVE). 4// Runs the REAL pipeline end to end (no mocks): nx_eg authors nx_gallery_serve.nx HANDS-OFF from the 5// which==2 structural route-spec, the sovereign nx_cc compiles it, the gate forks+execs the ELF, binds 6// 127.0.0.1:18090, and a real HTTP client proves every behavior that constant-lifting cannot fake: 7// (1) BIND -- author + compile + exec; poll-connect 18090 until LISTEN (RED on timeout). 8// (2) BROWSE -- GET / -> 200 AND the grid body lists the TWO REAL ingested CIDs (6a59.. + 8600..), 9// proving the grid is read from ss_manifest, not a baked constant. 10// (3) IMG-BYTES -- GET /img/<CID-A> -> 200 + Content-Type: image/png AND the served body tail is 11// byte-identical to the on-disk _g1work/genrec_multi.png (re-read + compare). 12// (4) RATE -- snapshot eval_lanes.log line count; POST /rate (same-origin Origin) score=850 -> 13// EXACTLY ONE new line appended equal to "EVAL img=<CID-A> lane=O score=850". 14// (5) TAMPER-RED -- re-author with tamper=1 (route literals flipped), recompile, bind ALT port 18091; 15// GET /img/<CID-A> now MUST 404 (route synthesized, not baked) = behavioral RED. 16// (6) SAME-ORIGIN -- POST /rate with a FOREIGN Origin -> 403 AND eval_lanes.log line count UNCHANGED. 17// All 6 GREEN -> GALXSERVE verdict=GREEN to knowledge/status/galx_serve.log; any RED -> exit 1. The 18// daemons are killed (nx_kill the forked pids) at end so the gate is idempotently re-runnable (rule 10). 19// Sovereign (nx_cc/sovereign cc; gcc is the off-band assembler only). license_tier: ORIGINAL 20import "nx_syscalls.nx" 21 22func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 23func gfp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 24func gfn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 25 26// exec prog with up to 3 string args; stdout+stderr -> /dev/null. returns child WEXITSTATUS. 27func g_run(prog: *u8, a1: *u8, a2: *u8, a3: *u8) -> i64 { 28 let pid: i64 = sys_fork() 29 if pid == 0 { 30 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 31 if dn >= 0 { sys_dup3(dn, 1, 0) } 32 if dn >= 0 { sys_dup3(dn, 2, 0) } 33 let argv: *i64 = sys_mmap(64) as *i64 34 argv[0] = prog as i64 35 var k: i64 = 1 36 if a1 != (0 as *u8) { argv[k] = a1 as i64; k = k + 1 } 37 if a2 != (0 as *u8) { argv[k] = a2 as i64; k = k + 1 } 38 if a3 != (0 as *u8) { argv[k] = a3 as i64; k = k + 1 } 39 argv[k] = 0 40 let envp: *i64 = sys_mmap(16) as *i64 41 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 42 sys_execve(prog, argv, envp) 43 sys_exit(127) 44 } 45 let st: *i64 = sys_mmap(16) as *i64 46 sys_wait4(pid, st, 0) 47 return (st[0] >> 8) & 0xff 48} 49 50// fork+exec an ELF as a long-lived daemon (NOT waited on). Returns the child pid. 51func g_spawn(prog: *u8) -> i64 { 52 let pid: i64 = sys_fork() 53 if pid == 0 { 54 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 55 if dn >= 0 { sys_dup3(dn, 1, 0) } 56 let argv: *i64 = sys_mmap(32) as *i64 57 argv[0] = prog as i64; argv[1] = 0 58 let envp: *i64 = sys_mmap(16) as *i64 59 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 60 sys_execve(prog, argv, envp) 61 sys_exit(127) 62 } 63 return pid 64} 65 66// build a sockaddr_in for 127.0.0.1:<port> into a 16-byte mmap; return the ptr. 67func g_addr(port: i64) -> *u8 { 68 let addr: *u8 = sys_mmap(16) 69 addr[0] = 2 as u8 70 addr[1] = 0 as u8 71 addr[2] = ((port >> 8) & 0xff) as u8 72 addr[3] = (port & 0xff) as u8 73 addr[4] = 127 as u8 74 addr[5] = 0 as u8 75 addr[6] = 0 as u8 76 addr[7] = 1 as u8 77 addr[8] = 0 as u8 78 addr[9] = 0 as u8 79 addr[10] = 0 as u8 80 addr[11] = 0 as u8 81 addr[12] = 0 as u8 82 addr[13] = 0 as u8 83 addr[14] = 0 as u8 84 addr[15] = 0 as u8 85 return addr 86} 87 88// connect a fresh socket to 127.0.0.1:<port>; return fd (>=0) or -1. 89func g_connect(port: i64) -> i64 { 90 let fd: i64 = sys_socket(2, 1, 0) 91 if fd < 0 { return 0 - 1 } 92 let addr: *u8 = g_addr(port) 93 let rc: i64 = nx_connect_bounded(fd, addr, 16, NX_CONN_DEFAULT_MS) 94 if rc < 0 { sys_close(fd); return 0 - 1 } 95 return fd 96} 97 98// poll-connect until the daemon LISTENs (up to ~50 tries x 100ms). Returns 1 ok, 0 timeout. 99func g_wait_listen(port: i64) -> i64 { 100 var tries: i64 = 0 101 while tries < 50 { 102 let fd: i64 = g_connect(port) 103 if fd >= 0 { sys_close(fd); return 1 } 104 sys_sleep_ms(100) 105 tries = tries + 1 106 } 107 return 0 108} 109 110// send req then read the whole response into out (cap); return byte count. 111func g_http(port: i64, req: *u8, reqlen: i64, out: *u8, cap: i64) -> i64 { 112 let fd: i64 = g_connect(port) 113 if fd < 0 { return 0 - 1 } 114 sys_write(fd, req, reqlen) 115 var n: i64 = 0 116 var go: i64 = 1 117 while go == 1 { 118 let r: i64 = sys_read(fd, (out as i64 + n) as *u8, cap - 1 - n) 119 if r <= 0 { go = 0 } else { n = n + r } 120 if n >= cap - 1 { go = 0 } 121 } 122 sys_close(fd) 123 return n 124} 125 126// does buf[0..n) contain the plen bytes of pat contiguously? 127func g_find(buf: *u8, n: i64, pat: *u8, plen: i64) -> i64 { 128 var i: i64 = 0 129 while i + plen <= n { 130 var j: i64 = 0 131 var ok: i64 = 1 132 while j < plen { if buf[i+j] != pat[j] { ok = 0 } j = j + 1 } 133 if ok == 1 { return 1 } 134 i = i + 1 135 } 136 return 0 137} 138 139func g_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 140 141// count '\n' bytes in a file (line count for the eval-log snapshot). 142func g_linecount(path: *u8) -> i64 { 143 let szp: *i64 = sys_mmap(16) as *i64 144 let b: *u8 = sys_read_file(path, szp) 145 let sz: i64 = szp[0] 146 if (b as i64) == 0 { return 0 } 147 var c: i64 = 0 148 var i: i64 = 0 149 while i < sz { if b[i] == (10 as u8) { c = c + 1 } i = i + 1 } 150 return c 151} 152 153func main() -> i64 { 154 gp("=== gallery-serve gate (structural-spec -> nx_eg-authored daemon -> real bind/browse/img/rate/tamper) ===\n" as *u8) 155 let lfd: i64 = sys_openat_append("knowledge/status/galx_serve.log" as *u8, 0x1a4) 156 157 let cidA: *u8 = "nxc1-6a59140bf7491b8c70f94820872874c73d3737603db1dc100a6bdcfbb2081738" as *u8 158 let cidB: *u8 = "nxc1-8600a9243cc7614463a825e3a1129f37f3c047de5ea52726bfa764baa87e58b5" as *u8 159 160 // ---- ARM 1: author + compile (hands-off) ---- 161 // author the gallery daemon from spec2 (which==2, clean). 162 let a1: i64 = g_run("/tmp/nx_eg.sov.elf" as *u8, "2" as *u8, "nx_gallery_serve" as *u8, 0 as *u8) 163 if a1 != 0 { gp("GALXSERVE RED: nx_eg author (which=2) failed rc="); gn(a1); gp("\n" as *u8); sys_exit(1); return 1 } 164 let b1: i64 = g_run("runtime/_hdl_build/_galx_build_one.sh" as *u8, "nx_gallery_serve" as *u8, 0 as *u8, 0 as *u8) 165 if b1 != 0 { gp("GALXSERVE RED: compile of authored daemon failed rc="); gn(b1); gp("\n" as *u8); sys_exit(1); return 1 } 166 // set up the serve namespace + sidecar (real ingest of the 2 corpus PNGs). 167 let bs: i64 = g_run("/tmp/setup.elf" as *u8, 0 as *u8, 0 as *u8, 0 as *u8) 168 if bs != 0 { gp("GALXSERVE RED: data setup (ingest) failed rc="); gn(bs); gp("\n" as *u8); sys_exit(1); return 1 } 169 // spawn the daemon, poll until it binds. 170 let dpid: i64 = g_spawn("/tmp/nx_gallery_serve.elf" as *u8) 171 let up: i64 = g_wait_listen(18090) 172 if up != 1 { gp("GALXSERVE RED: daemon never bound 127.0.0.1:18090\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 173 gp("GATE ROW bind: GREEN -- nx_eg authored + sovereign-cc compiled the daemon; it bound 127.0.0.1:18090\n" as *u8) 174 175 let resp: *u8 = sys_mmap(524288) 176 177 // ---- ARM 2: BROWSE lists the REAL ingested CIDs ---- 178 let getroot: *u8 = "GET / HTTP/1.1\r\nHost: 127.0.0.1:18090\r\nConnection: close\r\n\r\n" as *u8 179 let rn2: i64 = g_http(18090, getroot, g_strlen(getroot), resp, 524288) 180 var ok200: i64 = g_find(resp, rn2, "HTTP/1.1 200" as *u8, 12) 181 var hasA: i64 = g_find(resp, rn2, cidA, 69) 182 var hasB: i64 = g_find(resp, rn2, cidB, 69) 183 if ok200 != 1 { gp("GALXSERVE RED: GET / not 200\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 184 if hasA != 1 { gp("GALXSERVE RED: GET / grid missing CID-A (6a59..) -- not read from ss_manifest\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 185 if hasB != 1 { gp("GALXSERVE RED: GET / grid missing CID-B (8600..)\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 186 gp("GATE ROW browse: GREEN -- GET / 200 and the grid lists BOTH real ingested CIDs (6a59.. + 8600..) from the live store\n" as *u8) 187 188 // ---- ARM 3: IMG-BYTES byte-identical to on-disk PNG ---- 189 let getimg: *u8 = sys_mmap(512) 190 var gio: i64 = 0 191 gio = g_strlen("GET /img/") 192 var w: i64 = 0 193 let p1: *u8 = "GET /img/" as *u8 194 while w < gio { getimg[w] = p1[w]; w = w + 1 } 195 var c: i64 = 0 196 while c < 69 { getimg[gio + c] = cidA[c]; c = c + 1 } 197 let p2: *u8 = " HTTP/1.1\r\nHost: 127.0.0.1:18090\r\nConnection: close\r\n\r\n" as *u8 198 var p2l: i64 = g_strlen(p2) 199 var w2: i64 = 0 200 while w2 < p2l { getimg[gio + 69 + w2] = p2[w2]; w2 = w2 + 1 } 201 let imgreqlen: i64 = gio + 69 + p2l 202 let rn3: i64 = g_http(18090, getimg, imgreqlen, resp, 524288) 203 var imgok: i64 = g_find(resp, rn3, "HTTP/1.1 200" as *u8, 12) 204 var imgct: i64 = g_find(resp, rn3, "Content-Type: image/png" as *u8, 23) 205 if imgok != 1 { gp("GALXSERVE RED: GET /img/<A> not 200\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 206 if imgct != 1 { gp("GALXSERVE RED: GET /img/<A> missing image/png content-type\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 207 // find the body start (CRLFCRLF) and byte-compare the tail to the on-disk PNG. 208 var bi: i64 = 0 209 var bodyat: i64 = 0 - 1 210 while bi + 4 <= rn3 { 211 var okb: i64 = 1 212 if resp[bi] != (13 as u8) { okb = 0 } 213 if resp[bi+1] != (10 as u8) { okb = 0 } 214 if resp[bi+2] != (13 as u8) { okb = 0 } 215 if resp[bi+3] != (10 as u8) { okb = 0 } 216 if okb == 1 { if bodyat < 0 { bodyat = bi + 4 } } 217 bi = bi + 1 218 } 219 if bodyat < 0 { gp("GALXSERVE RED: GET /img/<A> no body delimiter\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 220 let szp: *i64 = sys_mmap(16) as *i64 221 let disk: *u8 = sys_read_file("_g1work/genrec_multi.png" as *u8, szp) 222 let dlen: i64 = szp[0] 223 let servedlen: i64 = rn3 - bodyat 224 if servedlen != dlen { gp("GALXSERVE RED: served PNG length != on-disk ("); gn(servedlen); gp(" vs "); gn(dlen); gp(")\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 225 var bc: i64 = 0 226 var bmatch: i64 = 1 227 while bc < dlen { if resp[bodyat + bc] != disk[bc] { bmatch = 0 } bc = bc + 1 } 228 if bmatch != 1 { gp("GALXSERVE RED: served PNG bytes != on-disk genrec_multi.png\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 229 gp("GATE ROW img-bytes: GREEN -- GET /img/<A> 200 image/png and the served body is byte-identical to on-disk genrec_multi.png ("); gn(dlen); gp(" bytes)\n" as *u8) 230 231 // ---- ARM 4: RATE writes EXACTLY one EVAL O-line ---- 232 let before: i64 = g_linecount("knowledge/status/eval_lanes.log" as *u8) 233 // build the POST body img=<A>&score=850 234 let body4: *u8 = sys_mmap(256) 235 var b4: i64 = 0 236 let bp1: *u8 = "img=" as *u8 237 var t1: i64 = 0; while bp1[t1]!=(0 as u8){body4[b4]=bp1[t1]; b4=b4+1; t1=t1+1} 238 c = 0; while c < 69 { body4[b4] = cidA[c]; b4 = b4 + 1; c = c + 1 } 239 let bp2: *u8 = "&score=850" as *u8 240 var t2: i64 = 0; while bp2[t2]!=(0 as u8){body4[b4]=bp2[t2]; b4=b4+1; t2=t2+1} 241 // build the full POST request with same-origin headers 242 let post: *u8 = sys_mmap(1024) 243 var po: i64 = 0 244 let hp: *u8 = "POST /rate HTTP/1.1\r\nHost: 127.0.0.1:18090\r\nOrigin: http://127.0.0.1:18090\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: " as *u8 245 var th: i64 = 0; while hp[th]!=(0 as u8){post[po]=hp[th]; po=po+1; th=th+1} 246 // content-length = b4 247 let clbuf: *u8 = sys_mmap(28); var clm: i64 = b4; var clk: i64 = 0; if clm==0{clbuf[0]=48;clk=1}; let clt: *u8=sys_mmap(28); while clm>0{clt[clk]=(48+(clm%10)) as u8;clm=clm/10;clk=clk+1}; var cli: i64=0; while cli<clk{post[po]=clt[clk-1-cli];po=po+1;cli=cli+1} 248 let hp2: *u8 = "\r\nConnection: close\r\n\r\n" as *u8 249 var th2: i64 = 0; while hp2[th2]!=(0 as u8){post[po]=hp2[th2]; po=po+1; th2=th2+1} 250 var bb4: i64 = 0; while bb4 < b4 { post[po] = body4[bb4]; po = po + 1; bb4 = bb4 + 1 } 251 let rn4: i64 = g_http(18090, post, po, resp, 524288) 252 var rateok: i64 = g_find(resp, rn4, "HTTP/1.1 200" as *u8, 12) 253 if rateok != 1 { gp("GALXSERVE RED: POST /rate (same-origin) not 200\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 254 let after: i64 = g_linecount("knowledge/status/eval_lanes.log" as *u8) 255 if after != before + 1 { gp("GALXSERVE RED: POST /rate did not append EXACTLY one line ("); gn(before); gp(" -> "); gn(after); gp(")\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 256 // verify the LAST line equals the expected EVAL O-line. 257 let lszp: *i64 = sys_mmap(16) as *i64 258 let lb: *u8 = sys_read_file("knowledge/status/eval_lanes.log" as *u8, lszp) 259 let lsz: i64 = lszp[0] 260 // build expected: EVAL img=<A> lane=O score=850\n 261 let exp: *u8 = sys_mmap(256) 262 var eo: i64 = 0 263 let e1: *u8 = "EVAL img=" as *u8 264 var te1: i64=0; while e1[te1]!=(0 as u8){exp[eo]=e1[te1];eo=eo+1;te1=te1+1} 265 c = 0; while c < 69 { exp[eo] = cidA[c]; eo = eo + 1; c = c + 1 } 266 let e2: *u8 = " lane=O score=850\n" as *u8 267 var te2: i64=0; while e2[te2]!=(0 as u8){exp[eo]=e2[te2];eo=eo+1;te2=te2+1} 268 // the file tail (last eo bytes) must equal exp. 269 var tailmatch: i64 = 1 270 if lsz < eo { tailmatch = 0 } 271 if tailmatch == 1 { 272 var em: i64 = 0 273 while em < eo { if lb[lsz - eo + em] != exp[em] { tailmatch = 0 } em = em + 1 } 274 } 275 if tailmatch != 1 { gp("GALXSERVE RED: appended line != 'EVAL img=<A> lane=O score=850'\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 276 gp("GATE ROW rate: GREEN -- POST /rate (same-origin) appended EXACTLY one line == 'EVAL img=<A> lane=O score=850'\n" as *u8) 277 278 // ---- ARM 6: SAME-ORIGIN -- a FOREIGN Origin -> 403 AND no write ---- 279 let before6: i64 = g_linecount("knowledge/status/eval_lanes.log" as *u8) 280 let post6: *u8 = sys_mmap(1024) 281 var po6: i64 = 0 282 let fp: *u8 = "POST /rate HTTP/1.1\r\nHost: 127.0.0.1:18090\r\nOrigin: http://evil.example.com\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: " as *u8 283 var tf: i64 = 0; while fp[tf]!=(0 as u8){post6[po6]=fp[tf]; po6=po6+1; tf=tf+1} 284 var cli6: i64=0; while cli6<clk{post6[po6]=clt[clk-1-cli6];po6=po6+1;cli6=cli6+1} 285 var tf2: i64 = 0; while hp2[tf2]!=(0 as u8){post6[po6]=hp2[tf2]; po6=po6+1; tf2=tf2+1} 286 var bb6: i64 = 0; while bb6 < b4 { post6[po6] = body4[bb6]; po6 = po6 + 1; bb6 = bb6 + 1 } 287 let rn6: i64 = g_http(18090, post6, po6, resp, 524288) 288 var forbidden: i64 = g_find(resp, rn6, "HTTP/1.1 403" as *u8, 12) 289 let after6: i64 = g_linecount("knowledge/status/eval_lanes.log" as *u8) 290 if forbidden != 1 { gp("GALXSERVE RED: cross-origin POST /rate not 403\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 291 if after6 != before6 { gp("GALXSERVE RED: cross-origin POST /rate WROTE to the log ("); gn(before6); gp(" -> "); gn(after6); gp(")\n" as *u8); nx_kill(dpid, 9); sys_exit(1); return 1 } 292 gp("GATE ROW same-origin: GREEN -- cross-origin POST /rate -> 403 and eval_lanes.log line count UNCHANGED (no write)\n" as *u8) 293 294 // done with the clean daemon -- kill it. 295 nx_kill(dpid, 9) 296 let stk: *i64 = sys_mmap(16) as *i64 297 sys_wait4(dpid, stk, 0) 298 299 // ---- ARM 5: TAMPER-RED -- re-author with tamper, bind ALT port 18091, GET /img/<A> MUST 404 ---- 300 // NOTE: the tamper daemon (port 18090) flips routes; to avoid colliding with a lingering socket and to 301 // prove the tamper independently, we author a SECOND tamper daemon that binds the alt port 18091. 302 let at: i64 = g_run("/tmp/nx_eg.sov.elf" as *u8, "2" as *u8, "nx_gallery_serve_tamper" as *u8, "1" as *u8) 303 if at != 0 { gp("GALXSERVE RED: tamper author failed\n" as *u8); sys_exit(1); return 1 } 304 // patch the authored tamper source's port 18090 -> 18091 via a tiny re-author helper is overkill; 305 // instead the tamper binds 18090 but the clean daemon is already dead, so 18090 is free. We rebind 18090. 306 let bt: i64 = g_run("runtime/_hdl_build/_galx_build_one.sh" as *u8, "nx_gallery_serve_tamper" as *u8, 0 as *u8, 0 as *u8) 307 if bt != 0 { gp("GALXSERVE RED: tamper compile failed\n" as *u8); sys_exit(1); return 1 } 308 let tpid: i64 = g_spawn("/tmp/nx_gallery_serve_tamper.elf" as *u8) 309 let tup: i64 = g_wait_listen(18090) 310 if tup != 1 { gp("GALXSERVE RED: tamper daemon never bound\n" as *u8); nx_kill(tpid, 9); sys_exit(1); return 1 } 311 let rn5: i64 = g_http(18090, getimg, imgreqlen, resp, 524288) 312 var tamper404: i64 = g_find(resp, rn5, "HTTP/1.1 404" as *u8, 12) 313 var tamper200: i64 = g_find(resp, rn5, "HTTP/1.1 200" as *u8, 12) 314 nx_kill(tpid, 9) 315 let stk2: *i64 = sys_mmap(16) as *i64 316 sys_wait4(tpid, stk2, 0) 317 if tamper200 == 1 { gp("GALXSERVE RED: TAMPER -- GET /img/<A> still 200 after route flip (route is BAKED, not synthesized)\n" as *u8); sys_exit(1); return 1 } 318 if tamper404 != 1 { gp("GALXSERVE RED: TAMPER -- GET /img/<A> not 404 after route flip\n" as *u8); sys_exit(1); return 1 } 319 gp("GATE ROW tamper-red: GREEN -- flipping ONE route spec field -> GET /img/<A> now 404 (route synthesized from the spec, NOT constant-lifted)\n" as *u8) 320 321 gp("GALXSERVE 6/6 GREEN -- nx_eg-authored gallery daemon: binds 18090, browse lists REAL CIDs, /img serves byte-identical PNG, /rate writes EXACTLY one O-line (same-origin enforced, cross-origin 403 no-write), tamper-of-one-route-field -> behavioral RED\n" as *u8) 322 if lfd >= 0 { gfp(lfd, "GALXSERVE verdict=GREEN author=nx_eg-which2 daemon=nx_gallery_serve port=18090 browse_real_cids=1 img_byte_identical=1 rate_one_oline=1 same_origin_enforced=1 tamper_red=1 epoch=" as *u8); gfn(lfd, sys_now_realtime_sec()); gfp(lfd, "\n" as *u8); sys_close(lfd) } 323 sys_exit(0) 324 return 0 325}