code wiki / _hdl_build / nx_mgmt_api.nx
nx_mgmt_api.nx
buildroot/runtime/_hdl_build/nx_mgmt_api.nx
about
nx_mgmt_api.nx -- THE IO / TRANSPORT ring of the sovereign ecosystem control-plane API (the primary adapter).
THIN by design (clean three-tier / hexagonal -- see knowledge/library/arch_*): it owns ONLY transport --
the socket loop, HTTP request parse, routing, JSON serialization, and auth gating. ALL business rules live in
the LOGIC core (nx_mgmt_core, mc_*); ALL outside-world access lives in the DATA adapters (nx_mgmt_data, md_*).
Dependency direction: api -> {core, data}, data -> core-free, core -> nothing (dependency inversion). The
router is a PURE FUNCTION ma_handle(ctx, req, req_n, snapfile, out) -> out_n (bytes in, bytes out, NO socket);
the gate drives it IN-PROCESS (no curl/shell). Reuses nx_status_daemon's HTTP-parse + Modern-Auth helpers.
TRUE MONITORING (no false +/-): /api/health + /api/services read a live SNAPSHOT (md_read_file) and surface
dueling-supervisors / duplicate-instances / crash-loops via the core rules; missing snapshot -> UNKNOWN,
never OK. Health/services + all write actions are AUTH-gated; write actions are confirm-gated + fail-closed.
Routes (auth = X-Nishi-Session Ed25519 session header, canonical Modern Auth, NO cookies):
GET /api -> 200 route index (public)
POST /api/login -> 200 {"token":...} | 401
GET /api/health -> (auth) 200 {overall,degraded,reasons[...]} | 401
GET /api/services -> (auth) 200 {services:[...]} | 401
POST /api/upload?target=&seq=&final=[&sha256=] -> (auth) chunked artifact publish; append raw body chunk ->
<target>.upload, on final rename -> <target>.new (staged for /api/deploy; NEVER promotes) | 400 | 401
POST /api/deploy -> (auth) allowlist+validate->promote->http-health->auto-rollback | 400 | 401
POST /api/rollback -> (auth, confirm=yes) | 400 | 401
POST /api/reconcile -> (auth, confirm=yes) single-supervisor | 400 | 401
POST /api/restart -> (auth, confirm=yes, service=) surgical kick | 400 | 401
POST /api/migrate|update -> (auth) 501 reserved (R3b: URL->.site ingest) | 401
(any other) -> 404
Snapshot line format (the monitor writes; md_* reads): "SUP <n>" / "SVC <name> <port> <state> <procs> <rwin> <rtot>"
argv: [1]=port [2]=keysfile [3]=storefile [4]=realm [5]=snapfile [6]=budget. license_tier: ORIGINAL
dependencies 11 imports · 7 importers
diagram shows first 10 each side; +1 more imports, +0 more importers in the complete lists below.
imports: nx_status_daemon.nxnx_mgmt_data.nxnx_organkind.nxnx_mgmt_core.nxnx_access_lib.nxnx_os_introspect.nxnx_shard_view.nxnx_fio.nxnx_sha256.nxnx_routeguard_lib.nxnx_mgmt_upload.nx
imported by: nx_content_publish_gate.nxnx_mgmt_api_gate.nxnx_mgmt_cap_mint_gate.nxnx_mgmt_promote_gate.nxnx_mgmt_tools_register_gate.nxnx_mgmt_upload_gate.nxnx_schema_backfill.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 40 | const MA_BODYCAP: i64 = 131072 |
| 49 | const MA_UPLOAD_REQCAP: i64 = 2097152 // 2 MiB -- the scoped upload-request buffer (headers + one big chunk body) |
| 50 | const MA_UPLOAD_TOOBIG: i64 = 0 - 1 // sentinel: declared Content-Length would overflow MA_UPLOAD_REQCAP -> 413 refuse |
| 51 | const MA_SHARDS_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/shards.conf" as *u8 // the shard-registry SSOT the control plane reads |
| 54 | const MA_ROLES: *u8 = "/volume1/ai/hub/roles.tsv" as *u8 |
| 55 | const MA_IDX: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_uid_handle.tsv" as *u8 |
| 56 | const MA_LVL_READ: i64 = 2 // member+ may READ /api/health + /api/services |
| 57 | const MA_LVL_ACT: i64 = 3 // OPERATOR required for the write actions (deploy/rollback/reconcile/restart) |
| 60 | const CM_DAYS_DEFAULT: i64 = 30 // default cap lifetime when `days` is omitted |
| 61 | const CM_DAYS_MAX: i64 = 730 // 2 years -- upper bound so a mint can't grant a near-eternal cap |
| 62 | const CM_SECS_PER_DAY: i64 = 86400 // exp = now + days * this |
| 63 | const CM_ALLOW_MAX: i64 = 480 // max bytes of the allow= csv (bounds the mint scratch buffers) |
| 64 | const CM_NAME_MAX: i64 = 120 // max bytes of one tool name inside the csv |
| 610 | const MA_MEM_AVAIL_MIN_PERMIL: i64 = 150 |
| 611 | const MA_SWAP_USED_MAX_PERMIL: i64 = 950 |
| 1131 | const MA_DEPLOY_STATUS: *u8 = "/tmp/nx_ma_deploy_status" as *u8 |
| 1682 | const MA_ORGAN_ALLOWLIST: *u8 = "tool_allowlist.conf" as *u8 |
| 1683 | const MA_ORGAN_CONFCAP: i64 = 262144 |
| 1684 | const MA_ORGAN_MAXARGS: i64 = 12 |
| 2340 | const MA_D001_BUF: i64 = 262144 |
| 2762 | const MA_ARGSDEC_CAP: i64 = 4096 |
| 3410 | const RL_SLOTS: i64 = 128 |
| 3411 | const RL_WINDOW: i64 = 10 // seconds |
| 3412 | const RL_MAX: i64 = 300 // requests / window / client (generous; protects vs floods, won't lock out an operator) |
| 3416 | const IDEM_SLOTS: i64 = 512 |
| 3417 | const IDEM_TTL: i64 = 3600 // seconds a processed Idempotency-Key is remembered |
| 3627 | const MA_PATHPTR_BUF: i64 = 8 |
| 3875 | const MA_MAX_HANDLERS: i64 = 8 |
functions
| 68 | func ma_emit_json(out: *u8, prefix: *u8, body: *u8, body_n: i64) -> i64 called by 16: ma_index_textma_docsma_indexma_openapima_emit_404ma_emit_403+10 calls 2: sd_catsd_catn |
| 81 | func ma_wants_text(req: *u8, req_n: i64) -> i64 called by 1: ma_handle |
| 94 | func ma_index_text(out: *u8) -> i64 |
| 102 | func ma_docs(out: *u8) -> i64 |
| 108 | func ma_events(out: *u8) -> i64 |
| 117 | func ma_emit_binary(out: *u8, body: *u8, body_n: i64) -> i64 |
| 127 | func ma_rpc(req: *u8, req_n: i64, out: *u8) -> i64 |
| 146 | func ma_rpc_contract(out: *u8) -> i64 |
| 163 | func ma_inventory(out: *u8) -> i64 |
| 218 | func ma_index(out: *u8) -> i64 |
| 226 | func op_path(out: *u8, o: i64, path: *u8, method: *u8, summary: *u8, authed: i64) -> i64 |
| 237 | func ma_openapi(out: *u8) -> i64 |
| 268 | func ma_emit_404(out: *u8) -> i64 |
| 273 | func ma_emit_403(out: *u8) -> i64 |
| 278 | func ma_emit_501(out: *u8) -> i64 |
| 285 | func ma_emit_400(out: *u8, body: *u8) -> i64 |
| 294 | func ma_emit_200(out: *u8, body: *u8) -> i64 |
| 303 | func ma_emit_503(out: *u8, body: *u8) -> i64 |
| 314 | func ma_emit_413(out: *u8) -> i64 |
| 319 | func ma_comma(body: *u8, b: i64, first: *i64) -> i64 |
| 326 | func ma_emit_services(snap: *u8, snap_n: i64, out: *u8) -> i64 |
| 378 | func ma_emit_shards(out: *u8) -> i64 |
| 384 | func ma_emit_services_file(snapfile: *u8, out: *u8) -> i64 |
| 398 | func mnp_readproc(path: *u8, buf: *u8, cap: i64) -> i64 |
| 406 | func mnp_skip_sp(buf: *u8, n: i64, p: i64) -> i64 |
| 414 | func mnp_pdec(buf: *u8, n: i64, p: i64, pend: *i64) -> i64 |
| 427 | func mnp_count_sub(buf: *u8, n: i64, needle: *u8, nl: i64) -> i64 |
| 438 | func mnp_find_after(buf: *u8, n: i64, key: *u8, klen: i64) -> i64 |
| 450 | func mnp_loadavg_milli(buf: *u8) -> i64 |
| 475 | func mnp_ncpu(buf: *u8, cap: i64) -> i64 |
| 482 | func mnp_meminfo_kb(buf: *u8, n: i64, key: *u8, klen: i64) -> i64 |
| 489 | func ma_emit_nodes(out: *u8) -> i64 |
| 527 | func ma_health_count(snap: *u8, snap_n: i64, supb: *i64, nsvcb: *i64, ndownb: *i64) -> i64 |
| 560 | func ma_health_reasons(snap: *u8, snap_n: i64, sup: i64, body: *u8, b0: i64) -> i64 |
| 617 | func ma_key_int(buf: *u8, n: i64, key: *u8) -> i64 |
| 650 | func ma_read_small(path: *u8, buf: *u8, cap: i64) -> i64 |
| 657 | func ma_mem_conf(key: *u8, defv: i64) -> i64 |
| 666 | func ma_mem_pressure() -> i64 |
| 685 | func ma_emit_health(snap: *u8, snap_n: i64, out: *u8) -> i64 |
| 738 | func ma_emit_health_file(snapfile: *u8, out: *u8) -> i64 |
| 750 | func ma_authed(ctx: *NxAuthContext, req: *u8, req_n: i64) -> i64 |
| 760 | func ma_level_of(ctx: *NxAuthContext, req: *u8, req_n: i64) -> i64 |
| 767 | func ma_confirmed(req: *u8, req_n: i64) -> i64 |
| 779 | func ma_login(ctx: *NxAuthContext, req: *u8, req_n: i64, out: *u8) -> i64 |
| 832 | func mau_query_off(path: *u8, pn: i64) -> i64 |
| 842 | func mau_qparam(path: *u8, pn: i64, qoff: i64, name: *u8, name_n: i64, voff: *i64, vlen: *i64) -> i64 |
| 869 | func mau_qint(path: *u8, off: i64, len: i64) -> i64 |
| 885 | func mau_build_path(path: *u8, toff: i64, tlen: i64, suffix: *u8, buf: *u8) -> i64 |
| 897 | func mau_read_seq(sidecar: *u8) -> i64 |
| 907 | func mau_write_seq(sidecar: *u8, val: i64) -> i64 |
| 924 | func mau_hex32(dig: *u8, out: *u8) -> i64 |
| 939 | func mau_hex_eq(path: *u8, hoff: i64, hlen: i64, want: *u8) -> i64 |
| 955 | func mau_mkdirs(path: *u8) -> i64 |
| 973 | func ma_do_upload(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1132 | func ma_write_status(s: *u8) -> i64 |
| 1152 | func ma_do_adnet_creative(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1182 | func ma_do_adnet_invoice(out: *u8) -> i64 |
| 1191 | func ma_do_deploy_status(out: *u8) -> i64 |
| 1203 | func ma_sanitize_name(src: *u8, off: i64, len: i64, buf: *u8, cap: i64) -> i64 |
| 1224 | func ma_json_esc_tail(src: *u8, n: i64, maxsrc: i64, dst: *u8, cap: i64) -> i64 |
| 1246 | func ma_find(src: *u8, n: i64, pat: *u8) -> i64 |
| 1263 | func ma_path_exists(path: *u8) -> i64 |
| 1280 | func ma_bank_staged(nm: *u8) -> i64 |
| 1301 | func ma_restore_staged(nm: *u8) -> i64 |
| 1317 | func ma_build_dup_shadow(nm: *u8) -> i64 |
| 1331 | func ma_do_build(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1585 | func ma_do_unpack(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1646 | func ma_gate_esc(d: *u8, o: i64, s: *u8, n: i64) -> i64 |
| 1688 | func ma_organ_resolve(nm: *u8, outp: *u8) -> i64 |
| 1744 | func ma_do_organ_run(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1853 | func ma_do_gate_run(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1917 | func ma_do_proc_kill(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1949 | func ma_do_put_source(req: *u8, req_n: i64, out: *u8) -> i64 |
| 1996 | func ma_do_deploy(req: *u8, req_n: i64, out: *u8) -> i64 |
| 2205 | func ma_do_hostctl(req: *u8, req_n: i64, out: *u8) -> i64 |
| 2231 | func ma_do_promote_content(req: *u8, req_n: i64, out: *u8) -> i64 |
| 2282 | func mau_is_elf(path: *u8) -> i64 |
| 2297 | func ma_hexlc(c: i64) -> i64 |
| 2303 | func ma_hex_eq(hex: *u8, buf: *u8, off: i64, n: i64) -> i64 |
| 2342 | func ma_name_is_oracle(nm: *u8, n: i64) -> i64 |
| 2361 | func ma_d001_scan(path: *u8, buf: *u8) -> i64 |
| 2388 | func ma_inherits_verdict(nm: *u8, nmlen: i64) -> i64 |
| 2423 | func ma_do_promote(req: *u8, req_n: i64, out: *u8) -> i64 |
| 2667 | func ma_do_promote_toolchain(req: *u8, req_n: i64, out: *u8) -> i64 |
| 2726 | func ma_write_str(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 } |
| 2729 | func ma_sanitize_base(src: *u8, off: i64, len: i64, buf: *u8, cap: i64) -> i64 |
| 2765 | func ma_ensure_trailing_nl(path: *u8, af: i64) -> i64 |
| 2782 | func ma_schema_has_name(nm: *u8) -> i64 |
| 2811 | func ma_schema_append_row(nm: *u8, body: *u8, toff: i64, tn: i64) -> i64 |
| 2827 | func ma_do_tools_register(req: *u8, req_n: i64, out: *u8) -> i64 |
| 2973 | func ma_do_cap_mint(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3107 | func ma_do_rollback(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3143 | func ma_do_reconcile(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3155 | func ma_do_restart(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3224 | func ma_do_route(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3266 | func sd_ends(s: *u8, n: i64, suf: *u8) -> i64 |
| 3273 | func ma_srcwrite_pathok(p: *u8, n: i64) -> i64 |
| 3300 | func ma_do_srcwrite(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3367 | func ma_is_write_route(path: *u8, pn: i64) -> i64 |
| 3373 | func ma_path_eq(path: *u8, pn: i64, s: *u8) -> i64 |
| 3388 | func ma_emit_dashboard(out: *u8) -> i64 |
| 3422 | func ma_state_init() -> i64 |
| 3432 | func ma_slot(h: i64, slots: i64) -> i64 { var x: i64 = h; if x < 0 { x = 0 - x } return x - (x / slots) * slots } |
| 3434 | func ma_hdr_hash(req: *u8, req_n: i64, key: *u8, keyn: i64) -> i64 |
| 3452 | func ma_client_id(req: *u8, req_n: i64) -> i64 |
| 3459 | func ma_rate_ok(cid: i64, now: i64) -> i64 |
| 3468 | func ma_emit_429(out: *u8) -> i64 |
| 3472 | func ma_idem_seen(ik: i64, now: i64) -> i64 { let s: i64 = ma_slot(ik, IDEM_SLOTS); if idem_key[s] == ik { if now - idem_ts[s] < IDEM_TTL { return 1 } } return 0 } |
| 3473 | func ma_idem_record(ik: i64, now: i64) -> i64 { let s: i64 = ma_slot(ik, IDEM_SLOTS); idem_key[s] = ik; idem_ts[s] = now; return 0 } |
| 3474 | func ma_emit_idem_replay(out: *u8) -> i64 |
| 3484 | func ma_do_cmp_registry(out: *u8) -> i64 |
| 3494 | func ma_do_cmp_upsert(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3539 | func ma_do_cmp_publish(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3588 | func ma_do_cmp_regen(out: *u8) -> i64 |
| 3600 | func ma_vqoe(req: *u8, req_n: i64, out: *u8) -> i64 |
| 3629 | func ma_handle(ctx: *NxAuthContext, req: *u8, req_n: i64, snapfile: *u8, out: *u8) -> i64 |
| 3803 | func ma_req_is_upload(req: *u8, req_n: i64) -> i64 |
| 3826 | func ma_upload_fill_body(cfd: i64, buf: *u8, cap: i64, prefix_n: i64, body_off: i64, cl: i64) -> i64 |
| 3863 | func ma_route_is_long(p: *u8, n: i64) -> i64 |
| 3877 | func main(argc: i64, argv: *i64) -> i64 |