code wiki / _hdl_build / nx_legal_portal_boot_gate.nx
nx_legal_portal_boot_gate.nx source
↩ module page · 209 lines · 9942 B
1// nx_legal_portal_boot_gate.nx -- GATE for LEGAL D8 (nx_legal_portal_boot), ENGINEER verify.
2//
3// Proves the portal's tenant state SURVIVES A REBOOT: build a pctx with a SENT
4// 1-of-2-signed envelope (real Ed25519 seal) + a vault doc + a pending checklist,
5// persist it, then RELOAD into FRESH arrays (the restart) and serve through the
6// real lp_handle router -- the persisted state must reappear. Each with a control:
7// T1 ENVELOPES SURVIVE : after reload, GET /portal/envelopes -> "env 9601 status SENT" + "of 2"
8// T2 SIGNATURES SURVIVE : GET /portal/status?env=9601 -> "SENT" + "signed 1 of 2"
9// T3 CHECKLIST SURVIVES : GET /portal/checklist?doc=8601 -> "remaining 1"
10// T4 NEG no-load : a fresh pctx with NO reload shows NO envelope (the reload is what restored it)
11// T5 FIRST-BOOT clean : loading a tenant with NO files -> empty (env_count 0), not garbage
12//
13// Evidence -> knowledge/status/legal_portal_boot.log
14// license_tier: ORIGINAL
15import "nx_legal_portal_boot.nx"
16import "nx_legal_portal.nx"
17import "nx_doc_envelope.nx"
18import "nx_doc_annotate.nx"
19import "nx_doc_vault.nx"
20import "nx_doc_seal.nx"
21import "nx_legal_store.nx"
22import "nx_legal_compliance.nx"
23import "nx_syscalls.nx"
24
25const LPB_LOG: *u8 = "knowledge/status/legal_portal_boot.log"
26const LPB_BASE: *u8 = "/tmp/nx_lpb_"
27
28func ew(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 }
29func ewn(fd: i64, v: i64) -> i64 {
30 let bb: *u8 = sys_mmap(28); var m: i64 = v
31 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
32 let t: *u8 = sys_mmap(28); var k: i64 = 0
33 if m == 0 { t[0] = 48; k = 1 }
34 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
35 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
36 sys_write(fd, bb, k); return 0
37}
38func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
39func g_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o + i] = s[i]; i = i + 1 } return o + i }
40func g_starts(buf: *u8, n: i64, s: *u8) -> i64 {
41 let sn: i64 = slen(s)
42 if n < sn { return 0 }
43 var i: i64 = 0
44 while i < sn { if buf[i] != s[i] { return 0 } i = i + 1 }
45 return 1
46}
47func g_contains(hay: *u8, n: i64, needle: *u8) -> i64 {
48 let nn: i64 = slen(needle)
49 if nn == 0 { return 1 }
50 var i: i64 = 0
51 while i + nn <= n {
52 var m: i64 = 1
53 var j: i64 = 0
54 while j < nn { if hay[i + j] != needle[j] { m = 0; break } j = j + 1 }
55 if m == 1 { return 1 }
56 i = i + 1
57 }
58 return 0
59}
60func mk_seal(s: *NxSeal, dt: i64, ewills: i64, signer: *u8, ts: i64,
61 intent: i64, consent: i64, attribution: i64, retainable: i64,
62 witnesses: i64, notarized: i64) -> i64 {
63 s.doc_type = dt; s.e_wills_allowed = ewills
64 s.intent = intent; s.consent = consent; s.attribution = attribution
65 s.retainable = retainable; s.witnesses = witnesses; s.notarized = notarized
66 s.signer_id = signer; s.signer_id_len = slen(signer); s.ts = ts
67 return nx_seal_create(s)
68}
69
70func main() -> i64 {
71 var ok: i64 = 1
72
73 // ---- RFC 8032 test-1 keypair ----
74 let priv: *u8 = sys_mmap(64)
75 priv[0]=0x9d; priv[1]=0x61; priv[2]=0xb1; priv[3]=0x9d; priv[4]=0xef; priv[5]=0xfd; priv[6]=0x5a; priv[7]=0x60
76 priv[8]=0xba; priv[9]=0x84; priv[10]=0x4a; priv[11]=0xf4; priv[12]=0x92; priv[13]=0xec; priv[14]=0x2c; priv[15]=0xc4
77 priv[16]=0x44; priv[17]=0x49; priv[18]=0xc5; priv[19]=0x69; priv[20]=0x7b; priv[21]=0x32; priv[22]=0x69; priv[23]=0x19
78 priv[24]=0x70; priv[25]=0x3b; priv[26]=0xac; priv[27]=0x03; priv[28]=0x1c; priv[29]=0xae; priv[30]=0x7f; priv[31]=0x60
79 let pub: *u8 = sys_mmap(64)
80 pub[0]=0xd7; pub[1]=0x5a; pub[2]=0x98; pub[3]=0x01; pub[4]=0x82; pub[5]=0xb1; pub[6]=0x0a; pub[7]=0xb7
81 pub[8]=0xd5; pub[9]=0x4b; pub[10]=0xfe; pub[11]=0xd3; pub[12]=0xc9; pub[13]=0x64; pub[14]=0x07; pub[15]=0x3a
82 pub[16]=0x0e; pub[17]=0xe1; pub[18]=0x72; pub[19]=0xf3; pub[20]=0xda; pub[21]=0xa6; pub[22]=0x23; pub[23]=0x25
83 pub[24]=0xaf; pub[25]=0x02; pub[26]=0x1a; pub[27]=0x68; pub[28]=0xf7; pub[29]=0x07; pub[30]=0x51; pub[31]=0x1a
84 let dh: *u8 = sys_mmap(64)
85 var di: i64 = 0
86 while di < 32 { dh[di] = ((di * 7 + 3) & 0xff) as u8; di = di + 1 }
87 let s: *NxSeal = sys_mmap(256) as *NxSeal
88 s.doc_hash = dh; s.doc_hash_len = 32; s.priv = priv; s.canon = sys_mmap(512); s.sig = sys_mmap(128)
89
90 let ecap: i64 = 8
91 let rcap: i64 = 16
92 let ncap: i64 = 8
93 let vcap: i64 = 8
94
95 // ======== build pctx1: SENT 1-of-2-signed envelope + vault doc + checklist ========
96 let eflat1: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64
97 let rflat1: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64
98 let anflat1: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64
99 let vflat1: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64
100 var ne: i64 = 0
101 var nr: i64 = 0
102 var na: i64 = 0
103 var vc: i64 = 0
104 ne = nx_env_create(eflat1, ne, ecap, 9601, 8601, "Services Agreement" as *u8, 1, 1000)
105 nr = nx_env_add_recipient(rflat1, nr, rcap, 9601, 101, ROLE_SIGNER, 1)
106 nr = nx_env_add_recipient(rflat1, nr, rcap, 9601, 102, ROLE_SIGNER, 2)
107 nx_env_send(eflat1, ne, rflat1, nr, 9601)
108 let cs: i64 = mk_seal(s, DT_CONTRACT, 1, "client1@andelinwest.com" as *u8, 1100, 1, 1, 1, 1, 0, 0)
109 nx_env_sign(eflat1, ne, rflat1, nr, 9601, 101, s, pub)
110 vc = nx_vault_add(vflat1, vc, vcap, 8601, 5001, 64, 1000)
111 na = nx_ann_add(anflat1, na, ncap, 0, 1, 8601, 1, AN_CHECK, 0, 700, ANF_REQUIRED, 1000)
112
113 let ctx1: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx
114 ctx1.eflat = eflat1; ctx1.ne = ne
115 ctx1.rflat = rflat1; ctx1.nr = nr
116 ctx1.anflat = anflat1; ctx1.na = na
117 ctx1.vflat = vflat1; ctx1.vc = vc
118
119 // ---- PERSIST, then RELOAD into FRESH arrays (the restart) ----
120 lp_boot_save(ctx1, LPB_BASE, "clientA" as *u8)
121 let eflat2: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64
122 let rflat2: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64
123 let anflat2: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64
124 let vflat2: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64
125 let eidbuf2: *i64 = sys_mmap(64) as *i64
126 let ctx2: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx
127 ctx2.user_level = 1
128 lp_boot_load(ctx2, LPB_BASE, "clientA" as *u8, eflat2, ecap, rflat2, rcap, anflat2, ncap, vflat2, vcap, eidbuf2)
129
130 let req: *u8 = sys_mmap(4096)
131 let out: *u8 = sys_mmap(16384)
132
133 // ---- T1: envelopes survive the reboot ----
134 var t1: i64 = 1
135 var rn: i64 = g_cat(req, 0, "GET /portal/envelopes HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
136 var on: i64 = lp_handle(ctx2, req, rn, out)
137 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t1 = 0 }
138 if g_contains(out, on, "env 9601 status SENT" as *u8) != 1 { t1 = 0 }
139 if g_contains(out, on, "of 2" as *u8) != 1 { t1 = 0 }
140 if t1 != 1 { ok = 0 }
141
142 // ---- T2: signatures survive (signed 1 of 2) ----
143 var t2: i64 = 1
144 rn = g_cat(req, 0, "GET /portal/status?env=9601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
145 on = lp_handle(ctx2, req, rn, out)
146 if g_contains(out, on, "status SENT" as *u8) != 1 { t2 = 0 }
147 if g_contains(out, on, "signed 1 of 2" as *u8) != 1 { t2 = 0 }
148 if t2 != 1 { ok = 0 }
149
150 // ---- T3: checklist survives ----
151 var t3: i64 = 1
152 rn = g_cat(req, 0, "GET /portal/checklist?doc=8601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
153 on = lp_handle(ctx2, req, rn, out)
154 if g_contains(out, on, "remaining 1 NOT_READY" as *u8) != 1 { t3 = 0 }
155 if t3 != 1 { ok = 0 }
156
157 // ---- T4: NEG control -- a fresh pctx with NO reload shows no envelope ----
158 var t4: i64 = 1
159 let eflat3: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64
160 let rflat3: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64
161 let anflat3: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64
162 let vflat3: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64
163 let eidbuf3: *i64 = sys_mmap(64) as *i64
164 let ctx3: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx
165 ctx3.user_level = 1
166 ctx3.eflat = eflat3; ctx3.ne = 0
167 ctx3.rflat = rflat3; ctx3.nr = 0
168 ctx3.anflat = anflat3; ctx3.na = 0
169 ctx3.vflat = vflat3; ctx3.vc = 0
170 ctx3.env_ids = eidbuf3; ctx3.env_count = 0
171 rn = g_cat(req, 0, "GET /portal/envelopes HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
172 on = lp_handle(ctx3, req, rn, out)
173 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t4 = 0 }
174 if g_contains(out, on, "9601" as *u8) != 0 { t4 = 0 } // must NOT contain it (not loaded)
175 if t4 != 1 { ok = 0 }
176
177 // ---- T5: first boot for a tenant with NO files -> clean empty ----
178 var t5: i64 = 1
179 let ctx4: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx
180 ctx4.user_level = 1
181 lp_boot_load(ctx4, LPB_BASE, "freshtenant" as *u8, eflat3, ecap, rflat3, rcap, anflat3, ncap, vflat3, vcap, eidbuf3)
182 if ctx4.env_count != 0 { t5 = 0 }
183 if ctx4.ne != 0 { t5 = 0 }
184 rn = g_cat(req, 0, "GET /portal/envelopes HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
185 on = lp_handle(ctx4, req, rn, out)
186 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t5 = 0 }
187 if g_contains(out, on, "9601" as *u8) != 0 { t5 = 0 }
188 if t5 != 1 { ok = 0 }
189
190 // ---- evidence ----
191 var fd: i64 = 1
192 while fd >= 1 {
193 ew(fd, "LEGALPORTALBOOTGATE authored=organ composes=D6+D7 envelopes_survive_reboot=" as *u8); ewn(fd, t1)
194 ew(fd, " signatures_survive=" as *u8); ewn(fd, t2)
195 ew(fd, " checklist_survives=" as *u8); ewn(fd, t3)
196 ew(fd, " neg_no_load_empty=" as *u8); ewn(fd, t4)
197 ew(fd, " first_boot_clean=" as *u8); ewn(fd, t5)
198 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) }
199 if fd == 1 {
200 let lf: i64 = sys_openat_append(LPB_LOG, 420)
201 if lf >= 1 { fd = lf } else { fd = 0 }
202 } else {
203 sys_close(fd); fd = 0
204 }
205 }
206
207 if ok == 1 { return 0 }
208 return 1
209}