nx_compare_gw.nx
buildroot/runtime/nx_compare_gw.nx
about
nx_compare_gw.nx -- the /compare GATEWAY DAEMON (loopback HTTP): the compare surface behind the same
OPAQUE login wall and the same HR access structure as /studio and /hub (operator 2026-08-27: "i can
see them as the owner but then others see different levels of /compare so i can provide a client a
/compare"). It sits behind sites_daemon's fail-closed `gated` reverse-proxy for /compare, mirroring
the /hub -> hub_gw topology exactly, and changes NOTHING about how nx_compare_regen emits the pages --
it gates at SERVE time from knowledge/compare/access.conf, so the single-emission publish pipeline is
untouched and a board's visibility is one conf row, live with no restart.
THE CHAIN, all sovereign and all already proven elsewhere:
olg_whoami (nx_hr_access -> hac_session_level) validates the no-cookie X-Nishi-Session token against
the nishi_site_admin realm and resolves the viewer's HR LEVEL (deny-by-default: an invalid/expired
token, or a valid token for someone not enrolled in HR, resolves to 0 = public) ; then
cg_required(access.conf, domain) gives the board's required level ; then cg_decide serves, 404s or
403s. FAIL-CLOSED and NO-LEAK by construction: a board a viewer may not see is absent from their index
bytes AND answers 404, the SAME answer a board that does not exist gives -- an anonymous visitor can
never tell a gated board from a missing one, while the owner serves it.
HARDENING baked in from the studio/hub post-mortems: binds 127.0.0.1 ONLY (the edge reaches it through
the proxy), and sets FD_CLOEXEC on the listener so a forked child can never hold the port (the outage
that survives every restart). All buffers are allocated ONCE before the accept loop and reused, and
every per-request read is bounded into a reused buffer -> a flat virtual footprint. This daemon never
forks. license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 5 imports · 0 importers
imports: nx_syscalls.nxnx_hr_access.nxnx_opaque_login.nxnx_compare_openapi.nxnx_compare_gw_lib.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 29 | const CGW_DOCROOT: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/compare" as *u8 |
| 30 | const CGW_ACCESS: *u8 = "knowledge/compare/access.conf" as *u8 |
| 33 | const CGW_HR: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_hr-" as *u8 |
| 34 | const CGW_REALM: *u8 = "nishi_site_admin" as *u8 |
| 35 | const CGW_REALM_N: i64 = 16 |
| 36 | const CGW_DISP: *u8 = "Nishi Compare" as *u8 |
| 37 | const CGW_DISP_N: i64 = 13 |
| 39 | const CGW_REQ: i64 = 32768 |
| 40 | const CGW_CONF: i64 = 262144 |
| 41 | const CGW_BODY: i64 = 4194304 |
| 42 | const CGW_SCRATCH: i64 = 8388608 |
| 43 | const CGW_DENTS: i64 = 65536 |
| 44 | const CGW_PATH: i64 = 1024 |
| 45 | const CGW_TITLE: i64 = 512 |
| 46 | const CGW_TOK: i64 = 512 |
| 47 | const CGW_DOM: i64 = 128 |
| 48 | const CGW_REST: i64 = 512 |
| 49 | const CGW_STAT: i64 = 256 |
| 50 | const CGW_DEFAULT_STEPS: i64 = 65536 |
| 51 | const CGW_TCOST: i64 = 3 |
| 52 | const CGW_PCOST: i64 = 4 |
| 54 | const CGW_STMODE_OFF: i64 = 24 |
| 55 | const CGW_S_IFMT: i64 = 61440 |
| 56 | const CGW_S_IFDIR: i64 = 16384 |
| 57 | const CGW_S_IFREG: i64 = 32768 |
| 58 | const CGW_FCNTL: i64 = 72 |
| 59 | const CGW_FSETFD: i64 = 2 |
| 60 | const CGW_FD_CLOEXEC: i64 = 1 |
| 172 | const CGW_FEED_FILE: *u8 = "feed.xml" as *u8 |
| 173 | const CGW_FEED_PATH: *u8 = "/feed.xml" as *u8 |
| 174 | const CGW_CTYPE_RSS: *u8 = "application/rss+xml; charset=utf-8" as *u8 |
| 175 | const CGW_FEED_CTR_BYTES: i64 = 16 // kept + dropped, one i64 each |
functions
| 62 | func cgw_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 63 | func cgw_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p } |
| 64 | func cgw_catn(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64 = 0; var p: i64 = o; while i < n { d[p] = s[i]; p = p + 1; i = i + 1 } return p } called by 1: cgw_send |
| 65 | func cgw_itoa(d: *u8, o: i64, v: i64) -> i64 |
| 78 | func cgw_read_file(path: *u8, out: *u8, cap: i64) -> i64 |
| 95 | func cgw_kind(path: *u8, stbuf: *u8) -> i64 |
| 102 | func cgw_send(cfd: i64, scratch: *u8, status: *u8, ctype: *u8, body: *u8, blen: i64) -> i64 |
| 112 | func cgw_text(cfd: i64, scratch: *u8, status: *u8, msg: *u8) -> i64 |
| 119 | func cgw_index(level: i64, with_upgrade: i64, json: i64, conf: *u8, cn: i64, called by 1: main calls 16: cg_api_opencg_index_opensys_openat_rdsys_getdents64dirent_reclendirent_type+10 |
| 176 | func cgw_feed(cfd: i64, scratch: *u8, level: i64, conf: *u8, cnv: i64, body: *u8, jbuf: *u8, pathb: *u8, dom: *u8) -> i64 |
| 189 | func main(argc: i64, argv: *i64) -> i64 |