code wiki / _hdl_build / nx_aid.nx
nx_aid.nx source
↩ module page · 264 lines · 13641 B
1// nx_aid.nx -- LIB: CHARITY ANTI-SCAM integrity (R-AID, pillar 4 of seed-to-feed). Operator: "the descamming
2// capabilities so that food banks and other charitable orgs can make sure that people in need get the food not
3// people exploiting it." An ADDITIVE, auditable aid ledger + exploit-pattern detection that DISTINGUISHES the
4// needy from exploiters WITHOUT ever punishing need.
5//
6// TWO ETHICAL GUARANTEES, enforced by construction (not promised):
7// (A) PRIVACY-FIRST -- recipients are opaque tokens (rid), never PII. Sovereign data, not harvested.
8// (B) FAIL-OPEN -- the automated system NEVER auto-denies (ad_auto_deny == 0 for EVERYONE, always). It only
9// RAISES a risk level for a HUMAN to review. A false positive can never block a hungry person; a real
10// exploiter is surfaced for a person to decide. "People in need get the food; exploiters get reviewed."
11//
12// Descam signals (all measured from the recorded ledger, data-driven thresholds in aid:policy -- rule 11):
13// - DUPLICATE: claiming from too many DISTINCT orgs within the period (double-dipping across charities).
14// - VOLUME: claim value in the period far exceeds the household's expected need.
15// - RESELLER: units in the period far exceed any household's use (a reselling signature).
16// Sovereign seg-store (knowledge/store/aid-*, NO TSV), integer-only. license_tier: ORIGINAL
17import "nx_food_science.nx"
18import "nx_seg_store.nx"
19import "nx_syscalls.nx"
20const K_MAGIC_4096: i64 = 4096
21
22func ad_put(prefix: *u8, key: *u8, val: *u8) -> i64 {
23 let vl: i64 = as_len(val)
24 if fd_streq_store(prefix, key, val, vl) == 1 { return 0 }
25 let w: *i64 = ss_begin()
26 ss_add(w, 1, key, val, vl)
27 let seg: i64 = fd_seg_next(prefix)
28 ss_commit(prefix, w, seg)
29 return 1
30}
31
32// policy: max_distinct_orgs \t period_days \t per_person_value_cents \t value_overage_pct \t reseller_units_per_person
33func ad_seed_policy(prefix: *u8) -> i64 { return ad_put(prefix, "aid:policy" as *u8, "2\t30\t5000\t150\t20" as *u8) }
34func ad_policy_int(prefix: *u8, f: i64) -> i64 {
35 let pq: *i64 = sys_mmap(16) as *i64
36 let lq: *i64 = sys_mmap(16) as *i64
37 if ss_get(prefix, "aid:policy" as *u8, pq, lq) != 1 { return 0 - 1 }
38 let fb: *u8 = sys_mmap(16)
39 let fl: i64 = fd_field(pq[0] as *u8, lq[0], f, fb)
40 return fd_atoi(fb, fl)
41}
42
43// ---- recipients (opaque tokens) + orgs + the additive claim ledger ----
44func ad_recip_key(rid: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "aid:recip:" as *u8); o = as_append(out, o, rid); out[o] = 0 as u8; return o }
45func ad_claimn_key(rid: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "aid:claimn:" as *u8); o = as_append(out, o, rid); out[o] = 0 as u8; return o }
46func ad_claim_key(rid: *u8, seq: i64, out: *u8) -> i64 {
47 var o: i64 = 0
48 o = as_append(out, o, "aid:claim:" as *u8); o = as_append(out, o, rid)
49 out[o] = 58 as u8; o = o + 1
50 o = fd_apnum(out, o, seq); out[o] = 0 as u8; return o
51}
52
53func ad_add_recipient(prefix: *u8, rid: *u8, household: i64, need_tier: i64, enrolled_day: i64, cite: *u8) -> i64 {
54 let key: *u8 = sys_mmap(96); ad_recip_key(rid, key)
55 let val: *u8 = sys_mmap(128)
56 var o: i64 = 0
57 o = fd_apnum(val, o, household); val[o] = 9 as u8; o = o + 1
58 o = fd_apnum(val, o, need_tier); val[o] = 9 as u8; o = o + 1
59 o = fd_apnum(val, o, enrolled_day); val[o] = 9 as u8; o = o + 1
60 o = as_append(val, o, cite)
61 val[o] = 0 as u8
62 let w: i64 = ad_put(prefix, key, val)
63 // index for the review page
64 let pq: *i64 = sys_mmap(16) as *i64
65 let lq: *i64 = sys_mmap(16) as *i64
66 let cur: *u8 = sys_mmap(K_MAGIC_4096)
67 var co: i64 = 0
68 if ss_get(prefix, "aid:recipids" as *u8, pq, lq) == 1 {
69 let b: *u8 = pq[0] as *u8; let n: i64 = lq[0]
70 var u: i64 = 0; while u < n { cur[u] = b[u]; u = u + 1 } co = n
71 // dedup
72 var i: i64 = 0; var ls: i64 = 0; var found: i64 = 0
73 while i <= n {
74 var sep: i64 = 0
75 if i == n { sep = 1 } else { if b[i] == (9 as u8) { sep = 1 } }
76 if sep == 1 {
77 let tl: i64 = i - ls
78 if tl > 0 { if as_len(rid) == tl { var m: i64 = 0; var eq: i64 = 1; while m < tl { if b[ls + m] != rid[m] { eq = 0 } m = m + 1 } if eq == 1 { found = 1 } } }
79 ls = i + 1
80 }
81 i = i + 1
82 }
83 if found == 1 { return w }
84 cur[co] = 9 as u8; co = co + 1
85 }
86 co = as_append(cur, co, rid); cur[co] = 0 as u8
87 ad_put(prefix, "aid:recipids" as *u8, cur)
88 return w
89}
90func ad_recip_int(prefix: *u8, rid: *u8, f: i64) -> i64 {
91 let key: *u8 = sys_mmap(96); ad_recip_key(rid, key)
92 let pq: *i64 = sys_mmap(16) as *i64
93 let lq: *i64 = sys_mmap(16) as *i64
94 if ss_get(prefix, key, pq, lq) != 1 { return 0 - 1 }
95 let fb: *u8 = sys_mmap(16)
96 let fl: i64 = fd_field(pq[0] as *u8, lq[0], f, fb)
97 return fd_atoi(fb, fl)
98}
99
100func ad_claimn(prefix: *u8, rid: *u8) -> i64 {
101 let key: *u8 = sys_mmap(96); ad_claimn_key(rid, key)
102 let pq: *i64 = sys_mmap(16) as *i64
103 let lq: *i64 = sys_mmap(16) as *i64
104 if ss_get(prefix, key, pq, lq) != 1 { return 0 }
105 return fd_atoi(pq[0] as *u8, lq[0])
106}
107// record an aid claim (ADDITIVE -- never overwrites prior claims; the ledger is the audit trail).
108func ad_record_claim(prefix: *u8, rid: *u8, oid: *u8, day: i64, value_cents: i64, units: i64, note: *u8) -> i64 {
109 let seq: i64 = ad_claimn(prefix, rid)
110 let key: *u8 = sys_mmap(96); ad_claim_key(rid, seq, key)
111 let val: *u8 = sys_mmap(256)
112 var o: i64 = 0
113 o = as_append(val, o, oid); val[o] = 9 as u8; o = o + 1
114 o = fd_apnum(val, o, day); val[o] = 9 as u8; o = o + 1
115 o = fd_apnum(val, o, value_cents); val[o] = 9 as u8; o = o + 1
116 o = fd_apnum(val, o, units); val[o] = 9 as u8; o = o + 1
117 o = as_append(val, o, note)
118 val[o] = 0 as u8
119 ad_put(prefix, key, val)
120 let nk: *u8 = sys_mmap(96); ad_claimn_key(rid, nk)
121 let nv: *u8 = sys_mmap(16); var no: i64 = fd_apnum(nv, 0, seq + 1); nv[no] = 0 as u8
122 ad_put(prefix, nk, nv)
123 return seq
124}
125func ad_claim_str(prefix: *u8, rid: *u8, seq: i64, f: i64, out: *u8) -> i64 {
126 let key: *u8 = sys_mmap(96); ad_claim_key(rid, seq, key)
127 let pq: *i64 = sys_mmap(16) as *i64
128 let lq: *i64 = sys_mmap(16) as *i64
129 if ss_get(prefix, key, pq, lq) != 1 { out[0] = 0 as u8; return 0 }
130 return fd_field(pq[0] as *u8, lq[0], f, out)
131}
132func ad_claim_int(prefix: *u8, rid: *u8, seq: i64, f: i64) -> i64 {
133 let fb: *u8 = sys_mmap(24)
134 let fl: i64 = ad_claim_str(prefix, rid, seq, f, fb)
135 if fl == 0 { return 0 }
136 return fd_atoi(fb, fl)
137}
138
139// 1 if claim `seq` falls within the policy period ending at now_day.
140func ad_in_period(prefix: *u8, rid: *u8, seq: i64, now_day: i64) -> i64 {
141 let period: i64 = ad_policy_int(prefix, 1)
142 let day: i64 = ad_claim_int(prefix, rid, seq, 1)
143 if day > now_day { return 0 }
144 if (now_day - day) <= period { return 1 }
145 return 0
146}
147
148// distinct orgs claimed-from within the period (the double-dipping signal).
149func ad_distinct_orgs(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
150 let n: i64 = ad_claimn(prefix, rid)
151 let seen: *i64 = sys_mmap(8 * 64) as *i64
152 var ns: i64 = 0
153 var i: i64 = 0
154 while i < n {
155 if ad_in_period(prefix, rid, i, now_day) == 1 {
156 let oid: *u8 = sys_mmap(48); ad_claim_str(prefix, rid, i, 0, oid)
157 var found: i64 = 0
158 var j: i64 = 0
159 while j < ns { if fd_streq(seen[j] as *u8, oid) == 1 { found = 1 } j = j + 1 }
160 if found == 0 { seen[ns] = oid as i64; ns = ns + 1 }
161 }
162 i = i + 1
163 }
164 return ns
165}
166func ad_value_in_period(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
167 let n: i64 = ad_claimn(prefix, rid)
168 var s: i64 = 0
169 var i: i64 = 0
170 while i < n { if ad_in_period(prefix, rid, i, now_day) == 1 { s = s + ad_claim_int(prefix, rid, i, 2) } i = i + 1 }
171 return s
172}
173func ad_units_in_period(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
174 let n: i64 = ad_claimn(prefix, rid)
175 var s: i64 = 0
176 var i: i64 = 0
177 while i < n { if ad_in_period(prefix, rid, i, now_day) == 1 { s = s + ad_claim_int(prefix, rid, i, 3) } i = i + 1 }
178 return s
179}
180
181// ---- the descam signals (measured; a needy household trips NONE) ----
182func ad_dup_flag(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
183 if ad_distinct_orgs(prefix, rid, now_day) > ad_policy_int(prefix, 0) { return 1 }
184 return 0
185}
186func ad_expected_value(prefix: *u8, rid: *u8) -> i64 {
187 let hh: i64 = ad_recip_int(prefix, rid, 0)
188 if hh < 1 { return ad_policy_int(prefix, 2) }
189 return hh * ad_policy_int(prefix, 2)
190}
191func ad_volume_flag(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
192 let thresh: i64 = (ad_expected_value(prefix, rid) * ad_policy_int(prefix, 3)) / 100
193 if ad_value_in_period(prefix, rid, now_day) > thresh { return 1 }
194 return 0
195}
196func ad_reseller_flag(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
197 let hh: i64 = ad_recip_int(prefix, rid, 0)
198 var base: i64 = hh
199 if base < 1 { base = 1 }
200 let thresh: i64 = base * ad_policy_int(prefix, 4)
201 if ad_units_in_period(prefix, rid, now_day) > thresh { return 1 }
202 return 0
203}
204// composite risk: 0 clear, 1 review, 2 high. A reseller is high; dup/volume alone is review.
205func ad_risk(prefix: *u8, rid: *u8, now_day: i64) -> i64 {
206 if ad_reseller_flag(prefix, rid, now_day) == 1 { return 2 }
207 if ad_dup_flag(prefix, rid, now_day) == 1 { return 1 }
208 if ad_volume_flag(prefix, rid, now_day) == 1 { return 1 }
209 return 0
210}
211// THE FAIL-OPEN GUARANTEE: the automated system NEVER denies. Always 0. Denial is a human decision on review.
212func ad_auto_deny(prefix: *u8, rid: *u8, now_day: i64) -> i64 { return 0 }
213// 1 if this case should be surfaced to a human reviewer (risk >= 1) -- it is still served now.
214func ad_needs_review(prefix: *u8, rid: *u8, now_day: i64) -> i64 { if ad_risk(prefix, rid, now_day) >= 1 { return 1 } return 0 }
215
216func ad_risk_label(r: i64) -> *u8 {
217 if r == 2 { return "HIGH — review before large fulfillment" as *u8 }
218 if r == 1 { return "Review — served now, check later" as *u8 }
219 return "Clear" as *u8
220}
221
222// the food-bank REVIEW QUEUE (privacy-preserving: tokens + reasons, no PII). Sovereign no-JS.
223func ad_render_review(prefix: *u8, now_day: i64, out: *u8) -> i64 {
224 var o: i64 = 0
225 o = as_append(out, o, "<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Aid integrity review</title><style>body{margin:0;font-family:system-ui,sans-serif;color:#241c2a;background:#f5f1f7;line-height:1.5}header{background:#4a2f5f;color:#fff;padding:22px}header h1{margin:0;font-size:1.4rem}header p{margin:4px 0 0;color:#e3d5ef}main{max-width:700px;margin:0 auto;padding:16px}table{border-collapse:collapse;width:100%;background:#fff;border-radius:12px;overflow:hidden}th,td{padding:9px 12px;text-align:left;border-top:1px solid #efe9f3}th{background:#ece2f3;color:#42305a}.hi{color:#a23a2a;font-weight:700}.rv{color:#9a6a1f;font-weight:700}.muted{color:#6a5b78;font-size:.88rem}</style></head><body><header><h1>Aid integrity — review queue</h1><p>Flagged for a human to check. Nobody is auto-denied; everyone flagged was still served.</p></header><main><table><tr><th>Recipient</th><th>Household</th><th>Risk</th><th>Why</th></tr>" as *u8)
226 let pq: *i64 = sys_mmap(16) as *i64
227 let lq: *i64 = sys_mmap(16) as *i64
228 if ss_get(prefix, "aid:recipids" as *u8, pq, lq) == 1 {
229 let b: *u8 = pq[0] as *u8
230 let n: i64 = lq[0]
231 var i: i64 = 0
232 var ls: i64 = 0
233 while i <= n {
234 var sep: i64 = 0
235 if i == n { sep = 1 } else { if b[i] == (9 as u8) { sep = 1 } }
236 if sep == 1 {
237 let tl: i64 = i - ls
238 if tl > 0 {
239 let rid: *u8 = sys_mmap(48)
240 var t: i64 = 0
241 while t < tl { rid[t] = b[ls + t]; t = t + 1 } rid[tl] = 0 as u8
242 let r: i64 = ad_risk(prefix, rid, now_day)
243 if r >= 1 {
244 o = as_append(out, o, "<tr><td>" as *u8)
245 o = as_append_escaped(out, o, rid, as_len(rid))
246 o = as_append(out, o, "</td><td>" as *u8); o = fd_apnum(out, o, ad_recip_int(prefix, rid, 0))
247 if r == 2 { o = as_append(out, o, "</td><td class='hi'>" as *u8) } else { o = as_append(out, o, "</td><td class='rv'>" as *u8) }
248 o = as_append(out, o, ad_risk_label(r))
249 o = as_append(out, o, "</td><td>" as *u8)
250 if ad_reseller_flag(prefix, rid, now_day) == 1 { o = as_append(out, o, "high units (resale signature) " as *u8) }
251 if ad_dup_flag(prefix, rid, now_day) == 1 { o = as_append(out, o, "claims across many orgs " as *u8) }
252 if ad_volume_flag(prefix, rid, now_day) == 1 { o = as_append(out, o, "value exceeds household need " as *u8) }
253 o = as_append(out, o, "</td></tr>" as *u8)
254 }
255 }
256 ls = i + 1
257 }
258 i = i + 1
259 }
260 }
261 o = as_append(out, o, "</table><p class='muted'>Recipients are opaque tokens, never personal data (privacy-first). The automated system never denies aid — it only flags patterns for a person to review, so a false positive can never block someone in need.</p></main></body></html>" as *u8)
262 out[o] = 0 as u8
263 return o
264}