code wiki / (root) / nx_mgmt_client.nx

nx_mgmt_client.nx

buildroot/runtime/nx_mgmt_client.nx

39671 B687 linesdepth 20pulls 136 transitivereach 1 importersview sourcekind tooltopic mgmt
docsdependenciesstructsconstsfunctions

about

nx_mgmt_client.nx -- SOVEREIGN CLIENT for the live control-plane mgmt API (nx_mgmt_api.nx, https://<host>/api). Operates the ecosystem OVER THE WIRE (sovereign TLS-1.3 + canonical Modern Auth: the X-Nishi-Session header, NO cookies) instead of the shell/ssh dance. Two modes (parse argv): nx_mgmt_client <base_url> login <handle> <passphrase_file> <token_out_file> POST <base_url>/api/login body "handle=<enc>&passphrase=<enc>" (x-www-form-urlencoded, url-ENCODED so a '&'/'='/space in a passphrase can't corrupt the form the daemon's sd_form_field parses) -> parse the {"token":"<b64>"} value -> write the RAW b64 token to <token_out_file> (0600). Prints LOGIN OK | LOGIN FAIL status=<n>. nx_mgmt_client <base_url> call <METHOD> <path> <token_file> [body_file] <METHOD> <base_url><path> with header "X-Nishi-Session: <token>" (token read from file), optional x-www-form-urlencoded body from body_file. Prints "status=<n>" then the response body. nx_mgmt_client <base_url> upload <target> <artifact_file> <token_file> PUBLISH an artifact over the authenticated API from ANYWHERE (retires the LAN-only nx_aw_send). Reads <artifact_file>, splits it into <=48KB chunks (one request must fit under the daemon's 64KB read cap), and POSTs each as POST /api/upload?target=<t>&seq=<i>&final=<0|1> with "X-Nishi-Session: <token>" and the RAW chunk as the body. Aborts loudly on any non-200. On the final chunk prints the {"staged":...} body + "UPLOAD OK <target>.new (<bytes> bytes)". The staged <target>.new is then promoted by /api/deploy. REUSE (compose, don't rebuild TLS): the request BUILDERS (mcl_build_login_body / mcl_build_request) are pure byte emitters; the TRANSPORT (mcl_send_drain) composes the SHIPPED TLS-1.3 record primitives -- exactly the primitives nx_https_post_complete + nx_login_e2e_probe's e2e_send compose -- the ONLY difference is we send a caller-built request so we can carry the X-Nishi-Session header the baked builders (nx_http_client_build_request*) cannot. Token extraction reuses nx_http_response_parse + nx_acme_json_str (fail-closed: a well-formed closing quote is required, else empty -- no garbage). The connect+handshake path reuses nx_https_url_for_fetch / nx_https_url_connect / nx_tls13_client_session_run with fresh nx_csprng ephemerals (forward secrecy per run). OPERATOR-DRIVEN by design: a human runs this; nothing acts autonomously. This file gate-proves its codec in-process (nx_mgmt_client_gate.nx); the LIVE TLS round-trip is driven by the operator/parent. license_tier: ORIGINAL expect_exit: 0

dependencies 10 imports · 1 importers

nx_acme_http.nx nx_https_url_for_fetch.nx nx_https_url_connect.nx nx_tls13_client_session_run.nx nx_tls13_client_session.nx nx_tls13.nx nx_tls13_record.nx nx_tls13_read_record_from_fd.nx nx_csprng.nx nx_sha256.nx nx_mgmt_client.nx nx_mgmt_client_gate.nx

imports: nx_acme_http.nxnx_https_url_for_fetch.nxnx_https_url_connect.nxnx_tls13_client_session_run.nxnx_tls13_client_session.nxnx_tls13.nxnx_tls13_record.nxnx_tls13_read_record_from_fd.nxnx_csprng.nxnx_sha256.nx

imported by: nx_mgmt_client_gate.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main mcl_usage mcl_puts nx_trust_store_load_from_c sys_mmap sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close nx_nss_certdata_parse sys_mmap ↻ _pat_class_cert _pat_value_octal _pat_end _find_newline _starts_with _parse_octal_line sys_mmap ↻ _is_space _decode_octal_escape _is_octal trust_store_alloc sys_mmap ↻ nx_x509_trust_store_load sys_mmap ↻ x509_parse sys_mmap ↻ asn1_cursor_init asn1_expect_tag sys_mmap ↻ asn1_read_tlv_header asn1_read_tag asn1_read_length asn1_read_length ↻ x509_read_tlv sys_mmap ↻ asn1_expect_tag ↻ x509_read_alg_id

structs

none

consts

38const MCL_MAGIC_16384: i64 = 16384
39const MCL_MAGIC_16645: i64 = 16645
40const MCL_MAGIC_4194304: i64 = 4194304
41const MCL_MAGIC_4096: i64 = 4096
42const MCL_MAGIC_2097152: i64 = 2097152
43const MCL_MAGIC_2026: i64 = 2026
44const MCL_MAGIC_1048576: i64 = 1048576
45const MCL_MAGIC_4095: i64 = 4095
46const MCL_MAGIC_65536: i64 = 65536
47const MCL_MAGIC_2000: i64 = 2000
48const MCL_MAGIC_65535: i64 = 65535
50const MCL_TOKEN_OUT_MODE: i64 = 0x180 // 0600 -- session token is a secret; owner rw only
51const MCL_CONNECT_FAIL: i64 = 0 - 11
52const MCL_HANDSHAKE_FAIL: i64 = 0 - 12
53const MCL_URL_FAIL: i64 = 0 - 10
54const MCL_UPLOAD_RETRIES: i64 = 8 // per-chunk retry budget: transport rc<0 + lost-response status=0 + 5xx (fresh connection+ephemerals + EXPONENTIAL BACKOFF each attempt; safe via the daemon's idempotent replay-ack). 8 attempts w/ backoff caps ~10s of edge-wedge ride-out per chunk.
55const MCL_ARTIFACT_CAP: i64 = 134217728 // 128 MiB artifact read buffer (raised for build-over-API full-tree .pack ~80MB); a file that fills it is REFUSED (never silently truncate). Chunks still <=48KB (daemon 64KB read cap) so a big tree = many chunks; multi-part packs are the future optimization.

functions

59func mcl_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
called by 2: mcl_usagemain
60func mcl_putn(v: i64) -> i64
called by 1: main
70func mcl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 1: main
71func mcl_streq(a: *u8, b: *u8) -> i64
called by 1: main
78func mcl_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o + i] = s[i]; i = i + 1 } return o + i }
80func mcl_catb(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { d[o + i] = s[i]; i = i + 1 } return o + i }
82func mcl_catn(d: *u8, o: i64, v: i64) -> i64
90func mcl_hexdigit(v: i64) -> i64 { if v < 10 { return 48 + v } return 55 + v } // 0-9 then A-F (uppercase)
called by 1: mcl_url_encode
93func mcl_hex32(dig: *u8, out: *u8) -> i64
called by 2: mainmain
108func mcl_is_unreserved(c: i64) -> i64
called by 1: mcl_url_encode
122func mcl_url_encode(src: *u8, n: i64, out: *u8) -> i64
140func mcl_build_login_body(handle: *u8, hn: i64, pass: *u8, pn: i64, out: *u8) -> i64
called by 2: mainmain calls 2: mcl_catmcl_url_encode
156func mcl_build_request(
called by 2: mainmain calls 3: mcl_catbmcl_catmcl_catn
195func mcl_extract_token(resp: *u8, total: i64, out_status: *i64, out: *u8, out_cap: i64) -> i64
217func mcl_write_n(fd: i64, buf: *u8, n: i64) -> i64
called by 1: mcl_send_drain
231func mcl_send_drain(s: *Tls13ClientSession, fd: i64, req: *u8, req_len: i64, out: *u8, out_cap: i64) -> i64
284func mcl_req(store: *TrustStore, full_url: *u8, target: *NxHttpsTarget, req: *u8, req_len: i64, out: *u8, out_cap: i64, vc_in: *TlsValidationContext) -> i64
315func mcl_read_file(path: *u8, out: *u8, cap: i64) -> i64
called by 1: main calls 1: sys_read
331func mcl_rtrim_nl(buf: *u8, n: i64) -> i64
called by 1: main
345func mcl_join_url(base_url: *u8, suffix: *u8, out: *u8) -> i64
called by 1: main calls 1: mcl_cat
356func mcl_usage() -> i64
called by 1: main calls 1: mcl_puts
367func mcl_upload_qpath(base_path: *u8, base_plen: i64, target: *u8, seq: i64, final: i64, sha_hex: *u8, sha_len: i64, out: *u8) -> i64
called by 2: mainmain calls 3: mcl_catbmcl_catmcl_catn
388func main(argc: i64, argv: *i64) -> i64