code wiki / _hdl_build / nx_legal_portal_post_gate.nx

nx_legal_portal_post_gate.nx source

↩ module page · 164 lines · 7434 B

1// nx_legal_portal_post_gate.nx -- GATE for the interactive POST routes (lp_handle_post), ENGINEER verify. 2// 3// Proves the portal's MUTATING actions over HTTP (the markup/checklist interactivity), 4// composing D4 (annotate) + D8 (persist), each with a control: 5// T1 POST annotate : POST /portal/annotate adds a note -> 200, store grows 6// T2 POST check : add a required checklist item then POST /portal/check?ann= -> 7// the item is DONE (GET /portal/checklist -> remaining 0 READY) 8// T3 MUTATION PERSISTS : after the POSTs, save + reload into FRESH arrays -> the 9// checklist done-state + the note survive (durable interactivity) 10// T4 AUTHZ : POST to /staff at level 1 -> 403 ; unknown path -> 404 11// T5 NEG : POST /portal/annotate with no doc -> 400 (not silent) 12// 13// lp_handle (GET) is UNCHANGED -- the POST router is a new function, so the existing 14// portal GET gates are not regressed (re-verified separately). 15// 16// Evidence -> knowledge/status/legal_portal_post.log 17// license_tier: ORIGINAL 18import "nx_legal_portal.nx" 19import "nx_legal_portal_boot.nx" 20import "nx_doc_annotate.nx" 21import "nx_doc_envelope.nx" 22import "nx_doc_vault.nx" 23import "nx_legal_compliance.nx" 24import "nx_syscalls.nx" 25 26const LPP_LOG: *u8 = "knowledge/status/legal_portal_post.log" 27const LPP_BASE: *u8 = "/tmp/nx_lpp_" 28 29func 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 } 30func ewn(fd: i64, v: i64) -> i64 { 31 let bb: *u8 = sys_mmap(28); var m: i64 = v 32 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 33 let t: *u8 = sys_mmap(28); var k: i64 = 0 34 if m == 0 { t[0] = 48; k = 1 } 35 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 36 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 37 sys_write(fd, bb, k); return 0 38} 39func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 40func 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 } 41func g_starts(buf: *u8, n: i64, s: *u8) -> i64 { 42 let sn: i64 = slen(s) 43 if n < sn { return 0 } 44 var i: i64 = 0 45 while i < sn { if buf[i] != s[i] { return 0 } i = i + 1 } 46 return 1 47} 48func g_contains(hay: *u8, n: i64, needle: *u8) -> i64 { 49 let nn: i64 = slen(needle) 50 if nn == 0 { return 1 } 51 var i: i64 = 0 52 while i + nn <= n { 53 var m: i64 = 1 54 var j: i64 = 0 55 while j < nn { if hay[i + j] != needle[j] { m = 0; break } j = j + 1 } 56 if m == 1 { return 1 } 57 i = i + 1 58 } 59 return 0 60} 61 62func main() -> i64 { 63 var ok: i64 = 1 64 let ncap: i64 = 16 65 let vcap: i64 = 8 66 let ecap: i64 = 8 67 let rcap: i64 = 8 68 let eflat: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64 69 let rflat: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64 70 let anflat: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64 71 let vflat: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64 72 let eidbuf: *i64 = sys_mmap(32) as *i64 73 var vc: i64 = nx_vault_add(vflat, 0, vcap, 8601, 5001, 64, 1000) 74 75 let ctx: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx 76 ctx.user_level = 1 77 ctx.eflat = eflat; ctx.ne = 0 78 ctx.rflat = rflat; ctx.nr = 0 79 ctx.anflat = anflat; ctx.na = 0 80 ctx.vflat = vflat; ctx.vc = vc 81 ctx.env_ids = eidbuf; ctx.env_count = 0 82 83 let req: *u8 = sys_mmap(4096) 84 let out: *u8 = sys_mmap(16384) 85 86 // ---- T1: POST annotate adds a note ---- 87 var t1: i64 = 1 88 var rn: i64 = g_cat(req, 0, "POST /portal/annotate?doc=8601&ann=50&author=700&typ=0 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 89 var on: i64 = lp_handle_post(ctx, ncap, req, rn, out) 90 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t1 = 0 } 91 if g_contains(out, on, "ANNOTATED doc 8601 ann 50" as *u8) != 1 { t1 = 0 } 92 if nx_ann_count(anflat, ctx.na, 8601, 1) != 1 { t1 = 0 } 93 if t1 != 1 { ok = 0 } 94 95 // ---- T2: POST add a required checklist item, then POST check it done ---- 96 var t2: i64 = 1 97 rn = g_cat(req, 0, "POST /portal/annotate?doc=8601&ann=60&author=700&typ=4&req=1 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 98 on = lp_handle_post(ctx, ncap, req, rn, out) 99 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t2 = 0 } 100 if nx_ann_checklist_remaining(anflat, ctx.na, 8601, 1) != 1 { t2 = 0 } // pending 101 rn = g_cat(req, 0, "POST /portal/check?ann=60 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 102 on = lp_handle_post(ctx, ncap, req, rn, out) 103 if g_starts(out, on, "HTTP/1.1 200" as *u8) != 1 { t2 = 0 } 104 if g_contains(out, on, "CHECKED ann 60" as *u8) != 1 { t2 = 0 } 105 // GET the checklist via lp_handle -> now READY 106 rn = g_cat(req, 0, "GET /portal/checklist?doc=8601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 107 on = lp_handle(ctx, req, rn, out) 108 if g_contains(out, on, "remaining 0 READY" as *u8) != 1 { t2 = 0 } 109 if t2 != 1 { ok = 0 } 110 111 // ---- T3: the mutations PERSIST across a reboot ---- 112 var t3: i64 = 1 113 lp_boot_save(ctx, LPP_BASE, "clientA" as *u8) 114 let anflat2: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64 115 let eflat2: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64 116 let rflat2: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64 117 let vflat2: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64 118 let eidbuf2: *i64 = sys_mmap(32) as *i64 119 let ctx2: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx 120 ctx2.user_level = 1 121 lp_boot_load(ctx2, LPP_BASE, "clientA" as *u8, eflat2, ecap, rflat2, rcap, anflat2, ncap, vflat2, vcap, eidbuf2) 122 if nx_ann_count(anflat2, ctx2.na, 8601, 1) != 2 { t3 = 0 } // note + check persisted 123 rn = g_cat(req, 0, "GET /portal/checklist?doc=8601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 124 on = lp_handle(ctx2, req, rn, out) 125 if g_contains(out, on, "remaining 0 READY" as *u8) != 1 { t3 = 0 } // done-state persisted 126 if t3 != 1 { ok = 0 } 127 128 // ---- T4: authz ---- 129 var t4: i64 = 1 130 rn = g_cat(req, 0, "POST /staff/x HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 131 on = lp_handle_post(ctx, ncap, req, rn, out) 132 if g_starts(out, on, "HTTP/1.1 403" as *u8) != 1 { t4 = 0 } 133 rn = g_cat(req, 0, "POST /portal/bogus HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 134 on = lp_handle_post(ctx, ncap, req, rn, out) 135 if g_starts(out, on, "HTTP/1.1 404" as *u8) != 1 { t4 = 0 } 136 if t4 != 1 { ok = 0 } 137 138 // ---- T5: NEG -- missing doc -> 400 ---- 139 var t5: i64 = 1 140 rn = g_cat(req, 0, "POST /portal/annotate?ann=99 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 141 on = lp_handle_post(ctx, ncap, req, rn, out) 142 if g_starts(out, on, "HTTP/1.1 400" as *u8) != 1 { t5 = 0 } 143 if t5 != 1 { ok = 0 } 144 145 // ---- evidence ---- 146 var fd: i64 = 1 147 while fd >= 1 { 148 ew(fd, "LEGALPORTALPOSTGATE authored=organ composes=D4+D8 post_annotate=" as *u8); ewn(fd, t1) 149 ew(fd, " post_check_done=" as *u8); ewn(fd, t2) 150 ew(fd, " mutation_persists=" as *u8); ewn(fd, t3) 151 ew(fd, " authz=" as *u8); ewn(fd, t4) 152 ew(fd, " neg_missing_doc=" as *u8); ewn(fd, t5) 153 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) } 154 if fd == 1 { 155 let lf: i64 = sys_openat_append(LPP_LOG, 420) 156 if lf >= 1 { fd = lf } else { fd = 0 } 157 } else { 158 sys_close(fd); fd = 0 159 } 160 } 161 162 if ok == 1 { return 0 } 163 return 1 164}