code wiki / _hdl_build / nx_legal_blob_gate.nx
nx_legal_blob_gate.nx source
↩ module page · 126 lines · 5212 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"
20
21const LBLOB_LOG: *u8 = "knowledge/status/legal_blob.log"
22const LBLOB_BASE: *u8 = "/tmp/nx_blob_"
23
24func 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 }
25func ewn(fd: i64, v: i64) -> i64 {
26 let bb: *u8 = sys_mmap(28); var m: i64 = v
27 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
28 let t: *u8 = sys_mmap(28); var k: i64 = 0
29 if m == 0 { t[0] = 48; k = 1 }
30 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
31 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
32 sys_write(fd, bb, k); return 0
33}
34
35func main() -> i64 {
36 var ok: i64 = 1
37 let p: *u8 = sys_mmap(512)
38 let pB: *u8 = sys_mmap(512)
39
40 // a document blob with adversarial bytes (CRLFCRLF + NUL inside)
41 let doc: *u8 = sys_mmap(64)
42 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
43 let dlen: i64 = 11
44
45 // ---- T1: blob round-trip ----
46 var t1: i64 = 1
47 if ls_path(p, LBLOB_BASE, "clientA" as *u8, "8601.blob" as *u8) < 0 { t1 = 0 }
48 if ls_blob_save(doc, dlen, p) != LS_OK { t1 = 0 }
49 let rbuf: *u8 = sys_mmap(64)
50 let ll: i64 = ls_blob_load(rbuf, 64, p)
51 if ll != dlen { t1 = 0 }
52 var i: i64 = 0
53 while i < dlen {
54 if rbuf[i] != doc[i] { t1 = 0 }
55 i = i + 1
56 }
57 if t1 != 1 { ok = 0 }
58
59 // ---- T2: serve the RELOADED blob byte-exact (compose D3) ----
60 var t2: i64 = 1
61 let resp: *u8 = sys_mmap(4096)
62 let rn: i64 = nx_doc_serve_response(resp, rbuf, ll, DF_PDF, DISP_INLINE, "doc" as *u8)
63 if nx_doc_serve_roundtrip_ok(resp, rn, doc, dlen) != 1 { t2 = 0 }
64 if t2 != 1 { ok = 0 }
65
66 // ---- T3: tenant isolation ----
67 var t3: i64 = 1
68 if ls_path(pB, LBLOB_BASE, "clientB" as *u8, "8601.blob" as *u8) < 0 { t3 = 0 }
69 if ls_blob_load(rbuf, 64, pB) != (0 - 1) { t3 = 0 } // clientB has no such blob
70 if ls_path(p, LBLOB_BASE, "../x" as *u8, "8601.blob" as *u8) != (0 - 1) { t3 = 0 }
71 if t3 != 1 { ok = 0 }
72
73 // ---- T4: absent + corrupt ----
74 var t4: i64 = 1
75 let pmiss: *u8 = sys_mmap(512)
76 if ls_path(pmiss, LBLOB_BASE, "nobody" as *u8, "x.blob" as *u8) < 0 { t4 = 0 }
77 if ls_blob_load(rbuf, 64, pmiss) != (0 - 1) { t4 = 0 }
78 let pbad: *u8 = sys_mmap(512)
79 if ls_path(pbad, LBLOB_BASE, "corrupt" as *u8, "x.blob" as *u8) < 0 { t4 = 0 }
80 let bfd: i64 = sys_openat_wr(pbad, 420)
81 if bfd < 0 { t4 = 0 } else {
82 let bh: *i64 = sys_mmap(32) as *i64
83 bh[0] = 0xDEADBEEF; bh[1] = 4
84 sys_write(bfd, bh as *u8, 16)
85 sys_close(bfd)
86 }
87 if ls_blob_load(rbuf, 64, pbad) != (0 - LS_ERR_MAGIC) { t4 = 0 }
88 if t4 != 1 { ok = 0 }
89
90 // ---- T5: a large (1000-byte) blob round-trips ----
91 var t5: i64 = 1
92 let big: *u8 = sys_mmap(2048)
93 var bi: i64 = 0
94 while bi < 1000 { big[bi] = ((bi * 31 + 7) & 0xff) as u8; bi = bi + 1 }
95 if ls_path(p, LBLOB_BASE, "clientA" as *u8, "big.blob" as *u8) < 0 { t5 = 0 }
96 if ls_blob_save(big, 1000, p) != LS_OK { t5 = 0 }
97 let rbig: *u8 = sys_mmap(2048)
98 let bl: i64 = ls_blob_load(rbig, 2048, p)
99 if bl != 1000 { t5 = 0 }
100 var bj: i64 = 0
101 while bj < 1000 {
102 if rbig[bj] != big[bj] { t5 = 0 }
103 bj = bj + 1
104 }
105 if t5 != 1 { ok = 0 }
106
107 // ---- evidence ----
108 var fd: i64 = 1
109 while fd >= 1 {
110 ew(fd, "LEGALBLOBGATE authored=organ composes=D3 blob_roundtrip=" as *u8); ewn(fd, t1)
111 ew(fd, " serve_byteexact=" as *u8); ewn(fd, t2)
112 ew(fd, " tenant_isolation=" as *u8); ewn(fd, t3)
113 ew(fd, " absent_corrupt=" as *u8); ewn(fd, t4)
114 ew(fd, " large_blob=" as *u8); ewn(fd, t5)
115 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) }
116 if fd == 1 {
117 let lf: i64 = sys_openat_append(LBLOB_LOG, 420)
118 if lf >= 1 { fd = lf } else { fd = 0 }
119 } else {
120 sys_close(fd); fd = 0
121 }
122 }
123
124 if ok == 1 { return 0 }
125 return 1
126}