code wiki / _hdl_build / nx_hr_gate.nx
nx_hr_gate.nx source
↩ module page · 65 lines · 4904 B
1// nx_hr_gate.nx -- referee for NISHI HR (the S-class user-management SSOT). PROVES the lifecycle + deny-by-default:
2// enroll operator(3)+family(1) -> resolve 3 / 1 · unknown cred -> 0 (deny-by-default)
3// suspend family -> resolve 0 (LEAK-CHECK: a suspended user grants nothing) · set_role 1->3 -> resolve 3
4// hr_cred_id stable (provision-by-handle id == re-derived id) · append-only (history records > current users)
5// GREEN iff every row matches. Prints verdict=GREEN to STDOUT *and* returns the exit code.
6// Durable -> knowledge/status/hr_gate.log. license_tier: ORIGINAL
7import "nx_hr.nx"
8import "nx_g_puts_lib.nx"
9import "nx_syscalls.nx"
10
11func 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 }
12func 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 }
13func 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 }
14func gtrunc(path: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd>=0 { sys_close(fd) } return 0 }
15func g_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while 1==1 { let ca: i64=a[i] as i64; let cb: i64=b[i] as i64; if ca!=cb { return 0 } if ca==0 { return 1 } i=i+1 } return 1 }
16func chk(got: i64, want: i64, label: *u8) -> i64 {
17 g_puts(" "); g_puts(label); g_puts(" got="); g_num(got); g_puts(" want="); g_num(want)
18 if got == want { g_puts(" PASS\n"); return 1 }
19 g_puts(" FAIL\n"); return 0
20}
21
22func main() -> i64 {
23 g_puts("=== NISHI HR GATE (S-class user management: enroll/resolve/role/suspend, deny-by-default, append-only) ===\n" as *u8)
24 var pass: i64=0
25 var rows: i64=0
26 let store: *u8 = "/tmp/nx_hr_test" as *u8
27 let realm: *u8 = "nishi_hub_test" as *u8; let realm_n: i64 = 14
28 let fam: *u8 = "andelin" as *u8
29 let actor: *u8 = "operator" as *u8
30 gtrunc(store)
31
32 let cid_op: *u8 = sys_mmap(96); let cid_aunt: *u8 = sys_mmap(96)
33 rows=rows+1; pass=pass+chk(hr_enroll(store, realm, realm_n, "operator" as *u8, 8, 3, fam, 1000, actor, cid_op), 0, "enroll operator(3)" as *u8)
34 rows=rows+1; pass=pass+chk(hr_slen(cid_op), 64, " -> cred_id is 64-hex" as *u8)
35 rows=rows+1; pass=pass+chk(hr_enroll(store, realm, realm_n, "aunt" as *u8, 4, 1, fam, 1000, actor, cid_aunt), 0, "enroll aunt(1)" as *u8)
36
37 rows=rows+1; pass=pass+chk(hr_resolve_level(store, cid_op, 64), 3, "resolve operator -> 3" as *u8)
38 rows=rows+1; pass=pass+chk(hr_resolve_level(store, cid_aunt, 64), 1, "resolve aunt -> 1" as *u8)
39 rows=rows+1; pass=pass+chk(hr_resolve_level(store, "0000000000000000000000000000000000000000000000000000000000000000" as *u8, 64), 0, "resolve UNKNOWN -> 0 (deny-by-default)" as *u8)
40
41 rows=rows+1; pass=pass+chk(hr_suspend(store, cid_aunt, "aunt" as *u8, fam, 2000, actor), 0, "suspend aunt" as *u8)
42 rows=rows+1; pass=pass+chk(hr_resolve_level(store, cid_aunt, 64), 0, " -> resolve aunt -> 0 (SUSPENDED leak-check)" as *u8)
43 rows=rows+1; pass=pass+chk(hr_resolve_level(store, cid_op, 64), 3, " -> operator still 3 (others unaffected)" as *u8)
44
45 rows=rows+1; pass=pass+chk(hr_set_role(store, cid_aunt, "aunt" as *u8, 3, fam, 3000, actor), 0, "set_role aunt -> 3 (promote+reactivate)" as *u8)
46 rows=rows+1; pass=pass+chk(hr_resolve_level(store, cid_aunt, 64), 3, " -> resolve aunt -> 3 (role change live)" as *u8)
47
48 // stability: provision-by-handle derives the SAME id the runtime resolves (the SSOT correctness property)
49 let cid_op2: *u8 = sys_mmap(96); hr_cred_id(realm, realm_n, "operator" as *u8, 8, cid_op2)
50 rows=rows+1; pass=pass+chk(g_streq(cid_op, cid_op2), 1, "hr_cred_id STABLE (same handle -> same id)" as *u8)
51
52 // append-only: 2 enroll + 1 suspend + 1 set_role = 4 records preserved (history, not overwrite)
53 rows=rows+1; pass=pass+chk(hr_record_count(store), 4, "append-only: 4 history records preserved" as *u8)
54
55 g_puts("----\nNISHI-HR-GATE rows=" as *u8); g_num(rows); g_puts(" pass=" as *u8); g_num(pass)
56 if pass==rows { g_puts(" verdict=GREEN\n" as *u8) } else { g_puts(" verdict=RED\n" as *u8) }
57 let lg: i64=sys_openat_append("knowledge/status/hr_gate.log" as *u8, 0x1a4)
58 if lg>=0 {
59 g_w(lg, "NISHI-HR-GATE rows=" as *u8); g_wn(lg, rows); g_w(lg, " pass=" as *u8); g_wn(lg, pass)
60 if pass==rows { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) }
61 sys_close(lg)
62 }
63 if pass==rows { sys_exit(0); return 0 }
64 sys_exit(1); return 1
65}