nx_compare_gw_lib.nx
buildroot/runtime/nx_compare_gw_lib.nx
about
nx_compare_gw_lib.nx -- THE PURE DECISION CORE of the /compare gateway: who may see which board.
WHY A GATEWAY AT ALL (operator 2026-08-27: "/compare against the login walls so its behind the same thing
as opaque and has the same access structure -- i can see them as the owner but then others see different
levels of /compare so i can provide a client a /compare"). Today /compare is plain static docroot bytes:
no route row, no session, every domain public. This lib decides, per request, from THREE inputs --
the viewer's LEVEL (resolved by the estate's one access spine, nx_hr_access: OPAQUE session -> HR level,
deny-by-default), the DOMAIN the path names, and the ACCESS the domain declares as DATA in
knowledge/compare/access.conf -- whether the bytes are served, and what an index at that level lists.
ACCESS IS DATA, NEVER CODE (rule 11). access.conf rows:
default|<access> the access every domain gets unless a row names it (ABSENT = operator: fail-closed)
domain|<dom>|<access> one domain's access
access vocabulary, identical to nx_maturity_registry's mr_level_of so the hub and the compare wall cannot
disagree on a word: public=0 viewer=1 member=2 operator=3 ; an UNKNOWN word reads operator (fail-closed:
a typo locks a board to the owner, it never exposes one). HR enrols owner=3 and family/client=1, so a
client handed a /compare sees the public boards plus every board declared viewer; the owner sees all.
NO-LEAK AT THE RENDER LAYER: a viewer's index bytes never contain the name of a board above their level
(absent from the bytes, not hidden by style), and a request for such a board answers exactly like a
request for a board that does not exist. Not-even-listed is the property, and it is measured by the gate.
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 1 imports · 3 importers
imports: nx_syscalls.nx
imported by: nx_compare_gw.nxnx_compare_gw_gate.nxnx_compare_openapi.nx
structs
| none |
consts
| 25 | const CG_LVL_PUBLIC: i64 = 0 |
| 26 | const CG_LVL_VIEWER: i64 = 1 |
| 27 | const CG_LVL_MEMBER: i64 = 2 |
| 28 | const CG_LVL_OPERATOR: i64 = 3 |
| 30 | const CG_ROW_DEFAULT: *u8 = "default" as *u8 |
| 31 | const CG_ROW_DOMAIN: *u8 = "domain" as *u8 |
| 32 | const CG_PREFIX: *u8 = "/compare" as *u8 |
| 35 | const CG_FEED_LINK_TAG: *u8 = "<link rel='alternate' type='application/rss+xml' title='Nishi /compare daily positions and reviews' href='/compare/feed.xml'>" as *u8 |
| 38 | const CG_D_SERVE: i64 = 1 |
| 39 | const CG_D_DENY: i64 = 0 |
| 40 | const CG_D_NOTFOUND: i64 = 0 - 1 |
| 41 | const CG_D_BADPATH: i64 = 0 - 2 |
| 43 | const CG_CH_NL: i64 = 10 |
| 44 | const CG_CH_CR: i64 = 13 |
| 45 | const CG_CH_SPACE: i64 = 32 |
| 46 | const CG_CH_HASH: i64 = 35 |
| 47 | const CG_CH_QUOTE: i64 = 34 |
| 48 | const CG_CH_BSLASH: i64 = 92 |
| 49 | const CG_CH_DOT: i64 = 46 |
| 50 | const CG_CH_SLASH: i64 = 47 |
| 51 | const CG_CH_PIPE: i64 = 124 |
| 52 | const CG_CH_QMARK: i64 = 63 |
| 53 | const CG_CH_COLON: i64 = 58 |
| 54 | const CG_MAXF: i64 = 4 |
| 55 | const CG_I64_BYTES: i64 = 8 |
| 56 | const CG_DOM_CAP: i64 = 128 |
| 428 | const CG_FEED_ITEM_OPEN: *u8 = "<item>" as *u8 |
| 429 | const CG_FEED_ITEM_CLOSE: *u8 = "</item>" as *u8 |
| 430 | const CG_FEED_LINK_OPEN: *u8 = "<link>" as *u8 |
| 431 | const CG_FEED_BOARD_MARK: *u8 = "/compare/" as *u8 |
| 432 | const CG_CH_LT: i64 = 60 |
| 515 | const CG_INDEX_FILE: *u8 = "index.html" |
| 516 | const CG_INDEX_SUFFIX_BYTES: i64 = 16 |
| 517 | const CG_CH_SLASH: i64 = 47 |
| 534 | const CG_BODY_SERVE: i64 = 1 |
| 535 | const CG_BODY_TOO_LARGE: i64 = 2 |
| 536 | const CG_BODY_MISSING: i64 = 0 - 1 |
functions
| 58 | func cg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 59 | func cg_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 } |
| 60 | func cg_catn(d: *u8, o: i64, src: *u8, n: i64) -> i64 { var i: i64 = 0; var p: i64 = o; while i < n { d[p] = src[i]; p = p + 1; i = i + 1 } return p } called by 1: cg_declared |
| 61 | func cg_catnum(d: *u8, o: i64, v: i64) -> i64 |
| 75 | func cg_sl_eq(buf: *u8, a: i64, b: i64, lit: *u8) -> i64 |
| 82 | func cg_streq(a: *u8, b: *u8) -> i64 |
| 91 | func cg_access_level(buf: *u8, a: i64, b: i64) -> i64 |
| 98 | func cg_level_name(l: i64) -> *u8 called by 1: cg_index_open |
| 108 | func cg_row_fields(buf: *u8, s: i64, e: i64, fa: *i64, fb: *i64) -> i64 |
| 123 | func cg_eol(buf: *u8, n: i64, i: i64) -> i64 |
| 132 | func cg_required(conf: *u8, n: i64, dom: *u8) -> i64 |
| 158 | func cg_declared(conf: *u8, n: i64, out: *u8, cap: i64, count_out: *i64) -> i64 |
| 181 | func cg_req_path(req: *u8, n: i64, out: *u8, cap: i64) -> i64 |
| 202 | func cg_req_header(req: *u8, n: i64, name: *u8, out: *u8, cap: i64) -> i64 |
| 231 | func cg_path_safe(p: *u8, n: i64) -> i64 |
| 245 | func cg_split(path: *u8, n: i64, dom: *u8, dcap: i64, rest: *u8, rcap: i64) -> i64 |
| 275 | func cg_decide(level: i64, required: i64, exists: i64) -> i64 |
| 280 | func cg_decision_name(d: i64) -> *u8 |
| 289 | func cg_json_str(buf: *u8, n: i64, key: *u8, out: *u8, cap: i64) -> i64 |
| 326 | func cg_index_open(out: *u8, level: i64, with_upgrade: i64) -> i64 |
| 344 | func cg_index_row(out: *u8, o: i64, dom: *u8, title: *u8) -> i64 |
| 355 | func cg_index_close(out: *u8, o: i64, shown: i64) -> i64 |
| 365 | func cg_api_open(out: *u8, now: i64) -> i64 |
| 371 | func cg_api_row(out: *u8, o: i64, first: i64, dom: *u8, title: *u8) -> i64 |
| 392 | func cg_api_close(out: *u8, o: i64, shown: i64) -> i64 |
| 401 | func cg_ctype(file: *u8) -> *u8 |
| 434 | func cg_find(buf: *u8, n: i64, from: i64, needle: *u8) -> i64 |
| 449 | func cg_feed_item_board(src: *u8, ib: i64, ie: i64, dom: *u8, dcap: i64) -> i64 |
| 466 | func cg_feed_project(src: *u8, n: i64, level: i64, conf: *u8, cn: i64, out: *u8, cap: i64, dom: *u8, dcap: i64, kept: *i64, dropped: *i64) -> i64 |
| 518 | func cg_board_file(rest: *u8, rest_is_dir: i64, out: *u8) -> i64 |
| 537 | func cg_body_verdict(n: i64, cap: i64) -> i64 |