code wiki / (root) / nx_hr.nx

nx_hr.nx source

↩ module page · 96 lines · 6822 B

1// nx_hr.nx -- NISHI HR: the S-class sovereign USER-MANAGEMENT structure (the access SSOT). Built ON the OPAQUE 2// identity: a user's primary key is the cred_id = lowercase-hex of SHA-256(realm|||handle) -- the STABLE per-realm 3// id, derivable from a handle WITHOUT a login (so the operator provisions people by handle). The directory is 4// APPEND-ONLY (CLAUDE.md #13 additive-only, DV2.0 satellite/is_current): every lifecycle event appends a record; 5// the LATEST record per cred_id is current. DENY-BY-DEFAULT: an unknown OR suspended user resolves to level 0. 6// History is preserved (audit + rollback). This REPLACES the hand-maintained flat roles TSV as the "granted 7// level" source for every gated surface (torrent, gallery, hub). Composes hub/nx_no_cookie_session (the id hash). 8// record: cred_id <TAB> handle <TAB> level <TAB> family <TAB> status <TAB> ts <TAB> actor \n 9// status: active | suspended level: 3=owner/operator, 1=family/member, 0=none license_tier: ORIGINAL 10import "hub/nx_no_cookie_session.nx" // nx_ncs_derive_user_id_hash + NX_NCS_OK 11import "nx_syscalls.nx" 12const HR_MAGIC_1048576: i64 = 1048576 13 14const HR_TAB: i64 = 9 15const HR_NL: i64 = 10 16 17func hr_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 18func hr_puts(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[o+i]=s[i]; i=i+1 } return o+i } 19func hr_putn(dst: *u8, o: i64, v: i64) -> i64 { if v==0 { dst[o]=48 as u8; return o+1 } var m: i64=v; if m<0{m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{dst[o+j]=t[k-1-j];j=j+1} return o+k } 20func hr_read(path: *u8, buf: *u8, cap: i64) -> i64 { let fd: i64=sys_openat_rd(path); if fd<0 {return 0} var off: i64=0; var go: i64=1; while go==1 { if off>=cap {go=0} else { let r: i64=sys_read(fd, buf+off, cap-off); if r<=0 {go=0} else {off=off+r} } } sys_close(fd); return off } 21 22// lowercase-hex encode in[0..n) -> out (NUL-term). returns 2n. (local-bound const = no nx_cc const-index crash) 23func hr_hexenc(inp: *u8, n: i64, out: *u8) -> i64 { 24 let hx: *u8 = "0123456789abcdef" as *u8 25 var i: i64=0 26 while i<n { out[i*2]=hx[((inp[i] as i64)>>4)&15]; out[i*2+1]=hx[(inp[i] as i64)&15]; i=i+1 } 27 out[n*2]=0 as u8; return n*2 28} 29// the stable credential-id (64-hex) for (realm, handle) -- the HR primary key, derivable WITHOUT login. 30func hr_cred_id(realm: *u8, realm_n: i64, handle: *u8, hn: i64, out_hex: *u8) -> i64 { 31 let uid: *u8 = sys_mmap(32) 32 if nx_ncs_derive_user_id_hash(realm, realm_n, handle, hn, uid) != NX_NCS_OK { out_hex[0]=0 as u8; return 0 } 33 return hr_hexenc(uid, 32, out_hex) 34} 35 36// append ONE directory record (atomic O_APPEND -- never clobbers history; concurrent appends can't lose a record). 37func hr_append(store: *u8, cred_id: *u8, handle: *u8, level: i64, family: *u8, status_active: i64, ts: i64, actor: *u8) -> i64 { 38 let line: *u8 = sys_mmap(640); var o: i64 = 0 39 o = hr_puts(line, o, cred_id); line[o]=HR_TAB as u8; o=o+1 40 o = hr_puts(line, o, handle); line[o]=HR_TAB as u8; o=o+1 41 o = hr_putn(line, o, level); line[o]=HR_TAB as u8; o=o+1 42 o = hr_puts(line, o, family); line[o]=HR_TAB as u8; o=o+1 43 if status_active==1 { o=hr_puts(line, o, "active" as *u8) } else { o=hr_puts(line, o, "suspended" as *u8) } 44 line[o]=HR_TAB as u8; o=o+1 45 o = hr_putn(line, o, ts); line[o]=HR_TAB as u8; o=o+1 46 o = hr_puts(line, o, actor); line[o]=HR_NL as u8; o=o+1 47 let fd: i64 = __syscall(SYS_OPENAT, AT_FDCWD, store as i64, O_WRONLY_CA, 0x1a4, 0, 0) // O_WRONLY|O_CREAT|O_APPEND 48 if fd < 0 { return 0 - 1 } 49 sys_write(fd, line, o); sys_close(fd) 50 return 0 51} 52 53// ENROLL a user by handle (derives cred_id, writes it to out_hex). returns 0 ok. 54func hr_enroll(store: *u8, realm: *u8, realm_n: i64, handle: *u8, hn: i64, level: i64, family: *u8, ts: i64, actor: *u8, out_hex: *u8) -> i64 { 55 if hr_cred_id(realm, realm_n, handle, hn, out_hex) <= 0 { return 1 } 56 return hr_append(store, out_hex, handle, level, family, 1, ts, actor) 57} 58// lifecycle changes = append an updated record for an existing cred_id (history preserved). 59func hr_set_role(store: *u8, cred_id: *u8, handle: *u8, level: i64, family: *u8, ts: i64, actor: *u8) -> i64 { return hr_append(store, cred_id, handle, level, family, 1, ts, actor) } 60func hr_suspend(store: *u8, cred_id: *u8, handle: *u8, family: *u8, ts: i64, actor: *u8) -> i64 { return hr_append(store, cred_id, handle, 0, family, 0, ts, actor) } 61 62// index of the next TAB at or after `start` (capped at `le`); flat helper to avoid deep nested loops. 63func hr_field_end(buf: *u8, start: i64, le: i64) -> i64 { var e: i64=start; while e<le { if buf[e]==(HR_TAB as u8) { return e } e=e+1 } return le } 64func hr_line_end(buf: *u8, start: i64, n: i64) -> i64 { var e: i64=start; while e<n { if buf[e]==(HR_NL as u8) { return e } e=e+1 } return n } 65func hr_eqrange(buf: *u8, s: i64, e: i64, lit: *u8, litn: i64) -> i64 { if (e-s)!=litn { return 0 } var k: i64=0; while k<litn { if buf[s+k]!=lit[k] { return 0 } k=k+1 } return 1 } 66func hr_intrange(buf: *u8, s: i64, e: i64) -> i64 { var v: i64=0; var q: i64=s; while q<e { let c: i64=buf[q] as i64; if c>=48 { if c<=57 { v=v*10+(c-48); q=q+1 } else { q=e } } else { q=e } } return v } 67 68// THE RESOLVER (the access SSOT): the LATEST record for cred_id; its level if status=active, else 0. Unknown 69// cred_id or suspended -> 0 (DENY-BY-DEFAULT). Scans append-only so the last matching line = current state. 70func hr_resolve_level(store: *u8, cred_id: *u8, cidlen: i64) -> i64 { 71 let buf: *u8 = sys_mmap(HR_MAGIC_1048576); let n: i64 = hr_read(store, buf, HR_MAGIC_1048576) 72 if n <= 0 { return 0 } 73 var level: i64 = 0 74 var i: i64 = 0 75 while i < n { 76 let le: i64 = hr_line_end(buf, i, n) 77 let f0e: i64 = hr_field_end(buf, i, le) // cred_id 78 if hr_eqrange(buf, i, f0e, cred_id, cidlen) == 1 { 79 let f1e: i64 = hr_field_end(buf, f0e+1, le) // handle 80 let f2s: i64 = f1e+1; let f2e: i64 = hr_field_end(buf, f2s, le) // level 81 let f3e: i64 = hr_field_end(buf, f2e+1, le) // family 82 let f4s: i64 = f3e+1; let f4e: i64 = hr_field_end(buf, f4s, le) // status 83 if hr_eqrange(buf, f4s, f4e, "active" as *u8, 6) == 1 { level = hr_intrange(buf, f2s, f2e) } else { level = 0 } 84 } 85 i = le + 1 86 } 87 return level 88} 89 90// count records in the directory (audit: history length, incl. superseded records -- proves append-only). 91func hr_record_count(store: *u8) -> i64 { 92 let buf: *u8 = sys_mmap(HR_MAGIC_1048576); let n: i64 = hr_read(store, buf, HR_MAGIC_1048576) 93 var c: i64 = 0; var i: i64 = 0 94 while i < n { if buf[i]==(HR_NL as u8) { c=c+1 } i=i+1 } 95 return c 96}