code wiki / _hdl_build / nx_portal_builder.nx
nx_portal_builder.nx source
↩ module page · 95 lines · 4753 B
1// nx_portal_builder.nx -- ADMIN-001 (CALLOUT-013): the admin-portal SHELL authoring tool. Reads the
2// module registry (knowledge/registry/modules.tsv) + a ROLE (argv[1]) and EMITS the role-filtered
3// portal page via the PROVEN nx_web_builder -- a WordPress-like portal showing ONLY the modules the
4// role may access (RBAC, same levels as roleaccess_gate). One tool authors the client /portal AND the
5// lawyer /admin from the SAME registry (data-driven, growable). Writes to knowledge/staging/media/
6// (PRIVATE behind login -- not public). Prints PORTALGATE role= modules= for the gate. license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_web_builder.nx"
9const PB_MAGIC_40000: i64 = 40000
10
11const PB_REG: *u8 = "knowledge/registry/modules.tsv"
12
13func pb_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
14func pb_putn(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;k=1}; while m>0 {t[k]=48+(m%10); 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 pb_read(path: *u8, buf: *u8, cap: i64) -> i64 {
16 let fd: i64 = sys_openat_rd(path)
17 if fd < 0 { return 0 - 1 }
18 var tot: i64 = 0
19 var r: i64 = 1
20 while r > 0 { let dst: *u8 = ((buf as i64) + tot) as *u8; r = sys_read(fd, dst, cap - tot); if r > 0 { tot = tot + r } }
21 sys_close(fd)
22 return tot
23}
24func pb_scan(buf: *u8, n: i64, start: i64, delim: i64) -> i64 { var i: i64 = start; var s: i64 = 1; while s == 1 { if i >= n { s = 0 } else { if buf[i] == (delim as u8) { s = 0 } else { i = i + 1 } } } return i }
25// role level from a word: pub->0 cli->1 law->2 (compare first 3 bytes)
26func pb_lvl(w: *u8) -> i64 {
27 if w[0] == (112 as u8) { return 0 } // p ublic
28 if w[0] == (99 as u8) { return 1 } // c lient
29 if w[0] == (108 as u8) { return 2 } // l awyer
30 return 0
31}
32
33func main(argc: i64, argv: *i64) -> i64 {
34 if argc < 2 { pb_puts("PORTALGATE verdict=REFUSED reason=usage:nx_portal_builder <role>\n" as *u8); return 2 }
35 let role: *u8 = argv[1] as *u8
36 let rl: i64 = pb_lvl(role)
37
38 let rb: *u8 = sys_mmap(PB_MAGIC_40000)
39 let rn: i64 = pb_read(PB_REG, rb, PB_MAGIC_40000)
40 if rn <= 0 { pb_puts("PORTALGATE verdict=REFUSED reason=registry-unreadable\n" as *u8); return 2 }
41
42 // output path knowledge/staging/media/portal_<role>.html
43 let outp: *u8 = sys_mmap(256)
44 var o: i64 = 0
45 let pre: *u8 = "knowledge/staging/media/portal_"
46 var j: i64 = 0; while pre[j] != (0 as u8) { outp[o] = pre[j]; o = o + 1; j = j + 1 }
47 j = 0; while role[j] != (0 as u8) { outp[o] = role[j]; o = o + 1; j = j + 1 }
48 let suf: *u8 = ".html"
49 j = 0; while suf[j] != (0 as u8) { outp[o] = suf[j]; o = o + 1; j = j + 1 }
50 outp[o] = 0 as u8
51
52 let fd: i64 = sys_openat_wr(outp, 420)
53 if fd < 0 { pb_puts("PORTALGATE verdict=REFUSED reason=out-unwritable\n" as *u8); return 2 }
54
55 wb_doc_open(fd, "Nishi Admin Portal" as *u8)
56 wb_header(fd, "Nishi Portal" as *u8, "Sign out" as *u8, "/wiki/logout" as *u8)
57 wb_cards_open(fd, "Your modules (behind login)" as *u8)
58
59 // walk modules.tsv; emit a card per module the role may access
60 var count: i64 = 0
61 var p: i64 = 0
62 while p < rn {
63 let a: i64 = p
64 let e: i64 = pb_scan(rb, rn, a, 10)
65 if rb[a] == (35 as u8) { p = e + 1 }
66 else { if a >= e { p = e + 1 }
67 else {
68 let t1: i64 = pb_scan(rb, rn, a, 9); rb[t1] = 0 as u8 // module
69 let r2: i64 = t1 + 1
70 let t2: i64 = pb_scan(rb, rn, r2, 9); rb[t2] = 0 as u8 // route
71 let r3: i64 = t2 + 1
72 let t3: i64 = pb_scan(rb, rn, r3, 9); rb[t3] = 0 as u8 // role_required
73 let r4: i64 = t3 + 1
74 let t4: i64 = pb_scan(rb, rn, r4, 9); rb[t4] = 0 as u8 // capability
75 let r5: i64 = t4 + 1
76 let t5: i64 = pb_scan(rb, rn, r5, 10); rb[t5] = 0 as u8 // desc
77 let modp: *u8 = ((rb as i64) + a) as *u8
78 let routep: *u8 = ((rb as i64) + r2) as *u8
79 let reqp: *u8 = ((rb as i64) + r3) as *u8
80 let descp: *u8 = ((rb as i64) + r5) as *u8
81 if rl >= pb_lvl(reqp) { wb_card(fd, modp, descp); count = count + 1 }
82 p = t5 + 1
83 } }
84 }
85 wb_cards_close(fd)
86 wb_footer(fd, "Nishi unified admin portal -- one portal across the family of sites, behind your login." as *u8)
87 wb_doc_close(fd)
88 sys_close(fd)
89
90 pb_puts("PORTALGATE role=" as *u8); pb_puts(role)
91 pb_puts(" modules=" as *u8); pb_putn(count)
92 pb_puts(" -> " as *u8); pb_puts(outp)
93 pb_puts(" verdict=GREEN\n" as *u8)
94 return 0
95}