code wiki / _hdl_build / nx_doc_vault_gate.nx
nx_doc_vault_gate.nx source
↩ module page · 138 lines · 6475 B
1// nx_doc_vault_gate.nx -- GATE for LEGAL D1 (nx_doc_vault).
2//
3// Drives the REAL vault and asserts the retention invariants:
4// ADDITIVE+VERSIONED : 3 versions of doc A -> version_count(A)=3, current is
5// version 3 (older versions retained, not overwritten).
6// SINGLE-AUTHORITATIVE: exactly one is_current per doc (UETA 16).
7// CHAIN TAMPER-EVIDENT: verify_chain(A)=OK; corrupt a non-final version's
8// hash -> CHAIN_BROKEN; restore -> OK (UETA 12).
9// SOFT-DELETE KEEPS HISTORY: soft_delete(A) -> no current, but
10// version_count(A) still 3 (Rule 13 additive-only).
11// SEAL ATTACH : a D5 seal attaches to the CURRENT version only.
12// TENANT ISOLATION : valid tid accepted; '.'/'/'/empty rejected (no
13// cross-tenant traversal -- MRPC 1.6 confidentiality).
14// MULTI-DOC : adding doc B leaves doc A's history untouched.
15//
16// Evidence -> knowledge/status/doc_vault.log
17// license_tier: ORIGINAL
18import "nx_doc_vault.nx"
19import "nx_syscalls.nx"
20import "nx_gate_verdict.nx"
21
22const DV_LOG: *u8 = "knowledge/status/doc_vault.log"
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 cap: i64 = 64
38 let flat: *i64 = sys_mmap(cap * VF_STRIDE * 8) as *i64
39 var count: i64 = 0
40
41 let docA: i64 = 7001
42 let docB: i64 = 7002
43
44 // ---- ADDITIVE + VERSIONED: 3 chained versions of A ----
45 var add_ok: i64 = 1
46 count = nx_vault_add(flat, count, cap, docA, 1001, 500, 100)
47 if count != 1 { add_ok = 0 }
48 count = nx_vault_add(flat, count, cap, docA, 1002, 510, 200)
49 if count != 2 { add_ok = 0 }
50 count = nx_vault_add(flat, count, cap, docA, 1003, 520, 300)
51 if count != 3 { add_ok = 0 }
52 if nx_vault_version_count(flat, count, docA) != 3 { add_ok = 0 }
53 // current is version 3
54 let cur: i64 = nx_vault_current_idx(flat, count, docA)
55 if cur < 0 { add_ok = 0 }
56 if flat[cur * VF_STRIDE + VF_VER] != 3 { add_ok = 0 }
57 if add_ok != 1 { ok = 0 }
58
59 // ---- SINGLE AUTHORITATIVE COPY ----
60 var single_ok: i64 = 1
61 if nx_vault_current_count(flat, count, docA) != 1 { single_ok = 0 }
62 if single_ok != 1 { ok = 0 }
63
64 // ---- CHAIN: ok, then tamper a non-final version, then restore ----
65 var chain_ok: i64 = 1
66 if nx_vault_verify_chain(flat, count, docA) != VAULT_OK { chain_ok = 0 }
67 // corrupt version 2's content hash (record index 1) -> version 3's prev no longer links
68 let save_h: i64 = flat[1 * VF_STRIDE + VF_HASH]
69 flat[1 * VF_STRIDE + VF_HASH] = 9999
70 if nx_vault_verify_chain(flat, count, docA) != VAULT_CHAIN_BROKEN { chain_ok = 0 }
71 flat[1 * VF_STRIDE + VF_HASH] = save_h
72 if nx_vault_verify_chain(flat, count, docA) != VAULT_OK { chain_ok = 0 }
73 if chain_ok != 1 { ok = 0 }
74
75 // ---- SEAL attaches to the CURRENT version only ----
76 var seal_ok: i64 = 1
77 if nx_vault_attach_seal(flat, count, docA) != VAULT_OK { seal_ok = 0 }
78 if flat[2 * VF_STRIDE + VF_SEAL] != 1 { seal_ok = 0 } // v3 (current) sealed
79 if flat[0 * VF_STRIDE + VF_SEAL] != 0 { seal_ok = 0 } // v1 not
80 if flat[1 * VF_STRIDE + VF_SEAL] != 0 { seal_ok = 0 } // v2 not
81 if seal_ok != 1 { ok = 0 }
82
83 // ---- MULTI-DOC isolation: add B, A untouched ----
84 var multi_ok: i64 = 1
85 count = nx_vault_add(flat, count, cap, docB, 2001, 700, 400)
86 if count != 4 { multi_ok = 0 }
87 if nx_vault_version_count(flat, count, docA) != 3 { multi_ok = 0 }
88 if nx_vault_version_count(flat, count, docB) != 1 { multi_ok = 0 }
89 if nx_vault_verify_chain(flat, count, docB) != VAULT_OK { multi_ok = 0 }
90 if multi_ok != 1 { ok = 0 }
91
92 // ---- SOFT-DELETE keeps history (Rule 13) ----
93 var del_ok: i64 = 1
94 if nx_vault_soft_delete(flat, count, docA) != VAULT_OK { del_ok = 0 }
95 if nx_vault_current_idx(flat, count, docA) != (0 - 1) { del_ok = 0 } // no current
96 if nx_vault_current_count(flat, count, docA) != 0 { del_ok = 0 }
97 if nx_vault_version_count(flat, count, docA) != 3 { del_ok = 0 } // history retained
98 if del_ok != 1 { ok = 0 }
99
100 // ---- TENANT-ID isolation ----
101 var tid_ok: i64 = 1
102 if nx_vault_valid_tid("client_andelinwest" as *u8) != 1 { tid_ok = 0 }
103 if nx_vault_valid_tid("andelin-west-2026" as *u8) != 1 { tid_ok = 0 }
104 if nx_vault_valid_tid("../secret" as *u8) != 0 { tid_ok = 0 }
105 if nx_vault_valid_tid("a/b" as *u8) != 0 { tid_ok = 0 }
106 if nx_vault_valid_tid("dot.tid" as *u8) != 0 { tid_ok = 0 }
107 if nx_vault_valid_tid("" as *u8) != 0 { tid_ok = 0 }
108 if tid_ok != 1 { ok = 0 }
109
110 // ---- evidence ----
111 var fd: i64 = 1
112 while fd >= 1 {
113 ew(fd, "DOCVAULTGATE authored=organ additive_versioned=" as *u8); ewn(fd, add_ok)
114 ew(fd, " single_authoritative=" as *u8); ewn(fd, single_ok)
115 ew(fd, " chain_tamper_evident=" as *u8); ewn(fd, chain_ok)
116 ew(fd, " seal_current_only=" as *u8); ewn(fd, seal_ok)
117 ew(fd, " multidoc_isolated=" as *u8); ewn(fd, multi_ok)
118 ew(fd, " softdelete_keeps_history=" as *u8); ewn(fd, del_ok)
119 ew(fd, " tenant_id_no_traversal=" as *u8); ewn(fd, tid_ok)
120 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) }
121 if fd == 1 {
122 let lf: i64 = sys_openat_append(DV_LOG, 420)
123 if lf >= 1 { fd = lf } else { fd = 0 }
124 } else {
125 sys_close(fd); fd = 0
126 }
127 }
128
129 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
130 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
131 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
132 let ctr__dry: *i64 = gv_ctr()
133 ctr__dry[0] = ok
134 ctr__dry[1] = 1
135 let rc__dry: i64 = gv_verdict("DOC-VAULT-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
136 sys_exit(rc__dry)
137 return rc__dry
138}