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 &mdash; review before large fulfillment" as *u8 } 218 if r == 1 { return "Review &mdash; 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 &mdash; 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 &mdash; 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}