code wiki / _hdl_build / nx_ad_conversion_gate.nx

nx_ad_conversion_gate.nx source

↩ module page · 86 lines · 4189 B

1// nx_ad_conversion_gate.nx -- GATE (runnable) for ADS-018 privacy-preserving conversion measure. 2// The DELIVERABLE organ: loads the SAME rules + k-anon floor used in production FROM THE SOVEREIGN 3// STORE (adcfg:botrules, adcfg:kanon_k -- pure Nishi, no TSV) and proves the full pipeline 4// (consent-gate -> bot-filter -> aggregate -> k-anon) on baked adversarial controls, parametrized 5// by the configured K. Cannot false-green: each neg control must drop its events, and a small 6// campaign must suppress. 7// 8// happy : consented human conversions summing to >= K -> released count == the exact sum 9// consent: an UNCONSENTED bucket -> contributes 0 (consent-gated) 10// bot : a CONSENTED but bot-class bucket -> contributes 0 (invalid-traffic) 11// k-anon : a consented human campaign with < K total -> SUPPRESSED ("<k", release == -1) 12// 13// Evidence -> knowledge/status/ad_conversion.log (CONVERSIONGATE authored=organ ... verdict=GREEN). 14// license_tier: ORIGINAL 15import "nx_ad_conversion.nx" 16import "nx_ad_store.nx" 17import "nx_ad_botfilter.nx" 18import "nx_kanon.nx" 19import "nx_syscalls.nx" 20import "nx_gate_verdict.nx" 21 22const CG_LOG: *u8 = "knowledge/status/ad_conversion.log" 23 24func cg_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 25func cg_wn(fd: i64, v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64=v; if m<0 {m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8 = sys_mmap(28); var k: i64=0; if m==0 {t[0]=48;k=1}; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1}; var i: i64=0; while i<k {bb[i]=t[k-1-i]; i=i+1}; sys_write(fd, bb, k); return 0 } 26 27func cg_emit(fd: i64, k: i64, rawh: i64, relh: i64, relk: i64, ok: i64) -> i64 { 28 cg_w(fd, "CONVERSIONGATE authored=organ source=store k=" as *u8); cg_wn(fd, k) 29 cg_w(fd, " happy_raw=" as *u8); cg_wn(fd, rawh) 30 cg_w(fd, " happy_released=" as *u8); cg_wn(fd, relh) 31 cg_w(fd, " small_released=" as *u8); cg_wn(fd, relk) 32 cg_w(fd, " attribution=aggregate-only-no-visitor-id" as *u8) 33 if ok == 1 { cg_w(fd, " verdict=GREEN\n" as *u8) } else { cg_w(fd, " verdict=RED\n" as *u8) } 34 return 0 35} 36 37func cg_set(ev: *i64, b: i64, consent: i64, ctype: i64, ua: i64, src: i64, js: i64, n: i64) -> i64 { 38 ev[b * 6] = consent 39 ev[b * 6 + 1] = ctype 40 ev[b * 6 + 2] = ua 41 ev[b * 6 + 3] = src 42 ev[b * 6 + 4] = js 43 ev[b * 6 + 5] = n 44 return 0 45} 46 47func main() -> i64 { 48 let rules: *i64 = sys_mmap(BF_MAXRULES * 2 * 8) as *i64 49 let nrules: i64 = ads_botrules(rules, BF_MAXRULES) 50 let k: i64 = ads_kanon_k() 51 52 let ev: *i64 = sys_mmap(256) as *i64 53 cg_set(ev, 0, 1, 2, 0, 0, 1, k + 3) // consented human purchase 54 cg_set(ev, 1, 1, 0, 0, 0, 1, 4) // consented human click-through 55 cg_set(ev, 2, 0, 0, 0, 0, 1, 99) // UNCONSENTED human -> dropped (consent-gate) 56 cg_set(ev, 3, 1, 1, 1, 1, 0, 77) // consented BOT -> dropped (bot-filter) 57 let rawh: i64 = cv_raw(ev, 4, rules, nrules) 58 let relh: i64 = cv_release(ev, 4, rules, nrules, k) 59 60 let ev2: *i64 = sys_mmap(64) as *i64 61 cg_set(ev2, 0, 1, 0, 0, 0, 1, k - 1) 62 let raws: i64 = cv_raw(ev2, 1, rules, nrules) 63 let relk: i64 = cv_release(ev2, 1, rules, nrules, k) 64 65 var ok: i64 = 1 66 if k < 2 { ok = 0 } 67 if nrules < 1 { ok = 0 } 68 if rawh != k + 7 { ok = 0 } 69 if relh != k + 7 { ok = 0 } 70 if raws != k - 1 { ok = 0 } 71 if relk != 0 - 1 { ok = 0 } 72 73 cg_emit(1, k, rawh, relh, relk, ok) 74 let lf: i64 = sys_openat_append(CG_LOG, 420) 75 if lf >= 0 { cg_emit(lf, k, rawh, relh, relk, ok); sys_close(lf) } 76 77 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 78 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 79 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 80 let ctr__dry: *i64 = gv_ctr() 81 ctr__dry[0] = ok 82 ctr__dry[1] = 1 83 let rc__dry: i64 = gv_verdict("AD-CONVERSION-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 84 sys_exit(rc__dry) 85 return rc__dry 86}