code wiki / _hdl_build / nx_connect_wards.nx

nx_connect_wards.nx source

↩ module page · 109 lines · 6434 B

1// nx_connect_wards.nx -- Enforces community-only boundaries in ward groups by checking field classes and consent gates. 2// nx_connect_wards.nx -- CONNECT / LDS vertical: WARD & BRANCH COMMUNITY groups (the LC census cell). 3// COMMUNITY layer ONLY -- never congregation administration, never proselytizing (the parent vision's 4// hard boundary). That boundary is enforced BY CONSTRUCTION, not by promise: 5// - the group schema's FIELD REGISTRY is data (rule 11); a checker scans it and REFUSES any 6// congregation-admin field class (calling / membership record / attendance / ordinance / donation). 7// NEG-CONTROL: an incumbent-style ward-admin model WITH an attendance field is FLAGGED by the SAME 8// checker -- proving the boundary is load-bearing. 9// - joining a ward COMMUNITY group is faith-revealing, so it REQUIRES the member's explicit faith 10// consent (GDPR Art.9 idiom from nx_connect_graph): no consent -> join refused, and a non-joined 11// member never appears in any roster render. 12// - youth channels inside a ward group compose the two-deep wall (>=2 adults) -- same invariant as 13// nx_connect_lds_room / nx_connect_events. 14// - joins are IDEMPOTENT (rule 10). 15// 100% sovereign. license_tier: ORIGINAL expect_exit: 0 16// 2026-07-23 LIBRARY SPLIT: the registry checker, the consent-gated join and the youth-channel rule moved 17// to nx_connect_wards_lib.nx so THIS gate and the LIVE app (nx_connect_serve /community) bind ONE 18// implementation. Before the split the live page only ASSERTED the community-only boundary in prose while 19// nothing enforced it. This file is now purely the VERIFIER; its output is byte-identical to the pre-split 20// version, which proves the extraction changed no behavior. 21import "nx_syscalls.nx" 22import "nx_connect_wards_lib.nx" 23 24func sw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 25func sn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;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(1,bb,k); return 0 } 26func tcheck(pass: i64, label: *u8, fails: *i64) -> i64 { 27 sw(" " as *u8); sw(label); sw(": " as *u8) 28 if pass==1 { sw("PASS\n" as *u8) } else { sw("FAIL\n" as *u8); fails[0]=fails[0]+1 } 29 return 0 30} 31 32func main() -> i64 { 33 let fails: *i64 = sys_mmap(16) as *i64 34 fails[0]=0 35 sw("=== nx_connect_wards -- ward/branch COMMUNITY groups (community-only boundary BY CONSTRUCTION) ===\n" as *u8) 36 37 // OUR ward-community group schema field registry (data): name|class 38 // fields: unit_locality(0) display_name(0) member_list(0) youth_channel_flag(0) event_link(0) 39 let our_classes: *i64 = sys_mmap(FR_MAX*8) as *i64 40 our_classes[0]=0; our_classes[1]=0; our_classes[2]=0; our_classes[3]=0; our_classes[4]=0 41 let our_n: i64 = 5 42 let our_forbidden: i64 = wd_forbidden_count(our_classes, our_n) 43 44 // NEG incumbent-style ward-ADMIN model: adds attendance(3) + calling(1) + donation(5) fields 45 let adm_classes: *i64 = sys_mmap(FR_MAX*8) as *i64 46 adm_classes[0]=0; adm_classes[1]=0; adm_classes[2]=3; adm_classes[3]=1; adm_classes[4]=5 47 let adm_forbidden: i64 = wd_forbidden_count(adm_classes, 5) 48 49 // T1: our schema passes the community-only field census (0 forbidden classes) 50 var t1: i64=0; if our_forbidden==0 { t1=1 } 51 sw(" our schema forbidden-fields=" as *u8); sn(our_forbidden) 52 sw(" admin-model forbidden-fields=" as *u8); sn(adm_forbidden); sw("\n" as *u8) 53 tcheck(t1, "T1 community-only schema: zero congregation-admin field classes" as *u8, fails) 54 55 // T2: NEG-CONTROL -- the congregation-admin model is FLAGGED by the same checker 56 var t2: i64=0; if adm_forbidden==3 { t2=1 } 57 tcheck(t2, "T2 NEG-CONTROL admin model (attendance+calling+donation) flagged by the same checker" as *u8, fails) 58 59 // membership world: ward 71 (a ward community), users 1..3 (consented), 4 (NO faith consent) 60 let mw: *i64 = sys_mmap(WM_MAX*8) as *i64 61 let mu: *i64 = sys_mmap(WM_MAX*8) as *i64 62 let nm: *i64 = sys_mmap(8) as *i64 63 nm[0]=0 64 65 // T3: consented joins work; join is idempotent 66 let j1: i64 = wd_join(mw, mu, nm, 71, 1, 1) 67 let j2: i64 = wd_join(mw, mu, nm, 71, 2, 1) 68 let j1b: i64 = wd_join(mw, mu, nm, 71, 1, 1) 69 var t3: i64=0 70 if j1==1 { if j2==1 { if j1b==2 { if nm[0]==2 { t3=1 } } } } 71 tcheck(t3, "T3 consented joins; repeat join idempotent (roster unchanged)" as *u8, fails) 72 73 // T4: NO faith consent -> join REFUSED (Art.9: ward membership is faith-revealing) 74 let j4: i64 = wd_join(mw, mu, nm, 71, 4, 0) 75 var t4: i64=0 76 if j4==(0-1) { if wd_in(mw, mu, nm, 71, 4)==0 { t4=1 } } 77 tcheck(t4, "T4 join without explicit faith consent refused; user never appears in roster" as *u8, fails) 78 79 // T5: roster render lists ONLY joined members (the non-consenting user is invisible) 80 var count71: i64=0 81 var i: i64=0 82 while i<nm[0] { if mw[i]==71 { count71=count71+1 } i=i+1 } 83 var t5: i64=0 84 if count71==2 { if wd_in(mw, mu, nm, 71, 3)==0 { t5=1 } } 85 tcheck(t5, "T5 roster = joined members only (2); non-members invisible" as *u8, fails) 86 87 // T6: youth channel inside the ward group composes the two-deep wall 88 let y1: i64 = wd_youth_channel_ok(1) 89 let y2: i64 = wd_youth_channel_ok(2) 90 var t6: i64=0 91 if y1==0 { if y2==1 { t6=1 } } 92 tcheck(t6, "T6 ward youth channel requires two-deep (1 adult denied, 2 allowed)" as *u8, fails) 93 94 // T7: the boundary is DATA (rule 11): adding a proposed field is a registry row the checker 95 // re-validates -- a proposed 'home_teaching_report' (class 2) is refused before it ever ships. 96 let prop_classes: *i64 = sys_mmap(FR_MAX*8) as *i64 97 var k: i64=0 98 while k<our_n { prop_classes[k]=our_classes[k]; k=k+1 } 99 prop_classes[our_n]=2 100 let prop_forbidden: i64 = wd_forbidden_count(prop_classes, our_n+1) 101 var t7: i64=0; if prop_forbidden==1 { t7=1 } 102 tcheck(t7, "T7 proposed record-class field refused by the registry checker (boundary is data)" as *u8, fails) 103 104 sw(" fails=" as *u8); sn(fails[0]); sw("\n" as *u8) 105 if fails[0]==0 { sw("VERDICT: GREEN (ward COMMUNITY groups: community-only by construction, Art.9 consent, two-deep youth)\n" as *u8); sys_exit(0) } 106 sw("VERDICT: RED\n" as *u8) 107 sys_exit(1) 108 return 1 109}