code wiki / _hdl_build / nx_office_import_sign_gate.nx

nx_office_import_sign_gate.nx source

↩ module page · 259 lines · 16131 B

1// nx_office_import_sign_gate.nx -- INDEPENDENT GATE for the office IMPORT (LP1) and SIGN-FROM-VERSION (LP4) rungs of 2// /compare/legalpractice. Drives the pure core nx_office_serve IN-PROCESS (of_handle, real HTTP bytes, no sockets) 3// against a FRESH fixture under /tmp/<gate>/<now_us> (never a production plane). Inherits nx_gate_verdict: one 4// gv_check per tooth, gv_bite for the consent gate (fires on no-consent, silent on consent), gv_verdict carries the 5// verdict in the EXIT CODE. Two import fixtures: a .docx the office itself wrote (mechanism) and a GENUINE Microsoft 6// Word document banked in knowledge/fetched (real-world producer: 25 parts, headers, footnotes, a 13-column table). 7// Runs the REAL format organs (_offc/nx_docx.elf) via fork+exec, so it runs from the nishihost root. license_tier: ORIGINAL 8import "nx_office_serve.nx" 9import "nx_gate_verdict.nx" 10 11const OG_SCRATCH: *u8 = "/tmp/nx_office_import_sign_gate" 12const OG_WORD_FIXTURE: *u8 = "knowledge/fetched/cmp_legalpractice_msword_fixture.docx" 13const OG_DIRMODE: i64 = 493 14const OG_OUTCAP: i64 = 1048576 15const OG_REQCAP: i64 = 2097152 16const OG_PATHCAP: i64 = 600 17const OG_SMALL: i64 = 256 18const OG_SZP: i64 = 16 19const OG_BOUNDARY: *u8 = "nxOfficeGateBoundary7f3a" 20const OG_DOCX_CT: *u8 = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" 21const OG_SEED_SPEC: *u8 = "name=seed&kind=doc&spec=H+Seed+Title%0AP+A+paragraph+of+body+text.%0AT+a%7Cb%7Cc%0AT+1%7C2%7C3" 22const OG_WORD_MIN_LINES: i64 = 10 23 24func og_path(out: *u8, root: *u8, tail: *u8) -> i64 { 25 var o: i64 = of_cat(out, 0, root) 26 o = of_cat(out, o, tail) 27 out[o] = 0 as u8 28 return o 29} 30// urlencoded POST through of_handle; returns response length 31func og_post(root: *u8, base: *u8, path: *u8, body: *u8, req: *u8, out: *u8) -> i64 { 32 var ro: i64 = of_cat(req, 0, "POST " as *u8) 33 ro = of_cat(req, ro, path) 34 ro = of_cat(req, ro, " HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 35 ro = of_catn(req, ro, of_slen(body)) 36 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 37 ro = of_cat(req, ro, body) 38 return of_handle(root, base, req, ro, out, OG_OUTCAP) 39} 40func og_get(root: *u8, base: *u8, path: *u8, req: *u8, out: *u8) -> i64 { 41 var ro: i64 = of_cat(req, 0, "GET " as *u8) 42 ro = of_cat(req, ro, path) 43 ro = of_cat(req, ro, " HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8) 44 return of_handle(root, base, req, ro, out, OG_OUTCAP) 45} 46// multipart/form-data POST /import: optional name part, then the file part (filename + raw bytes). withfile=0 omits 47// the file part entirely (the "no file part" negative). 48func og_import(root: *u8, base: *u8, name: *u8, filename: *u8, bytes: *u8, n: i64, withfile: i64, req: *u8, body: *u8, out: *u8) -> i64 { 49 var bo: i64 = 0 50 if name[0] != (0 as u8) { 51 bo = of_cat(body, bo, "--" as *u8); bo = of_cat(body, bo, OG_BOUNDARY) 52 bo = of_cat(body, bo, "\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n" as *u8) 53 bo = of_cat(body, bo, name); bo = of_cat(body, bo, "\r\n" as *u8) 54 } 55 if withfile == 1 { 56 bo = of_cat(body, bo, "--" as *u8); bo = of_cat(body, bo, OG_BOUNDARY) 57 bo = of_cat(body, bo, "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"" as *u8) 58 bo = of_cat(body, bo, filename) 59 bo = of_cat(body, bo, "\"\r\nContent-Type: application/octet-stream\r\n\r\n" as *u8) 60 var i: i64 = 0 61 while i < n { body[bo] = bytes[i]; bo = bo + 1; i = i + 1 } 62 bo = of_cat(body, bo, "\r\n" as *u8) 63 } 64 bo = of_cat(body, bo, "--" as *u8); bo = of_cat(body, bo, OG_BOUNDARY); bo = of_cat(body, bo, "--\r\n" as *u8) 65 var ro: i64 = of_cat(req, 0, "POST /import HTTP/1.1\r\nHost: office.local\r\nContent-Type: multipart/form-data; boundary=" as *u8) 66 ro = of_cat(req, ro, OG_BOUNDARY) 67 ro = of_cat(req, ro, "\r\nContent-Length: " as *u8) 68 ro = of_catn(req, ro, bo) 69 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 70 var k: i64 = 0 71 while k < bo { req[ro] = body[k]; ro = ro + 1; k = k + 1 } 72 return of_handle(root, base, req, ro, out, OG_OUTCAP) 73} 74// the HTTP status token of a response is the first line: "HTTP/1.1 <code> ..." 75func og_status_is(out: *u8, n: i64, code: *u8) -> i64 { 76 if n < 12 { return 0 } 77 return of_memhas(out, 13, code) 78} 79// offset of the body (after CRLFCRLF), -1 if none 80func og_body_off(out: *u8, n: i64) -> i64 { 81 var i: i64 = 0 82 while i + 3 < n { 83 if out[i] == (13 as u8) { if out[i+1] == (10 as u8) { if out[i+2] == (13 as u8) { if out[i+3] == (10 as u8) { return i + 4 } } } } 84 i = i + 1 85 } 86 return 0 - 1 87} 88func og_same(a: *u8, an: i64, b: *u8, bn: i64) -> i64 { 89 if an != bn { return 0 } 90 if an <= 0 { return 0 } 91 var i: i64 = 0 92 while i < an { if a[i] != b[i] { return 0 } i = i + 1 } 93 return 1 94} 95func og_count_lines(buf: *u8, n: i64) -> i64 { 96 var c: i64 = 0 97 var i: i64 = 0 98 while i < n { if buf[i] == (10 as u8) { c = c + 1 } i = i + 1 } 99 return c 100} 101// read a whole file into a fresh map; returns length (-1 absent); caller frees with sys_free_file 102func og_read(path: *u8, outp: *i64) -> i64 { 103 let szp: *i64 = sys_mmap(OG_SZP) as *i64 104 szp[0] = 0 105 let b: *u8 = sys_read_file(path, szp) 106 outp[0] = b as i64 107 if (b as i64) == 0 { sys_munmap(szp as *u8, OG_SZP); return 0 - 1 } 108 let n: i64 = szp[0] 109 sys_munmap(szp as *u8, OG_SZP) 110 return n 111} 112// "key=value" line value (NUL-terminated copy into out); 0 if absent 113func og_field(buf: *u8, n: i64, key: *u8, out: *u8, cap: i64) -> i64 { 114 let kl: i64 = of_slen(key) 115 var i: i64 = 0 116 while i + kl <= n { 117 var at_line: i64 = 0 118 if i == 0 { at_line = 1 } else { if buf[i - 1] == (10 as u8) { at_line = 1 } } 119 if at_line == 1 { if of_memhas((buf as i64 + i) as *u8, kl, key) == 1 { 120 var q: i64 = i + kl 121 var o: i64 = 0 122 while q < n { if buf[q] == (10 as u8) { q = n } else { if o < cap - 1 { out[o] = buf[q]; o = o + 1 } q = q + 1 } } 123 out[o] = 0 as u8 124 return o 125 } } 126 i = i + 1 127 } 128 out[0] = 0 as u8 129 return 0 130} 131 132func main() -> i64 { 133 gv_head("NX-OFFICE-IMPORT-SIGN-GATE -- LP1 import (.docx in, original kept byte for byte, paragraph-faithful spec) + LP4 sign-from-version (UETA consent gate, hash-chained audit, sealed certificate) over the pure core, fixture under /tmp" as *u8) 134 let ctr: *i64 = gv_ctr() 135 sys_mkdir(OG_SCRATCH, OG_DIRMODE) 136 let root: *u8 = sys_mmap(OG_SMALL) 137 var ro: i64 = of_cat(root, 0, OG_SCRATCH) 138 ro = of_cat(root, ro, "/" as *u8) 139 ro = of_catn(root, ro, sys_now_us()) 140 root[ro] = 0 as u8 141 let base: *u8 = sys_mmap(4) 142 base[0] = 0 as u8 143 let req: *u8 = sys_mmap(OG_REQCAP) 144 let body: *u8 = sys_mmap(OG_REQCAP) 145 let out: *u8 = sys_mmap(OG_OUTCAP) 146 let pth: *u8 = sys_mmap(OG_PATHCAP) 147 let bp: *i64 = sys_mmap(OG_SZP) as *i64 148 gv_puts(" fixture root: " as *u8); gv_puts(root); gv_puts("\n" as *u8) 149 150 // ---- seed: the office writes a real .docx (the mechanism fixture) ---- 151 var n: i64 = og_post(root, base, "/save" as *u8, OG_SEED_SPEC, req, out) 152 gv_check("seed-doc-created-by-the-office-itself" as *u8, og_status_is(out, n, "303" as *u8), ctr) 153 og_path(pth, root, "/seed/v1/file.docx" as *u8) 154 let seedn: i64 = og_read(pth, bp) 155 let seed: *u8 = bp[0] as *u8 156 gv_puts(" seed docx bytes=" as *u8); gv_num(seedn); gv_puts("\n" as *u8) 157 var seedzip: i64 = 0 158 if seedn > 4 { if seed[0] == (80 as u8) { if seed[1] == (75 as u8) { seedzip = 1 } } } 159 gv_check("seed-docx-is-a-zip-package" as *u8, seedzip, ctr) 160 161 // ---- T: import the seed as a NEW document ---- 162 n = og_import(root, base, "imported" as *u8, "seed.docx" as *u8, seed, seedn, 1, req, body, out) 163 gv_check("import-docx-answers-303-to-the-new-document" as *u8, ((og_status_is(out, n, "303" as *u8)) as i64) & ((of_memhas(out, n, "Location: /doc/imported" as *u8)) as i64), ctr) 164 og_path(pth, root, "/imported/v1/original.docx" as *u8) 165 let on: i64 = og_read(pth, bp) 166 let orig: *u8 = bp[0] as *u8 167 gv_check("original-kept-byte-for-byte-as-v1" as *u8, og_same(orig, on, seed, seedn), ctr) 168 n = og_get(root, base, "/original/imported/v1" as *u8, req, out) 169 let bo1: i64 = og_body_off(out, n) 170 var served_same: i64 = 0 171 if bo1 > 0 { served_same = og_same((out as i64 + bo1) as *u8, n - bo1, seed, seedn) } 172 gv_check("original-route-serves-the-untouched-upload-with-docx-content-type" as *u8, (served_same) & ((of_memhas(out, bo1, OG_DOCX_CT)) as i64), ctr) 173 og_path(pth, root, "/imported/v1/spec.txt" as *u8) 174 let sn: i64 = og_read(pth, bp) 175 let spec: *u8 = bp[0] as *u8 176 gv_puts(" imported spec lines=" as *u8); gv_num(og_count_lines(spec, sn)); gv_puts("\n" as *u8) 177 gv_check("spec-is-paragraph-faithful-heading-paragraph-and-table-rows" as *u8, ((of_memhas(spec, sn, "H Seed Title" as *u8)) as i64) & ((of_memhas(spec, sn, "P A paragraph of body text." as *u8)) as i64) & ((of_memhas(spec, sn, "T a|b|c" as *u8)) as i64) & ((of_memhas(spec, sn, "T 1|2|3" as *u8)) as i64), ctr) 178 og_path(pth, root, "/imported/manifest.txt" as *u8) 179 let mn: i64 = og_read(pth, bp) 180 let man: *u8 = bp[0] as *u8 181 gv_check("manifest-row-marks-v1-as-import" as *u8, of_memhas(man, mn, "import" as *u8), ctr) 182 n = og_get(root, base, "/doc/imported" as *u8, req, out) 183 gv_check("doc-page-opens-the-import-in-the-editor-with-its-spec" as *u8, ((og_status_is(out, n, "200" as *u8)) as i64) & ((of_memhas(out, n, "H Seed Title" as *u8)) as i64) & ((of_memhas(out, n, "<th>Sign</th>" as *u8)) as i64), ctr) 184 // negatives, each naming WHICH refusal fired 185 n = og_import(root, base, "imported" as *u8, "seed.docx" as *u8, seed, seedn, 1, req, body, out) 186 gv_check("neg-control-duplicate-name-refused-409-import-never-appends" as *u8, og_status_is(out, n, "409" as *u8), ctr) 187 n = og_import(root, base, "nota" as *u8, "nota.docx" as *u8, "this is not a zip package" as *u8, 25, 1, req, body, out) 188 gv_check("neg-control-non-package-bytes-refused-415" as *u8, og_status_is(out, n, "415" as *u8), ctr) 189 n = og_import(root, base, "nofile" as *u8, "x.docx" as *u8, seed, seedn, 0, req, body, out) 190 gv_check("neg-control-missing-file-part-refused-400" as *u8, og_status_is(out, n, "400" as *u8), ctr) 191 n = og_import(root, base, "" as *u8, "My Draft Letter.docx" as *u8, seed, seedn, 1, req, body, out) 192 gv_check("blank-name-derives-my-draft-letter-from-the-filename" as *u8, ((og_status_is(out, n, "303" as *u8)) as i64) & ((of_memhas(out, n, "Location: /doc/my-draft-letter" as *u8)) as i64), ctr) 193 194 // ---- the GENUINE Microsoft Word document (real-world producer) ---- 195 let wn: i64 = og_read(OG_WORD_FIXTURE, bp) 196 let word: *u8 = bp[0] as *u8 197 if gv_need("real-word-fixture knowledge/fetched/cmp_legalpractice_msword_fixture.docx" as *u8, (wn > 0) as i64, ctr) == 1 { 198 gv_puts(" word fixture bytes=" as *u8); gv_num(wn); gv_puts("\n" as *u8) 199 n = og_import(root, base, "msword" as *u8, "Real Word Agreement.docx" as *u8, word, wn, 1, req, body, out) 200 gv_check("real-word-docx-imports-303" as *u8, og_status_is(out, n, "303" as *u8), ctr) 201 og_path(pth, root, "/msword/v1/original.docx" as *u8) 202 let won: i64 = og_read(pth, bp) 203 gv_check("real-word-original-kept-byte-for-byte" as *u8, og_same(bp[0] as *u8, won, word, wn), ctr) 204 og_path(pth, root, "/msword/v1/spec.txt" as *u8) 205 let wsn: i64 = og_read(pth, bp) 206 let wspec: *u8 = bp[0] as *u8 207 let wlines: i64 = og_count_lines(wspec, wsn) 208 gv_puts(" word spec lines=" as *u8); gv_num(wlines); gv_puts(" bytes=" as *u8); gv_num(wsn); gv_puts("\n" as *u8) 209 gv_check("real-word-spec-has-table-rows-and-paragraphs-at-least-10-lines" as *u8, ((wlines >= OG_WORD_MIN_LINES) as i64) & ((of_memhas(wspec, wsn, "T " as *u8)) as i64) & ((of_memhas(wspec, wsn, "P " as *u8)) as i64), ctr) 210 gv_check("real-word-spec-keeps-utf8-punctuation-intact" as *u8, (of_memhas(wspec, wsn, "VVUQ 1 – Verification" as *u8)) as i64, ctr) 211 } 212 213 // ---- LP4: sign-from-version over the imported document ---- 214 n = og_post(root, base, "/sign" as *u8, "name=imported&version=1&signer=alice" as *u8, req, out) 215 let noconsent_403: i64 = og_status_is(out, n, "403" as *u8) 216 og_path(pth, root, "/imported/v1/cert.txt" as *u8) 217 let c0: i64 = og_read(pth, bp) 218 gv_check("neg-control-no-consent-refused-403-and-no-certificate-written" as *u8, (noconsent_403) & ((c0 < 0) as i64), ctr) 219 n = og_post(root, base, "/sign" as *u8, "name=imported&version=1&signer=alice&consent=yes" as *u8, req, out) 220 let consent_303: i64 = og_status_is(out, n, "303" as *u8) 221 let consent_403: i64 = og_status_is(out, n, "403" as *u8) 222 gv_check("consent-yes-signs-and-answers-303-back-to-the-document" as *u8, consent_303, ctr) 223 gv_bite("ueta-consent-gate" as *u8, noconsent_403, consent_403, ctr) 224 let c1: i64 = og_read(pth, bp) 225 let cert: *u8 = bp[0] as *u8 226 let fld: *u8 = sys_mmap(OG_SMALL) 227 og_field(cert, c1, "document=" as *u8, fld, OG_SMALL) 228 og_path(pth, root, "/imported/v1/file.docx" as *u8) 229 let szb: *i64 = sys_mmap(OG_SZP) as *i64 230 let doccid: *u8 = sys_mmap(OG_SMALL) 231 cid_of_file(pth, szb, doccid) 232 gv_puts(" cert document=" as *u8); gv_puts(fld); gv_puts(" file cid=" as *u8); gv_puts(doccid); gv_puts("\n" as *u8) 233 gv_check("certificate-binds-the-document-cid-of-the-signed-version" as *u8, ((c1 > 0) as i64) & ((of_seq(fld, doccid)) as i64), ctr) 234 gv_check("certificate-records-completed-with-one-signer" as *u8, ((of_memhas(cert, c1, "status=completed" as *u8)) as i64) & ((of_memhas(cert, c1, "signers=1" as *u8)) as i64) & ((of_memhas(cert, c1, "certificate=nxc1-" as *u8)) as i64), ctr) 235 let head1: *u8 = sys_mmap(OG_SMALL) 236 og_field(cert, c1, "audit_head=" as *u8, head1, OG_SMALL) 237 og_path(pth, root, "/imported/sign-manifest.txt" as *u8) 238 let smn: i64 = og_read(pth, bp) 239 gv_check("certificate-retained-in-the-immutable-sign-store" as *u8, (smn > 0) as i64, ctr) 240 n = og_get(root, base, "/cert/imported/v1" as *u8, req, out) 241 gv_check("cert-route-serves-the-receipt-as-text" as *u8, ((og_status_is(out, n, "200" as *u8)) as i64) & ((of_memhas(out, n, "certificate=nxc1-" as *u8)) as i64) & ((of_memhas(out, n, "text/plain" as *u8)) as i64), ctr) 242 n = og_get(root, base, "/doc/imported" as *u8, req, out) 243 gv_check("doc-page-shows-signed-receipt-link-on-the-signed-version" as *u8, of_memhas(out, n, "signed &middot; receipt" as *u8), ctr) 244 n = og_post(root, base, "/sign" as *u8, "name=imported&version=1&signer=bob&consent=yes" as *u8, req, out) 245 og_path(pth, root, "/imported/v1/cert.txt" as *u8) 246 let c2: i64 = og_read(pth, bp) 247 let cert2: *u8 = bp[0] as *u8 248 let head2: *u8 = sys_mmap(OG_SMALL) 249 og_field(cert2, c2, "audit_head=" as *u8, head2, OG_SMALL) 250 gv_puts(" audit head 1=" as *u8); gv_puts(head1); gv_puts("\n audit head 2=" as *u8); gv_puts(head2); gv_puts("\n" as *u8) 251 gv_check("second-signer-chains-signers-2-and-advances-the-audit-head" as *u8, ((og_status_is(out, n, "303" as *u8)) as i64) & ((of_memhas(cert2, c2, "signers=2" as *u8)) as i64) & (((of_seq(head1, head2)) == 0) as i64) & ((of_slen(head2) == OF_HEXSZ) as i64), ctr) 252 n = og_post(root, base, "/sign" as *u8, "name=imported&version=1&signer=a%20b&consent=yes" as *u8, req, out) 253 gv_check("neg-control-signer-with-a-space-refused-400" as *u8, og_status_is(out, n, "400" as *u8), ctr) 254 n = og_post(root, base, "/sign" as *u8, "name=imported&version=9&signer=alice&consent=yes" as *u8, req, out) 255 gv_check("neg-control-unknown-version-refused-404" as *u8, og_status_is(out, n, "404" as *u8), ctr) 256 n = og_get(root, base, "/cert/seed/v1" as *u8, req, out) 257 gv_check("neg-control-unsigned-version-has-no-receipt-404" as *u8, og_status_is(out, n, "404" as *u8), ctr) 258 return gv_verdict("OFFICE-IMPORT-SIGN-GATE" as *u8, ctr, "LP1 import + LP4 sign over the pure core against a /tmp fixture; a genuine Word document is the real-world producer" as *u8) 259}