code wiki / _hdl_build / nx_aw_hostctl.nx
nx_aw_hostctl.nx source
↩ module page · 290 lines · 22860 B
1// nx_aw_hostctl.nx -- SOVEREIGN deploy/supervision TRIGGER for the NAS control plane. Retires the
2// nascmd.txt + nx_aw_nasfix "run arbitrary shell" escape hatch for the deploy path (operator: "no .txt and
3// other bullshit... nishi ecosystem all the way up from the hardware rung, each rung"). It gets the NAS
4// password from the sovereign vault (composes _offc/nx_machine_key.elf + _offc/nx_vault.elf, exactly as
5// nx_aw_nasfix/nx_secret_cli do), opens the team's OWN sovereign SSH (nx_ssh_lib), and runs EXACTLY ONE
6// thing remotely: the sovereign control-plane binary nx_hostctl with an ALLOWLISTED subcommand. The remote
7// payload is an absolute binary path + one validated arg -- NO command file, NO cd/&&, NO tar/kill/setsid/
8// fuser/dev-tcp coreutils. All real lifecycle work (atomic binary swap, kill, respawn, health) is done by
9// nx_hostctl's own syscalls. This is the "named sovereign op-organ" the sovereignty memo specified.
10// nx_aw_hostctl selfswap -> run nx_hostctl.new selfswap : install+adopt the NEW supervisor (wiki-aware)
11// nx_aw_hostctl deploy -> run nx_hostctl deploy : atomic-swap sites.elf + respawn (/wiki route)
12// nx_aw_hostctl wikideploy -> run nx_hostctl wikideploy : atomic-swap the wiki gateway + respawn
13// nx_aw_hostctl galxdeploy -> run nx_hostctl galxdeploy : atomic-swap the gallery gateway + respawn
14// nx_aw_hostctl reconcile -> run nx_hostctl reconcile : one-supervisor reconcile (adopt sites.elf)
15// license_tier: ORIGINAL (vault+SSH spine reused from nx_aw_nasfix; the shell escape hatch removed)
16import "nx_syscalls.nx"
17import "nx_ssh_lib.nx"
18import "nx_arbiter.nx" // fl_acquire/fl_release -- serialize control-plane ops vs sibling publishes (the queue)
19import "nx_receipt.nx" // rcpt_emit -- the op acceptance/receipt ledger (every control-plane op reports back to the workstream)
20const AH_MAGIC_8095: i64 = 8095
21const AH_MAGIC_18190: i64 = 18190
22const AH_MAGIC_18794: i64 = 18794
23const AH_MAGIC_18795: i64 = 18795
24const AH_MAGIC_18099: i64 = 18099
25const AH_MAGIC_9099: i64 = 9099
26const AH_MAGIC_9091: i64 = 9091
27const AH_MAGIC_9444: i64 = 9444
28const AH_MAGIC_8453: i64 = 8453
29const AH_MAGIC_8444: i64 = 8444
30const AH_MAGIC_8791: i64 = 8791
31const AH_MAGIC_8097: i64 = 8097
32const AH_MAGIC_18797: i64 = 18797
33const AH_MAGIC_18793: i64 = 18793
34const AH_MAGIC_6881: i64 = 6881
35const AH_MAGIC_18090: i64 = 18090
36const AH_MAGIC_18796: i64 = 18796
37const AH_MAGIC_18456: i64 = 18456
38const AH_MAGIC_65536: i64 = 65536
39const AH_MAGIC_1048576: i64 = 1048576
40const AH_MAGIC_16384: i64 = 16384
41const AH_MAGIC_1024: i64 = 1024
42const AH_MAGIC_1800: i64 = 1800
43
44const AH_SECRET_OUT: *u8 = "/tmp/nxsecret.out" as *u8
45const AH_VAULT_NV: *u8 = "/home/elderwesto/.nishi/secrets/nas.nv" as *u8
46const AH_HOSTCTL: *u8 = "/volume1/homes/elderwesto/nishihost/nx_hostctl" as *u8
47const AH_HOSTCTL_NEW: *u8 = "/volume1/homes/elderwesto/nishihost/nx_hostctl.new" as *u8
48
49func ah_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
50func ah_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8) { if a[i]!=b[i] { return 0 } i=i+1 } if b[i]!=(0 as u8) { return 0 } return 1 }
51
52// fork+execve a sovereign helper binary; parent waits; returns child WEXITSTATUS (mirrors nx_aw_nasfix).
53func ah_run(path: *u8, a1: *u8, a2: *u8) -> i64 {
54 let pid: i64 = sys_fork()
55 if pid == 0 {
56 let argv: *i64 = sys_mmap(64) as *i64
57 argv[0] = path as i64
58 var ai: i64 = 1
59 if (a1 as i64) != 0 { argv[ai] = a1 as i64; ai = ai + 1 }
60 if (a2 as i64) != 0 { argv[ai] = a2 as i64; ai = ai + 1 }
61 argv[ai] = 0
62 let envp: *i64 = sys_mmap(16) as *i64
63 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
64 sys_execve(path, argv, envp)
65 sys_exit(127)
66 }
67 let st: *i64 = sys_mmap(16) as *i64
68 sys_wait4(pid, st, 0)
69 return (st[0] >> 8) & 0xff
70}
71func ah_unlink(path: *u8) -> i64 { __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) return 0 }
72
73// DEFENSIVE BOUNDARY (operator: "no one can ever get into areas they shouldnt"): only these exact subcommands
74// may be sent to the NAS control plane. Anything else is REFUSED before any SSH happens -- zero command
75// injection surface (this organ can NEVER run arbitrary shell, by construction, unlike nx_aw_nasfix).
76func ah_allowed(sub: *u8) -> i64 {
77 if ah_streq(sub, "selfswap" as *u8) == 1 { return 1 }
78 if ah_streq(sub, "galxpipeline" as *u8) == 1 { return 1 } // run analysis-on-ingest pipeline (thumbnails + NXVI)
79 if ah_streq(sub, "mgmtdeploy" as *u8) == 1 { return 1 } // deploy the mgmt-API allowlist update (pure-MCP run path)
80 if ah_streq(sub, "status" as *u8) == 1 { return 1 }
81 if ah_streq(sub, "sitetest" as *u8) == 1 { return 1 }
82 if ah_streq(sub, "startsite" as *u8) == 1 { return 1 }
83 if ah_streq(sub, "statushtml" as *u8) == 1 { return 1 }
84 if ah_streq(sub, "deploy" as *u8) == 1 { return 1 }
85 if ah_streq(sub, "wikideploy" as *u8) == 1 { return 1 }
86 if ah_streq(sub, "galxdeploy" as *u8) == 1 { return 1 }
87 if ah_streq(sub, "galxservedeploy" as *u8) == 1 { return 1 } // promote+restart the gallery SERVE (mirror galxdeploy)
88 if ah_streq(sub, "libdeploy" as *u8) == 1 { return 1 } // promote+launch the sovereign library backend :AH_MAGIC_8095 (/research)
89 if ah_streq(sub, "reconcile" as *u8) == 1 { return 1 }
90 if ah_streq(sub, "restart" as *u8) == 1 { return 1 } // restart <known-service>: heal action -- kill+respawn a wedged supervised daemon (2nd arg = service name)
91 if ah_streq(sub, "buildrun" as *u8) == 1 { return 1 } // buildrun <target>: COMPILE a target on the NAS (build-over-API) -> stage <target>.sov.elf.new
92 if ah_streq(sub, "buildsetup" as *u8) == 1 { return 1 } // buildsetup: mkdir buildroot/{_offc,runtime} (once, before toolchain deploy)
93 if ah_streq(sub, "galxauthprobe" as *u8) == 1 { return 1 } // loopback POST :AH_MAGIC_18190 auth -- isolates olg_login-hang vs proxy
94 if ah_streq(sub, "galxregprobe" as *u8) == 1 { return 1 } // loopback POST :AH_MAGIC_18190 register -- proves a user can create an account
95 if ah_streq(sub, "superrollback" as *u8) == 1 { return 1 } // never-brick rollback of a bad selfswap (restore nx_hostctl.prev)
96 if ah_streq(sub, "supervisetest" as *u8) == 1 { return 1 } // read-only lease check = mechanical single-supervisor proof
97 if ah_streq(sub, "hubdeploy" as *u8) == 1 { return 1 } // mkdir /volume1/ai/hub{,/pages} (sovereign sys_mkdir)
98 if ah_streq(sub, "gendeploy" as *u8) == 1 { return 1 } // mkdir /volume1/ai/gen + chmod gen daemons +x (HC_GEN guards launch :AH_MAGIC_18794/:AH_MAGIC_18795)
99 if ah_streq(sub, "mirror" as *u8) == 1 { return 1 } // NAS-resident Apertus/model mirror -> /volume1/ai/apertus (run-on-target, not the dev laptop)
100 if ah_streq(sub, "mirrorpar" as *u8) == 1 { return 1 } // NAS-resident PARALLEL concurrent download (proves what crashed WSL)
101 if ah_streq(sub, "mirrorstop" as *u8) == 1 { return 1 } // stop the NAS mirror/parallel pulls (full-cmdline kill)
102 if ah_streq(sub, "distpub" as *u8) == 1 { return 1 } // publish a real NAS file into the hub distribution index
103 if ah_streq(sub, "distserve" as *u8) == 1 { return 1 } // start the /dist content-addressed download server (:AH_MAGIC_18099)
104 if ah_streq(sub, "distprobe" as *u8) == 1 { return 1 } // loopback self-test: GET a published cid -> real bytes
105 if ah_streq(sub, "genprobe" as *u8) == 1 { return 1 } // one-shot LIVE proof: run nx_gen_live_probe.elf -> drive the deployed /gen gateway, relay PASS/FAIL
106 if ah_streq(sub, "rollback" as *u8) == 1 { return 1 } // restore sites.elf.prev (reverse a bad deploy)
107 if ah_streq(sub, "certswap" as *u8) == 1 { return 1 } // backup live TLS cert -> .bak, install .new -> live, restart sites.elf (no binary swap)
108 if ah_streq(sub, "certrollback" as *u8) == 1 { return 1 } // restore TLS cert .bak -> live + restart (reverse a bad certswap)
109 if ah_streq(sub, "logintest" as *u8) == 1 { return 1 } // spawn login .new on :AH_MAGIC_9099 (pre-flight, live :AH_MAGIC_9091 untouched)
110 if ah_streq(sub, "mtlsproxytest" as *u8) == 1 { return 1 } // sovereign-launch the mTLS reverse proxy on TEST :AH_MAGIC_9444 (no :443/DSM change)
111 if ah_streq(sub, "platformtest" as *u8) == 1 { return 1 } // sovereign-launch andelinwest :AH_MAGIC_8453 + SNI router :AH_MAGIC_8444 (INTERNAL, no :443/DSM change)
112 if ah_streq(sub, "nftread" as *u8) == 1 { return 1 } // sovereign netfilter R0: READ-ONLY nat-table probe (grounds legacy-vs-nft; cannot touch DSM's rules)
113 if ah_streq(sub, "nettap" as *u8) == 1 { return 1 } // NX-NETSCOPE wire tap: read-only bounded 60s capture of inbound SYNs to [arg=port|443] -- the wireshark-in-the-API
114 if ah_streq(sub, "logindeploy" as *u8) == 1 { return 1 } // swap+restart the 24h-TTL login daemon (.prev rollback)
115 if ah_streq(sub, "loginrollback" as *u8) == 1 { return 1 } // restore nx_opaque_login.elf.prev
116 if ah_streq(sub, "findlaunch" as *u8) == 1 { return 1 } // recover the original login launch args (read-only grep)
117 if ah_streq(sub, "receipts" as *u8) == 1 { return 1 } // dump op_receipts.tsv (acceptance + MEASURED ms per op, read-only)
118 if ah_streq(sub, "kickreader" as *u8) == 1 { return 1 } // surgical: kill the wedged :AH_MAGIC_8791 reader; keeper respawns
119 if ah_streq(sub, "kicktorrent" as *u8) == 1 { return 1 } // surgical: kill the :AH_MAGIC_8097 media daemon; guard respawns the NEW (loopback) binary
120 if ah_streq(sub, "kickdevapi" as *u8) == 1 { return 1 } // surgical: kill the :AH_MAGIC_18797 dev/CI API daemon; guard respawns the NEW binary
121 if ah_streq(sub, "devapitoolchain" as *u8) == 1 { return 1 } // extract the nx_cc toolchain tarball on the hub -> /api/dev/build compiles on the NAS
122 if ah_streq(sub, "kicktorrentgw" as *u8) == 1 { return 1 } // surgical: kill the :AH_MAGIC_18793 torrent gateway; guard respawns the NEW binary
123 if ah_streq(sub, "kickseed" as *u8) == 1 { return 1 } // surgical: kill the :AH_MAGIC_6881 BitTorrent seeder; hc_guard_seed respawns the NEW binary (+ re-reads seed_index.conf)
124 if ah_streq(sub, "torstat" as *u8) == 1 { return 1 } // diagnostic: seedeval per active download -> SCARCE/IGNORING/COMPLETE (read-only)
125 if ah_streq(sub, "kickworkers" as *u8) == 1 { return 1 } // kill stale download workers -> kicktorrent respawns the NEW worker binary
126 if ah_streq(sub, "reseed" as *u8) == 1 { return 1 } // register all completed downloads for seeding (share the library back)
127 if ah_streq(sub, "trackerrefresh" as *u8) == 1 { return 1 } // grow trackers.txt from live public lists (sovereign TLS fetch)
128 if ah_streq(sub, "portmap" as *u8) == 1 { return 1 } // NAT-PMP auto-open :AH_MAGIC_6881 on the router (WAN reach)
129 if ah_streq(sub, "routerctl" as *u8) == 1 { return 1 } // sovereign GL.iNet dashboard (model/wan/forwards/clients via SSH+uci)
130 if ah_streq(sub, "torrentdeploy" as *u8) == 1 { return 1 } // P1 off-LAN parity: promote staged torrent daemon/seedeval -> /volume1/ai/torrent/ + kick
131 if ah_streq(sub, "torrentrollback" as *u8) == 1 { return 1 } // never-brick reverse of a bad torrentdeploy (.prev -> live)
132 if ah_streq(sub, "kickseedann" as *u8) == 1 { return 1 } // surgical: kill the DHT announcer; hc_guard_seedann respawns it (immediate re-announce sweep)
133 if ah_streq(sub, "killdurindex" as *u8) == 1 { return 1 } // surgical: kill the stray durindex holding the gallery's :AH_MAGIC_18090 socket (fd-leak from a removed boot-spawn)
134 if ah_streq(sub, "durindexrun" as *u8) == 1 { return 1 } // proper detached one-shot: launch the duration-index batch (fds closed, flock) -> runtime-sort populates
135 if ah_streq(sub, "durindexstat" as *u8) == 1 { return 1 } // read-only: galx_dur.raw durations done vs vid_paths total (runtime-sort data readiness)
136 if ah_streq(sub, "tsdurtest" as *u8) == 1 { return 1 } // diagnostic: run nx_ts_dur on one tail video + show output
137 if ah_streq(sub, "durbinbuild" as *u8) == 1 { return 1 } // compact galx_dur.raw -> galx_dur.bin: O(1) /dur seekbar lookup (no 16MB PCR re-scan), no gallery restart
138 if ah_streq(sub, "galxdurprobe" as *u8) == 1 { return 1 } // LIVE proof: loopback GET :AH_MAGIC_18090/vid/0/dur asserts the /dur fast-path serves a duration (no crash)
139 if ah_streq(sub, "galxtagprobe" as *u8) == 1 { return 1 } // LIVE proof: POST /tag -> GET /api/tags round-trip (R4 tag store write+read+last-wins over loopback)
140 if ah_streq(sub, "galxstreamprobe" as *u8) == 1 { return 1 } // read-only MEASURE: time /segs + .idx build + /init + /seg (grounds the streaming-perf fix; no playback change)
141 if ah_streq(sub, "galxgwprobe" as *u8) == 1 { return 1 } // read-only: loopback GET :AH_MAGIC_18190/gallery -> isolates the /gallery 404 (gateway vs sites.elf route)
142 if ah_streq(sub, "kicksites" as *u8) == 1 { return 1 } // kill sites.elf -> supervisor respawns live binary (re-reads proxy_routes.conf; NO binary swap)
143 if ah_streq(sub, "kicksynth" as *u8) == 1 { return 1 } // kill nx_synth_serve_daemon.elf -> hc_guard_synth respawns the freshly-staged binary (:AH_MAGIC_18796 /synth/api redeploy)
144 if ah_streq(sub, "kickdocportal" as *u8) == 1 { return 1 } // kill the docportal admin daemon (:AH_MAGIC_18456); guard respawns the NEW shipped binary (was remote-only, never client-allowlisted)
145 if ah_streq(sub, "tsindextest" as *u8) == 1 { return 1 } // read-only MEASURE: run nx_ts_index on a .ts + show scan_ms (the .idx build time) + keyframes/dur
146 if ah_streq(sub, "galxlibstats" as *u8) == 1 { return 1 } // read-only: library scale (count + total runtime) from galx_dur.bin
147 return 0
148}
149
150// non-blocking drain of pending server packets (prevents the bidirectional deadlock while streaming stdin).
151func ah_drain(st: *SshState) -> i64 {
152 let pfd: *u8 = sys_mmap(8); let fdv: i64 = st.fd
153 pfd[0]=(fdv&0xff) as u8; pfd[1]=((fdv>>8)&0xff) as u8; pfd[2]=((fdv>>16)&0xff) as u8; pfd[3]=((fdv>>24)&0xff) as u8
154 pfd[4]=1 as u8; pfd[5]=0 as u8
155 let buf: *u8 = sys_mmap(AH_MAGIC_65536); var run: i64 = 1
156 while run == 1 { let r: i64 = sys_poll(pfd, 1, 0); if r <= 0 { run = 0 } else { if ssh_enc_recv(st, buf) < 0 { run = 0 } } }
157 return 0
158}
159// open an exec channel for `wcmd`, stream `data` (the sudo password + newline) to its stdin, print the
160// remote output (channel-data) to fd 1, drain to EOF. Same SSH-channel mechanism as nx_aw_send's writer.
161// quiet_max = drain patience in 500ms polls with NO channel data before giving up: 8 (=4s) suits fast
162// verbs; LONG-RUNNING verbs (nettap's bounded 60s capture prints nothing until a SYN arrives) pass a
163// bigger budget so the results aren't orphaned mid-window (2026-07-05: nettap output died at the banner).
164func ah_sudo_put(st: *SshState, wcmd: *u8, wcmdlen: i64, data: *u8, datalen: i64, quiet_max: i64) -> i64 {
165 let co: *u8 = sys_mmap(64); var c: i64 = 0
166 c = ssh_put_byte(co, c, 90); c = ssh_put_str(co, c, "session" as *u8, 7)
167 c = ssh_put_u32(co, c, 0); c = ssh_put_u32(co, c, AH_MAGIC_1048576); c = ssh_put_u32(co, c, AH_MAGIC_16384)
168 ssh_enc_send(st, co, c)
169 let rep: *u8 = sys_mmap(AH_MAGIC_65536); var rcid: i64 = 0 - 1; var guard: i64 = 0
170 while rcid < 0 {
171 if guard > 16 { return 0 - 1 }
172 let rl: i64 = ssh_enc_recv(st, rep); if rl < 0 { return 0 - 1 }
173 if rep[0] == 91 as u8 { rcid = ssh_u32be(rep, 5) }
174 if rep[0] == 92 as u8 { return 0 - 2 }
175 guard = guard + 1
176 }
177 let cr: *u8 = sys_mmap(AH_MAGIC_1024); var q: i64 = 0
178 q = ssh_put_byte(cr, q, 98); q = ssh_put_u32(cr, q, rcid); q = ssh_put_str(cr, q, "exec" as *u8, 4); q = ssh_put_byte(cr, q, 1); q = ssh_put_str(cr, q, wcmd, wcmdlen)
179 ssh_enc_send(st, cr, q)
180 var off: i64 = 0
181 while off < datalen {
182 var nn: i64 = datalen - off; if nn > AH_MAGIC_16384 { nn = AH_MAGIC_16384 }
183 let dp: *u8 = sys_mmap(nn + 64); var p: i64 = 0
184 p = ssh_put_byte(dp, p, 94); p = ssh_put_u32(dp, p, rcid); p = ssh_put_u32(dp, p, nn)
185 var i: i64 = 0; while i < nn { dp[p + i] = data[off + i]; i = i + 1 } p = p + nn
186 ssh_enc_send(st, dp, p)
187 ah_drain(st)
188 off = off + nn
189 }
190 let eo: *u8 = sys_mmap(16); var e: i64 = 0; e = ssh_put_byte(eo, e, 96); e = ssh_put_u32(eo, e, rcid); ssh_enc_send(st, eo, e)
191 let pfd2: *u8 = sys_mmap(8); let fdv2: i64 = st.fd
192 pfd2[0]=(fdv2&0xff) as u8; pfd2[1]=((fdv2>>8)&0xff) as u8; pfd2[2]=((fdv2>>16)&0xff) as u8; pfd2[3]=((fdv2>>24)&0xff) as u8
193 pfd2[4]=1 as u8; pfd2[5]=0 as u8
194 var done: i64 = 0; var quiet: i64 = 0
195 while done == 0 {
196 let pr: i64 = sys_poll(pfd2, 1, 500)
197 if pr <= 0 { quiet = quiet + 1; if quiet >= quiet_max { done = 1 } }
198 else { let rl: i64 = ssh_enc_recv(st, rep); if rl < 0 { done = 1 } else {
199 if rep[0] == 94 as u8 { let dl: i64 = ssh_u32be(rep, 5); sys_write(1, (rep as i64 + 9) as *u8, dl) }
200 if rep[0] == 97 as u8 { done = 1 } } }
201 }
202 let clo: *u8 = sys_mmap(16); var k: i64 = 0; k = ssh_put_byte(clo, k, 97); k = ssh_put_u32(clo, k, rcid); ssh_enc_send(st, clo, k)
203 return 0
204}
205
206func main(argc: i64, argv: *i64) -> i64 {
207 if argc < 2 {
208 ssh_puts("usage: nx_aw_hostctl <selfswap|deploy|wikideploy|galxdeploy|reconcile|kickreader|status>\n" as *u8); return 2
209 }
210 let sub: *u8 = argv[1] as *u8
211 if ah_allowed(sub) == 0 {
212 ssh_puts("nx_aw_hostctl: REFUSED -- subcommand not in the allowlist (no arbitrary remote exec)\n" as *u8); return 2
213 }
214 // QUEUE: a deploy/selfswap/reconcile restarts daemons -- concurrent ones are THE disaster. Serialize on the
215 // SAME nas_push lease as content publishes so the whole NAS mutation path is one-at-a-time (mutual exclusion).
216 let lock_fd: i64 = fl_acquire("nas_push" as *u8, AH_MAGIC_1800, 100)
217 if lock_fd < 0 { ssh_puts("nx_aw_hostctl: nas_push lease busy >180s -- aborting (retry)\n" as *u8); return 9 }
218
219 // ---- sovereign credential retrieval (no shell, no typed passphrase) ----
220 if ah_run("_offc/nx_machine_key.elf" as *u8, 0 as *u8, 0 as *u8) != 0 {
221 ssh_puts("nx_aw_hostctl: machine-key derive FAILED\n" as *u8); ah_unlink("/tmp/nxpass" as *u8); return 1
222 }
223 if ah_run("_offc/nx_vault.elf" as *u8, "open" as *u8, AH_VAULT_NV) != 0 {
224 ssh_puts("nx_aw_hostctl: vault open nas.nv FAILED (no secret / wrong machine / tampered)\n" as *u8)
225 ah_unlink("/tmp/nxpass" as *u8); return 2
226 }
227 ah_unlink("/tmp/nxpass" as *u8) // shred the passphrase ephemeral immediately
228 let pwbox: *i64 = sys_mmap(16) as *i64
229 let pw: *u8 = sys_read_file(AH_SECRET_OUT, pwbox)
230 if (pw as i64) == 0 { ssh_puts("nx_aw_hostctl: cannot read decrypted secret\n" as *u8); return 3 }
231 var pwlen: i64 = pwbox[0]
232 while pwlen > 0 { if pw[pwlen-1] == 10 as u8 { pwlen = pwlen - 1 } else { if pw[pwlen-1] == 13 as u8 { pwlen = pwlen - 1 } else { break } } }
233
234 // ---- sovereign SSH to the NAS (192.168.8.227) ----
235 let st: *SshState = sys_mmap(SSH_STATE_BYTES) as *SshState
236 if ssh_open_session(st, (192 << 24) | (168 << 16) | (8 << 8) | 227) != 0 {
237 ssh_puts("nx_aw_hostctl: SSH session FAILED (NAS unreachable on :22)\n" as *u8); ah_unlink(AH_SECRET_OUT); return 5
238 }
239 if ssh_userauth_password(st, "elderwesto" as *u8, 10, pw, pwlen) != 1 {
240 ssh_puts("nx_aw_hostctl: SSH auth FAILED\n" as *u8); sys_close(st.fd); ah_unlink(AH_SECRET_OUT); return 6
241 }
242 ah_unlink(AH_SECRET_OUT) // shred the decrypted secret file (pw stays only in this process)
243
244 // ---- compose the SINGLE remote invocation: "<abs-binpath> <allowlisted-sub>" ----
245 // selfswap must run the NEW binary (nx_hostctl.new) so it installs+adopts; everything else runs the live
246 // nx_hostctl. Absolute path => the remote login shell just execs the sovereign binary (no cd, no &&, no
247 // PATH lookup). One binary + one validated arg = the entire remote payload.
248 var bin: *u8 = AH_HOSTCTL
249 // ONLY selfswap runs the staged .new (to install it); everything else runs the LIVE binary -- because
250 // selfswap CONSUMES .new (renames it onto live), so after an install .new no longer exists. Live is the
251 // freshly-installed (memory-fixed) binary, so status/sitetest/startsite/etc. get the fix from live.
252 if ah_streq(sub, "selfswap" as *u8) == 1 { bin = AH_HOSTCTL_NEW }
253 // ROOT control plane: "sudo -S <abs>/nx_hostctl <sub>" with the vault password streamed to sudo's stdin.
254 // reconcile/deploy/selfswap MUST run as root to manage the boot-launched ROOT supervisor + daemons
255 // (kill/respawn). nx_hostctl self-chdirs, so NO shell `cd`; argv-driven sub, so NO .cmd staging file.
256 let pfx: *u8 = "sudo -S " as *u8
257 let pfxlen: i64 = ah_slen(pfx)
258 let binlen: i64 = ah_slen(bin)
259 let sublen: i64 = ah_slen(sub)
260 // forward ONE optional 2nd arg (e.g. `restart <service>`). The allowlisted sub bounds what it can do; the
261 // hostctl re-validates the arg (restart's fail-closed known-service allowlist), so this is not arbitrary exec.
262 var arg2: *u8 = 0 as *u8
263 var arg2len: i64 = 0
264 if argc >= 3 { arg2 = argv[2] as *u8; arg2len = ah_slen(arg2) }
265 let full: *u8 = sys_mmap(pfxlen + binlen + sublen + arg2len + 16)
266 var fo: i64 = 0
267 var ppi: i64 = 0; while ppi < pfxlen { full[fo] = pfx[ppi]; fo = fo + 1; ppi = ppi + 1 }
268 var bi: i64 = 0; while bi < binlen { full[fo] = bin[bi]; fo = fo + 1; bi = bi + 1 }
269 full[fo] = 32 as u8; fo = fo + 1 // space
270 var si: i64 = 0; while si < sublen { full[fo] = sub[si]; fo = fo + 1; si = si + 1 }
271 if arg2len > 0 { full[fo] = 32 as u8; fo = fo + 1; var ai: i64 = 0; while ai < arg2len { full[fo] = arg2[ai]; fo = fo + 1; ai = ai + 1 } }
272
273 // sudo -S reads the password from stdin: stream the vault password + newline.
274 let sin: *u8 = sys_mmap(pwlen + 4)
275 var pj: i64 = 0; while pj < pwlen { sin[pj] = pw[pj]; pj = pj + 1 }
276 sin[pwlen] = 10 as u8
277
278 ssh_puts("nx_aw_hostctl: [auth ok] sovereign ROOT control-plane call ->\n " as *u8)
279 ssh_puts(full)
280 ssh_puts("\n---- remote nx_hostctl output ----\n" as *u8)
281 // nettap runs a bounded 60s wire capture that may be SILENT the whole window -> 150*500ms = 75s
282 // of drain patience; every other verb keeps the snappy 4s disconnect.
283 var qmax: i64 = 8
284 if ah_streq(sub, "nettap" as *u8) == 1 { qmax = 150 }
285 ah_sudo_put(st, full, fo, sin, pwlen + 1, qmax)
286 rcpt_emit("nx_aw_hostctl" as *u8, sub, "nas:nishihost" as *u8, "ISSUED" as *u8, sub) // acceptance receipt -> the workstream ledger
287 sys_close(st.fd)
288 fl_release(lock_fd) // release the queue lease -> next waiting sibling op proceeds
289 return 0
290}