code wiki / _hdl_build / nx_deploy_ready.nx

nx_deploy_ready.nx source

↩ module page · 270 lines · 15934 B

1// nx_deploy_ready.nx -- PRE-DEPLOY SAFETY GATE (operator: "prevent things like this... deploy... managed"). 2// The capstone of the deploy-reliability trilogy: an agent/session calls this BEFORE deploying an organ to 3// learn if it is SAFE. Aggregates the supervised signals into ONE actionable verdict instead of 3 separate 4// checks -- proactive prevention (won't deploy into a drifted buildroot or after a contract regression). 5// Data-driven (rule 11): knowledge/registry/deploy_checks.tsv rows = name<TAB>file<TAB>marker<TAB>severity<TAB>remediation. 6// A check PASSES if <file> contains <marker>. severity BLOCK -> a fail makes deploy UNSAFE; WARN -> advisory. 7// nx_deploy_ready check [manifest] [target] (JSON: deploy_safe + per-check pass/severity + blockers + remediations) 8// 9// LOOSE COUPLING (operator 2026-09-02: "a supervisor deploy has no business being blocked by a search domain's 10// RED ... estate wide loose coupling small sharp intelligent pieces"). The evidence-honesty row used to be a 11// GLOBAL conjunction: any RED compare domain blocked EVERY deploy, so two content domains blocked a fleet- 12// supervisor memory-leak fix and the gate got overridden -- a gate that blocks too broadly is disabled in 13// practice and protects nothing. Now, when the caller names the deploy TARGET (a deploy_targets.conf row 14// name), that ONE row is SCOPED to the target's blast radius: it blocks iff the target's OWN domain, or a 15// SHARED-FATE domain (the deploy machinery itself), is named on the RED_DOMAINS= line nx_sota_status emits. 16// Every other row is unchanged. With no target, or an unmapped target, or an evidence log that carries no 17// RED_DOMAINS= line (an older producer), the row keeps its GLOBAL marker check -- the fallback fails in the 18// direction of REFUSING, never of acquitting, and the JSON names which scope applied so the audit is visible. 19// Data-driven (rule 11): knowledge/registry/deploy_domain.conf rows = <target> <domain>; 20// knowledge/registry/deploy_sharedfate.conf rows = one shared-fate domain per line. 21// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 22import "nx_syscalls.nx" 23 24const DR_CAP: i64 = 262144 25const DR_TAB: i64 = 9 26const DR_NL: i64 = 10 27const DR_HASH: i64 = 35 28const DR_SPACE: i64 = 32 29const DR_STDERR: i64 = 2 30const DR_SPAN: i64 = 16 31const DR_EXIT_USAGE: i64 = 2 32const DR_NAMECAP: i64 = 256 33const DR_DOMAIN_CONF: *u8 = "knowledge/registry/deploy_domain.conf" 34const DR_SHAREDFATE_CONF: *u8 = "knowledge/registry/deploy_sharedfate.conf" 35const DR_RED_KEY: *u8 = "RED_DOMAINS=" 36const DR_SCOPED_ROW: *u8 = "evidence-honesty" 37 38func dr_werr(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(DR_STDERR, s, n); return 0 } 39func dr_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 40func dr_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o] = s[i]; o = o + 1; i = i + 1 } return o } 41func dr_catn(d: *u8, o: i64, v: i64) -> i64 { let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { d[o] = 45 as u8; o = o + 1; m = 0 - m } 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 } var i: i64 = 0; while i < k { d[o] = t[k-1-i]; o = o + 1; i = i + 1 } return o } 42func dr_cat_esc(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 { var i: i64 = s; while i < e { var c: i64 = q[i] as i64; if c == 34 { c = 39 } if c == 92 { c = 47 } if c < 32 { c = 32 } d[o] = c as u8; o = o + 1; i = i + 1 } return o } 43func dr_read(path: *u8, buf: *u8, cap: i64) -> i64 { 44 let fd: i64 = sys_openat_rd(path) 45 if fd < 0 { return 0 - 1 } 46 var n: i64 = 0 47 var go: i64 = 1 48 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } } 49 sys_close(fd) 50 return n 51} 52func dr_contains(buf: *u8, n: i64, lit: *u8) -> i64 { 53 var ll: i64 = 0 54 while lit[ll] != (0 as u8) { ll = ll + 1 } 55 if ll == 0 { return 1 } 56 var i: i64 = 0 57 while i + ll <= n { 58 var j: i64 = 0 59 var ok: i64 = 1 60 while j < ll { if buf[i+j] != lit[j] { ok = 0; j = ll } else { j = j + 1 } } 61 if ok == 1 { return 1 } 62 i = i + 1 63 } 64 return 0 65} 66func dr_le(q: *u8, i: i64, n: i64) -> i64 { var e: i64 = i; var s: i64 = 1; while s == 1 { if e >= n { s = 0 } else { if q[e] == (DR_NL as u8) { s = 0 } else { e = e + 1 } } } return e } 67func dr_col(q: *u8, ls: i64, le: i64, c: i64, out: *i64) -> i64 { 68 var col: i64 = 0 69 var p: i64 = ls 70 while col < c { 71 var s: i64 = 1 72 while s == 1 { if p >= le { return 0 } if q[p] == (DR_TAB as u8) { s = 0 } else { p = p + 1 } } 73 p = p + 1 74 col = col + 1 75 } 76 var e: i64 = p 77 var s2: i64 = 1 78 while s2 == 1 { if e >= le { s2 = 0 } else { if q[e] == (DR_TAB as u8) { s2 = 0 } else { e = e + 1 } } } 79 out[0] = p 80 out[1] = e 81 return 1 82} 83func dr_cstr(q: *u8, s: i64, e: i64, dst: *u8) -> i64 { var i: i64 = 0; while s + i < e { dst[i] = q[s+i]; i = i + 1 } dst[i] = 0 as u8; return i } 84func dr_span_is(q: *u8, s: i64, e: i64, lit: *u8) -> i64 { var i: i64 = 0; while s + i < e { if lit[i] == (0 as u8) { return 0 } if q[s+i] != lit[i] { return 0 } i = i + 1 } if lit[i] != (0 as u8) { return 0 } return 1 } 85 86// ---- SCOPING HELPERS (2026-09-02) ------------------------------------------------------------------------- 87// The RED_DOMAINS= line is " a b c " -- every name wrapped in spaces -- so the needle " <domain> " is an EXACT 88// token match: "search" can never match "performersearch". Returns 1 iff the evidence buffer carries a 89// RED_DOMAINS= line at all (out[0]=1) AND names <domain> (return 1). out[0]=0 means NO such line: an older 90// producer wrote this log, and the caller must fall back to the global marker rather than acquit. 91func dr_red_names(buf: *u8, n: i64, domain: *u8, out: *i64) -> i64 { 92 out[0] = 0 93 if dr_contains(buf, n, DR_RED_KEY) == 0 { return 0 } 94 out[0] = 1 95 let needle: *u8 = sys_mmap(DR_NAMECAP + 4) 96 var o: i64 = 0 97 needle[o] = DR_SPACE as u8; o = o + 1 98 var i: i64 = 0 99 while domain[i] != (0 as u8) { if i < DR_NAMECAP { needle[o] = domain[i]; o = o + 1 } i = i + 1 } 100 needle[o] = DR_SPACE as u8; o = o + 1 101 needle[o] = 0 as u8 102 return dr_contains(buf, n, needle) 103} 104// deploy_domain.conf: one row per deployable, "<target> <domain>" separated by a SPACE, hash-comment lines. 105// Copies the domain into dst and returns 1; 0 = target has no row (the caller treats that as GLOBAL scope). 106func dr_lookup_domain(conf: *u8, n: i64, target: *u8, dst: *u8) -> i64 { 107 var i: i64 = 0 108 while i < n { 109 let le: i64 = dr_le(conf, i, n) 110 if le > i { if (conf[i] as i64) != DR_HASH { 111 var p: i64 = i 112 var k: i64 = 0 113 var same: i64 = 1 114 while p < le { if conf[p] == (DR_SPACE as u8) { p = le + 1 } else { if target[k] == (0 as u8) { same = 0; p = le + 1 } else { if conf[p] != target[k] { same = 0; p = le + 1 } else { p = p + 1; k = k + 1 } } } } 115 if same == 1 { if target[k] == (0 as u8) { 116 var q: i64 = i + k 117 if q < le { if conf[q] == (DR_SPACE as u8) { 118 q = q + 1 119 var w: i64 = 0 120 while q < le { if conf[q] == (DR_SPACE as u8) { q = le } else { if w < DR_NAMECAP - 1 { dst[w] = conf[q]; w = w + 1 } q = q + 1 } } 121 dst[w] = 0 as u8 122 if w > 0 { return 1 } 123 } } 124 } } 125 } } 126 i = le + 1 127 } 128 return 0 129} 130// deploy_sharedfate.conf: one domain per line. Returns 1 iff ANY listed domain is on the RED_DOMAINS= line: 131// a RED in the deploy machinery itself is shared fate and blocks every target, exactly as before. 132func dr_sharedfate_red(sf: *u8, sfn: i64, ev: *u8, evn: i64) -> i64 { 133 let name: *u8 = sys_mmap(DR_NAMECAP) 134 let flag: *i64 = sys_mmap(8) as *i64 135 var i: i64 = 0 136 while i < sfn { 137 let le: i64 = dr_le(sf, i, sfn) 138 if le > i { if (sf[i] as i64) != DR_HASH { 139 var w: i64 = 0 140 var p: i64 = i 141 while p < le { if sf[p] == (DR_SPACE as u8) { p = le } else { if w < DR_NAMECAP - 1 { name[w] = sf[p]; w = w + 1 } p = p + 1 } } 142 name[w] = 0 as u8 143 if w > 0 { if dr_red_names(ev, evn, name, flag) == 1 { return 1 } } 144 } } 145 i = le + 1 146 } 147 return 0 148} 149 150func main(argc: i64, argv: *i64) -> i64 { 151 var verb: *u8 = "check" as *u8 152 if argc > 1 { verb = argv[1] as *u8 } 153 if dr_contains(verb, dr_vlen(verb), "check" as *u8) == 0 { dr_werr("usage: nx_deploy_ready check [manifest] [target]\n" as *u8); sys_exit(DR_EXIT_USAGE); return DR_EXIT_USAGE } 154 var mpath: *u8 = "knowledge/registry/deploy_checks.tsv" as *u8 155 if argc > 2 { mpath = argv[2] as *u8 } 156 // ---- the deploy TARGET (optional argv[3]) resolves to ONE compare domain = the blast radius ---- 157 var have_target: i64 = 0 158 var target: *u8 = "" as *u8 159 if argc > 3 { target = argv[3] as *u8; if target[0] != (0 as u8) { have_target = 1 } } 160 let tdomain: *u8 = sys_mmap(DR_NAMECAP) 161 tdomain[0] = 0 as u8 162 var mapped: i64 = 0 163 let dconf: *u8 = sys_mmap(DR_CAP) 164 var dcn: i64 = 0 165 let sfconf: *u8 = sys_mmap(DR_CAP) 166 var sfn: i64 = 0 167 if have_target == 1 { 168 dcn = dr_read(DR_DOMAIN_CONF, dconf, DR_CAP) 169 if dcn > 0 { mapped = dr_lookup_domain(dconf, dcn, target, tdomain) } 170 sfn = dr_read(DR_SHAREDFATE_CONF, sfconf, DR_CAP) 171 if sfn < 0 { sfn = 0 } 172 } 173 let man: *u8 = sys_mmap(DR_CAP) 174 let mn: i64 = dr_read(mpath, man, DR_CAP) 175 if mn <= 0 { dr_werr("DR-FAIL manifest empty or unreadable\n" as *u8); sys_exit(1); return 1 } 176 let fbuf: *u8 = sys_mmap(DR_CAP) 177 let fpath: *u8 = sys_mmap(512) 178 let mark: *u8 = sys_mmap(512) 179 let c0: *i64 = sys_mmap(DR_SPAN) as *i64 180 let c1: *i64 = sys_mmap(DR_SPAN) as *i64 181 let c2: *i64 = sys_mmap(DR_SPAN) as *i64 182 let c3: *i64 = sys_mmap(DR_SPAN) as *i64 183 let c4: *i64 = sys_mmap(DR_SPAN) as *i64 184 let redflag: *i64 = sys_mmap(8) as *i64 185 let out: *u8 = sys_mmap(DR_CAP) 186 var o: i64 = 0 187 o = dr_cat(out, o, "{\"verb\":\"check\",\"checks\":[" as *u8) 188 var total: i64 = 0 189 var blockers: i64 = 0 190 var warns: i64 = 0 191 var emitted: i64 = 0 192 // scope_kind: 0 global (no target) | 1 domain-scoped | 2 global-unmapped-target | 3 global-no-RED_DOMAINS-line 193 var scope_kind: i64 = 0 194 if have_target == 1 { if mapped == 1 { scope_kind = 1 } else { scope_kind = 2 } } 195 var i: i64 = 0 196 while i < mn { 197 let le: i64 = dr_le(man, i, mn) 198 if le > i { if (man[i] as i64) != DR_HASH { 199 if dr_col(man, i, le, 0, c0) == 1 { if dr_col(man, i, le, 1, c1) == 1 { if dr_col(man, i, le, 2, c2) == 1 { if dr_col(man, i, le, 3, c3) == 1 { 200 dr_cstr(man, c1[0], c1[1], fpath) 201 dr_cstr(man, c2[0], c2[1], mark) 202 total = total + 1 203 let fn: i64 = dr_read(fpath, fbuf, DR_CAP) 204 var pass: i64 = 0 205 var scoped_here: i64 = 0 206 if scope_kind == 1 { if dr_span_is(man, c0[0], c0[1], DR_SCOPED_ROW) == 1 { 207 // THE SCOPED ROW: block iff the target's OWN domain or a SHARED-FATE domain is RED. 208 // An evidence log with no RED_DOMAINS= line cannot be scoped -> global marker (refuse-side). 209 if fn > 0 { 210 let own_red: i64 = dr_red_names(fbuf, fn, tdomain, redflag) 211 if redflag[0] == 1 { 212 scoped_here = 1 213 pass = 1 214 if own_red == 1 { pass = 0 } 215 if pass == 1 { if sfn > 0 { if dr_sharedfate_red(sfconf, sfn, fbuf, fn) == 1 { pass = 0 } } } 216 } else { scope_kind = 3 } 217 } 218 } } 219 if scoped_here == 0 { if fn > 0 { if dr_contains(fbuf, fn, mark) == 1 { pass = 1 } } } 220 var is_block: i64 = 0 221 if dr_span_is(man, c3[0], c3[1], "BLOCK" as *u8) == 1 { is_block = 1 } 222 if pass == 0 { if is_block == 1 { blockers = blockers + 1 } else { warns = warns + 1 } } 223 if emitted > 0 { o = dr_cat(out, o, "," as *u8) } 224 o = dr_cat(out, o, "{\"name\":\"" as *u8) 225 o = dr_cat_esc(out, o, man, c0[0], c0[1]) 226 o = dr_cat(out, o, "\",\"pass\":" as *u8) 227 o = dr_catn(out, o, pass) 228 o = dr_cat(out, o, ",\"severity\":\"" as *u8) 229 o = dr_cat_esc(out, o, man, c3[0], c3[1]) 230 o = dr_cat(out, o, "\"" as *u8) 231 if scoped_here == 1 { o = dr_cat(out, o, ",\"scope\":\"domain:" as *u8); o = dr_cat(out, o, tdomain); o = dr_cat(out, o, "\"" as *u8) } 232 if pass == 0 { if dr_col(man, i, le, 4, c4) == 1 { o = dr_cat(out, o, ",\"remediation\":\"" as *u8); o = dr_cat_esc(out, o, man, c4[0], c4[1]); o = dr_cat(out, o, "\"" as *u8) } } 233 o = dr_cat(out, o, "}" as *u8) 234 emitted = emitted + 1 235 } } } } 236 } } 237 i = le + 1 238 } 239 o = dr_cat(out, o, "],\"total\":" as *u8) 240 o = dr_catn(out, o, total) 241 o = dr_cat(out, o, ",\"blockers\":" as *u8) 242 o = dr_catn(out, o, blockers) 243 o = dr_cat(out, o, ",\"warnings\":" as *u8) 244 o = dr_catn(out, o, warns) 245 o = dr_cat(out, o, ",\"deploy_safe\":" as *u8) 246 if blockers == 0 { o = dr_cat(out, o, "true" as *u8) } else { o = dr_cat(out, o, "false" as *u8) } 247 o = dr_cat(out, o, ",\"scope\":\"" as *u8) 248 if scope_kind == 0 { o = dr_cat(out, o, "global" as *u8) } 249 if scope_kind == 1 { o = dr_cat(out, o, "domain:" as *u8); o = dr_cat(out, o, tdomain) } 250 if scope_kind == 2 { o = dr_cat(out, o, "global-unmapped-target:" as *u8); o = dr_cat(out, o, target) } 251 if scope_kind == 3 { o = dr_cat(out, o, "global-no-RED_DOMAINS-line" as *u8) } 252 o = dr_cat(out, o, "\",\"verdict\":\"" as *u8) 253 if blockers > 0 { o = dr_cat(out, o, "DEPLOY-BLOCKED" as *u8) } else { if warns > 0 { o = dr_cat(out, o, "DEPLOY-SAFE-WITH-WARNINGS" as *u8) } else { o = dr_cat(out, o, "DEPLOY-SAFE" as *u8) } } 254 o = dr_cat(out, o, "\",\"envelope\":\"manifest knowledge/registry/deploy_checks.tsv + each evidence file read bounded per DR_CAP; a check whose evidence file exceeds the cap reads TRUNCATED and its marker may be missed -- declared per the scale-law (F846), never silent. evidence-honesty is SCOPED to the target domain + shared-fate domains when a target is named and the log carries RED_DOMAINS=, else GLOBAL (refuse-side fallback)\"}\n" as *u8) 255 sys_write(1, out, o) 256 // ---- EXIT CODE NOW CARRIES THE VERDICT (2026-07-30) ------------------------------------------------ 257 // This was sys_exit(0) UNCONDITIONALLY -- even when the verdict is DEPLOY-BLOCKED. So `nx_deploy_ready 258 // check && deploy` sailed straight through a blocking verdict, and NO caller checking $? could ever act 259 // on this gate. A gate whose exit code is constant cannot gate anything; it can only be read by something 260 // that already knows to parse its JSON. 0 = safe, 3 = DEPLOY-BLOCKED. 261 // WARNINGS DELIBERATELY STILL EXIT 0: warnings here are evidence DEBT, not a stop. A gate that exits 262 // nonzero on every warning gets wrapped in `|| true` and then protects nothing -- this file's own 263 // manifest makes that argument, and it is right. 264 // BLAST RADIUS MEASURED, NOT ASSUMED: grep across 19951 files found exactly ONE in-tree caller of 265 // nx_deploy_ready.elf (md_exec_deploy_ready), and it ignores the exit code and parses the JSON. So no 266 // existing in-tree behaviour changes; this only stops the gate from lying to future callers. 267 if blockers > 0 { sys_exit(3); return 3 } 268 sys_exit(0) 269 return 0 270}