nx_hr_access.nx source
↩ module page · 48 lines · 3239 B
1// nx_hr_access.nx -- the SHARED access adapter: resolve a no-cookie SESSION TOKEN to an HR level, so EVERY gated
2// surface (gallery, hub, torrent already does this) uses the ONE access SSOT (nx_hr) instead of its own flat/realm
3// gating. This is the mechanism the HR roadmap called for ("wire gallery/hub level resolution to HR"); it is ADDITIVE
4// -- a surface IMPORTS it and calls hac_gate(...) at its resource boundary, no surface daemon is rewritten here
5// (coordination-correct: provide the mechanism, the owning workstream adopts it).
6//
7// The chain (all sovereign): olg_whoami validates the Ed25519 no-cookie token -> the 32-byte user-id hash == the HR
8// cred_id (SHA-256(realm|||handle); verified) -> hr_resolve_level. DENY-BY-DEFAULT at every step: an invalid/expired
9// token, or a valid token for a user NOT enrolled in HR (authenticated but not authorized), or a suspended user, all
10// resolve to level 0. So AUTHENTICATION alone grants nothing -- HR is the authority. realm-agnostic (the token's uid
11// already encodes its realm), so one adapter serves every property.
12import "nx_opaque_login.nx" // olg_whoami + NxAuthContext + NX_MAUTH_OK
13import "nx_hr.nx" // hr_resolve_level / hr_hexenc
14import "nx_hr_admin.nx" // hra_is_superadmin
15import "nx_syscalls.nx"
16
17// validate the session token -> write the 64-hex user-id (== HR cred_id) to out_hex. returns its length (64) or 0
18// if the token is invalid/expired (deny). token = the base64 X-Nishi-Session value; tn its length; now = epoch sec.
19func hac_uid_hex(ctx: *NxAuthContext, token: *u8, tn: i64, now: i64, out_hex: *u8) -> i64 {
20 let uh: *u8 = sys_mmap(64); let uhn: *i64 = sys_mmap(16) as *i64
21 if olg_whoami(ctx, token, tn, now, uh, 64, uhn) != NX_MAUTH_OK { out_hex[0]=0 as u8; return 0 }
22 return hr_hexenc(uh, uhn[0], out_hex) // 2*32 = 64 hex chars
23}
24
25// THE access resolver: the session's HR level (0 if invalid token / not-enrolled / suspended -- deny-by-default).
26func hac_session_level(ctx: *NxAuthContext, token: *u8, tn: i64, now: i64, hr_store: *u8) -> i64 {
27 let hx: *u8 = sys_mmap(72)
28 let n: i64 = hac_uid_hex(ctx, token, tn, now, hx)
29 if n <= 0 { return 0 }
30 return hra_resolve_level(hr_store, hx, n) // cutover: seg_store-backed (was nx_hr TAB-log)
31}
32
33// 1 iff the session resolves to an ACTIVE superadmin (owner). Deny-by-default otherwise.
34func hac_session_is_super(ctx: *NxAuthContext, token: *u8, tn: i64, now: i64, hr_store: *u8) -> i64 {
35 let hx: *u8 = sys_mmap(72)
36 let n: i64 = hac_uid_hex(ctx, token, tn, now, hx)
37 if n <= 0 { return 0 }
38 return hra_is_superadmin(hr_store, hx, n)
39}
40
41// policy: does `level` meet the `required` minimum? (data-driven thresholds live in the caller, rule #11.)
42func hac_allows(level: i64, required: i64) -> i64 { if level >= required { return 1 } return 0 }
43
44// THE ONE-CALL GATE a surface puts at a resource boundary: 1 = serve, 0 = 401/403. required = the resource's
45// minimum level (e.g. 1 = any family member, 3 = owner-only). Fail-closed by construction.
46func hac_gate(ctx: *NxAuthContext, token: *u8, tn: i64, now: i64, hr_store: *u8, required: i64) -> i64 {
47 return hac_allows(hac_session_level(ctx, token, tn, now, hr_store), required)
48}