code wiki / _hdl_build / nx_cron_reconcile.nx
nx_cron_reconcile.nx
buildroot/runtime/_hdl_build/nx_cron_reconcile.nx
about
nx_cron_reconcile.nx -- SOVEREIGN crontab reconciler (operator directive 2026-07-16: "make the
capabilities native to the nishi ecosystem, don't make me do it"). The nishi-managed block of a crontab
becomes DATA: cron.reg declares exactly the nishi rows that must exist; this organ rewrites the crontab
so its nishi rows (any line containing /nishihost/) equal EXACTLY the declared set, leaving every
non-nishi row BYTE-EXACT. Dead rows (retired reconcilers) vanish by construction; new rows = a registry
line. Runs as root with ZERO operator action by piggybacking on the existing root cron row
(nx_edge443_reconcile.sh -- the same proven pattern as the vsz_watchdog on the rail).
NEVER-BRICK BY CONSTRUCTION (this writes a root-owned BOOT FILE):
R1 only lines containing /nishihost/ are ever touched -- the filter IS the blast-radius bound
R2 refuse (exit 3, no write) if the registry is missing/empty -- an absent SSOT must never wipe rows
R3 refuse (exit 5, no write) if ANY declared row lacks /nishihost/ -- the organ cannot inject
non-nishi rows even if the registry is corrupted/hostile
R4 refuse (exit 4, no write) if the crontab is unreadable or EMPTY -- a boot file is never empty
R5 idempotent: byte-identical result -> NO-CHANGE, zero writes (safe at any frequency)
R6 atomic: write <crontab>.nxnew then renameat over -- no torn boot file ever exists on disk
After a real change, SIGHUP every `crond` (reload -- standard, non-destructive; if crond ignores it,
stale in-memory entries keep harmlessly firing removed paths until its next restart = no regression).
usage: nx_cron_reconcile <crontab-path> <reg-path> (gate runs it on COPIES; prod = /etc/crontab)
exit: 0 ok (CHANGED or NO-CHANGE) | 2 usage | 3 reg-refuse | 4 crontab-refuse | 5 reg-taint | 6 write-fail
license_tier: ORIGINAL module: nishi-core.ops.cron_reconcile
dependencies 1 imports · 0 importers
imports: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 24 | const CR_MAGIC_65536: i64 = 65536 |
| 26 | const CR_CTCAP: i64 = 65536 |
| 27 | const CR_REGCAP: i64 = 16384 |
| 28 | const CR_MARK: *u8 = "/nishihost/" as *u8 |
functions
| 30 | func cr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 31 | func cr_p(s: *u8) -> i64 { sys_write(1, s, cr_slen(s)); return 0 } |
| 32 | func cr_decw(v: i64, out: *u8) -> i64 called by 1: cr_pn |
| 44 | func cr_pn(v: i64) -> i64 { let b: *u8 = sys_mmap(28); let n: i64 = cr_decw(v, b); sys_write(1, b, n); sys_munmap(b, 28); return 0 } |
| 45 | func cr_contains(hay: *u8, hlen: i64, needle: *u8) -> i64 |
| 59 | func cr_line_end(buf: *u8, pos: i64, end: i64) -> i64 called by 1: main |
| 64 | func cr_read(path: *u8, buf: *u8, cap: i64) -> i64 |
| 72 | func main(argc: i64, argv: *i64) -> i64 |