code wiki / _hdl_build / nx_legal_blob_gate.nx

nx_legal_blob_gate.nx source

↩ module page · 134 lines · 5748 B

1// nx_legal_blob_gate.nx -- GATE for doc-blob persistence (ls_blob_save/load), ENGINEER verify. 2// 3// Completes the durability story: the actual document BYTES survive a restart (the 4// workflow state already did via D7/D8; the blob is the doc itself). Composes 5// nx_legal_store (blob save/load) + nx_doc_serve (serve byte-exact), each w/ a control: 6// T1 ROUND-TRIP : a blob with adversarial bytes (CRLFCRLF + NUL) reloads byte-exact 7// T2 SERVE BYTE-EXACT: serving the RELOADED blob via nx_doc_serve round-trips bit-for-bit 8// (the served document == the persisted bytes == what was sealed) 9// T3 TENANT ISOLATION: another tenant's blob path is a different file -> absent; bad tenant rejected 10// T4 ABSENT + CORRUPT: missing -> -1 ; wrong-magic -> -MAGIC (never silent garbage) 11// T5 LARGE BLOB : a 1000-byte doc round-trips exactly (not just tiny) 12// 13// nx_legal_store's record save/load is UNCHANGED (blob funcs are additive) -> no regression. 14// Evidence -> knowledge/status/legal_blob.log 15// license_tier: ORIGINAL 16import "nx_legal_store.nx" 17import "nx_doc_serve.nx" 18import "nx_doc_vault.nx" 19import "nx_syscalls.nx" 20import "nx_gate_verdict.nx" 21 22const LBLOB_LOG: *u8 = "knowledge/status/legal_blob.log" 23const LBLOB_BASE: *u8 = "/tmp/nx_blob_" 24 25func 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 } 26func ewn(fd: i64, v: i64) -> i64 { 27 let bb: *u8 = sys_mmap(28); var m: i64 = v 28 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 29 let t: *u8 = sys_mmap(28); var k: i64 = 0 30 if m == 0 { t[0] = 48; k = 1 } 31 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 32 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 33 sys_write(fd, bb, k); return 0 34} 35 36func main() -> i64 { 37 var ok: i64 = 1 38 let p: *u8 = sys_mmap(512) 39 let pB: *u8 = sys_mmap(512) 40 41 // a document blob with adversarial bytes (CRLFCRLF + NUL inside) 42 let doc: *u8 = sys_mmap(64) 43 doc[0]=37; doc[1]=80; doc[2]=68; doc[3]=70; doc[4]=13; doc[5]=10; doc[6]=13; doc[7]=10; doc[8]=0; doc[9]=88; doc[10]=89 44 let dlen: i64 = 11 45 46 // ---- T1: blob round-trip ---- 47 var t1: i64 = 1 48 if ls_path(p, LBLOB_BASE, "clientA" as *u8, "8601.blob" as *u8) < 0 { t1 = 0 } 49 if ls_blob_save(doc, dlen, p) != LS_OK { t1 = 0 } 50 let rbuf: *u8 = sys_mmap(64) 51 let ll: i64 = ls_blob_load(rbuf, 64, p) 52 if ll != dlen { t1 = 0 } 53 var i: i64 = 0 54 while i < dlen { 55 if rbuf[i] != doc[i] { t1 = 0 } 56 i = i + 1 57 } 58 if t1 != 1 { ok = 0 } 59 60 // ---- T2: serve the RELOADED blob byte-exact (compose D3) ---- 61 var t2: i64 = 1 62 let resp: *u8 = sys_mmap(4096) 63 let rn: i64 = nx_doc_serve_response(resp, rbuf, ll, DF_PDF, DISP_INLINE, "doc" as *u8) 64 if nx_doc_serve_roundtrip_ok(resp, rn, doc, dlen) != 1 { t2 = 0 } 65 if t2 != 1 { ok = 0 } 66 67 // ---- T3: tenant isolation ---- 68 var t3: i64 = 1 69 if ls_path(pB, LBLOB_BASE, "clientB" as *u8, "8601.blob" as *u8) < 0 { t3 = 0 } 70 if ls_blob_load(rbuf, 64, pB) != (0 - 1) { t3 = 0 } // clientB has no such blob 71 if ls_path(p, LBLOB_BASE, "../x" as *u8, "8601.blob" as *u8) != (0 - 1) { t3 = 0 } 72 if t3 != 1 { ok = 0 } 73 74 // ---- T4: absent + corrupt ---- 75 var t4: i64 = 1 76 let pmiss: *u8 = sys_mmap(512) 77 if ls_path(pmiss, LBLOB_BASE, "nobody" as *u8, "x.blob" as *u8) < 0 { t4 = 0 } 78 if ls_blob_load(rbuf, 64, pmiss) != (0 - 1) { t4 = 0 } 79 let pbad: *u8 = sys_mmap(512) 80 if ls_path(pbad, LBLOB_BASE, "corrupt" as *u8, "x.blob" as *u8) < 0 { t4 = 0 } 81 let bfd: i64 = sys_openat_wr(pbad, 420) 82 if bfd < 0 { t4 = 0 } else { 83 let bh: *i64 = sys_mmap(32) as *i64 84 bh[0] = 0xDEADBEEF; bh[1] = 4 85 sys_write(bfd, bh as *u8, 16) 86 sys_close(bfd) 87 } 88 if ls_blob_load(rbuf, 64, pbad) != (0 - LS_ERR_MAGIC) { t4 = 0 } 89 if t4 != 1 { ok = 0 } 90 91 // ---- T5: a large (1000-byte) blob round-trips ---- 92 var t5: i64 = 1 93 let big: *u8 = sys_mmap(2048) 94 var bi: i64 = 0 95 while bi < 1000 { big[bi] = ((bi * 31 + 7) & 0xff) as u8; bi = bi + 1 } 96 if ls_path(p, LBLOB_BASE, "clientA" as *u8, "big.blob" as *u8) < 0 { t5 = 0 } 97 if ls_blob_save(big, 1000, p) != LS_OK { t5 = 0 } 98 let rbig: *u8 = sys_mmap(2048) 99 let bl: i64 = ls_blob_load(rbig, 2048, p) 100 if bl != 1000 { t5 = 0 } 101 var bj: i64 = 0 102 while bj < 1000 { 103 if rbig[bj] != big[bj] { t5 = 0 } 104 bj = bj + 1 105 } 106 if t5 != 1 { ok = 0 } 107 108 // ---- evidence ---- 109 var fd: i64 = 1 110 while fd >= 1 { 111 ew(fd, "LEGALBLOBGATE authored=organ composes=D3 blob_roundtrip=" as *u8); ewn(fd, t1) 112 ew(fd, " serve_byteexact=" as *u8); ewn(fd, t2) 113 ew(fd, " tenant_isolation=" as *u8); ewn(fd, t3) 114 ew(fd, " absent_corrupt=" as *u8); ewn(fd, t4) 115 ew(fd, " large_blob=" as *u8); ewn(fd, t5) 116 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) } 117 if fd == 1 { 118 let lf: i64 = sys_openat_append(LBLOB_LOG, 420) 119 if lf >= 1 { fd = lf } else { fd = 0 } 120 } else { 121 sys_close(fd); fd = 0 122 } 123 } 124 125 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 126 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 127 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 128 let ctr__dry: *i64 = gv_ctr() 129 ctr__dry[0] = ok 130 ctr__dry[1] = 1 131 let rc__dry: i64 = gv_verdict("LEGAL-BLOB-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 132 sys_exit(rc__dry) 133 return rc__dry 134}