code wiki / (root) / nx_share_consent.nx

nx_share_consent.nx source

↩ module page · 134 lines · 7104 B

1// nx_share_consent.nx -- PRIVACY / CONSENT ON SHARES (sharing ring rung 3; frontier momentum 170). The ACL 2// discipline applied to the share plane, DENY-BY-DEFAULT: 3// SHARE-CONSENT: a share lands ONLY if the recipient consented -- by PERSON ("Dana may share anything with me"), 4// by CONTEXT ("professional contacts may share jobs"), or wildcard -- SCOPED by item type, with explicit BLOCKS 5// OUTRANKING every allow. No record = DENY (privacy by default, the exact inverse of every social feed). 6// INTRO-CONSENT: an intro exposes a THIRD party -- introducing Priya shares Priya. So intros ALSO require the 7// SUBJECT's own standing consent to be introduced. Both sides must say yes or nothing moves. 8// Consent policy = additive records (person | from-or-"ctx:<context>"-or-* | allow/block | scope-itype-or-*) -- 9// data, not code; the share layer (nx_share/serve) MUST call sc_check (+ sc_intro_ok for intros) BEFORE sh_save. 10// Pure logic + selftest gate (argless): a 7-check matrix incl. block-outranks-context and third-party intro consent. 11// license_tier: ORIGINAL expect_exit: 0 12import "nx_syscalls.nx" 13 14func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 15func p(s: *u8) -> i64 { sys_write(1, s, slen(s)); return 0 } 16func pn(v: i64) -> i64 { 17 var m: i64 = v; if m < 0 { p("-" as *u8); m = 0 - m } 18 let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 19 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 20 let o: *u8 = sys_mmap(24); var i: i64 = 0; while i < k { o[i] = t[k-1-i]; i = i + 1 } sys_write(1, o, k); return 0 21} 22func seq(a: *u8, b: *u8) -> i64 { 23 var i: i64 = 0 24 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 25 if b[i] != (0 as u8) { return 0 } 26 return 1 27} 28// does the from-pattern match? pat = exact person | "ctx:<context>" | "*" 29func sc_from_match(pat: *u8, from: *u8, fromctx: *u8) -> i64 { 30 if seq(pat, "*" as *u8) == 1 { return 1 } 31 if seq(pat, from) == 1 { return 1 } 32 // "ctx:" prefix? 33 if pat[0] == (99 as u8) { if pat[1] == (116 as u8) { if pat[2] == (120 as u8) { if pat[3] == (58 as u8) { 34 let sub: *u8 = (pat as i64 + 4) as *u8 35 if seq(sub, fromctx) == 1 { return 1 } 36 } } } } 37 return 0 38} 39// policy ctx bundle: [0]=cw persons *i64, [1]=cf from-patterns *i64, [2]=ck kinds *i64 (1 allow/0 block), 40// [3]=cs scopes *i64, [4]=n 41// DENY-BY-DEFAULT; explicit BLOCK on (from) outranks every allow. 42func sc_check(pol: *i64, from: *u8, to: *u8, itype: *u8, fromctx: *u8) -> i64 { 43 let cw: *i64 = pol[0] as *i64 44 let cf: *i64 = pol[1] as *i64 45 let ck: *i64 = pol[2] as *i64 46 let cs: *i64 = pol[3] as *i64 47 let n: i64 = pol[4] 48 // pass 1: blocks outrank 49 var i: i64 = 0 50 while i < n { 51 if seq(cw[i] as *u8, to) == 1 { 52 if ck[i] == 0 { if sc_from_match(cf[i] as *u8, from, fromctx) == 1 { return 0 } } 53 } 54 i = i + 1 55 } 56 // pass 2: any covering allow 57 i = 0 58 while i < n { 59 if seq(cw[i] as *u8, to) == 1 { 60 if ck[i] == 1 { 61 if sc_from_match(cf[i] as *u8, from, fromctx) == 1 { 62 let sc: *u8 = cs[i] as *u8 63 if seq(sc, "*" as *u8) == 1 { return 1 } 64 if seq(sc, itype) == 1 { return 1 } 65 } 66 } 67 } 68 i = i + 1 69 } 70 // deny by default 71 return 0 72} 73// intro third-party consent: the SUBJECT must hold a standing allow with scope "intro" 74func sc_intro_ok(pol: *i64, subject: *u8) -> i64 { 75 let cw: *i64 = pol[0] as *i64 76 let ck: *i64 = pol[2] as *i64 77 let cs: *i64 = pol[3] as *i64 78 let n: i64 = pol[4] 79 var i: i64 = 0 80 while i < n { 81 if seq(cw[i] as *u8, subject) == 1 { 82 if ck[i] == 1 { if seq(cs[i] as *u8, "intro" as *u8) == 1 { return 1 } } 83 } 84 i = i + 1 85 } 86 return 0 87} 88func sc_say(label: *u8, got: i64, want: i64) -> i64 { 89 p(" SHARE-CONSENT " as *u8); p(label) 90 if got == 1 { p(" -> ALLOW" as *u8) } else { p(" -> DENY" as *u8) } 91 if got == want { p("\n" as *u8); return 1 } 92 p(" (WRONG)\n" as *u8) 93 return 0 94} 95 96func main() -> i64 { 97 p("=== NX-SHARE-CONSENT SELFTEST (deny-by-default; blocks outrank; scoped; INTRO needs the SUBJECT's consent) ===\n" as *u8) 98 var ok: i64 = 1 99 // Emma's policy: professional contacts may share JOBS; Dana may share anything; Spam Sam is blocked. 100 // Priya starts WITHOUT intro consent. 101 let cw: *i64 = sys_mmap(8 * 8) as *i64 102 let cf: *i64 = sys_mmap(8 * 8) as *i64 103 let ck: *i64 = sys_mmap(8 * 8) as *i64 104 let cs: *i64 = sys_mmap(8 * 8) as *i64 105 cw[0]="Emma" as *u8 as i64; cf[0]="ctx:professional" as *u8 as i64; ck[0]=1; cs[0]="job" as *u8 as i64 106 cw[1]="Emma" as *u8 as i64; cf[1]="Dana" as *u8 as i64; ck[1]=1; cs[1]="*" as *u8 as i64 107 cw[2]="Emma" as *u8 as i64; cf[2]="Spam Sam" as *u8 as i64; ck[2]=0; cs[2]="*" as *u8 as i64 108 let pol: *i64 = sys_mmap(8 * 8) as *i64 109 pol[0]=cw as i64; pol[1]=cf as i64; pol[2]=ck as i64; pol[3]=cs as i64; pol[4]=3 110 111 if sc_say("Marcus(professional) shares JOB to Emma" as *u8, sc_check(pol, "Marcus" as *u8, "Emma" as *u8, "job" as *u8, "professional" as *u8), 1) == 0 { ok = 0 } 112 if sc_say("Marcus(professional) shares RESOURCE (scope=job only)" as *u8, sc_check(pol, "Marcus" as *u8, "Emma" as *u8, "resource" as *u8, "professional" as *u8), 0) == 0 { ok = 0 } 113 if sc_say("Dana shares RESOURCE (person-allow, scope *)" as *u8, sc_check(pol, "Dana" as *u8, "Emma" as *u8, "resource" as *u8, "personal" as *u8), 1) == 0 { ok = 0 } 114 if sc_say("Spam Sam(professional) shares JOB -- BLOCK outranks context-allow" as *u8, sc_check(pol, "Spam Sam" as *u8, "Emma" as *u8, "job" as *u8, "professional" as *u8), 0) == 0 { ok = 0 } 115 if sc_say("stranger Zed(community), no record -- default" as *u8, sc_check(pol, "Zed" as *u8, "Emma" as *u8, "job" as *u8, "community" as *u8), 0) == 0 { ok = 0 } 116 117 // intro: recipient consent (Dana->Emma ok) is NOT enough -- Priya (the subject) must consent too 118 let rec_ok: i64 = sc_check(pol, "Dana" as *u8, "Emma" as *u8, "intro" as *u8, "personal" as *u8) 119 let sub1: i64 = sc_intro_ok(pol, "Priya" as *u8) 120 p(" SHARE-CONSENT intro Dana->Emma about Priya: recipient=" as *u8); pn(rec_ok); p(" subject-consent=" as *u8); pn(sub1); p(" -> DENY (third party has not consented)\n" as *u8) 121 if rec_ok != 1 { ok = 0 } 122 if sub1 != 0 { ok = 0 } 123 // Priya grants standing intro consent -> now both sides say yes 124 cw[3]="Priya" as *u8 as i64; cf[3]="*" as *u8 as i64; ck[3]=1; cs[3]="intro" as *u8 as i64 125 pol[4]=4 126 let sub2: i64 = sc_intro_ok(pol, "Priya" as *u8) 127 p(" SHARE-CONSENT after Priya's standing intro-consent: subject-consent=" as *u8); pn(sub2); p(" -> ALLOW\n" as *u8) 128 if sub2 != 1 { ok = 0 } 129 130 p("NX-SHARE-CONSENT-SELFTEST checks=7 " as *u8) 131 if ok == 1 { p("verdict=GREEN (privacy by default: no consent, no share; intros need BOTH sides)\n" as *u8); return 0 } 132 p("verdict=RED\n" as *u8) 133 return 1 134}