code wiki / _hdl_build / nx_hr_entitle_gate.nx
nx_hr_entitle_gate.nx source
↩ module page · 94 lines · 7705 B
1// nx_hr_entitle_gate.nx -- referee for SUPERUSER-BY-CONSTRUCTION entitlement resolution (nx_hr_entitle). PROVES:
2// * an ACTIVE owner (elderwesto, lvl 3) is entitled to EVERY line even though NONE are keyed to "elderwesto"
3// (auto-access to everything) ; a member (brad) gets only public("*") + own-handle lines (deny-by-default) ;
4// * THE BY-CONSTRUCTION / NO-DRIFT PROOF: append a brand-new resource -> the owner's count auto-increments with
5// ZERO edits to any grant, while the member's count is unchanged ; leak-checks: a member cannot see an
6// admin-keyed resource, and an INVITED (not-yet-active) owner gets NOTHING extra (superadmin requires active).
7// GREEN iff every row matches. Durable -> knowledge/status/hr_entitle_gate.log.
8import "nx_hr_entitle.nx"
9import "nx_g_puts_lib.nx"
10import "nx_hr_admin.nx"
11import "nx_hr.nx"
12import "nx_syscalls.nx"
13
14func g_num(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 }
15func 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 }
16func g_wn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; 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(fd,bb,k); return 0 }
17func gtrunc(path: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd>=0 { sys_close(fd) } return 0 }
18func g_mkpfx(base: *u8, ms: i64, out: *u8) -> i64 { var o: i64=0; while base[o]!=(0 as u8){out[o]=base[o];o=o+1} let t: *u8=sys_mmap(28); var m: i64=ms; 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 z: i64=k-1; while z>=0{out[o]=t[z];o=o+1;z=z-1} out[o]=0 as u8; return o }
19func g_writefile(path: *u8, s: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd<0 { return 1 } var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd, s, n); sys_close(fd); return 0 }
20func g_append(path: *u8, s: *u8) -> i64 { let fd: i64 = sys_openat_append(path, 0x1a4); if fd<0 { return 1 } var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd, s, n); sys_close(fd); return 0 }
21func g_contains(hay: *u8, hlen: i64, needle: *u8) -> i64 {
22 var nl: i64=0; while needle[nl]!=(0 as u8){nl=nl+1}
23 if nl==0 { return 1 }
24 var i: i64=0
25 while i+nl<=hlen { var j: i64=0; var ok: i64=1; while j<nl { if hay[i+j]!=needle[j]{ok=0;j=nl} else {j=j+1} } if ok==1 {return 1} i=i+1 }
26 return 0
27}
28func chk(got: i64, want: i64, label: *u8) -> i64 {
29 g_puts(" "); g_puts(label); g_puts(" got="); g_num(got); g_puts(" want="); g_num(want)
30 if got == want { g_puts(" PASS\n"); return 1 }
31 g_puts(" FAIL\n"); return 0
32}
33
34func main() -> i64 {
35 g_puts("=== NISHI HR ENTITLE GATE (superuser-by-construction: owner=auto-everything, no drift) ===\n" as *u8)
36 var pass: i64=0; var rows: i64=0
37 let hr: *u8 = sys_mmap(96); g_mkpfx("/tmp/nx_he_hr_" as *u8, sys_now_ms(), hr) // seg_store prefix (cutover)
38 let ent: *u8 = sys_mmap(96); g_mkpfx("/tmp/nx_he_ent_" as *u8, sys_now_ms(), ent) // entitlement seg_store (cutover)
39 let NR: *u8 = "nishi_site_admin" as *u8; let NRN: i64 = 16
40 let fam: *u8 = "andelin" as *u8
41
42 // HR roster: elderwesto active owner(3); brad active member(1); ghost INVITED owner(3) -- not yet active.
43 let cid: *u8 = sys_mmap(96)
44 hra_enroll(hr, NR, NRN, "elderwesto" as *u8, 10, HRA_LVL_OWNER, fam, 1000, "system" as *u8, cid)
45 hra_enroll(hr, NR, NRN, "brad" as *u8, 4, HRA_LVL_MEMBER, fam, 1000, "elderwesto" as *u8, cid)
46 hra_invite(hr, NR, NRN, "ghost" as *u8, 5, HRA_LVL_OWNER, fam, 1000, "elderwesto" as *u8, cid)
47
48 // entitlements: 2 public + 3 member-keyed + 1 admin-keyed("gallery", nobody's handle) = 6 lines. NONE keyed "elderwesto".
49 he_ent_put(ent, "*" as *u8, "Public Wiki" as *u8, "/wiki" as *u8)
50 he_ent_put(ent, "*" as *u8, "Family Video" as *u8, "/video" as *u8)
51 he_ent_put(ent, "brad" as *u8, "Brad Photos" as *u8, "/u/brad" as *u8)
52 he_ent_put(ent, "jensen" as *u8, "Jensen Photos" as *u8, "/u/jensen" as *u8)
53 he_ent_put(ent, "kelli" as *u8, "Kelli Photos" as *u8, "/u/kelli" as *u8)
54 he_ent_put(ent, "gallery" as *u8, "Gallery" as *u8, "/gallery" as *u8)
55
56 // owner sees ALL 6 (auto-everything) though zero lines are keyed to elderwesto
57 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "elderwesto" as *u8, 10, ent), 6, "owner elderwesto sees ALL 6 (auto-everything)" as *u8)
58 // member brad: public(2) + own(1) = 3
59 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "brad" as *u8, 4, ent), 3, "member brad sees 3 (public + own only)" as *u8)
60 // jensen not enrolled (unknown) -> not super -> public(2) + jensen-keyed(1) = 3
61 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "jensen" as *u8, 6, ent), 3, "unenrolled jensen sees 3 (no superadmin)" as *u8)
62 // stranger with no keyed line -> public only
63 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "stranger" as *u8, 8, ent), 2, "stranger sees 2 (public only, deny-by-default)" as *u8)
64 // INVITED owner ghost is NOT active -> NOT superadmin -> public only (must be active to be super)
65 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "ghost" as *u8, 5, ent), 2, "INVITED owner ghost sees 2 (superadmin requires ACTIVE)" as *u8)
66
67 // === THE BY-CONSTRUCTION / NO-DRIFT PROOF: add a brand-new resource; owner auto-sees it, member unchanged ===
68 he_ent_put(ent, "newapp" as *u8, "New App" as *u8, "/newapp" as *u8)
69 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "elderwesto" as *u8, 10, ent), 7, "ADD resource -> owner auto-sees it (6->7, ZERO grants edited)" as *u8)
70 rows=rows+1; pass=pass+chk(he_count_access(hr, NR, NRN, "brad" as *u8, 4, ent), 3, "ADD resource -> member brad UNCHANGED (3)" as *u8)
71
72 // emit shape + content
73 let ob: *u8 = sys_mmap(65536)
74 let lo: i64 = he_emit_access(hr, NR, NRN, "elderwesto" as *u8, 10, ent, ob, 65536)
75 rows=rows+1; pass=pass+chk(g_contains(ob, lo, "\"super\":1" as *u8), 1, "owner emit has super:1" as *u8)
76 rows=rows+1; pass=pass+chk(g_contains(ob, lo, "/newapp" as *u8), 1, "owner emit includes the NEW /newapp url" as *u8)
77 let ob2: *u8 = sys_mmap(65536)
78 let lo2: i64 = he_emit_access(hr, NR, NRN, "brad" as *u8, 4, ent, ob2, 65536)
79 rows=rows+1; pass=pass+chk(g_contains(ob2, lo2, "\"super\":0" as *u8), 1, "member emit has super:0" as *u8)
80 rows=rows+1; pass=pass+chk(g_contains(ob2, lo2, "/u/brad" as *u8), 1, "member emit includes own /u/brad" as *u8)
81 rows=rows+1; pass=pass+chk(g_contains(ob2, lo2, "/newapp" as *u8), 0, "member emit EXCLUDES /newapp (leak-check)" as *u8)
82 rows=rows+1; pass=pass+chk(g_contains(ob2, lo2, "/gallery" as *u8), 0, "member emit EXCLUDES admin /gallery (leak-check)" as *u8)
83
84 g_puts("----\nNISHI-HR-ENTITLE-GATE rows=" as *u8); g_num(rows); g_puts(" pass=" as *u8); g_num(pass)
85 if pass==rows { g_puts(" verdict=GREEN\n" as *u8) } else { g_puts(" verdict=RED\n" as *u8) }
86 let lg: i64=sys_openat_append("knowledge/status/hr_entitle_gate.log" as *u8, 0x1a4)
87 if lg>=0 {
88 g_w(lg, "NISHI-HR-ENTITLE-GATE rows=" as *u8); g_wn(lg, rows); g_w(lg, " pass=" as *u8); g_wn(lg, pass)
89 if pass==rows { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) }
90 sys_close(lg)
91 }
92 if pass==rows { sys_exit(0); return 0 }
93 sys_exit(1); return 1
94}