code wiki / (root) / nx_site_publish_lib.nx

nx_site_publish_lib.nx

buildroot/runtime/nx_site_publish_lib.nx

58495 B989 linesdepth 7pulls 23 transitivereach 13 importersview sourcekind librarytopic site
docsdependenciesstructsconstsfunctions

about

nx_site_publish_lib.nx -- ARTIFACT-PUBLISH, LIBRARY half (sp_main dispatcher) capability (closes the coverage BUILD-queue gap "artifact-publish"; retires the ssh-cat content lane for pages). Places a NAS-local file into the live sites docroot the SAFE way, composing the proven IO layer: publish <src-file> <site> <relpath> -> sites/<site>/<relpath> - ATOMIC placement via fsx_write (tmp+fsync+rename -- a browser never sees a torn page) - PRIOR VERSION PRESERVED: an existing target is first copied to <relpath>.prev (rename-not-delete doctrine; one-deep history -- generated artifacts, git holds sources) - DENY BY CONSTRUCTION (fsx_write_denied: secrets/device-ns/allowlist) PLUS path-traversal refusal: any ".." segment or absolute site/relpath is DENIED (an MCP caller must not escape the docroot) The organ prints the live URL; verification is the SEPARATE browser-grade organ (composition, not a built-in fallback): run nx_page_verify <url> from a WAN vantage (on-NAS bare-domain fetches hit DSM -- the documented trap). The publish->verify recipe is the contract; this organ does the placement half. - THE PUBLISH GATEWAY (F763 second half, wired 2026-07-30): for a site listed in knowledge/pub_sites.conf, a <relpath> absent from that site's publishing REGISTRY -- or carrying a non-publishable status (withdrawn/redirect/debris) -- is REFUSED. This is the half that makes "random and arbitrary" impossible instead of merely visible: nx_pub_desk stated the rule in 2026-07-19 and its own header recorded that enforcement inside the publish organ was never wired, so anything could be dropped into any docroot and become site truth. MEASURED before wiring: 54 pages served on nishifamily.com were in NO registry. Sites NOT in the site table publish UNGATED (with a warning) -- onboarding is a config row, and a control that refuses everything on day one is a control someone disables by lunchtime. exit: 0 ok | 2 usage | 3 src absent | 4 io | 5 DENIED license_tier: ORIGINAL

dependencies 7 imports · 10 importers

nx_fsops_lib.nx nx_pub_lib.nx nx_pub_release_lib.nx nx_sha256.nx nx_comparestale_lib.nx nx_json.nx json_emit.nx nx_site_publish_lib.nx nx_alpha_release_workflow_canonica nx_site_publish.nx nx_site_publish_boundary_canonical nx_site_publish_edge_canonical_gat nx_site_publish_gate.nx nx_site_publish_legacy_gate_t26.nx nx_site_publish_multi_candidate_t3 nx_site_publish_multi_canonical_ga nx_site_release_cli_gate_t141.nx nx_torrent_acquisition_cli_gate_t2

imports: nx_fsops_lib.nxnx_pub_lib.nxnx_pub_release_lib.nxnx_sha256.nxnx_comparestale_lib.nxnx_json.nxjson_emit.nx

imported by: nx_alpha_release_workflow_canonical_gate_t343.nxnx_site_publish.nxnx_site_publish_boundary_canonical_gate_t336.nxnx_site_publish_edge_canonical_gate_t139.nxnx_site_publish_gate.nxnx_site_publish_legacy_gate_t26.nxnx_site_publish_multi_candidate_t322.nxnx_site_publish_multi_canonical_gate_t322.nxnx_site_release_cli_gate_t141.nxnx_torrent_acquisition_cli_gate_t270.nx

structs

none

consts

31const PB_ARG_VERB: i64 = 1 // argv: verb ("publish")
32const PB_RC_USAGE: i64 = 2 // exit: usage
33const PB_ARG_SRC: i64 = 2 // argv: source file (NAS-local)
34const PB_ARG_SITE: i64 = 3 // argv: site dir under sites/
35const PB_ARG_REL: i64 = 4 // argv: page path under the site
36const PB_ARGC: i64 = 5 // publish src site relpath
37const PB_STAGE_ARGC: i64 = 6 // stage src site releases/<path> sha256
38const PB_GUARDED_ARGC: i64 = PB_STAGE_ARGC + 1 // adds expected live digest
39const PB_GUARDED_SIZED_ARGC: i64 = PB_GUARDED_ARGC + 1 // optional exact artifact extent
40const PB_PATH: i64 = 1024 // destination path buffer
41const PB_CONFCAP: i64 = 65536 // site-table read buffer (the gateway)
42const PB_SPANCAP: i64 = 128 // site-table span vector
43const PB_DOT: i64 = 46 // '.'
44const PB_SLASH: i64 = 47 // '/'
91const PB_LOCK_EX_NB: i64 = 6
92const PB_RC_CONFLICT: i64 = 8
93const PB_RC_BUSY: i64 = 9
94const PB_SHA_BYTES: i64 = 32
95const PB_SHA_HEX: i64 = 64
111const PB_SIZED_ARGC: i64 = 7
112const PB_I64_MAX: i64 = 9223372036854775807
406const PE_ARGC: i64=10
486const RM_FIELDS: i64=12
487const RM_VALUES_BYTES: i64=RM_FIELDS*8
488const RM_SCHEMA: *u8="site-release/v1"
489const RM_RECEIPT_ROOT: *u8="knowledge/gates/"
737const RM_JSON_WRITER_BYTES:i64=__size_of(JsonWriter)
808const RM2_COMMON:i64=12
809const RM2_DEP_WORDS:i64=5
810const RM2_STATE_WORDS:i64=3
811const RM2_SCHEMA:*u8="site-release/v2"

functions

47func pb_traversal(s: *u8) -> i64
73func pb_app(out: *u8, op: *i64, s: *u8) -> i64
83func pb_same_bytes(a: *u8, an: i64, b: *u8, bn: i64) -> i64
96func pb_hash(body: *u8, n: i64, hex: *u8) -> i64
113func pb_sized_bytes(s: *u8) -> i64
125func pb_read_bounded(path: *u8,b: *u8,cap: i64) -> i64
139func pb_main_edge(argc: i64, argv: *i64, edge_rel: *u8, edge_sha: *u8) -> i64
189func pb_release_path(rel: *u8) -> i64
198func pb_publish_locked_edge(argc: i64, argv: *i64, edge_rel: *u8, edge_sha: *u8) -> i64
408func pe_main(argc: i64,argv: *i64) -> i64
438func sp_main(argc: i64,argv: *i64) -> i64
451func pe_check(body: *u8,n: i64,argv: *i64,rel: *u8,sha: *u8) -> i64
482func pb_publish_locked(argc: i64,argv: *i64) -> i64 {return pb_publish_locked_edge(argc,argv,0 as *u8,0 as *u8)}
called by 1: rm2_preflight
490func rm_key(k: *u8) -> i64
500func rm_string(t: *NxJsonTok) -> *u8
509func rm_parse_tokens(t: *NxJsonTok,v: *i64) -> i64
525func rm_parse(body: *u8,n: i64,v: *i64) -> i64
530func rm_num(out: *u8,pos: *i64,value: i64) -> i64
544func rm_receipt(path: *u8,digest: *u8,phase: *u8,state: *u8,rc: i64) -> i64
559func rm_finish(receipt: *u8,digest: *u8,phase: *u8,rc: i64) -> i64
565func rm_artifact(src: *u8,size: *u8,hash: *u8,out: *i64) -> i64
called by 1: rm2_main calls 1: pb_read_bounded
577func rm_preflight(v: *i64,prefix: *u8) -> i64
608func rm_execute(v: *i64,prefix: *u8,receipt: *u8,digest: *u8) -> i64
627func rm_main(argc: i64,argv: *i64) -> i64
647func rm_sync(path: *u8) -> i64
656func rm_bank(body: *u8,n: i64,digest: *u8) -> i64
674func rm_cleanup(body: *u8,digest: *u8,v: *i64,receipt: *u8,pos: *i64,prefix: *u8) -> i64
683func pb_prepare_path(site:*u8,rel:*u8)->i64
738func rm_put_escaped(s:*u8)->i64
756func rm_prepare_emit(v:*i64,digest:*u8,observed:i64)->i64
783func rm_prepare_main(argc:i64,argv:*i64)->i64
812func rm2_dep_key(k:*u8)->i64
816func rm2_dep(t:*NxJsonTok,d:*i64)->i64
824func rm2_parse(body:*u8,n:i64,v:*i64,state:*i64)->i64
848func rm2_view(v:*i64,d:*i64)->*i64
853func rm2_path(site:*u8,rel:*u8)->*u8
858func rm2_existing(path:*u8,size:*u8,sha:*u8)->i64
863func rm2_live(v:*i64)->i64
874func rm2_preflight(v:*i64,state:*i64,prefix:*u8)->i64
885func rm2_phase(receipt:*u8,digest:*u8,kind:*u8,index:i64,rc:i64)->i64
892func rm2_publish(v:*i64,state:*i64,prefix:*u8)->i64
914func rm2_execute(v:*i64,state:*i64,prefix:*u8,receipt:*u8,digest:*u8)->i64
931func rm2_load(path:*u8,out:*i64)->i64
940func rm2_boundary_error(operation:*u8,path:*u8,stage:*u8,reason:*u8,rc:i64)->i64
956func rm2_alpha_path(path:*u8)->i64
967func rm2_main(argc:i64,argv:*i64)->i64