code wiki / _hdl_build / nx_buildroot_guard.nx
nx_buildroot_guard.nx source
↩ module page · 172 lines · 9100 B
1// nx_buildroot_guard.nx -- SELF-HEALING buildroot integrity (eats seq140: the recurring lib-drift that
2// breaks EVERY store-lib organ build when a sibling ships/reverts an OLD nx_seg_store.nx without ss_begin_cap).
3// Data-driven (rule 11): a manifest of <buildroot-lib-path> <required-symbol> <pinned-good-path> rows. The
4// drift signal is SEMANTIC (missing a required symbol = broken), NOT byte-equality -- so a legitimately-newer
5// lib that still has the symbol survives; only a BROKEN revert is healed. Fail-safe BY CONSTRUCTION: `pin`
6// refuses to snapshot a lib that lacks the symbol, and `heal` refuses to restore from a pin that lacks it
7// -- the guard can never make a build WORSE, only restore a known-good.
8// nx_buildroot_guard pin [manifest] (snapshot each currently-GOOD buildroot lib to its pinned-good path)
9// nx_buildroot_guard check [manifest] (JSON: per lib -- has_symbol, pinned_ok, drifted)
10// nx_buildroot_guard heal [manifest] (restore drifted libs from their pinned-good; JSON report)
11// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
12import "nx_syscalls.nx"
13
14const BG_CAP: i64 = 1048576
15const BG_TAB: i64 = 9
16const BG_NL: i64 = 10
17const BG_HASH: i64 = 35
18const BG_STDERR: i64 = 2
19const BG_MODE: i64 = 420
20const BG_SPAN: i64 = 16
21const BG_EXIT_USAGE: i64 = 2
22
23func bg_werr(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(BG_STDERR, s, n); return 0 }
24func bg_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
25func bg_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 }
26func bg_catn(d: *u8, o: i64, v: i64) -> i64 { let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 } 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 }
27func bg_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 }
28// read a whole file into buf (capped). returns byte count, or -1 if open fails.
29func bg_read(path: *u8, buf: *u8, cap: i64) -> i64 {
30 let fd: i64 = sys_openat_rd(path)
31 if fd < 0 { return 0 - 1 }
32 var n: i64 = 0
33 var go: i64 = 1
34 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 } }
35 sys_close(fd)
36 return n
37}
38// write buf[0..n) to path (O_TRUNC create). returns 0 ok, -1 fail.
39func bg_write(path: *u8, buf: *u8, n: i64) -> i64 {
40 let fd: i64 = sys_openat_wr(path, BG_MODE)
41 if fd < 0 { return 0 - 1 }
42 sys_write(fd, buf, n)
43 sys_close(fd)
44 return 0
45}
46// does buf[0..n) contain the NUL-terminated literal lit as a substring?
47func bg_contains(buf: *u8, n: i64, lit: *u8) -> i64 {
48 var ll: i64 = 0
49 while lit[ll] != (0 as u8) { ll = ll + 1 }
50 if ll == 0 { return 1 }
51 var i: i64 = 0
52 while i + ll <= n {
53 var j: i64 = 0
54 var ok: i64 = 1
55 while j < ll { if buf[i+j] != lit[j] { ok = 0; j = ll } else { j = j + 1 } }
56 if ok == 1 { return 1 }
57 i = i + 1
58 }
59 return 0
60}
61func bg_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] == (BG_NL as u8) { s = 0 } else { e = e + 1 } } } return e }
62func bg_col(q: *u8, ls: i64, le: i64, c: i64, out: *i64) -> i64 {
63 var col: i64 = 0
64 var p: i64 = ls
65 while col < c {
66 var s: i64 = 1
67 while s == 1 { if p >= le { return 0 } if q[p] == (BG_TAB as u8) { s = 0 } else { p = p + 1 } }
68 p = p + 1
69 col = col + 1
70 }
71 var e: i64 = p
72 var s2: i64 = 1
73 while s2 == 1 { if e >= le { s2 = 0 } else { if q[e] == (BG_TAB as u8) { s2 = 0 } else { e = e + 1 } } }
74 out[0] = p
75 out[1] = e
76 return 1
77}
78// copy span q[s..e) into dst as a NUL-terminated C string
79func bg_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 }
80func main(argc: i64, argv: *i64) -> i64 {
81 if argc < 2 { bg_werr("usage: nx_buildroot_guard {pin|check|heal} [manifest]\n" as *u8); sys_exit(BG_EXIT_USAGE); return BG_EXIT_USAGE }
82 let verb: *u8 = argv[1] as *u8
83 let vl: i64 = bg_vlen(verb)
84 var mpath: *u8 = "knowledge/registry/buildroot_libs.tsv" as *u8
85 if argc > 2 { mpath = argv[2] as *u8 }
86 var is_pin: i64 = 0
87 var is_check: i64 = 0
88 var is_heal: i64 = 0
89 if bg_vlen("pin" as *u8) == vl { if bg_contains(verb, vl, "pin" as *u8) == 1 { is_pin = 1 } }
90 if bg_vlen("check" as *u8) == vl { if bg_contains(verb, vl, "check" as *u8) == 1 { is_check = 1 } }
91 if bg_vlen("heal" as *u8) == vl { if bg_contains(verb, vl, "heal" as *u8) == 1 { is_heal = 1 } }
92 if is_pin == 0 { if is_check == 0 { if is_heal == 0 { bg_werr("PUT-FAIL unknown verb (pin|check|heal)\n" as *u8); sys_exit(BG_EXIT_USAGE); return BG_EXIT_USAGE } } }
93 let man: *u8 = sys_mmap(BG_CAP)
94 let mn: i64 = bg_read(mpath, man, BG_CAP)
95 if mn <= 0 { bg_werr("BG-FAIL manifest empty or unreadable\n" as *u8); sys_exit(1); return 1 }
96 let libbuf: *u8 = sys_mmap(BG_CAP)
97 let pinbuf: *u8 = sys_mmap(BG_CAP)
98 let libp: *u8 = sys_mmap(512)
99 let symp: *u8 = sys_mmap(512)
100 let pinp: *u8 = sys_mmap(512)
101 let c0: *i64 = sys_mmap(BG_SPAN) as *i64
102 let c1: *i64 = sys_mmap(BG_SPAN) as *i64
103 let c2: *i64 = sys_mmap(BG_SPAN) as *i64
104 let out: *u8 = sys_mmap(BG_CAP)
105 var o: i64 = 0
106 o = bg_cat(out, o, "{\"verb\":\"" as *u8)
107 o = bg_cat(out, o, verb)
108 o = bg_cat(out, o, "\",\"libs\":[" as *u8)
109 var total: i64 = 0
110 var acted: i64 = 0
111 var drifted: i64 = 0
112 var emitted: i64 = 0
113 var i: i64 = 0
114 while i < mn {
115 let le: i64 = bg_le(man, i, mn)
116 if le > i { if (man[i] as i64) != BG_HASH {
117 if bg_col(man, i, le, 0, c0) == 1 { if bg_col(man, i, le, 1, c1) == 1 { if bg_col(man, i, le, 2, c2) == 1 {
118 bg_cstr(man, c0[0], c0[1], libp)
119 bg_cstr(man, c1[0], c1[1], symp)
120 bg_cstr(man, c2[0], c2[1], pinp)
121 total = total + 1
122 let ln: i64 = bg_read(libp, libbuf, BG_CAP)
123 var has: i64 = 0
124 if ln > 0 { if bg_contains(libbuf, ln, symp) == 1 { has = 1 } }
125 var action: *u8 = "none" as *u8
126 if is_pin == 1 {
127 // fail-safe: only pin a lib that currently HAS the symbol (never snapshot a broken one)
128 if has == 1 { if bg_write(pinp, libbuf, ln) == 0 { action = "pinned" as *u8; acted = acted + 1 } } else { action = "skip-broken-not-pinned" as *u8 }
129 }
130 if is_heal == 1 {
131 if has == 0 {
132 drifted = drifted + 1
133 let pn: i64 = bg_read(pinp, pinbuf, BG_CAP)
134 var pin_ok: i64 = 0
135 if pn > 0 { if bg_contains(pinbuf, pn, symp) == 1 { pin_ok = 1 } }
136 // fail-safe: restore ONLY from a pin that itself has the symbol
137 if pin_ok == 1 { if bg_write(libp, pinbuf, pn) == 0 { action = "healed-restored" as *u8; acted = acted + 1 } } else { action = "DRIFTED-no-good-pin" as *u8 }
138 } else { action = "ok" as *u8 }
139 }
140 if is_check == 1 {
141 if has == 0 { drifted = drifted + 1; action = "DRIFTED" as *u8 } else { action = "ok" as *u8 }
142 }
143 if emitted > 0 { o = bg_cat(out, o, "," as *u8) }
144 o = bg_cat(out, o, "{\"lib\":\"" as *u8)
145 o = bg_cat_esc(out, o, man, c0[0], c0[1])
146 o = bg_cat(out, o, "\",\"symbol\":\"" as *u8)
147 o = bg_cat_esc(out, o, man, c1[0], c1[1])
148 o = bg_cat(out, o, "\",\"has_symbol\":" as *u8)
149 o = bg_catn(out, o, has)
150 o = bg_cat(out, o, ",\"bytes\":" as *u8)
151 if ln < 0 { o = bg_cat(out, o, "-1" as *u8) } else { o = bg_catn(out, o, ln) }
152 o = bg_cat(out, o, ",\"action\":\"" as *u8)
153 o = bg_cat(out, o, action)
154 o = bg_cat(out, o, "\"}" as *u8)
155 emitted = emitted + 1
156 } } }
157 } }
158 i = le + 1
159 }
160 o = bg_cat(out, o, "],\"total\":" as *u8)
161 o = bg_catn(out, o, total)
162 o = bg_cat(out, o, ",\"acted\":" as *u8)
163 o = bg_catn(out, o, acted)
164 o = bg_cat(out, o, ",\"drifted\":" as *u8)
165 o = bg_catn(out, o, drifted)
166 o = bg_cat(out, o, ",\"verdict\":\"" as *u8)
167 if drifted == 0 { o = bg_cat(out, o, "GREEN" as *u8) } else { if is_heal == 1 { o = bg_cat(out, o, "HEALED" as *u8) } else { o = bg_cat(out, o, "DRIFT-DETECTED" as *u8) } }
168 o = bg_cat(out, o, "\"}\n" as *u8)
169 sys_write(1, out, o)
170 sys_exit(0)
171 return 0
172}