code wiki / (root) / nx_provclass_lib.nx

nx_provclass_lib.nx source

↩ module page · 251 lines · 9251 B

1// nx_provclass_lib.nx -- THE PROVENANCE-CLASS RULER. One classifier, read by every organ that 2// admits a measured fact, so a class can never mean one thing to the writer and another to the reader. 3// 4// WHAT IT ADDS TO nx_refcorpus, AND WHAT IT DELIBERATELY DOES NOT TOUCH. rc_admit already walls off 5// asset PAYLOAD (length + plain alphabet) and enforces a global k-floor RC_KMIN=8. Both are properties 6// of the VALUE. Neither looks at WHERE the measured assets came from: rc_put_row bounds `provenance` 7// and `license` by LENGTH ONLY, so `unverified` and `cc0` pass identically. This lib is the missing 8// axis, and it is STRICTLY ADDITIVE -- it can only ever REFUSE something rc_admit would have taken. 9// It never loosens rc_admit and it is not a second copy of it. 10// 11// TWO REASONS THE `use` COLUMN EXISTS, and the second is the one that matters: 12// 1. `shipped` -- provenance is verifiable, the class may inform artifacts we ship. 13// 2. `reference-only` -- AGGREGATE STATISTICS ONLY. Never a shape target, never a fitted generator 14// axis, never resolved from a build closure. 15// Keeping an asset out of the build path stops us shipping its BYTES. It does not stop its IDENTITY 16// propagating through a generator fitted to it -- and that output IS shipped. The build-path rule is 17// structurally blind to that path; `reference-only` is what makes it enforceable rather than promised. 18// 19// FAIL CLOSED, IN BOTH DIRECTIONS THAT MATTER: 20// * an UNKNOWN tag refuses. It does not fall through to the permissive value. The estate has already 21// measured that cost: pr_mode returned BUFFERED for any unrecognised token, silently downgrading a 22// fail-closed route to an open one with no diagnostic. 23// * an UNREADABLE conf refuses too, with its own named code. A classifier that cannot read its table 24// must ABSTAIN, never acquit -- an admission wall that opens when its rules go missing is worse 25// than no wall, because its existence is counted as coverage. 26// 27// TWO-ROOT PROBE, ON PURPOSE. `knowledge/...` is a CWD-RELATIVE EXPRESSION and this estate has already 28// paid for that: the same literal names a different tree depending on the forking process's CWD. 29// pc_load probes the bare path FIRST, then the buildroot twin, and RECORDS WHICH ONE RESOLVED 30// (pc_conf_which) -- a resolver that returns bytes without saying where they came from reproduces the 31// original defect one layer up. 32// 33// NO LOOP-EXIT SENTINELS. The scanners below return early from helpers instead of writing a sentinel 34// into the cursor. The estate has recorded that defect four times in one day ("a loop-exit sentinel 35// written into the search cursor erases the answer"), and the first draft of THIS file committed it. 36// 37// license_tier: ORIGINAL 38import "nx_syscalls.nx" 39 40const PC_CONF_PRIMARY: *u8 = "knowledge/asset_provenance.conf" 41const PC_CONF_SECONDARY: *u8 = "buildroot/knowledge/asset_provenance.conf" 42 43const PC_USE_UNKNOWN: i64 = 0 44const PC_USE_SHIPPED: i64 = 1 45const PC_USE_REFERENCE_ONLY: i64 = 2 46 47const PC_OK: i64 = 0 48const PC_ERR_UNKNOWN_CLASS: i64 = 0 - 1 49const PC_ERR_BELOW_KMIN: i64 = 0 - 2 50const PC_ERR_NO_CONF: i64 = 0 - 3 51 52const PC_MAX_CLASSES: i64 = 64 53const PC_TAG_BYTES: i64 = 64 54const PC_TAB_BYTES: i64 = 4096 55const PC_IDX_BYTES: i64 = 512 56const PC_CH_SP: i64 = 32 57const PC_CH_TAB: i64 = 9 58const PC_CH_NL: i64 = 10 59const PC_CH_CR: i64 = 13 60const PC_CH_SEMI: i64 = 59 61const PC_D0: i64 = 48 62const PC_D9: i64 = 57 63 64static pc_loaded_g: i64 65static pc_n_g: i64 66static pc_which_g: i64 67static pc_tags_g: *u8 68static pc_kmin_g: *i64 69static pc_use_g: *i64 70 71func pc_is_space(c: i64) -> i64 { 72 if c == PC_CH_SP { return 1 } 73 if c == PC_CH_TAB { return 1 } 74 return 0 75} 76 77func pc_streq(a: *u8, b: *u8) -> i64 { 78 var i: i64 = 0 79 while a[i] != (0 as u8) { 80 if b[i] != a[i] { return 0 } 81 i = i + 1 82 } 83 if b[i] != (0 as u8) { return 0 } 84 return 1 85} 86 87func pc_eol(buf: *u8, n: i64, from: i64) -> i64 { 88 var j: i64 = from 89 while j < n { 90 if (buf[j] as i64) == PC_CH_NL { return j } 91 j = j + 1 92 } 93 return n 94} 95 96func pc_skip_sp(buf: *u8, end: i64, from: i64) -> i64 { 97 var j: i64 = from 98 while j < end { 99 if pc_is_space(buf[j] as i64) == 0 { return j } 100 j = j + 1 101 } 102 return end 103} 104 105func pc_tok_end(buf: *u8, end: i64, from: i64) -> i64 { 106 var j: i64 = from 107 while j < end { 108 let c: i64 = buf[j] as i64 109 if pc_is_space(c) == 1 { return j } 110 if c == PC_CH_CR { return j } 111 j = j + 1 112 } 113 return end 114} 115 116func pc_tok_is(buf: *u8, s: i64, e: i64, lit: *u8) -> i64 { 117 var k: i64 = 0 118 while lit[k] != (0 as u8) { 119 if s + k >= e { return 0 } 120 if buf[s + k] != lit[k] { return 0 } 121 k = k + 1 122 } 123 if s + k != e { return 0 } 124 return 1 125} 126 127func pc_tok_num(buf: *u8, s: i64, e: i64) -> i64 { 128 var v: i64 = 0 129 var k: i64 = s 130 var any: i64 = 0 131 while k < e { 132 let d: i64 = buf[k] as i64 133 if d < PC_D0 { return 0 - 1 } 134 if d > PC_D9 { return 0 - 1 } 135 v = v * 10 + (d - PC_D0) 136 any = 1 137 k = k + 1 138 } 139 if any == 0 { return 0 - 1 } 140 return v 141} 142 143func pc_conf_which() -> i64 { return pc_which_g } 144func pc_count() -> i64 { return pc_n_g } 145 146func pc_parse(buf: *u8, n: i64) -> i64 { 147 var count: i64 = 0 148 var i: i64 = 0 149 while i < n { 150 let eol: i64 = pc_eol(buf, n, i) 151 let a: i64 = pc_skip_sp(buf, eol, i) 152 if a < eol { 153 if (buf[a] as i64) != PC_CH_SEMI { 154 let e0: i64 = pc_tok_end(buf, eol, a) 155 if pc_tok_is(buf, a, e0, "class" as *u8) == 1 { 156 if count < PC_MAX_CLASSES { 157 let b: i64 = pc_skip_sp(buf, eol, e0) 158 let e1: i64 = pc_tok_end(buf, eol, b) 159 let c: i64 = pc_skip_sp(buf, eol, e1) 160 let e2: i64 = pc_tok_end(buf, eol, c) 161 let d: i64 = pc_skip_sp(buf, eol, e2) 162 let e3: i64 = pc_tok_end(buf, eol, d) 163 let kv: i64 = pc_tok_num(buf, c, e2) 164 var uv: i64 = PC_USE_UNKNOWN 165 if pc_tok_is(buf, d, e3, "shipped" as *u8) == 1 { uv = PC_USE_SHIPPED } 166 if pc_tok_is(buf, d, e3, "reference-only" as *u8) == 1 { uv = PC_USE_REFERENCE_ONLY } 167 if kv >= 0 { 168 if uv != PC_USE_UNKNOWN { 169 var glen: i64 = e1 - b 170 if glen > PC_TAG_BYTES - 1 { glen = PC_TAG_BYTES - 1 } 171 if glen > 0 { 172 var k: i64 = 0 173 while k < glen { pc_tags_g[count * PC_TAG_BYTES + k] = buf[b + k]; k = k + 1 } 174 pc_tags_g[count * PC_TAG_BYTES + glen] = 0 as u8 175 pc_kmin_g[count] = kv 176 pc_use_g[count] = uv 177 count = count + 1 178 } 179 } 180 } 181 } 182 } 183 } 184 } 185 i = eol + 1 186 } 187 return count 188} 189 190func pc_load() -> i64 { 191 if pc_loaded_g == 1 { 192 if pc_which_g == 0 { return PC_ERR_NO_CONF } 193 return pc_n_g 194 } 195 pc_tags_g = sys_mmap(PC_TAB_BYTES) 196 pc_kmin_g = sys_mmap(PC_IDX_BYTES) as *i64 197 pc_use_g = sys_mmap(PC_IDX_BYTES) as *i64 198 let lp: *i64 = sys_mmap(8) as *i64 199 lp[0] = 0 200 var buf: *u8 = sys_read_file(PC_CONF_PRIMARY, lp) 201 var which: i64 = 1 202 if (buf as i64) == 0 { 203 lp[0] = 0 204 buf = sys_read_file(PC_CONF_SECONDARY, lp) 205 which = 2 206 } 207 pc_loaded_g = 1 208 if (buf as i64) == 0 { pc_which_g = 0; pc_n_g = 0; return PC_ERR_NO_CONF } 209 if lp[0] <= 0 { pc_which_g = 0; pc_n_g = 0; return PC_ERR_NO_CONF } 210 pc_n_g = pc_parse(buf, lp[0]) 211 pc_which_g = which 212 return pc_n_g 213} 214 215func pc_find(tag: *u8) -> i64 { 216 if pc_load() < 0 { return PC_ERR_NO_CONF } 217 var i: i64 = 0 218 while i < pc_n_g { 219 if pc_streq(((pc_tags_g as i64) + i * PC_TAG_BYTES) as *u8, tag) == 1 { return i } 220 i = i + 1 221 } 222 return PC_ERR_UNKNOWN_CLASS 223} 224 225func pc_kmin(tag: *u8) -> i64 { 226 let idx: i64 = pc_find(tag) 227 if idx < 0 { return idx } 228 return pc_kmin_g[idx] 229} 230 231func pc_use(tag: *u8) -> i64 { 232 let idx: i64 = pc_find(tag) 233 if idx < 0 { return PC_USE_UNKNOWN } 234 return pc_use_g[idx] 235} 236 237func pc_admit(tag: *u8, n: i64) -> i64 { 238 let idx: i64 = pc_find(tag) 239 if idx == PC_ERR_NO_CONF { return PC_ERR_NO_CONF } 240 if idx < 0 { return PC_ERR_UNKNOWN_CLASS } 241 if n < pc_kmin_g[idx] { return PC_ERR_BELOW_KMIN } 242 return PC_OK 243} 244 245// May a class inform a fitted generator axis / shape target? ONLY `shipped` may. This is the query 246// the build-path rule cannot answer, so it gets its own name rather than being left to a caller's 247// reading of pc_use. 248func pc_may_fit_axis(tag: *u8) -> i64 { 249 if pc_use(tag) == PC_USE_SHIPPED { return 1 } 250 return 0 251}