nx_iot_hub_serve_realm.nx source
↩ module page · 75 lines · 3396 B
1// nx_iot_hub_serve_realm.nx -- rung-4-LIVE: the IoT hub serve, HR-SESSION-GATED per HOUSE (realm).
2//
3// Closes the killer-feature loop: a viewer opens GET /<house>/ in the Nishi browser with their
4// no-cookie OPAQUE session (X-Nishi-Session header); the hub resolves their HR level for that house
5// THROUGH the shared access spine (hac_session_level -> hra_resolve_level, the SAME SSOT torrent/
6// gallery use) and serves the house-scoped, tier-gated dashboard:
7// owner (lvl3) -> OWNER dashboard (control + /home/manage)
8// family (lvl1) -> FAMILY dashboard (control, no manage)
9// unenrolled / invalid / suspended / wrong-house -> DENIED (no devices, no controls)
10// Deny-by-default by construction (authentication != authorization). Composes the proven pieces --
11// nx_iot_hub_tenant (iot_tenant_render/iot_access_from_level) + nx_hr_access (hac_session_level) --
12// adding only the request glue: realm-from-path + token-from-header. No new auth/crypto. LAN-only,
13// zero-JS, no cloud at runtime. license_tier: ORIGINAL
14import "nx_iot_hub_tenant.nx"
15import "nx_hr_access.nx"
16
17// extract the house realm from the request path: "/westhouse" or "/westhouse/x" -> "westhouse".
18func iot_realm_from_path(req: *u8, poff: i64, plen: i64, out: *u8) -> i64 {
19 var i: i64 = poff
20 let end: i64 = poff + plen
21 if plen > 0 { if req[i] == (47 as u8) { i = i + 1 } } // skip leading '/'
22 var o: i64 = 0
23 var go: i64 = 1
24 while go == 1 {
25 if i >= end { go = 0 } else {
26 let c: i64 = req[i] as i64
27 if c == 47 { go = 0 } else { out[o] = req[i]; o = o + 1; i = i + 1 } // stop at next '/'
28 }
29 }
30 out[o] = 0 as u8
31 return o
32}
33
34// extract the X-Nishi-Session token value from the raw request headers (value to CRLF/LF). 0 if none.
35func iot_token_from_req(req: *u8, n: i64, out: *u8) -> i64 {
36 let key: *u8 = "X-Nishi-Session:" as *u8
37 let klen: i64 = 16
38 var i: i64 = 0
39 var found: i64 = 0 - 1
40 let lim: i64 = n - klen
41 while i <= lim {
42 if found == (0 - 1) {
43 var j: i64 = 0
44 var ok: i64 = 1
45 while j < klen { if req[i+j] != key[j] { ok = 0; j = klen } else { j = j + 1 } }
46 if ok == 1 { found = i + klen }
47 }
48 i = i + 1
49 }
50 if found == (0 - 1) { out[0] = 0 as u8; return 0 }
51 var p: i64 = found
52 var gs: i64 = 1
53 while gs == 1 { if p < n { if req[p] == (32 as u8) { p = p + 1 } else { gs = 0 } } else { gs = 0 } }
54 var o: i64 = 0
55 var gv: i64 = 1
56 while gv == 1 {
57 if p >= n { gv = 0 } else {
58 let c: i64 = req[p] as i64
59 if c == 13 { gv = 0 } else { if c == 10 { gv = 0 } else { out[o] = req[p]; o = o + 1; p = p + 1 } }
60 }
61 }
62 out[o] = 0 as u8
63 return o
64}
65
66// resolve a viewer's session to their IoT tier for this house's HR store (deny-by-default).
67func iot_hub_resolve_tier(ctx: *NxAuthContext, token: *u8, tn: i64, now: i64, hr_store: *u8) -> i64 {
68 return iot_access_from_level(hac_session_level(ctx, token, tn, now, hr_store))
69}
70
71// render the house-scoped dashboard gated by the session's tier; returns rendered length.
72func iot_hub_render_for(ctx: *NxAuthContext, token: *u8, tn: i64, now: i64,
73 realm_label: *u8, hr_store: *u8, h: *u8) -> i64 {
74 return iot_tenant_render(h, realm_label, iot_hub_resolve_tier(ctx, token, tn, now, hr_store))
75}