code wiki / _hdl_build / nx_docportal_policy_gate.nx

nx_docportal_policy_gate.nx source

↩ module page · 125 lines · 8441 B

1// nx_docportal_policy_gate.nx -- MEASURED gate for OWNER USAGE POLICY enforcement (operator: "lawyers or users on 2// any site able to flag how the results of their uploads are managed and whether an ai writer can publish blog posts 3// with the content"). Self-contained (in-process; real seg_store + real AI-blog composer). Proves the owner's flags 4// are honored BY CONSTRUCTION: 5// T1 ai_blog ON -> dp_may(AI_BLOG)=1 (permitted) 6// T2 ai_blog OFF -> dp_may(AI_BLOG)=0 (denied) even though the doc is public + searchable 7// T3 blog publish -> the draft CONTAINS the consented doc, EXCLUDES the non-consented doc (1 doc used) 8// T4 consent withdrawal -> after dp_set_policy turns ai_blog OFF, the doc vanishes from the blog AT ONCE, and the 9// doc bytes are preserved (the amendment never deletes content) 10// T5 search management -> a public doc whose owner did NOT flag pub_search is INVISIBLE to the live 11// store-native search (dss_search query-time consent filter), while a flagged doc IS findable 12// Verdict MEASURED. GREEN iff 5/5. Appends knowledge/status/docportal_policy_gate.log. license_tier: ORIGINAL 13import "nx_docportal_aiblog_lib.nx" 14import "nx_g_puts_lib.nx" 15import "nx_docportal_search_seg.nx" // dss_search: the store-native search referee (tsv emitter retired) 16 17func g_num(v: i64) -> i64 { 18 let bb: *u8 = sys_mmap(28); var m: i64 = v 19 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 20 let t: *u8 = sys_mmap(28); var k: i64 = 0 21 if m == 0 { t[0] = 48 as u8; k = 1 } 22 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 23 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 24} 25func g_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 } 26func g_wn(fd: i64, v: i64) -> i64 { 27 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 28 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 29 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 30 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(fd, bb, k); return 0 31} 32func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 33func g_contains(hay: *u8, n: i64, ndl: *u8) -> i64 { 34 let nl: i64 = g_slen(ndl); if nl == 0 { return 0 } 35 var i: i64 = 0 36 while i + nl <= n { var j: i64 = 0; var hit: i64 = 1; while j < nl { if hay[i + j] != ndl[j] { hit = 0; j = nl } else { j = j + 1 } } if hit == 1 { return 1 } i = i + 1 } 37 return 0 38} 39func g_trunc(path: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd >= 0 { sys_close(fd) } return 0 } 40func g_eq(a: *u8, al: i64, b: *u8, bl: i64) -> i64 { if al != bl { return 0 } var i: i64 = 0; while i < al { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 41 42func main() -> i64 { 43 g_puts("=== DOCPORTAL POLICY GATE (owner usage flags: public-search + AI-blog publish; enforced by construction) ===\n" as *u8) 44 let dom: *u8 = "dppol" as *u8 45 // deterministic re-runs: clear the derived AI-blog corpus (search has NO derived artifact to clear -- 46 // the store is the index, and the query-time consent filter is what T5 measures) 47 let bs: *u8 = sys_mmap(512); dp_blogsrc(dom, bs); g_trunc(bs) 48 49 let tA: *u8 = "TRUSTBLOGMARK Estate planning insight on how a living trust avoids probate in Utah." as *u8 50 let tB: *u8 = "PRIVATEMEMOMARK Notes on the Johnson divorce settlement for internal use only." as *u8 51 let tC: *u8 = "NOSEARCHMARK Internal draft not to be indexed for public search." as *u8 52 let cidA: *i64 = sys_mmap(16) as *i64 53 let cidB: *i64 = sys_mmap(16) as *i64 54 let cidC: *i64 = sys_mmap(16) as *i64 55 // docA: owner cleared it for search AND AI-blog ; docB: search only (NOT AI-blog) ; docC: neither 56 dp_ingest_policy(dom, DP_VIS_PUBLIC, DP_USE_PUB_SEARCH | DP_USE_AI_BLOG, tA, g_slen(tA), cidA) 57 dp_ingest_policy(dom, DP_VIS_PUBLIC, DP_USE_PUB_SEARCH, tB, g_slen(tB), cidB) 58 dp_ingest_policy(dom, DP_VIS_PUBLIC, 0, tC, g_slen(tC), cidC) 59 60 var pass: i64 = 0 61 62 // T1 / T2: the flag governs AI-blog permission 63 let mayA: i64 = dp_may(dom, DP_VIS_PUBLIC, cidA[0], DP_USE_AI_BLOG) 64 let mayB: i64 = dp_may(dom, DP_VIS_PUBLIC, cidB[0], DP_USE_AI_BLOG) 65 var t1: i64 = 0; if mayA == 1 { t1 = 1 } pass = pass + t1 66 g_puts(" T1 ai_blog ON -> permitted: "); if t1 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 67 var t2: i64 = 0; if mayB == 0 { t2 = 1 } pass = pass + t2 68 g_puts(" T2 ai_blog OFF -> denied: "); if t2 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 69 70 // T3: the AI-blog draft includes ONLY consented content 71 let blog: *u8 = sys_mmap(8192); let cnt: *i64 = sys_mmap(16) as *i64 72 let blen: i64 = ab_compose_blog(dom, "Andelin West -- Legal Insights" as *u8, blog, 8192, cnt) 73 var t3: i64 = 0 74 let hasA: i64 = g_contains(blog, blen, "TRUSTBLOGMARK" as *u8) 75 let hasB: i64 = g_contains(blog, blen, "PRIVATEMEMOMARK" as *u8) 76 if hasA == 1 { if hasB == 0 { if cnt[0] == 1 { t3 = 1 } } } 77 pass = pass + t3 78 g_puts(" T3 blog includes consented, excludes non-consented (hasA="); g_num(hasA); g_puts(" hasB="); g_num(hasB); g_puts(" used="); g_num(cnt[0]); g_puts("): ") 79 if t3 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 80 81 // T4: consent withdrawal takes effect at once, and the doc bytes survive the amendment 82 dp_set_policy(dom, DP_VIS_PUBLIC, cidA[0], DP_USE_PUB_SEARCH) // owner turns AI-blog OFF for docA 83 let mayA2: i64 = dp_may(dom, DP_VIS_PUBLIC, cidA[0], DP_USE_AI_BLOG) 84 let blog2: *u8 = sys_mmap(8192); let cnt2: *i64 = sys_mmap(16) as *i64 85 let blen2: i64 = ab_compose_blog(dom, "Andelin West -- Legal Insights" as *u8, blog2, 8192, cnt2) 86 let stillA: i64 = g_contains(blog2, blen2, "TRUSTBLOGMARK" as *u8) 87 let pq: *i64 = sys_mmap(16) as *i64; let lq: *i64 = sys_mmap(16) as *i64 88 var preserved: i64 = 0 89 if dp_read(dom, DP_VIS_PUBLIC, cidA[0], pq, lq) == 1 { if g_eq(pq[0] as *u8, lq[0], tA, g_slen(tA)) == 1 { preserved = 1 } } 90 var t4: i64 = 0 91 if mayA2 == 0 { if stillA == 0 { if preserved == 1 { t4 = 1 } } } 92 pass = pass + t4 93 g_puts(" T4 consent withdrawal live + doc preserved (may="); g_num(mayA2); g_puts(" inblog="); g_num(stillA); g_puts(" preserved="); g_num(preserved); g_puts("): ") 94 if t4 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 95 96 // T5: the owner's search flag controls LIVE findability -- docA (flag ON, marker TRUSTBLOGMARK) must be 97 // found by the store-native search; docC (flags=0, marker NOSEARCHMARK) must be invisible even though its 98 // bytes sit in the SAME public shard (query-time consent filter, not emission-time) 99 let scids: *i64 = sys_mmap(16 * 8) as *i64 100 let sscores: *i64 = sys_mmap(16 * 8) as *i64 101 let qA: *u8 = "trustblogmark" as *u8 102 let nA: i64 = dss_search(dom, qA, g_slen(qA), scids, sscores, 16) 103 var hasAsrc: i64 = 0 104 if nA >= 1 { if scids[0] == cidA[0] { hasAsrc = 1 } } 105 let qC: *u8 = "nosearchmark" as *u8 106 let nC: i64 = dss_search(dom, qC, g_slen(qC), scids, sscores, 16) 107 let hasCsrc: i64 = nC 108 var t5: i64 = 0 109 if hasAsrc == 1 { if hasCsrc == 0 { t5 = 1 } } 110 pass = pass + t5 111 g_puts(" T5 owner search-flag controls live findability (A_found="); g_num(hasAsrc); g_puts(" C_found="); g_num(hasCsrc); g_puts("): ") 112 if t5 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 113 114 g_puts("----\nDOCPORTAL-POLICY rows=5 pass="); g_num(pass); g_puts("\n" as *u8) 115 let lg: i64 = sys_openat_append("knowledge/status/docportal_policy_gate.log" as *u8, 0x1a4) 116 if lg >= 0 { 117 g_w(lg, "DOCPORTAL-POLICY ai_blog_permit="); g_wn(lg, t1); g_w(lg, " ai_blog_deny="); g_wn(lg, t2) 118 g_w(lg, " blog_consent_only="); g_wn(lg, t3); g_w(lg, " withdrawal_live_doc_preserved="); g_wn(lg, t4); g_w(lg, " search_flag_controls="); g_wn(lg, t5) 119 g_w(lg, " rows=5 pass="); g_wn(lg, pass) 120 if pass == 5 { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) } 121 sys_close(lg) 122 } 123 if pass == 5 { g_puts("DOCPORTAL-POLICY GREEN (owner usage flags enforced by construction; AI-blog consent-gated + amendable -- measured)\n" as *u8); sys_exit(0); return 0 } 124 g_puts("DOCPORTAL-POLICY RED\n" as *u8); sys_exit(1); return 1 125}