code wiki / _hdl_build / nx_adnet_selfserve.nx

nx_adnet_selfserve.nx source

↩ module page · 106 lines · 4151 B

1// nx_adnet_selfserve.nx -- LIB: self-serve advertiser intake for the sovereign ad network. An advertiser 2// submits a full inventory row (id/advertiser/img/clickurl/section/weight -- the exact nx_adnet contract); 3// the row is VALIDATED with the same fail-closed rules the serving slot enforces (first-party img only, 4// http(s)/path click only, clean id) and then appended to a STAGED submissions journal. STAGED IS NOT 5// LIVE: nothing an advertiser submits ever serves until the operator approves it into the live inventory 6// conf (ass_approve appends a validated staged row there -- an operator action, never automatic). 7// B2B only; the schema HAS NO VISITOR FIELD -- no visitor identity can transit this path by construction. 8// license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "_hdl_build/nx_adnet_slot.nx" 11 12// validate a submitted inventory row against the serving rules (same validators the slot uses). 13func ass_valid_row(row: *u8, rlen: i64) -> i64 { 14 if rlen <= 0 { return 0 } 15 if rlen > 1024 { return 0 } 16 if row[0] == (64 as u8) { return 0 } 17 let id: *u8 = sys_mmap(128) 18 let img: *u8 = sys_mmap(1024) 19 let clk: *u8 = sys_mmap(1024) 20 let sec: *u8 = sys_mmap(128) 21 aslot_field_b(row, rlen, 0, id, 128) 22 aslot_field_b(row, rlen, 2, img, 1024) 23 aslot_field_b(row, rlen, 3, clk, 1024) 24 aslot_field_b(row, rlen, 4, sec, 128) 25 if aslot_id_ok(id) == 0 { return 0 } 26 if aslot_img_ok(img) == 0 { return 0 } 27 if aslot_click_ok(clk) == 0 { return 0 } 28 var i: i64 = 0 29 while sec[i] != (0 as u8) { 30 let c: u8 = sec[i] 31 var ok: i64 = 0 32 if c >= (97 as u8) { if c <= (122 as u8) { ok = 1 } } 33 if c >= (48 as u8) { if c <= (57 as u8) { ok = 1 } } 34 if ok == 0 { return 0 } 35 i = i + 1 36 if i > 64 { return 0 } 37 } 38 if i == 0 { return 0 } 39 return 1 40} 41 42// append one validated row to the staged submissions journal (append-only; NEVER the live inventory). 43// Returns 1 on validated+persisted (read-back verified), 0 = REFUSED or io failure. 44func ass_submit(subs_path: *u8, row: *u8, rlen: i64) -> i64 { 45 if ass_valid_row(row, rlen) == 0 { return 0 } 46 let fd: i64 = sys_openat_append(subs_path, 420) 47 if fd < 0 { return 0 } 48 let line: *u8 = sys_mmap(1152) 49 var o: i64 = 0 50 var i: i64 = 0 51 while i < rlen { line[o] = row[i]; o = o + 1; i = i + 1 } 52 line[o] = 10 as u8 53 o = o + 1 54 let wr: i64 = sys_write(fd, line, o) 55 sys_close(fd) 56 if wr != o { return 0 } 57 let box: *i64 = (sys_mmap(8)) as *i64 58 box[0] = 0 59 let back: *u8 = sys_read_file(subs_path, box) 60 if (back as i64) == 0 { return 0 } 61 let bn: i64 = box[0] 62 var j: i64 = 0 63 while j + rlen <= bn { 64 var k: i64 = 0 65 var eq: i64 = 1 66 while k < rlen { if back[j + k] != row[k] { eq = 0; break } k = k + 1 } 67 if eq == 1 { return 1 } 68 j = j + 1 69 } 70 return 0 71} 72 73// anti-snoop scanner: 1 if a visitor-identity-looking token is present in the journal bytes. 74// (The schema has no visitor field; this detector exists so the gate can PROVE it would catch a leak.) 75func ass_snoop_scan(buf: *u8, n: i64) -> i64 { 76 let m: *u8 = "VISITOR-TOKEN" as *u8 77 var i: i64 = 0 78 while i + 13 <= n { 79 if buf[i] == (86 as u8) { 80 var k: i64 = 0 81 var eq: i64 = 1 82 while k < 13 { if buf[i + k] != m[k] { eq = 0; break } k = k + 1 } 83 if eq == 1 { return 1 } 84 } 85 i = i + 1 86 } 87 return 0 88} 89 90// OPERATOR APPROVE: re-validate a staged row and append it to the LIVE inventory conf. This is the 91// only staged->live bridge and it is invoked by the operator lane, never by the submit path. 92func ass_approve(inv_path: *u8, row: *u8, rlen: i64) -> i64 { 93 if ass_valid_row(row, rlen) == 0 { return 0 } 94 let fd: i64 = sys_openat_append(inv_path, 420) 95 if fd < 0 { return 0 } 96 let line: *u8 = sys_mmap(1152) 97 var o: i64 = 0 98 var i: i64 = 0 99 while i < rlen { line[o] = row[i]; o = o + 1; i = i + 1 } 100 line[o] = 10 as u8 101 o = o + 1 102 let wr: i64 = sys_write(fd, line, o) 103 sys_close(fd) 104 if wr != o { return 0 } 105 return 1 106}