code wiki / _hdl_build / nx_legal_portal_gate.nx
nx_legal_portal_gate.nx source
↩ module page · 243 lines · 11757 B
1// nx_legal_portal_gate.nx -- GATE for LEGAL D6 (nx_legal_portal).
2//
3// SOVEREIGN in-process referee (the nx_status_daemon_gate pattern): NO socket,
4// NO curl, NO shell. It builds one tenant's real workflow stores (a SENT contract
5// with 1-of-2 signed via a REAL Ed25519 seal, a Will refused into REQUIRES_WET, a
6// vault doc, a pending checklist), then feeds crafted HTTP request BYTES straight
7// into lp_handle and asserts the response bytes -- proving the portal composes
8// D0/D1/D2/D3/D4 + nx_authz + tenant isolation. Each test has a negative control:
9// T1 GET /portal/envelopes -> 200 + both envelopes + their statuses
10// T2 GET /portal/status?env=C -> 200 + SENT + UETA_GENERAL + "1 of 2"
11// T3 GET /portal/doc?id=V -> 200 + application/pdf + BYTE-EXACT body (D3)
12// T4 GET /portal/doc?id=bogus -> 404 (tenant vault does not own it)
13// T5 GET /staff/matters -> 403 as client(lvl1) / 200 as lawyer(lvl2)
14// T6 GET /portal/status?env=W -> 200 + REQUIRES_WET + "wet signature required"
15// (never-void SURFACED, not silently signable)
16// T7 GET /portal/checklist?doc=V-> 200 + "remaining 1 NOT_READY"; /portal/bogus -> 404
17//
18// Evidence -> knowledge/status/legal_portal.log
19// license_tier: ORIGINAL
20import "nx_legal_portal.nx"
21import "nx_doc_envelope.nx"
22import "nx_doc_serve.nx"
23import "nx_doc_annotate.nx"
24import "nx_doc_vault.nx"
25import "nx_doc_seal.nx"
26import "nx_legal_compliance.nx"
27import "nx_syscalls.nx"
28import "nx_gate_verdict.nx"
29
30const LP_LOG: *u8 = "knowledge/status/legal_portal.log"
31
32func 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 }
33func ewn(fd: i64, v: i64) -> i64 {
34 let bb: *u8 = sys_mmap(28); var m: i64 = v
35 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
36 let t: *u8 = sys_mmap(28); var k: i64 = 0
37 if m == 0 { t[0] = 48; k = 1 }
38 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
39 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
40 sys_write(fd, bb, k); return 0
41}
42func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
43func 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 }
44func g_starts(buf: *u8, n: i64, s: *u8) -> i64 {
45 let sn: i64 = slen(s)
46 if n < sn { return 0 }
47 var i: i64 = 0
48 while i < sn { if buf[i] != s[i] { return 0 } i = i + 1 }
49 return 1
50}
51func g_contains(hay: *u8, n: i64, needle: *u8) -> i64 {
52 let nn: i64 = slen(needle)
53 if nn == 0 { return 1 }
54 var i: i64 = 0
55 while i + nn <= n {
56 var m: i64 = 1
57 var j: i64 = 0
58 while j < nn { if hay[i + j] != needle[j] { m = 0; break } j = j + 1 }
59 if m == 1 { return 1 }
60 i = i + 1
61 }
62 return 0
63}
64func mk_seal(s: *NxSeal, dt: i64, ewills: i64, signer: *u8, ts: i64,
65 intent: i64, consent: i64, attribution: i64, retainable: i64,
66 witnesses: i64, notarized: i64) -> i64 {
67 s.doc_type = dt; s.e_wills_allowed = ewills
68 s.intent = intent; s.consent = consent; s.attribution = attribution
69 s.retainable = retainable; s.witnesses = witnesses; s.notarized = notarized
70 s.signer_id = signer; s.signer_id_len = slen(signer); s.ts = ts
71 return nx_seal_create(s)
72}
73
74func main() -> i64 {
75 var ok: i64 = 1
76
77 // ---- RFC 8032 test-1 keypair ----
78 let priv: *u8 = sys_mmap(64)
79 priv[0]=0x9d; priv[1]=0x61; priv[2]=0xb1; priv[3]=0x9d; priv[4]=0xef; priv[5]=0xfd; priv[6]=0x5a; priv[7]=0x60
80 priv[8]=0xba; priv[9]=0x84; priv[10]=0x4a; priv[11]=0xf4; priv[12]=0x92; priv[13]=0xec; priv[14]=0x2c; priv[15]=0xc4
81 priv[16]=0x44; priv[17]=0x49; priv[18]=0xc5; priv[19]=0x69; priv[20]=0x7b; priv[21]=0x32; priv[22]=0x69; priv[23]=0x19
82 priv[24]=0x70; priv[25]=0x3b; priv[26]=0xac; priv[27]=0x03; priv[28]=0x1c; priv[29]=0xae; priv[30]=0x7f; priv[31]=0x60
83 let pub: *u8 = sys_mmap(64)
84 pub[0]=0xd7; pub[1]=0x5a; pub[2]=0x98; pub[3]=0x01; pub[4]=0x82; pub[5]=0xb1; pub[6]=0x0a; pub[7]=0xb7
85 pub[8]=0xd5; pub[9]=0x4b; pub[10]=0xfe; pub[11]=0xd3; pub[12]=0xc9; pub[13]=0x64; pub[14]=0x07; pub[15]=0x3a
86 pub[16]=0x0e; pub[17]=0xe1; pub[18]=0x72; pub[19]=0xf3; pub[20]=0xda; pub[21]=0xa6; pub[22]=0x23; pub[23]=0x25
87 pub[24]=0xaf; pub[25]=0x02; pub[26]=0x1a; pub[27]=0x68; pub[28]=0xf7; pub[29]=0x07; pub[30]=0x51; pub[31]=0x1a
88 let dh: *u8 = sys_mmap(64)
89 var di: i64 = 0
90 while di < 32 { dh[di] = ((di * 7 + 3) & 0xff) as u8; di = di + 1 }
91 let s: *NxSeal = sys_mmap(256) as *NxSeal
92 s.doc_hash = dh; s.doc_hash_len = 32; s.priv = priv; s.canon = sys_mmap(512); s.sig = sys_mmap(128)
93
94 // ---- one tenant's stores ----
95 let ecap: i64 = 8
96 let rcap: i64 = 16
97 let ncap: i64 = 16
98 let vcap: i64 = 8
99 let eflat: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64
100 let rflat: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64
101 let anflat: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64
102 let vflat: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64
103 var ne: i64 = 0
104 var nr: i64 = 0
105 var na: i64 = 0
106 var vc: i64 = 0
107
108 // ENV_C 9601: contract, SENT, 1-of-2 signed (real Ed25519 seal)
109 ne = nx_env_create(eflat, ne, ecap, 9601, 8601, "Services Agreement" as *u8, 1, 1000)
110 nr = nx_env_add_recipient(rflat, nr, rcap, 9601, 101, ROLE_SIGNER, 1)
111 nr = nx_env_add_recipient(rflat, nr, rcap, 9601, 102, ROLE_SIGNER, 2)
112 if nx_env_send(eflat, ne, rflat, nr, 9601) != ENV_SEND_OK { ok = 0 }
113 let cseal: i64 = mk_seal(s, DT_CONTRACT, 1, "client1@andelinwest.com" as *u8, 1100, 1, 1, 1, 1, 0, 0)
114 if cseal != SEAL_OK { ok = 0 }
115 if nx_env_sign(eflat, ne, rflat, nr, 9601, 101, s, pub) != ENV_SIGN_OK { ok = 0 }
116
117 // ENV_W 9602: Will in a non-e-wills jurisdiction -> REQUIRES_WET, refused into DRAFT
118 ne = nx_env_create(eflat, ne, ecap, 9602, 8602, "Last Will and Testament" as *u8, 0, 2000)
119 nr = nx_env_add_recipient(rflat, nr, rcap, 9602, 201, ROLE_SIGNER, 1)
120 if nx_env_send(eflat, ne, rflat, nr, 9602) != ENV_SEND_REFUSED_VOID { ok = 0 }
121
122 // vault doc 8601 (v1) + a pending required checklist item on it
123 vc = nx_vault_add(vflat, vc, vcap, 8601, 5001, 64, 1000)
124 na = nx_ann_add(anflat, na, ncap, 0, 1, 8601, 1, AN_CHECK, 0, 700, ANF_REQUIRED, 1000)
125
126 // the doc bytes to serve (a tiny PDF-ish blob with adversarial bytes)
127 let docb: *u8 = sys_mmap(64)
128 docb[0]=37; docb[1]=80; docb[2]=68; docb[3]=70; docb[4]=13; docb[5]=10; docb[6]=0; docb[7]=88
129 let doclen: i64 = 8
130
131 let eidbuf: *i64 = sys_mmap(32) as *i64
132 eidbuf[0] = 9601; eidbuf[1] = 9602
133
134 let ctx: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx
135 ctx.user_level = 1
136 ctx.eflat = eflat; ctx.ne = ne
137 ctx.rflat = rflat; ctx.nr = nr
138 ctx.anflat = anflat; ctx.na = na
139 ctx.vflat = vflat; ctx.vc = vc
140 ctx.doc_id = 8601; ctx.doc_bytes = docb; ctx.doc_len = doclen; ctx.doc_fmt = DF_PDF
141 ctx.env_ids = eidbuf; ctx.env_count = 2
142
143 let req: *u8 = sys_mmap(4096)
144 let out: *u8 = sys_mmap(16384)
145
146 // ---- T1: list envelopes ----
147 var t1: i64 = 1
148 var rn: i64 = g_cat(req, 0, "GET /portal/envelopes HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
149 var on: i64 = lp_handle(ctx, req, rn, out)
150 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t1 = 0 }
151 if g_contains(out, on, "env 9601 status SENT" as *u8) != 1 { t1 = 0 }
152 if g_contains(out, on, "env 9602 status DRAFT" as *u8) != 1 { t1 = 0 }
153 if g_contains(out, on, "of 2" as *u8) != 1 { t1 = 0 }
154 if t1 != 1 { ok = 0 }
155
156 // ---- T2: contract status ----
157 var t2: i64 = 1
158 rn = g_cat(req, 0, "GET /portal/status?env=9601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
159 on = lp_handle(ctx, req, rn, out)
160 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t2 = 0 }
161 if g_contains(out, on, "status SENT" as *u8) != 1 { t2 = 0 }
162 if g_contains(out, on, "regime UETA_GENERAL" as *u8) != 1 { t2 = 0 }
163 if g_contains(out, on, "signed 1 of 2" as *u8) != 1 { t2 = 0 }
164 if t2 != 1 { ok = 0 }
165
166 // ---- T3: serve doc byte-exact (D3) ----
167 var t3: i64 = 1
168 rn = g_cat(req, 0, "GET /portal/doc?id=8601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
169 on = lp_handle(ctx, req, rn, out)
170 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t3 = 0 }
171 if g_contains(out, on, "Content-Type: application/pdf" as *u8) != 1 { t3 = 0 }
172 if nx_doc_serve_roundtrip_ok(out, on, docb, doclen) != 1 { t3 = 0 }
173 if t3 != 1 { ok = 0 }
174
175 // ---- T4: unknown doc id -> 404 (tenant vault does not own it) ----
176 var t4: i64 = 1
177 rn = g_cat(req, 0, "GET /portal/doc?id=9999 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
178 on = lp_handle(ctx, req, rn, out)
179 if g_starts(out, on, "HTTP/1.1 404" as *u8) != 1 { t4 = 0 }
180 if t4 != 1 { ok = 0 }
181
182 // ---- T5: /staff/matters denied to client(lvl1), allowed to lawyer(lvl2) ----
183 var t5: i64 = 1
184 ctx.user_level = 1
185 rn = g_cat(req, 0, "GET /staff/matters HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
186 on = lp_handle(ctx, req, rn, out)
187 if g_starts(out, on, "HTTP/1.1 403" as *u8) != 1 { t5 = 0 }
188 ctx.user_level = 2
189 on = lp_handle(ctx, req, rn, out)
190 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t5 = 0 }
191 if g_contains(out, on, "lawyer view" as *u8) != 1 { t5 = 0 }
192 ctx.user_level = 1
193 if t5 != 1 { ok = 0 }
194
195 // ---- T6: never-void SURFACED for the Will (REQUIRES_WET) ----
196 var t6: i64 = 1
197 rn = g_cat(req, 0, "GET /portal/status?env=9602 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
198 on = lp_handle(ctx, req, rn, out)
199 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t6 = 0 }
200 if g_contains(out, on, "regime REQUIRES_WET" as *u8) != 1 { t6 = 0 }
201 if g_contains(out, on, "wet signature required" as *u8) != 1 { t6 = 0 }
202 if t6 != 1 { ok = 0 }
203
204 // ---- T7: checklist readiness + unknown path -> 404 ----
205 var t7: i64 = 1
206 rn = g_cat(req, 0, "GET /portal/checklist?doc=8601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
207 on = lp_handle(ctx, req, rn, out)
208 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t7 = 0 }
209 if g_contains(out, on, "remaining 1 NOT_READY" as *u8) != 1 { t7 = 0 }
210 rn = g_cat(req, 0, "GET /portal/bogus HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
211 on = lp_handle(ctx, req, rn, out)
212 if g_starts(out, on, "HTTP/1.1 404" as *u8) != 1 { t7 = 0 }
213 if t7 != 1 { ok = 0 }
214
215 // ---- evidence ----
216 var fd: i64 = 1
217 while fd >= 1 {
218 ew(fd, "LEGALPORTALGATE authored=organ composes=D0+D1+D2+D3+D4+authz list_envelopes=" as *u8); ewn(fd, t1)
219 ew(fd, " envelope_status=" as *u8); ewn(fd, t2)
220 ew(fd, " serve_doc_byteexact=" as *u8); ewn(fd, t3)
221 ew(fd, " unknown_doc_404=" as *u8); ewn(fd, t4)
222 ew(fd, " authz_client_vs_lawyer=" as *u8); ewn(fd, t5)
223 ew(fd, " never_void_surfaced=" as *u8); ewn(fd, t6)
224 ew(fd, " checklist_and_404=" as *u8); ewn(fd, t7)
225 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) }
226 if fd == 1 {
227 let lf: i64 = sys_openat_append(LP_LOG, 420)
228 if lf >= 1 { fd = lf } else { fd = 0 }
229 } else {
230 sys_close(fd); fd = 0
231 }
232 }
233
234 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
235 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
236 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
237 let ctr__dry: *i64 = gv_ctr()
238 ctr__dry[0] = ok
239 ctr__dry[1] = 1
240 let rc__dry: i64 = gv_verdict("LEGAL-PORTAL-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
241 sys_exit(rc__dry)
242 return rc__dry
243}