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}