nx_cert_autorenew.nx source
↩ module page · 360 lines · 24222 B
1// nx_cert_autorenew.nx -- SOVEREIGN AUTO-RENEWAL for the per-domain wildcard TLS certs.
2// Closes the gap that started this whole arc: a per-domain wildcard cert SILENTLY lapsed because nothing
3// renewed it. This organ MONITORS the live SNI certs and RENEWS any inside the 21d warn window -- unattended.
4//
5// COMPOSES ONLY PROVEN PIECES (rule 15 DRY; no new high-stakes mechanism):
6// nx_cert_autorenew_lib -- domain->path mapping + WARN/EXPIRED trigger (gate-proven)
7// nx_cert_monitor -- CM_* verdict vocabulary + cm_status (local re-parse) + cm_name
8// nx_tls13_client_session_run + nx_trust_store_load_from_certdata -- the SAME live TLS-1.3-with-SNI probe
9// nx_torrent_live_probe uses (validates the SERVED cert against the Mozilla CA store at a chosen epoch)
10// _offc/nx_secret_cli.elf get porkbun -- Porkbun creds from the vault -> /tmp/nxsecret.out
11// _offc/nx_sov_build_run.elf + /tmp/nx_acme_dns01_issue.sov.elf <domain> -- LE-1.3 DNS-01 wildcard issuance
12// _offc/nx_aw_send.elf <local> <remote> -- vault-keyed SSH push to the NAS (proven)
13// _offc/nx_aw_hostctl.elf deploy -- atomic sites.elf swap + respawn = cert RELOAD (proven)
14//
15// MONITOR (live, location-independent): for each configured domain, drive a TLS handshake to the web host
16// presenting that SNI and validate the SERVED leaf at now AND at now+21d. valid-at-now + invalid-at-now+21d
17// = inside the warn window (CM_WARN); invalid-at-now = CM_EXPIRED; unreachable = CM_NOCERT (no false trigger).
18// This is best-in-class external SSL-expiry monitoring -- it watches what clients actually receive, from
19// anywhere, so it does not depend on the conductor sharing a filesystem with the NAS.
20//
21// RENEW (fail-safe BY CONSTRUCTION -- rule 12/13/14): issue to /tmp -> RE-PARSE the fresh cert locally
22// (never push a bad cert) -> push the per-domain fullchain+key to the live le_<label>_* paths -> stage the
23// durable current-good binary as sites.elf.new -> deploy (respawn=reload) -> VERIFY the served leaf advanced
24// past the warn window. Any step fails -> ABORT + structured log, leaving a working state: we renew EARLY
25// (21d slack) and the new cert is LE-validated, so the worst partial outcome still serves a valid cert.
26//
27// SCHEDULE: the conductor (nx_team_pulse tp_tail_d) calls this EVERY beat; a daily-check guard runs the real
28// sweep at most once/CHECK_INTERVAL, and a per-domain cooldown caps issuance at one/domain/COOLDOWN -- so the
29// per-beat call is cheap + idempotent + LE-budget-safe (rule 10/21).
30// license_tier: ORIGINAL
31import "nx_cert_autorenew_lib.nx"
32import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
33import "nx_syscalls.nx"
34import "nx_x509_trust_store.nx"
35import "nx_trust_store_load_from_certdata.nx"
36import "nx_tls13_client_validate_certificate.nx" // TlsValidationContext
37import "nx_tls13_client_session_run.nx" // nx_tls13_client_session_run
38import "nx_csprng.nx" // SEV-9 1785970852: real per-connection handshake entropy
39const CAR_MAGIC_86400: i64 = 86400
40const CAR_MAGIC_4000: i64 = 4000
41const CAR_MAGIC_8192: i64 = 8192
42const CAR_MAGIC_4194304: i64 = 4194304
43
44// ---- named infra constants (the proven organs use these exact values; single-source, documented) ----
45const CAR_TRUST_STORE: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/data/mozilla_certdata.txt\x00" as *u8
46const CAR_NAS_IP: i64 = (192 << 24) | (168 << 16) | (8 << 8) | 240 // the web TLS host (nx_torrent_live_probe)
47const CAR_TLS_PORT: i64 = 8443
48const CAR_VERIFY_FUTURE_DAYS: i64 = 30 // > 21d warn window, << chain validity (~years): proves notAfter advanced
49const CAR_CHECK_INTERVAL: i64 = 86400 // run the real sweep at most once/day (daily cadence over per-beat calls)
50const CAR_COOLDOWN: i64 = 86400 // at most one LE issuance / domain / day (LE-budget guard)
51const CAR_DOMAINS_CONF: *u8 = "knowledge/hosting/cert_domains.conf\x00" as *u8
52const CAR_CHECK_STAMP: *u8 = "knowledge/status/cert_autorenew_lastcheck\x00" as *u8
53const CAR_RENEW_LOG: *u8 = "knowledge/status/cert_renew.log\x00" as *u8
54const CAR_STAMP_DIR: *u8 = "knowledge/status/cert_renew_\x00" as *u8
55// DURABLE byte-identical copy of the CURRENT-live sites binary (operator stages it; see report flag #1).
56// NOT a session scratchpad path (those evaporate). deploy atomically swaps this in then respawns = cert reload.
57const CAR_SITES_BINARY: *u8 = "_offc/sites_live.elf\x00" as *u8
58const CAR_SITES_NEW: *u8 = "/volume1/homes/elderwesto/nishihost/sites.elf.new\x00" as *u8
59// ARM FILE -- live renewal (issue+push+deploy) is DISARMED until this file exists. Default = MONITOR-ONLY:
60// the sweep probes + logs WARN/EXPIRED but performs NO live LE issuance or daemon touch. The operator arms it
61// (create the file) ONLY after the one-time live end-to-end test passes (report flag #1). This makes wiring
62// the organ into the conductor SAFE BY CONSTRUCTION -- it cannot fire an unattended renewal pre-arming.
63const CAR_ARM_FILE: *u8 = "knowledge/hosting/cert_autorenew.enabled\x00" as *u8
64
65// ---- UI + durable log (rule 18: WHAT happened, WHY it matters, WHAT to do) ----
66func car_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
67func car_pn(v: i64) -> i64 {
68 let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }
69 var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
70 let b: *u8 = sys_mmap(28); var i: i64 = 0; while i < k { b[i] = t[k-1-i]; i = i + 1 } sys_write(1, b, k); return 0
71}
72// echo a line to stdout AND append it to the durable renewal ledger (so a headless beat leaves evidence).
73func car_log(s: *u8) -> i64 {
74 var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 }
75 sys_write(1, s, n)
76 let fd: i64 = sys_openat_append(CAR_RENEW_LOG, 0x1a4)
77 if fd >= 0 { sys_write(fd, s, n); sys_close(fd) }
78 return 0
79}
80
81// ---- fork+execve a sovereign helper; parent waits; returns child WEXITSTATUS (the proven ah_run pattern) ----
82func car_run(path: *u8, argv: *i64) -> i64 {
83 let pid: i64 = sys_fork()
84 if pid == 0 {
85 let envp: *i64 = sys_mmap(16) as *i64
86 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
87 sys_execve(path, argv, envp)
88 sys_exit(127)
89 }
90 let st: *i64 = sys_mmap(16) as *i64
91 sys_wait4(pid, st, 0)
92 return (st[0] >> 8) & 0xff
93}
94
95// ---- raw 8-byte epoch state files (lastcheck + per-domain cooldown stamps) ----
96func car_epoch_read(path: *u8) -> i64 {
97 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 }
98 let box: *i64 = sys_mmap(16) as *i64; box[0] = 0
99 let r: i64 = sys_read(fd, box as *u8, 8); sys_close(fd)
100 if r != 8 { return 0 }
101 return box[0]
102}
103func car_epoch_write(path: *u8, epoch: i64) -> i64 {
104 let fd: i64 = sys_openat_wr(path, 0x180); if fd < 0 { return 0 } // 0600
105 let box: *i64 = sys_mmap(16) as *i64; box[0] = epoch
106 sys_write(fd, box as *u8, 8); sys_close(fd); return 0
107}
108// per-domain cooldown stamp path: knowledge/status/cert_renew_<label>.stamp
109func car_stamp_path(label: *u8, out: *u8) -> i64 {
110 var o: i64 = 0; o = car_put(out, o, CAR_STAMP_DIR); o = car_put(out, o, label); o = car_put(out, o, ".stamp" as *u8)
111 out[o] = 0 as u8; return o
112}
113// 1 if it is OK to renew this label now (no successful renewal within COOLDOWN); 0 = throttle.
114func car_cooldown_ok(label: *u8, now: i64) -> i64 {
115 let p: *u8 = sys_mmap(256); car_stamp_path(label, p)
116 let last: i64 = car_epoch_read(p)
117 if last > 0 { if now - last < CAR_COOLDOWN { return 0 } }
118 return 1
119}
120
121// ---- live TLS probe: handshake to the web host with this SNI, validate the SERVED cert at `now_epoch`.
122// returns 1 = validated OK at now_epoch ; 0 = connected but cert INVALID at now_epoch ; -1 = host unreachable.
123func car_handshake_ok(domain: *u8, dlen: i64, store: *TrustStore, now_epoch: i64) -> i64 {
124 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
125 if fd < 0 { return 0 - 1 }
126 sys_set_socket_timeout(fd, 20)
127 let sa: *u8 = sys_mmap(16)
128 sa[0] = 2 as u8; sa[1] = 0 as u8
129 sa[2] = ((CAR_TLS_PORT >> 8) & 0xff) as u8; sa[3] = (CAR_TLS_PORT & 0xff) as u8
130 sa[4] = ((CAR_NAS_IP >> 24) & 0xff) as u8; sa[5] = ((CAR_NAS_IP >> 16) & 0xff) as u8
131 sa[6] = ((CAR_NAS_IP >> 8) & 0xff) as u8; sa[7] = (CAR_NAS_IP & 0xff) as u8
132 var z: i64 = 8; while z < 16 { sa[z] = 0 as u8; z = z + 1 }
133 if nx_connect_bounded(fd, sa, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0 - 1 } // unreachable -> NOCERT (not an expiry)
134 // SEV-9 FIX 2026-08-05 (debt 1785970852, CWE-330): these two loops hardcoded the X25519 scalar
135 // and client_random, so this probe opened every TLS session with the SAME ephemeral key. Even a
136 // read-only expiry probe must not, because the constant is the fleet-wide one.
137 let cr: *u8 = sys_mmap(32); var i: i64 = 0; nx_csprng_fill(cr, 32)
138 let priv: *u8 = sys_mmap(32); i = 0; nx_csprng_fill(priv, 32)
139 let vc: *TlsValidationContext = sys_mmap(64) as *TlsValidationContext
140 vc.store = store; vc.sni_host = domain; vc.sni_host_len = dlen; vc.now_epoch = now_epoch
141 let sr: i64 = nx_tls13_client_session_run(fd, domain, dlen, cr, priv, vc)
142 sys_close(fd)
143 if sr > 0 { return 1 } // handshake + cert validation succeeded at now_epoch
144 return 0 // connected, but the served cert did not validate at now_epoch
145}
146
147// dual-epoch verdict over the LIVE served cert (the monitor core). Reuses the SAME CM_WARN_DAYS the file
148// monitor uses, so file-based and live-based monitoring can never disagree about the warn window.
149func car_live_verdict(domain: *u8, dlen: i64, store: *TrustStore, now: i64) -> i64 {
150 let r_now: i64 = car_handshake_ok(domain, dlen, store, now)
151 if r_now == (0 - 1) { return CM_NOCERT } // unreachable -> do not trigger
152 if r_now == 0 { return CM_EXPIRED } // served cert invalid NOW (expired/broken)
153 let future: i64 = now + CM_WARN_DAYS * CAR_MAGIC_86400
154 let r_far: i64 = car_handshake_ok(domain, dlen, store, future)
155 if r_far == 1 { return CM_OK } // still valid 21d out -> far from expiry
156 return CM_WARN // valid now, not at now+21d -> inside the window
157}
158
159// 1 if the durable sites binary is stageable (exists). The operator must keep this byte-identical to live.
160func car_binary_ok() -> i64 {
161 let fd: i64 = sys_openat_rd(CAR_SITES_BINARY); if fd < 0 { return 0 }
162 sys_close(fd); return 1
163}
164// 1 if live renewal is ARMED (the enable file exists). Default disarmed -> monitor-only (safe to schedule).
165func car_armed() -> i64 {
166 let fd: i64 = sys_openat_rd(CAR_ARM_FILE); if fd < 0 { return 0 }
167 sys_close(fd); return 1
168}
169
170// ===== THE RENEWAL DRIVER: renew ONE domain, fail-safe at every step. returns 0 = renewed+verified. =====
171func car_renew_domain(domain: *u8, store: *TrustStore) -> i64 {
172 let dlen: i64 = car_slen(domain)
173 car_log("CERT-AUTORENEW begin domain=" as *u8); car_log(domain); car_log("\n" as *u8)
174 let av: *i64 = sys_mmap(64) as *i64
175
176 // 1. build the issue organ -> /tmp/nx_acme_dns01_issue.sov.elf (idempotent; heals a /tmp wipe). MUST precede
177 // the vault fetch: nx_sov_build_run's machine-key derivation / Warden clears /tmp/nxsecret.* mid-build, so
178 // creds fetched BEFORE the build are wiped before the issuer can read them (proven live -> rc=4 ABORT).
179 av[0] = "_offc/nx_sov_build_run.elf" as *u8 as i64; av[1] = "nx_acme_dns01_issue" as *u8 as i64; av[2] = "--build-only" as *u8 as i64; av[3] = 0
180 if car_run("_offc/nx_sov_build_run.elf" as *u8, av) != 0 { car_log(" ABORT: issue-organ build failed (cert untouched)\n" as *u8); return 3 }
181
182 // 2. Porkbun creds from the vault -> /tmp/nxsecret.out (the issue organ reads this, strips a UTF-8 BOM).
183 // AFTER the build, immediately before the issuer run, so the fresh creds survive to the read.
184 av[0] = "_offc/nx_secret_cli.elf" as *u8 as i64; av[1] = "get" as *u8 as i64; av[2] = "porkbun" as *u8 as i64; av[3] = 0
185 if car_run("_offc/nx_secret_cli.elf" as *u8, av) != 0 { car_log(" ABORT: porkbun vault fetch failed (cert untouched)\n" as *u8); return 2 }
186
187 // 3. ISSUE a fresh wildcard cert for <domain> (LE-1.3 + Porkbun DNS-01) -> /tmp/new_<domain>_{fullchain.der,ecdsa_key.bin}.
188 av[0] = "/tmp/nx_acme_dns01_issue.sov.elf" as *u8 as i64; av[1] = domain as i64; av[2] = 0
189 if car_run("/tmp/nx_acme_dns01_issue.sov.elf" as *u8, av) != 0 { car_log(" ABORT: LE issuance failed (cert untouched; old cert still served)\n" as *u8); return 4 }
190
191 // 4. PRE-PUSH SANITY (rule 12): re-parse the freshly-issued cert LOCALLY; never push a bad/short cert.
192 let der_path: *u8 = sys_mmap(256); car_issue_der(domain, der_path)
193 let d: *i64 = sys_mmap(16) as *i64; let na: *i64 = sys_mmap(16) as *i64
194 if cm_status(der_path, d, na) != CM_OK { car_log(" ABORT: issued cert failed local re-parse/validity -> refusing to push (old cert still served)\n" as *u8); return 5 }
195
196 // 5. push the per-domain fullchain + key to the LIVE SNI paths (le_<label>_*).
197 let label: *u8 = sys_mmap(64); car_label(domain, label)
198 let key_path: *u8= sys_mmap(256); car_issue_key(domain, key_path)
199 let rder: *u8 = sys_mmap(256); car_remote_der(label, rder)
200 let rkey: *u8 = sys_mmap(256); car_remote_key(label, rkey)
201 av[0] = "_offc/nx_aw_send.elf" as *u8 as i64; av[1] = der_path as i64; av[2] = rder as i64; av[3] = 0
202 if car_run("_offc/nx_aw_send.elf" as *u8, av) != 0 { car_log(" ABORT: push fullchain failed (old cert still valid in memory)\n" as *u8); return 6 }
203 av[1] = key_path as i64; av[2] = rkey as i64; av[3] = 0
204 if car_run("_offc/nx_aw_send.elf" as *u8, av) != 0 { car_log(" ABORT: push key failed -- re-run to complete (new fullchain+key are matched; daemon not yet reloaded)\n" as *u8); return 7 }
205
206 // 6. stage the durable current-good binary -> sites.elf.new, then deploy = atomic swap + respawn = RELOAD.
207 if car_binary_ok() == 0 { car_log(" RELOAD-SKIPPED: no durable sites binary at CAR_SITES_BINARY -> certs pushed+valid but daemon NOT restarted. Stage the live binary (report flag #1) or restart the daemon manually; old cert remains valid in the 21d window.\n" as *u8); return 8 }
208 av[0] = "_offc/nx_aw_send.elf" as *u8 as i64; av[1] = CAR_SITES_BINARY as i64; av[2] = CAR_SITES_NEW as i64; av[3] = 0
209 if car_run("_offc/nx_aw_send.elf" as *u8, av) != 0 { car_log(" ABORT: push sites.elf.new failed (certs pushed+valid; reload deferred)\n" as *u8); return 9 }
210 av[0] = "_offc/nx_aw_hostctl.elf" as *u8 as i64; av[1] = "deploy" as *u8 as i64; av[2] = 0
211 if car_run("_offc/nx_aw_hostctl.elf" as *u8, av) != 0 { car_log(" ABORT: deploy/respawn failed (certs pushed+valid; reload deferred)\n" as *u8); return 10 }
212
213 // 7. VERIFY the renewed cert is actually SERVED: handshake at now (must be valid) + at now+30d (must STILL
214 // validate -> the served leaf notAfter advanced past the warn window = the NEW cert is live, not stale).
215 // The deploy just killed sites.elf; the supervisor name-guard respawns it within ~15s. An IMMEDIATE probe
216 // sees it mid-restart (false VERIFY-FAIL). Poll the now-probe (~32s budget) until the respawned daemon answers.
217 let now2: i64 = sys_now_realtime_sec()
218 var vtry: i64 = 0
219 var vok: i64 = 0
220 while vtry < 8 {
221 sys_sleep_ms(CAR_MAGIC_4000)
222 if car_handshake_ok(domain, dlen, store, sys_now_realtime_sec()) == 1 { vok = 1; vtry = 8 } else { vtry = vtry + 1 }
223 }
224 if vok != 1 { car_log(" VERIFY-FAIL: served cert invalid after deploy + respawn-wait -- inspect the daemon (consider `nx_aw_hostctl rollback`)\n" as *u8); return 11 }
225 if car_handshake_ok(domain, dlen, store, now2 + CAR_VERIFY_FUTURE_DAYS * CAR_MAGIC_86400) != 1 { car_log(" VERIFY-WARN: a valid cert is served but notAfter did NOT advance -- the reload may not have taken (restart the daemon)\n" as *u8); return 12 }
226
227 // 8. success: stamp the cooldown + ledger the renewal.
228 let sp: *u8 = sys_mmap(256); car_stamp_path(label, sp); car_epoch_write(sp, now2)
229 car_log("CERT-AUTORENEW success domain=" as *u8); car_log(domain); car_log(" served leaf notAfter advanced past +30d (verified)\n" as *u8)
230
231 // 9. DOWNSTREAM CONSUMERS of this cert (2026-07-05): the DSM nginx vhosts (chat/matrix/mfg/staging.
232 // nishifamily.com) serve the SAME wildcard from a SEPARATE PEM store -- it went stale once (Mar 30
233 // issue, expired Jun 28, a week of browser "insecure" on every nginx sub) because renewal only fed
234 // sites.elf. nx_nginx_cert_sync (DER+rawkey -> PEM) + the guarded aw_sudo swap (backup, nginx -t,
235 // reload, auto-restore) closes the loop. Non-fatal: sites.elf is already renewed+verified above;
236 // a sync failure is logged for the next sweep rather than failing the renewal.
237 if car_streq(domain, "nishifamily.com" as *u8) == 1 {
238 let sv: *i64 = sys_mmap(40) as *i64
239 sv[0] = "_offc/nx_aw_sudo.elf" as *u8 as i64
240 sv[1] = "_offc/awsudo_nginx_certsync.cmd" as *u8 as i64
241 sv[2] = 0
242 if car_run("_offc/nx_aw_sudo.elf" as *u8, sv) != 0 { car_log(" NGINX-SYNC-FAIL: renewed cert NOT propagated to the DSM-nginx store -- run the awsudo_nginx_certsync cmd manually before Sep 27\n" as *u8) }
243 else { car_log(" NGINX-SYNC-OK: DSM-nginx wildcard store updated + reloaded from the renewed cert\n" as *u8) }
244 }
245 return 0
246}
247
248// byte string equality (nul-terminated)
249// car_streq removed: nx_cert_autorenew_lib.nx already defines it and is imported above.
250// Two definitions in one TU are resolved silently by ORDER -- the duplicate was a
251// hard parse error here, but the same shape elsewhere is a silent wrong-binding.
252
253
254// check ONE domain, renew if WARN/EXPIRED (cooldown-guarded). returns 1 if a renewal was attempted.
255func car_sweep_one(domain: *u8, store: *TrustStore, now: i64) -> i64 {
256 let dlen: i64 = car_slen(domain)
257 let v: i64 = car_live_verdict(domain, dlen, store, now)
258 car_p(" check " as *u8); car_p(domain); car_p(" -> " as *u8); car_p(cm_name(v)); car_p("\n" as *u8)
259 if car_should_renew(v) == 0 { return 0 }
260 // WARN/EXPIRED detected -- this is the actionable signal best-in-class fires and Nishi never did.
261 if car_armed() == 0 {
262 car_log("CERT-WARN domain=" as *u8); car_log(domain); car_log(" inside 21d window but auto-renew is DISARMED (monitor-only). Arm via knowledge/hosting/cert_autorenew.enabled after the one-time live test.\n" as *u8)
263 return 0
264 }
265 let label: *u8 = sys_mmap(64); car_label(domain, label)
266 if car_cooldown_ok(label, now) == 0 { car_p(" inside warn window but renewed within cooldown -> skipping (idempotent)\n" as *u8); return 0 }
267 car_renew_domain(domain, store)
268 return 1
269}
270
271// process one config line [start,end): trim, skip blank/#, take the first whitespace-delimited token as the domain.
272func car_sweep_line(buf: *u8, start: i64, end: i64, store: *TrustStore, now: i64) -> i64 {
273 var s: i64 = start
274 while s < end { let c: i64 = buf[s] as i64; if c == 0x20 { s = s + 1 } else { if c == 0x09 { s = s + 1 } else { break } } } // skip leading ws
275 if s >= end { return 0 } // blank line
276 if buf[s] == (0x23 as u8) { return 0 } // '#' comment
277 var e: i64 = s
278 while e < end { let c: i64 = buf[e] as i64; if c == 0x20 { break } if c == 0x09 { break } if c == 0x0d { break } e = e + 1 } // token end
279 let dlen: i64 = e - s
280 if dlen <= 0 { return 0 }
281 let dom: *u8 = sys_mmap(dlen + 1)
282 var i: i64 = 0; while i < dlen { dom[i] = buf[s + i]; i = i + 1 } dom[dlen] = 0 as u8
283 return car_sweep_one(dom, store, now)
284}
285
286// read the WHOLE config file into buf; returns bytes (or <=0). (cm_read-style streamed read.)
287func car_read_file(path: *u8, buf: *u8, cap: i64) -> i64 {
288 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 }
289 var off: i64 = 0; var go: i64 = 1
290 while go == 1 { if off >= cap { go = 0 } else { let r: i64 = sys_read(fd, ((buf as i64) + off) as *u8, cap - off); if r <= 0 { go = 0 } else { off = off + r } } }
291 sys_close(fd); return off
292}
293
294// sweep EVERY configured domain (data-driven). If the config is absent/empty -> graceful fallback to the two
295// known wildcard domains (rule 14) so a missing file never silently disables renewal.
296func car_sweep(store: *TrustStore, now: i64) -> i64 {
297 let buf: *u8 = sys_mmap(CAR_MAGIC_8192)
298 let n: i64 = car_read_file(CAR_DOMAINS_CONF, buf, CAR_MAGIC_8192)
299 if n <= 0 {
300 car_p(" cert_domains.conf absent/empty -> built-in fallback list (nishifamily.com, andelinwest.com)\n" as *u8)
301 car_sweep_one("nishifamily.com" as *u8, store, now)
302 car_sweep_one("andelinwest.com" as *u8, store, now)
303 return 0
304 }
305 var i: i64 = 0
306 while i < n {
307 let start: i64 = i
308 while i < n { if buf[i] == (0x0a as u8) { break } i = i + 1 }
309 let end: i64 = i
310 if i < n { i = i + 1 }
311 car_sweep_line(buf, start, end, store, now)
312 }
313 return 0
314}
315
316func main(argc: i64, argv: *i64) -> i64 {
317 car_p("=== NISHI PER-DOMAIN CERT AUTO-RENEWAL (live SNI probe -> LE wildcard renew within 21d) ===\n" as *u8)
318 let now: i64 = sys_now_realtime_sec()
319
320 // MANUAL FORCED MODE: `nx_cert_autorenew <domain>` -> renew THAT domain NOW (bypass the warn-window check,
321 // daily guard + arm file). This is the operator's deliberate one-time end-to-end test entry point (report
322 // flag #1) -- the explicit command IS the consent. It still runs EVERY fail-safe step (pre-push re-parse,
323 // staged binary check, post-deploy verify). exit = car_renew_domain rc (0 = renewed + verified).
324 if argc > 1 {
325 let a1: *u8 = argv[1] as *u8
326 var has_dot: i64 = 0; var k: i64 = 0
327 while a1[k] != (0 as u8) { if a1[k] == (0x2e as u8) { has_dot = 1 } k = k + 1 }
328 if has_dot == 1 {
329 let srm: i64 = nx_trust_store_load_from_certdata(CAR_TRUST_STORE, 300, CAR_MAGIC_4194304)
330 if srm <= 0 { car_p(" trust-store load FAIL -> abort (cannot verify the renewed cert)\n" as *u8); sys_exit(1); return 1 }
331 let storem: *TrustStore = srm as *TrustStore
332 car_p(" MANUAL forced renewal (operator one-time test): " as *u8); car_p(a1); car_p("\n" as *u8)
333 let rc: i64 = car_renew_domain(a1, storem)
334 car_p(" forced renewal rc=" as *u8); car_pn(rc); car_p(" (0 = renewed+verified; non-0 = see knowledge/status/cert_renew.log; binary rollback armed via `nx_aw_hostctl rollback`)\n" as *u8)
335 sys_exit(rc); return rc
336 }
337 }
338
339 // DAILY-CHECK GUARD: the conductor calls this every beat; run the real sweep at most once/CHECK_INTERVAL.
340 let last: i64 = car_epoch_read(CAR_CHECK_STAMP)
341 if last > 0 { if now - last < CAR_CHECK_INTERVAL {
342 car_p(" checked within the last day -> no-op (idempotent daily cadence)\n" as *u8); sys_exit(0); return 0
343 } }
344
345 // load the CA trust store -- the probe validates the SERVED cert against it. Load fail -> skip (fail-safe:
346 // no trust store means we cannot judge expiry, so we do NOT trigger a renewal on a false signal).
347 let sr: i64 = nx_trust_store_load_from_certdata(CAR_TRUST_STORE, 300, CAR_MAGIC_4194304)
348 if sr <= 0 { car_p(" trust-store load FAIL -> skipping this sweep (fail-safe, no false trigger)\n" as *u8); sys_exit(0); return 0 }
349 let store: *TrustStore = sr as *TrustStore
350
351 // record the check up-front so a slow renewal cannot cause the next beat to double-run the sweep.
352 car_epoch_write(CAR_CHECK_STAMP, now)
353 car_sweep(store, now)
354
355 // Fire-and-forget monitor (rule 14): a renewal hiccup is logged to cert_renew.log, it does not redden the
356 // whole team pulse. The sweep RAN -> exit 0. (Flip to a nonzero-on-renewal-fail policy if you want the
357 // pulse to flag it -- see report.)
358 car_p(" cert auto-renewal sweep complete (see knowledge/status/cert_renew.log)\n" as *u8)
359 sys_exit(0); return 0
360}