code wiki / _hdl_build / nx_doc_envelope_gate.nx

nx_doc_envelope_gate.nx source

↩ module page · 266 lines · 14238 B

1// nx_doc_envelope_gate.nx -- GATE for LEGAL D2 (nx_doc_envelope). 2// 3// Drives the e-signature ENVELOPE workflow composing D0 (compliance) + D1 4// (vault) + D5 (real Ed25519 seal over the RFC 8032 KAT keypair) and asserts 5// every workflow invariant WITH a negative control: 6// 7// T1 HAPPY+VAULT : a contract envelope with 2 ordered signers (+1 CC) sends, 8// cannot complete before signing, completes once both have 9// a verified seal, and the sealed version lands in the 10// additive per-tenant vault. 11// T2 NEVER-ROUTE-VOID (the s-class crux) : a Last Will & Testament in a 12// NON-e-wills jurisdiction -> SEND is REFUSED_VOID and the 13// envelope STAYS DRAFT. A generic e-sign clone would send it 14// and collect a legally void signature; this one cannot. 15// T3 ROUTING ORDER: signer 2 cannot sign before signer 1 (OUT_OF_ORDER), then 16// in-order both sign and it completes. 17// T4 TAMPER->NO-COMPLETE : a one-byte-tampered seal is rejected at SIGN 18// (BAD_SEAL) so the envelope cannot complete; restoring the 19// byte lets it sign + complete (forgery can't finish a deal). 20// T5 DECLINE ADDITIVE : a decline makes the envelope terminal-DECLINED while 21// the audit trail only GROWS and both recipients are retained 22// (Rule 13 additive-only). 23// T6 E-WILL NOT OVER-REFUSED : a properly executed e-will (testator + 2 24// witnesses + notary) in an e-wills state sends, signs and 25// completes -- we refuse the VOID path, not the valid one. 26// T7 TENANT ISOLATION : the per-tenant vault prefix discipline rejects 27// '.'/'/'/empty tenant ids (no cross-tenant traversal). 28// 29// NOTE (honest): the gate uses the single RFC 8032 KAT keypair for determinism; 30// binding each signer to their OWN key is a provisioning/PKI rung. What is 31// proven here is the WORKFLOW logic + the legal invariants, not multi-key PKI. 32// 33// Evidence -> knowledge/status/doc_envelope.log 34// license_tier: ORIGINAL 35import "nx_doc_envelope.nx" 36import "nx_doc_seal.nx" 37import "nx_doc_vault.nx" 38import "nx_legal_compliance.nx" 39import "nx_syscalls.nx" 40 41const DE_LOG: *u8 = "knowledge/status/doc_envelope.log" 42 43func 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 } 44func ewn(fd: i64, v: i64) -> i64 { 45 let bb: *u8 = sys_mmap(28); var m: i64 = v 46 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 47 let t: *u8 = sys_mmap(28); var k: i64 = 0 48 if m == 0 { t[0] = 48; k = 1 } 49 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 50 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 51 sys_write(fd, bb, k); return 0 52} 53func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 54 55// build + create a real seal in the shared NxSeal buffer; returns create status. 56func mk_seal(s: *NxSeal, dt: i64, ewills: i64, signer: *u8, ts: i64, 57 intent: i64, consent: i64, attribution: i64, retainable: i64, 58 witnesses: i64, notarized: i64) -> i64 { 59 s.doc_type = dt 60 s.e_wills_allowed = ewills 61 s.intent = intent 62 s.consent = consent 63 s.attribution = attribution 64 s.retainable = retainable 65 s.witnesses = witnesses 66 s.notarized = notarized 67 s.signer_id = signer 68 s.signer_id_len = slen(signer) 69 s.ts = ts 70 return nx_seal_create(s) 71} 72 73func main() -> i64 { 74 var ok: i64 = 1 75 76 // ---- RFC 8032 test-1 keypair (deterministic) ---- 77 let priv: *u8 = sys_mmap(64) 78 priv[0]=0x9d; priv[1]=0x61; priv[2]=0xb1; priv[3]=0x9d; priv[4]=0xef; priv[5]=0xfd; priv[6]=0x5a; priv[7]=0x60 79 priv[8]=0xba; priv[9]=0x84; priv[10]=0x4a; priv[11]=0xf4; priv[12]=0x92; priv[13]=0xec; priv[14]=0x2c; priv[15]=0xc4 80 priv[16]=0x44; priv[17]=0x49; priv[18]=0xc5; priv[19]=0x69; priv[20]=0x7b; priv[21]=0x32; priv[22]=0x69; priv[23]=0x19 81 priv[24]=0x70; priv[25]=0x3b; priv[26]=0xac; priv[27]=0x03; priv[28]=0x1c; priv[29]=0xae; priv[30]=0x7f; priv[31]=0x60 82 let pub: *u8 = sys_mmap(64) 83 pub[0]=0xd7; pub[1]=0x5a; pub[2]=0x98; pub[3]=0x01; pub[4]=0x82; pub[5]=0xb1; pub[6]=0x0a; pub[7]=0xb7 84 pub[8]=0xd5; pub[9]=0x4b; pub[10]=0xfe; pub[11]=0xd3; pub[12]=0xc9; pub[13]=0x64; pub[14]=0x07; pub[15]=0x3a 85 pub[16]=0x0e; pub[17]=0xe1; pub[18]=0x72; pub[19]=0xf3; pub[20]=0xda; pub[21]=0xa6; pub[22]=0x23; pub[23]=0x25 86 pub[24]=0xaf; pub[25]=0x02; pub[26]=0x1a; pub[27]=0x68; pub[28]=0xf7; pub[29]=0x07; pub[30]=0x51; pub[31]=0x1a 87 88 // ---- shared seal buffers + a synthetic 32-byte document hash ---- 89 let canon: *u8 = sys_mmap(512) 90 let sig: *u8 = sys_mmap(128) 91 let dh: *u8 = sys_mmap(64) 92 var di: i64 = 0 93 while di < 32 { dh[di] = ((di * 7 + 3) & 0xff) as u8; di = di + 1 } 94 let s: *NxSeal = sys_mmap(256) as *NxSeal 95 s.doc_hash = dh; s.doc_hash_len = 32 96 s.priv = priv; s.canon = canon; s.sig = sig 97 98 // ---- caller-allocated workflow stores ---- 99 let ecap: i64 = 16 100 let rcap: i64 = 32 101 let acap: i64 = 64 102 let vcap: i64 = 16 103 let eflat: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64 104 let rflat: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64 105 let aflat: *i64 = sys_mmap(acap * AF_STRIDE * 8) as *i64 106 let vflat: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64 107 var ne: i64 = 0 108 var nr: i64 = 0 109 var na: i64 = 0 110 var vcount: i64 = 0 111 112 let DOCID1: i64 = 7101 113 114 // ======== T1: happy path + vault integration ======== 115 var t1: i64 = 1 116 // the contract enters the additive vault as version 1 117 vcount = nx_vault_add(vflat, vcount, vcap, DOCID1, 5001, 1024, 1000) 118 if vcount != 1 { t1 = 0 } 119 ne = nx_env_create(eflat, ne, ecap, 9001, DOCID1, "Services Agreement" as *u8, 1, 1000) 120 if ne != 1 { t1 = 0 } 121 if nx_env_doctype(eflat, ne, 9001) != DT_CONTRACT { t1 = 0 } 122 if nx_env_regime(eflat, ne, 9001) != RG_UETA_GENERAL { t1 = 0 } 123 nr = nx_env_add_recipient(rflat, nr, rcap, 9001, 101, ROLE_SIGNER, 1) 124 nr = nx_env_add_recipient(rflat, nr, rcap, 9001, 102, ROLE_SIGNER, 2) 125 nr = nx_env_add_recipient(rflat, nr, rcap, 9001, 103, ROLE_CC, 3) 126 na = nx_env_audit_add(aflat, na, acap, 9001, EV_CREATED, 1, 1000) 127 if nx_env_send(eflat, ne, rflat, nr, 9001) != ENV_SEND_OK { t1 = 0 } 128 if nx_env_status(eflat, ne, 9001) != ENV_SENT { t1 = 0 } 129 na = nx_env_audit_add(aflat, na, acap, 9001, EV_SENT, 1, 1001) 130 // cannot complete before any signature 131 if nx_env_try_complete(eflat, ne, rflat, nr, 9001) != ENV_COMPLETE_NOT_READY { t1 = 0 } 132 // signer 1 signs (real VALID contract seal) 133 let a1: i64 = mk_seal(s, DT_CONTRACT, 1, "client1@andelinwest.com" as *u8, 1100, 1, 1, 1, 1, 0, 0) 134 if a1 != SEAL_OK { t1 = 0 } 135 if nx_env_sign(eflat, ne, rflat, nr, 9001, 101, s, pub) != ENV_SIGN_OK { t1 = 0 } 136 na = nx_env_audit_add(aflat, na, acap, 9001, EV_SIGNED, 101, 1100) 137 // still not complete (1 of 2) 138 if nx_env_try_complete(eflat, ne, rflat, nr, 9001) != ENV_COMPLETE_NOT_READY { t1 = 0 } 139 // signer 2 signs 140 let a2: i64 = mk_seal(s, DT_CONTRACT, 1, "client2@andelinwest.com" as *u8, 1200, 1, 1, 1, 1, 0, 0) 141 if a2 != SEAL_OK { t1 = 0 } 142 if nx_env_sign(eflat, ne, rflat, nr, 9001, 102, s, pub) != ENV_SIGN_OK { t1 = 0 } 143 na = nx_env_audit_add(aflat, na, acap, 9001, EV_SIGNED, 102, 1200) 144 // now completes 145 if nx_env_try_complete(eflat, ne, rflat, nr, 9001) != ENV_COMPLETE_OK { t1 = 0 } 146 if nx_env_status(eflat, ne, 9001) != ENV_COMPLETED { t1 = 0 } 147 na = nx_env_audit_add(aflat, na, acap, 9001, EV_COMPLETED, 1, 1300) 148 // the completed, sealed version is attached in the additive vault 149 if nx_vault_attach_seal(vflat, vcount, DOCID1) != VAULT_OK { t1 = 0 } 150 let vc: i64 = nx_vault_current_idx(vflat, vcount, DOCID1) 151 if vc < 0 { t1 = 0 } 152 if vflat[vc * VF_STRIDE + VF_SEAL] != 1 { t1 = 0 } 153 // a full audit trail exists (created/sent/signed/signed/completed) 154 if nx_env_audit_count(aflat, na, 9001) != 5 { t1 = 0 } 155 if t1 != 1 { ok = 0 } 156 157 // ======== T2: NEVER ROUTE A VOID INSTRUMENT (the s-class crux) ======== 158 var t2: i64 = 1 159 ne = nx_env_create(eflat, ne, ecap, 9002, 7102, "Last Will and Testament" as *u8, 0, 2000) 160 if nx_env_doctype(eflat, ne, 9002) != DT_WILL { t2 = 0 } 161 if nx_env_regime(eflat, ne, 9002) != RG_REQUIRES_WET { t2 = 0 } 162 nr = nx_env_add_recipient(rflat, nr, rcap, 9002, 201, ROLE_SIGNER, 1) 163 // SEND must refuse and leave the envelope in DRAFT (it never enters e-sign) 164 if nx_env_send(eflat, ne, rflat, nr, 9002) != ENV_SEND_REFUSED_VOID { t2 = 0 } 165 if nx_env_status(eflat, ne, 9002) != ENV_DRAFT { t2 = 0 } 166 if t2 != 1 { ok = 0 } 167 168 // ======== T3: routing order enforced ======== 169 var t3: i64 = 1 170 ne = nx_env_create(eflat, ne, ecap, 9003, 7103, "Partnership Agreement" as *u8, 1, 3000) 171 nr = nx_env_add_recipient(rflat, nr, rcap, 9003, 301, ROLE_SIGNER, 1) 172 nr = nx_env_add_recipient(rflat, nr, rcap, 9003, 302, ROLE_SIGNER, 2) 173 if nx_env_send(eflat, ne, rflat, nr, 9003) != ENV_SEND_OK { t3 = 0 } 174 // signer 2 (order 2) tries first -> OUT_OF_ORDER 175 let b2: i64 = mk_seal(s, DT_CONTRACT, 1, "p2@x.com" as *u8, 3200, 1, 1, 1, 1, 0, 0) 176 if nx_env_sign(eflat, ne, rflat, nr, 9003, 302, s, pub) != ENV_SIGN_OUT_OF_ORDER { t3 = 0 } 177 // signer 1 signs -> OK 178 let b1: i64 = mk_seal(s, DT_CONTRACT, 1, "p1@x.com" as *u8, 3300, 1, 1, 1, 1, 0, 0) 179 if nx_env_sign(eflat, ne, rflat, nr, 9003, 301, s, pub) != ENV_SIGN_OK { t3 = 0 } 180 // now signer 2 -> OK 181 let b3: i64 = mk_seal(s, DT_CONTRACT, 1, "p2@x.com" as *u8, 3400, 1, 1, 1, 1, 0, 0) 182 if nx_env_sign(eflat, ne, rflat, nr, 9003, 302, s, pub) != ENV_SIGN_OK { t3 = 0 } 183 if nx_env_try_complete(eflat, ne, rflat, nr, 9003) != ENV_COMPLETE_OK { t3 = 0 } 184 if t3 != 1 { ok = 0 } 185 186 // ======== T4: a tampered seal cannot sign or complete ======== 187 var t4: i64 = 1 188 ne = nx_env_create(eflat, ne, ecap, 9004, 7104, "Engagement Agreement" as *u8, 1, 4000) 189 nr = nx_env_add_recipient(rflat, nr, rcap, 9004, 401, ROLE_SIGNER, 1) 190 if nx_env_send(eflat, ne, rflat, nr, 9004) != ENV_SEND_OK { t4 = 0 } 191 let c4: i64 = mk_seal(s, DT_CONTRACT, 1, "client@x.com" as *u8, 4100, 1, 1, 1, 1, 0, 0) 192 if c4 != SEAL_OK { t4 = 0 } 193 // flip one canonical byte -> the Ed25519 seal no longer verifies 194 let cb4: *u8 = s.canon 195 cb4[10] = (cb4[10] ^ 0x55) as u8 196 if nx_env_sign(eflat, ne, rflat, nr, 9004, 401, s, pub) != ENV_SIGN_BAD_SEAL { t4 = 0 } 197 if nx_env_try_complete(eflat, ne, rflat, nr, 9004) != ENV_COMPLETE_NOT_READY { t4 = 0 } 198 // restore -> signs + completes 199 cb4[10] = (cb4[10] ^ 0x55) as u8 200 if nx_env_sign(eflat, ne, rflat, nr, 9004, 401, s, pub) != ENV_SIGN_OK { t4 = 0 } 201 if nx_env_try_complete(eflat, ne, rflat, nr, 9004) != ENV_COMPLETE_OK { t4 = 0 } 202 if t4 != 1 { ok = 0 } 203 204 // ======== T5: decline is additive (history retained) ======== 205 var t5: i64 = 1 206 ne = nx_env_create(eflat, ne, ecap, 9005, 7105, "Service Agreement" as *u8, 1, 5000) 207 nr = nx_env_add_recipient(rflat, nr, rcap, 9005, 501, ROLE_SIGNER, 1) 208 nr = nx_env_add_recipient(rflat, nr, rcap, 9005, 502, ROLE_SIGNER, 2) 209 if nx_env_send(eflat, ne, rflat, nr, 9005) != ENV_SEND_OK { t5 = 0 } 210 na = nx_env_audit_add(aflat, na, acap, 9005, EV_CREATED, 1, 5000) 211 na = nx_env_audit_add(aflat, na, acap, 9005, EV_SENT, 1, 5001) 212 na = nx_env_audit_add(aflat, na, acap, 9005, EV_VIEWED, 501, 5002) 213 if nx_env_audit_count(aflat, na, 9005) != 3 { t5 = 0 } 214 if nx_env_decline(eflat, ne, rflat, nr, 9005, 501) != 0 { t5 = 0 } 215 na = nx_env_audit_add(aflat, na, acap, 9005, EV_DECLINED, 501, 5003) 216 if nx_env_status(eflat, ne, 9005) != ENV_DECLINED { t5 = 0 } 217 // audit grew (never shrank) and both recipients are retained (not deleted) 218 if nx_env_audit_count(aflat, na, 9005) != 4 { t5 = 0 } 219 if nx_env_required_signers(rflat, nr, 9005) != 2 { t5 = 0 } 220 if t5 != 1 { ok = 0 } 221 222 // ======== T6: a proper e-will is NOT over-refused ======== 223 var t6: i64 = 1 224 ne = nx_env_create(eflat, ne, ecap, 9006, 7106, "Last Will and Testament" as *u8, 1, 6000) 225 if nx_env_regime(eflat, ne, 9006) != RG_ELECTRONIC_WILLS { t6 = 0 } 226 nr = nx_env_add_recipient(rflat, nr, rcap, 9006, 601, ROLE_SIGNER, 1) 227 // e-wills jurisdiction -> SEND is allowed (routed to the stricter regime) 228 if nx_env_send(eflat, ne, rflat, nr, 9006) != ENV_SEND_OK { t6 = 0 } 229 // properly executed e-will: testator + 2 witnesses + notary -> VALID 230 let e6: i64 = mk_seal(s, DT_WILL, 1, "testator@x.com" as *u8, 6100, 1, 0, 1, 1, 2, 1) 231 if e6 != SEAL_OK { t6 = 0 } 232 if s.regime != RG_ELECTRONIC_WILLS { t6 = 0 } 233 if nx_env_sign(eflat, ne, rflat, nr, 9006, 601, s, pub) != ENV_SIGN_OK { t6 = 0 } 234 if nx_env_try_complete(eflat, ne, rflat, nr, 9006) != ENV_COMPLETE_OK { t6 = 0 } 235 if t6 != 1 { ok = 0 } 236 237 // ======== T7: per-tenant vault prefix discipline (no traversal) ======== 238 var t7: i64 = 1 239 if nx_vault_valid_tid("client_andelinwest" as *u8) != 1 { t7 = 0 } 240 if nx_vault_valid_tid("../secret" as *u8) != 0 { t7 = 0 } 241 if nx_vault_valid_tid("a/b" as *u8) != 0 { t7 = 0 } 242 if nx_vault_valid_tid("" as *u8) != 0 { t7 = 0 } 243 if t7 != 1 { ok = 0 } 244 245 // ---- evidence ---- 246 var fd: i64 = 1 247 while fd >= 1 { 248 ew(fd, "DOCENVELOPEGATE authored=organ composes=D0+D1+D5 happy_complete=" as *u8); ewn(fd, t1) 249 ew(fd, " never_route_void=" as *u8); ewn(fd, t2) 250 ew(fd, " routing_order=" as *u8); ewn(fd, t3) 251 ew(fd, " tamper_no_complete=" as *u8); ewn(fd, t4) 252 ew(fd, " decline_additive=" as *u8); ewn(fd, t5) 253 ew(fd, " ewill_not_overrefused=" as *u8); ewn(fd, t6) 254 ew(fd, " tenant_isolation=" as *u8); ewn(fd, t7) 255 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) } 256 if fd == 1 { 257 let lf: i64 = sys_openat_append(DE_LOG, 420) 258 if lf >= 1 { fd = lf } else { fd = 0 } 259 } else { 260 sys_close(fd); fd = 0 261 } 262 } 263 264 if ok == 1 { return 0 } 265 return 1 266}