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}