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}