nx_acquire.nx source
↩ module page · 190 lines · 8955 B
1// nx_acquire.nx -- THE LIBRARIAN'S SHELF. Reads knowledge/acquire_sources.conf and answers, for every
2// external work we know of, the only question that matters: WHAT MAY WE DO WITH IT?
3//
4// This is the organ that makes the other two live. nx_acquire_lib holds the DOOR (evidence gates
5// rights) and nx_licgate_lib holds the RIGHTS TABLE; until something drove them from real data they
6// were a correct decision nobody asked. A capability with no caller is an adoption gap, not a feature.
7//
8// ONE RIGHTS TABLE. The licence columns come from knowledge/model_license.conf via lg_find_license --
9// the same table, the same encoding, the same fail-closed semantics the shippability verdict uses.
10// A second table keyed differently for "code" versus "models" is how two answers for one licence get
11// created, and the estate already measured FIVE non-communicating licence taxonomies.
12//
13// FAIL-CLOSED AT EVERY UNKNOWN: a malformed evidence word, an unparseable row, or a licence id absent
14// from the rights table all degrade toward REVIEW and never toward permission. Silence is never
15// permission, and "I could not read the row" must never arrive in the same word as "you may".
16// license_tier: ORIGINAL
17import "nx_syscalls.nx"
18import "nx_licgate_lib.nx"
19import "nx_acquire_lib.nx"
20
21const AQX_FCAP: i64 = 512
22const AQX_TAB: i64 = 9
23const AQX_NL: i64 = 10
24const AQX_HASH: i64 = 35
25const AQX_A: i64 = 65
26const AQX_L: i64 = 76
27const AQX_NUMCAP: i64 = 32
28
29func aqx_puts(s: *u8) -> i64 { sys_write(1, s, lg_len(s)); return 0 }
30
31func aqx_num(v: i64) -> i64 {
32 let t: *u8 = sys_mmap(AQX_NUMCAP)
33 var m: i64 = v
34 var k: i64 = 0
35 if m == 0 { t[0] = 48 as u8; k = 1 }
36 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
37 let o: *u8 = sys_mmap(AQX_NUMCAP)
38 var i: i64 = 0
39 while i < k { o[i] = t[k - 1 - i]; i = i + 1 }
40 sys_write(1, o, k)
41 sys_munmap(t, AQX_NUMCAP)
42 sys_munmap(o, AQX_NUMCAP)
43 return 0
44}
45
46// copy TAB-field idx of the row [s,e) into out, NUL-terminated. Returns its length, or -1 when the row
47// has fewer fields -- which the caller must treat as a MALFORMED ROW and never as an empty value.
48func aqx_fieldz(buf: *u8, s: i64, e: i64, idx: i64, out: *u8, cap: i64) -> i64 {
49 let box: *i64 = sys_mmap(32) as *i64
50 lg_field(buf, s, e, idx, box)
51 let off: i64 = box[0]
52 let ln: i64 = box[1]
53 if ln < 0 { out[0] = 0 as u8; return 0 - 1 }
54 if off < 0 { out[0] = 0 as u8; return 0 - 1 }
55 var i: i64 = 0
56 while i < ln {
57 if i < cap - 1 { out[i] = buf[off + i] }
58 i = i + 1
59 }
60 var w: i64 = ln
61 if w > cap - 1 { w = cap - 1 }
62 out[w] = 0 as u8
63 return w
64}
65
66func aqx_pad(s: *u8, width: i64) -> i64 {
67 aqx_puts(s)
68 var n: i64 = lg_len(s)
69 while n < width { aqx_puts(" " as *u8); n = n + 1 }
70 return 0
71}
72
73func main(argc: i64, argv: *i64) -> i64 {
74 let lp: *i64 = sys_mmap(16) as *i64
75 let buf: *u8 = sys_read_file("knowledge/acquire_sources.conf" as *u8, lp)
76 if (buf as i64) == 0 {
77 aqx_puts("REFUSED cannot-read knowledge/acquire_sources.conf -- no shelf is printed for a registry we do not hold\n" as *u8)
78 return 4
79 }
80 let n: i64 = lp[0]
81 let ctx: *i64 = lg_ctx()
82 if ctx[3] < 0 {
83 aqx_puts("REFUSED rights-table-unreadable (knowledge/model_license.conf) -- every verdict would be a guess\n" as *u8)
84 return 4
85 }
86
87 aqx_puts("=== NX-ACQUIRE SHELF -- what may we do with each external work we hold a record of ===\n" as *u8)
88 aqx_puts(" evidence: NONE no licence seen | DECLARED asserted upstream, unread | READ we hold and read the text\n" as *u8)
89 aqx_puts(" rights: YES granted | REVIEW a human must settle it, NOT a pass | NO refused\n\n" as *u8)
90
91 let fid: *u8 = sys_mmap(AQX_FCAP)
92 let fev: *u8 = sys_mmap(AQX_FCAP)
93 let flic: *u8 = sys_mmap(AQX_FCAP)
94 let res: *i64 = aq_res()
95
96 var rows: i64 = 0
97 var n_clear: i64 = 0
98 var n_review: i64 = 0
99 var n_refuse: i64 = 0
100 var n_malformed: i64 = 0
101 var n_licrows: i64 = 0
102 var n_read: i64 = 0
103
104 var p: i64 = 0
105 while p < n {
106 var q: i64 = p
107 var scan: i64 = 1
108 while scan == 1 {
109 if q >= n { scan = 0 }
110 else { if buf[q] == (AQX_NL as u8) { scan = 0 } else { q = q + 1 } }
111 }
112 // a row is processed only when it starts with the type letter AND a TAB. A '#' comment, a
113 // blank line and a continuation all fall through untouched.
114 if q > p + 1 {
115 if buf[p + 1] == (AQX_TAB as u8) {
116 if buf[p] == (AQX_L as u8) { n_licrows = n_licrows + 1 }
117 if buf[p] == (AQX_A as u8) {
118 rows = rows + 1
119 let lid: i64 = aqx_fieldz(buf, p, q, 1, fid, AQX_FCAP)
120 let lev: i64 = aqx_fieldz(buf, p, q, 3, fev, AQX_FCAP)
121 let llc: i64 = aqx_fieldz(buf, p, q, 4, flic, AQX_FCAP)
122 var bad: i64 = 0
123 if lid < 0 { bad = 1 }
124 if lev < 0 { bad = 1 }
125 if llc < 0 { bad = 1 }
126 var ev: i64 = 0 - 1
127 if bad == 0 { ev = aq_ev_parse(fev) }
128 if ev < 0 { bad = 1 }
129 if bad == 1 {
130 n_malformed = n_malformed + 1
131 aqx_puts(" " as *u8)
132 aqx_pad(fid, 30)
133 aqx_puts("MALFORMED-ROW -- refused, not defaulted\n" as *u8)
134 } else {
135 if ev == AQ_EV_READ { n_read = n_read + 1 }
136 // A LICENCE ID ABSENT FROM THE RIGHTS TABLE CANNOT GRANT. Passing verified=0
137 // caps the verdict at REVIEW by the door's own rule, so an unknown licence and
138 // an unread one land in the same honest place instead of silently granting.
139 var redist: i64 = 0
140 var vfy: i64 = 0
141 var known: i64 = 0
142 let li: i64 = lg_find_license(ctx, flic)
143 if li >= 0 {
144 redist = lg_lic_redist(ctx, li)
145 vfy = lg_lic_verified(ctx, li)
146 known = 1
147 }
148 let rc: i64 = aq_decide(ev, redist, vfy, res)
149 if rc == AQ_RC_OK { n_clear = n_clear + 1 }
150 if rc == AQ_RC_REVIEW { n_review = n_review + 1 }
151 if rc == AQ_RC_REFUSE { n_refuse = n_refuse + 1 }
152 aqx_puts(" " as *u8)
153 aqx_pad(fid, 30)
154 aqx_puts("ev=" as *u8); aqx_pad(aq_ev_name(ev), 9)
155 // 32, not 24: a LicenseRef- id is legitimately long (the SPDX escape for a
156 // licence the List cannot name is prefix + vendor + name), and at 24 the
157 // column ran into the next field. Sized from the longest id the rights table
158 // actually holds, not from what looked tidy on the first row.
159 aqx_puts("lic=" as *u8); aqx_pad(flic, 32)
160 if known == 0 { aqx_puts("[not-in-rights-table] " as *u8) }
161 aqx_puts("mirror=" as *u8); aqx_pad(aq_right_name(res[AQ_R_MIRROR]), 7)
162 aqx_puts("redist=" as *u8); aqx_pad(aq_right_name(res[AQ_R_REDIST]), 7)
163 aqx_puts("learn=" as *u8); aqx_pad(aq_right_name(res[AQ_R_LEARN]), 5)
164 aqx_puts("attrib=" as *u8); aqx_pad(aq_right_name(res[AQ_R_ATTRIB]), 5)
165 aqx_puts("=> " as *u8); aqx_puts(aq_rc_name(rc))
166 aqx_puts("\n" as *u8)
167 }
168 }
169 }
170 }
171 p = q + 1
172 }
173
174 // THE PARTITION MUST SUM AND THE SUM IS PRINTED. A residual nobody can reconcile is a leak, and a
175 // shelf that quietly drops a row is worse than one that refuses.
176 let sum: i64 = n_clear + n_review + n_refuse + n_malformed
177 aqx_puts("\nrows=" as *u8); aqx_num(rows)
178 aqx_puts(" clear=" as *u8); aqx_num(n_clear)
179 aqx_puts(" review=" as *u8); aqx_num(n_review)
180 aqx_puts(" refuse=" as *u8); aqx_num(n_refuse)
181 aqx_puts(" malformed=" as *u8); aqx_num(n_malformed)
182 aqx_puts(" sum=" as *u8); aqx_num(sum)
183 if sum == rows { aqx_puts(" partition=RECONCILES" as *u8) } else { aqx_puts(" partition=LEAK" as *u8) }
184 aqx_puts("\nlicence-evidence rows held (L)=" as *u8); aqx_num(n_licrows)
185 aqx_puts(" artifacts at evidence=READ=" as *u8); aqx_num(n_read)
186 aqx_puts("\n\nREVIEW IS NOT A PASS. Only YES permits. The work that clears a REVIEW is reading a licence:\n" as *u8)
187 aqx_puts(" nx_acquire_license derive <repo-url> -> fetch it -> pin it -> write an L row.\n" as *u8)
188 if sum != rows { return 1 }
189 return 0
190}