code wiki / _hdl_build / nx_sov_guard2.nx

nx_sov_guard2.nx source

↩ module page · 260 lines · 12174 B

1// nx_sov_guard2.nx -- the NO-NEW-TSV law with a WORKING TOOTH (eats seq279 at the root). 2// 3// WHY A REWRITE, NOT A PATCH (rule 3): v1 scanned exactly ONE directory and defaulted to `knowledge/status`, 4// so `knowledge/registry` -- which holds ~150 .tsv including the 3 this session created -- was NEVER SCANNED. 5// The law existed, the organ existed, the allowlist existed, and none of it could fire on the directory that 6// mattered. A guard that cannot see the violation is not a guard. 7// 8// TWO STRUCTURAL FIXES: 9// 1. MULTI-DIR, DATA-DRIVEN scan-set. Dirs come from the native plane knowledge/store/sovguard- (`dir<TAB>path` 10// rows) -- rule 11, and pointedly NOT from a .tsv (the anti-tsv guard configuring itself with a tsv would be 11// the joke that writes itself). If the plane is absent the organ still guards using a compiled-in default set 12// and DECLARES `config:default-set` -- fail-SAFE, because a guard that silently stops guarding is worse than 13// one that guards loudly with defaults. 14// 2. RATCHET, not a cliff. ~150 legacy files exist; a plain count>0 rule would be RED forever and get ignored 15// (an alarm nobody can silence is an alarm nobody hears). Instead we compare against a recorded BASELINE and 16// fail ONLY when the count RISES -- which is exactly what "no NEW tsv" means. Legacy shrinks lane by lane; 17// a new file trips it the same day. Same snapshot/check idiom as nx_tooldiff / nx_route_diff. 18// 19// nx_sov_guard2 check -> GREEN if count <= baseline; RED (exit 1) naming the NEW files if it rose 20// nx_sov_guard2 snapshot -> deliberately re-record the baseline (after a migration lands) 21// Emits knowledge/status/sov_guard.log with a VERDICT line for the reliability plane. 22// license_tier: ORIGINAL expect_exit: 0 23import "nx_store_seed_lib.nx" 24import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 25import "nx_seg_store.nx" 26import "nx_syscalls.nx" 27const SG2_MAGIC_65536: i64 = 65536 28const SG2_MAGIC_4096: i64 = 4096 29const SG2_MAGIC_1024: i64 = 1024 30const SG2_MAGIC_262144: i64 = 262144 31 32const SG2_PLANE: *u8 = "knowledge/store/sovguard-" 33const SG2_ALLOW: *u8 = "knowledge/registry/tsv_allow.list" 34const SG2_LOG: *u8 = "knowledge/status/sov_guard.log" 35const SG2_CAP: i64 = 1048576 36 37func sg_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 38// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 39// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 40// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 41// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 42func sg_wn(v: i64) -> i64 { nxi_out(v); return 0 } 43func sg_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 44func sg_cat(o: *u8, at: i64, s: *u8) -> i64 { var i: i64=0; var a: i64=at; while s[i]!=(0 as u8){o[a]=s[i]; a=a+1; i=i+1} return a } 45func sg_catn(o: *u8, at: i64, v: i64) -> i64 { 46 var a: i64=at; var x: i64=v 47 if x<0 { o[a]=45 as u8; a=a+1; x=0-x } 48 let tm: *u8=sys_mmap(24); var k: i64=0 49 if x==0 { tm[0]=48 as u8; k=1 } 50 while x>0 { tm[k]=(48+x%10) as u8; x=x/10; k=k+1 } 51 var j: i64=0 52 while j<k { o[a]=tm[k-1-j]; a=a+1; j=j+1 } 53 return a 54} 55func sg_ends(name: *u8, suf: *u8) -> i64 { 56 let n: i64=sg_slen(name); let s: i64=sg_slen(suf) 57 if n<s { return 0 } 58 var i: i64=0 59 while i<s { if name[n-s+i]!=suf[i] { return 0 } i=i+1 } 60 return 1 61} 62func sg_readfile(path: *u8, buf: *u8, cap: i64) -> i64 { 63 let fd: i64=sys_openat_rd(path) 64 if fd<0 { return 0 } 65 var off: i64=0; var go: i64=1 66 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 } } } 67 sys_close(fd) 68 return off 69} 70// exact non-# line match 71func sg_line_in(buf: *u8, n: i64, name: *u8) -> i64 { 72 let nl: i64=sg_slen(name) 73 var ls: i64=0; var i: i64=0 74 while i<=n { 75 var eol: i64=0 76 if i>=n { eol=1 } else { if buf[i]==(10 as u8) { eol=1 } } 77 if eol==1 { 78 let llen: i64=i-ls 79 if llen==nl { if buf[ls]!=(35 as u8) { 80 var m: i64=0; var ok: i64=1 81 while m<nl { if buf[ls+m]!=name[m] { ok=0; m=nl } else { m=m+1 } } 82 if ok==1 { return 1 } 83 } } 84 ls=i+1 85 } 86 i=i+1 87 } 88 return 0 89} 90// scan ONE dir; appends violating names to `names` (bounded); returns violation count, -1 unopenable 91func sg_scan_dir(dir: *u8, allow: *u8, an: i64, names: *u8, no: *i64, shown: *i64) -> i64 { 92 let dfd: i64 = __syscall(257, 0-100, dir, 0x10000, 0, 0, 0) 93 if dfd<0 { return 0-1 } 94 let buf: *u8=sys_mmap(SG2_MAGIC_65536) 95 let nm: *u8=sys_mmap(512) 96 var viol: i64=0 97 var go: i64=1 98 while go==1 { 99 let nread: i64 = __syscall(217, dfd, buf, SG2_MAGIC_65536, 0, 0, 0) 100 if nread<=0 { go=0 } else { 101 var pos: i64=0 102 while pos<nread { 103 let reclen: i64=(buf[pos+16] as i64)|((buf[pos+17] as i64)<<8) 104 let dtype: i64=buf[pos+18] as i64 105 var nl: i64=0 106 while buf[pos+19+nl]!=(0 as u8) { nm[nl]=buf[pos+19+nl]; nl=nl+1 } 107 nm[nl]=0 as u8 108 if dtype==8 { if sg_ends(nm, ".tsv\x00" as *u8)==1 { 109 if sg_line_in(allow, an, nm)==0 { 110 viol=viol+1 111 if shown[0]<12 { 112 var o: i64=no[0] 113 o=sg_cat(names, o, dir); names[o]=47 as u8; o=o+1 114 o=sg_cat(names, o, nm); names[o]=10 as u8; o=o+1 115 no[0]=o 116 shown[0]=shown[0]+1 117 } 118 } 119 } } 120 if reclen<=0 { pos=nread } else { pos=pos+reclen } 121 } 122 } 123 } 124 sys_close(dfd) 125 return viol 126} 127 128func main(argc: i64, argv: *i64) -> i64 { 129 var verb: *u8 = "check\x00" as *u8 130 if argc>=2 { verb = argv[1] as *u8 } 131 // ---- scan-set + baseline from the NATIVE plane (never a .tsv), else declared defaults 132 let pb: *u8=sys_mmap(SG2_CAP) 133 let pn: i64=sts_load(SG2_PLANE, pb, SG2_CAP-SG2_MAGIC_4096) 134 let dirs: *i64=sys_mmap(SG2_MAGIC_1024) as *i64 135 let dbuf: *u8=sys_mmap(SG2_MAGIC_65536) 136 var ndir: i64=0 137 var baseline: i64=0-1 138 var cfg: *u8="plane\x00" as *u8 139 var dbo: i64=0 140 if pn>0 { 141 var i: i64=0 142 while i<pn { 143 let ls: i64=i 144 var le: i64=ls 145 var sc: i64=1 146 while sc==1 { if le>=pn { sc=0 } else { if pb[le]==(10 as u8) { sc=0 } else { le=le+1 } } } 147 i=le+1 148 if le>ls { 149 // split at first TAB 150 var t: i64=ls 151 var found: i64=0-1 152 while t<le { if pb[t]==(9 as u8) { if found<0 { found=t } } t=t+1 } 153 if found>0 { 154 let klen: i64=found-ls 155 let vs: i64=found+1 156 let vlen: i64=le-vs 157 // key "dir" 158 if klen==3 { if pb[ls]==(100 as u8) { if pb[ls+1]==(105 as u8) { if pb[ls+2]==(114 as u8) { 159 if ndir<64 { if dbo+vlen+2<SG2_MAGIC_65536 { 160 dirs[ndir]=(dbuf as i64)+dbo 161 var k: i64=0 162 while k<vlen { dbuf[dbo]=pb[vs+k]; dbo=dbo+1; k=k+1 } 163 dbuf[dbo]=0 as u8; dbo=dbo+1 164 ndir=ndir+1 165 } } 166 } } } } 167 // key "baseline" 168 if klen==8 { if pb[ls]==(98 as u8) { 169 var v: i64=0; var k: i64=0 170 while k<vlen { let c: i64=pb[vs+k] as i64; if c>=48 { if c<=57 { v=v*10+(c-48) } } k=k+1 } 171 baseline=v 172 } } 173 } 174 } 175 } 176 } 177 if ndir==0 { 178 cfg="default-set\x00" as *u8 179 dirs[0]="knowledge/registry\x00" as *u8 as i64 180 dirs[1]="knowledge/status\x00" as *u8 as i64 181 ndir=2 182 } 183 // ---- scan 184 let allow: *u8=sys_mmap(SG2_MAGIC_262144) 185 let an: i64=sg_readfile(SG2_ALLOW, allow, SG2_MAGIC_262144) 186 let names: *u8=sys_mmap(SG2_MAGIC_65536) 187 let no: *i64=sys_mmap(16) as *i64 188 let shown: *i64=sys_mmap(16) as *i64 189 no[0]=0; shown[0]=0 190 var total: i64=0 191 var unopenable: i64=0 192 var d: i64=0 193 while d<ndir { 194 let v: i64=sg_scan_dir(dirs[d] as *u8, allow, an, names, no, shown) 195 if v<0 { unopenable=unopenable+1 } else { total=total+v } 196 d=d+1 197 } 198 names[no[0]]=0 as u8 199 // ---- snapshot: deliberately re-record the baseline into the native plane 200 if verb[0]==(115 as u8) { 201 let ob: *u8=sys_mmap(SG2_MAGIC_65536) 202 var o: i64=0 203 var k: i64=0 204 while k<ndir { o=sg_cat(ob, o, "dir\x09" as *u8); o=sg_cat(ob, o, dirs[k] as *u8); ob[o]=10 as u8; o=o+1; k=k+1 } 205 o=sg_cat(ob, o, "baseline\x09" as *u8); o=sg_catn(ob, o, total); ob[o]=10 as u8; o=o+1 206 let rc: i64=sts_seed(SG2_PLANE, ob, o) 207 sg_w("{\x22verb\x22:\x22snapshot\x22,\x22dirs\x22:" as *u8); sg_wn(ndir) 208 sg_w(",\x22unallowlisted_tsv\x22:" as *u8); sg_wn(total) 209 sg_w(",\x22baseline_recorded\x22:" as *u8); sg_wn(total) 210 sg_w(",\x22plane_rows\x22:" as *u8); sg_wn(rc) 211 sg_w("}\n" as *u8) 212 if rc<0 { sg_w("SOV-GUARD RED -- baseline commit failed\n" as *u8); sys_exit(2); return 2 } 213 sg_w("SOV-GUARD SNAPSHOT -- ratchet armed at the current count; any RISE is now a violation\n" as *u8) 214 return 0 215 } 216 // ---- check (the ratchet) 217 var eff: i64=baseline 218 var armed: i64=1 219 if baseline<0 { eff=total; armed=0 } // first ever run: adopt, declare UNARMED, never fake a pass 220 let delta: i64=total-eff 221 var red: i64=0 222 if delta>0 { red=1 } 223 sg_w("{\x22verb\x22:\x22check\x22,\x22config\x22:\x22" as *u8); sg_w(cfg) 224 sg_w("\x22,\x22dirs_scanned\x22:" as *u8); sg_wn(ndir) 225 sg_w(",\x22dirs_unopenable\x22:" as *u8); sg_wn(unopenable) 226 sg_w(",\x22unallowlisted_tsv\x22:" as *u8); sg_wn(total) 227 sg_w(",\x22baseline\x22:" as *u8); sg_wn(eff) 228 sg_w(",\x22delta\x22:" as *u8); sg_wn(delta) 229 sg_w(",\x22ratchet_armed\x22:" as *u8); sg_wn(armed) 230 sg_w(",\x22verdict\x22:\x22" as *u8) 231 if red==1 { sg_w("RED" as *u8) } else { sg_w("GREEN" as *u8) } 232 sg_w("\x22,\x22law\x22:\x22no NEW tsv -- legacy shrinks lane by lane, but the count must never RISE\x22}\n" as *u8) 233 if no[0]>0 { sg_w("unallowlisted (first 12):\n" as *u8); sg_w(names) } 234 // ---- evidence for the reliability plane 235 let lf: i64=sys_openat_wr(SG2_LOG, 0x1a4) 236 if lf>=0 { 237 let lb: *u8=sys_mmap(SG2_MAGIC_4096) 238 var o: i64=0 239 o=sg_cat(lb, o, "nx_sov_guard2 -- no-new-tsv ratchet (config=" as *u8); o=sg_cat(lb, o, cfg) 240 o=sg_cat(lb, o, ")\n dirs_scanned=" as *u8); o=sg_catn(lb, o, ndir) 241 o=sg_cat(lb, o, " unallowlisted_tsv=" as *u8); o=sg_catn(lb, o, total) 242 o=sg_cat(lb, o, " baseline=" as *u8); o=sg_catn(lb, o, eff) 243 o=sg_cat(lb, o, " delta=" as *u8); o=sg_catn(lb, o, delta) 244 o=sg_cat(lb, o, " armed=" as *u8); o=sg_catn(lb, o, armed) 245 o=sg_cat(lb, o, "\nVERDICT=" as *u8) 246 if red==1 { o=sg_cat(lb, o, "RED" as *u8) } else { o=sg_cat(lb, o, "GREEN" as *u8) } 247 o=sg_cat(lb, o, "\n" as *u8) 248 sys_write(lf, lb, o) 249 if no[0]>0 { sys_write(lf, names, no[0]) } 250 sys_close(lf) 251 } 252 if red==1 { 253 sg_w("SOV-GUARD RED -- a NEW unallowlisted .tsv appeared (count rose above baseline). Migrate it with nx_tsv_migrate, or allowlist it with an owner note; re-snapshot only when the rise is intentional.\n" as *u8) 254 sys_exit(1) 255 return 1 256 } 257 if armed==0 { sg_w("SOV-GUARD GREEN (ratchet UNARMED -- no baseline recorded yet; run `snapshot` to arm it)\n" as *u8); return 0 } 258 sg_w("SOV-GUARD GREEN -- no new tsv since the baseline\n" as *u8) 259 return 0 260}