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}