nx_sign_envelope_gate.nx source
↩ module page · 131 lines · 5874 B
1// nx_sign_envelope_gate.nx -- INDEPENDENT gate for the Nishi Sign core lib (imports the SAME
2// shipped code the organ runs -- validation edge in the atlas, not a copy). Stronger than the
3// organ's self-test: tamper at EVERY chain position, truncation-tamper, cross-envelope
4// separation, persist round-trip. SELF-PUBLISHES its receipt to
5// knowledge/status/office_sign_gate.log (the ecomat live-derive evidence pointer; needle
6// "VERDICT=") -- evidence generated by the gate itself on the hub, never hand-asserted.
7// license_tier: ORIGINAL
8
9import "nx_sign_envelope_lib.nx"
10import "nx_gate_verdict.nx"
11
12// chained head over the 3 canonical events
13func sg_head3(g: *u8, e0: *u8, l0: i64, e1: *u8, l1: i64, e2: *u8, l2: i64, out: *u8) -> i64 {
14 let a: *u8 = sys_mmap(40)
15 let b: *u8 = sys_mmap(40)
16 se_chain(g, e0, l0, a)
17 se_chain(a, e1, l1, b)
18 se_chain(b, e2, l2, out)
19 return 0
20}
21
22func main() -> i64 {
23 var pass: i64 = 0
24 let e0: *u8 = sys_mmap(SE_EVT_CAP)
25 let e1: *u8 = sys_mmap(SE_EVT_CAP)
26 let e2: *u8 = sys_mmap(SE_EVT_CAP)
27 let l0: i64 = se_event_encode("ENV-G" as *u8, 0, "alice@firm" as *u8, "created" as *u8, 2000, e0)
28 let l1: i64 = se_event_encode("ENV-G" as *u8, 1, "bob@client" as *u8, "signed" as *u8, 2100, e1)
29 let l2: i64 = se_event_encode("ENV-G" as *u8, 2, "alice@firm" as *u8, "completed" as *u8, 2200, e2)
30 let g: *u8 = sys_mmap(40)
31 se_genesis(g)
32 let head: *u8 = sys_mmap(40)
33 sg_head3(g, e0, l0, e1, l1, e2, l2, head)
34
35 // T1 determinism: identical recompute -> identical head
36 let rh: *u8 = sys_mmap(40)
37 sg_head3(g, e0, l0, e1, l1, e2, l2, rh)
38 if se_eq32(head, rh) == 1 { pass = pass + 1 }
39
40 // T2/T3/T4 tamper at EVERY position: flip one byte of event i -> head must differ
41 let tb: *u8 = sys_mmap(SE_EVT_CAP)
42 let th: *u8 = sys_mmap(40)
43 var ti: i64 = 0
44 while ti < 3 {
45 var sl: i64 = l0
46 var sp: *u8 = e0
47 if ti == 1 { sl = l1 sp = e1 }
48 if ti == 2 { sl = l2 sp = e2 }
49 var c: i64 = 0
50 while c < sl { tb[c] = sp[c]; c = c + 1 }
51 tb[sl / 2] = (tb[sl / 2] + 1) as u8
52 if ti == 0 { sg_head3(g, tb, l0, e1, l1, e2, l2, th) }
53 if ti == 1 { sg_head3(g, e0, l0, tb, l1, e2, l2, th) }
54 if ti == 2 { sg_head3(g, e0, l0, e1, l1, tb, l2, th) }
55 if se_eq32(head, th) == 0 { pass = pass + 1 }
56 ti = ti + 1
57 }
58
59 // T5 truncation-tamper: dropping the last event changes the head
60 let t2: *u8 = sys_mmap(40)
61 let t2b: *u8 = sys_mmap(40)
62 se_chain(g, e0, l0, t2)
63 se_chain(t2, e1, l1, t2b)
64 if se_eq32(head, t2b) == 0 { pass = pass + 1 }
65
66 // T6 cross-envelope separation: same signers/actions, different env id -> different head
67 let f0: *u8 = sys_mmap(SE_EVT_CAP)
68 let f1: *u8 = sys_mmap(SE_EVT_CAP)
69 let f2: *u8 = sys_mmap(SE_EVT_CAP)
70 let m0: i64 = se_event_encode("ENV-H" as *u8, 0, "alice@firm" as *u8, "created" as *u8, 2000, f0)
71 let m1: i64 = se_event_encode("ENV-H" as *u8, 1, "bob@client" as *u8, "signed" as *u8, 2100, f1)
72 let m2: i64 = se_event_encode("ENV-H" as *u8, 2, "alice@firm" as *u8, "completed" as *u8, 2200, f2)
73 let oh: *u8 = sys_mmap(40)
74 sg_head3(g, f0, m0, f1, m1, f2, m2, oh)
75 if se_eq32(head, oh) == 0 { pass = pass + 1 }
76
77 // T7 persist round-trip on the seg_store (byte-exact)
78 let hhex: *u8 = sys_mmap(80)
79 se_hex(head, hhex)
80 let ek: *i64 = sys_mmap(8 * 3) as *i64
81 let ev: *i64 = sys_mmap(8 * 3) as *i64
82 ek[0] = ("env" as *u8) as i64
83 ev[0] = ("ENV-G" as *u8) as i64
84 ek[1] = ("status" as *u8) as i64
85 ev[1] = ("completed" as *u8) as i64
86 ek[2] = ("audit_head" as *u8) as i64
87 ev[2] = hhex as i64
88 let rec: *u8 = sys_mmap(4096)
89 let rl: i64 = canon_encode(ek, ev, 3, rec)
90 let prefix: *u8 = "/tmp/nx_sign_gate-" as *u8
91 reg_put(prefix, "env:" as *u8, "env:__idx__" as *u8, "ENV-G" as *u8, rec, rl)
92 let po: *i64 = sys_mmap(16) as *i64
93 let lo: *i64 = sys_mmap(16) as *i64
94 var t7: i64 = 0
95 if reg_get(prefix, "env:" as *u8, "ENV-G" as *u8, po, lo) == 1 {
96 if lo[0] == rl {
97 let src: *u8 = po[0] as *u8
98 var eq: i64 = 1
99 var y: i64 = 0
100 while y < rl { if src[y] != rec[y] { eq = 0 } y = y + 1 }
101 if eq == 1 { t7 = 1 }
102 }
103 }
104 if t7 == 1 { pass = pass + 1 }
105
106 // ---- receipt (stdout + self-published evidence log) ----
107 let out: *u8 = sys_mmap(512)
108 var o: i64 = 0
109 o = se_catcopy(out, o, "OFFICE-SIGN-GATE tests=7 pass=" as *u8)
110 o = se_catn(out, o, pass)
111 o = se_catcopy(out, o, " tamper-all-positions+truncation+separation+persist head=" as *u8)
112 var z: i64 = 0
113 while z < 64 { out[o] = hhex[z]; o = o + 1; z = z + 1 }
114 o = se_catcopy(out, o, " VERDICT=" as *u8)
115 if pass == 7 { o = se_catcopy(out, o, "GREEN" as *u8) }
116 if pass != 7 { o = se_catcopy(out, o, "RED" as *u8) }
117 out[o] = 10 as u8
118 o = o + 1
119 let wrc: i64 = ss_writefile("knowledge/status/office_sign_gate.log" as *u8, out, o)
120 sys_write(1, out, o)
121 if wrc < 0 { sys_write(1, "logwrite=FAILED\n" as *u8, 16) }
122 // MIGRATED onto nx_gate_verdict (D001). The teeth above are untouched, so the PASS/FAIL vector
123 // cannot change; only the hand-rolled exit is replaced, so /api/gate_run and the harness frame can
124 // READ the outcome instead of inferring it. The old exit smuggled the count through the status
125 // channel as `30 + pass`. The rich receipt line -- including head= -- is unchanged, so the ecomat
126 // live-derive evidence pointer that greps "VERDICT=" still resolves (rule 19).
127 let ctr: *i64 = gv_ctr()
128 ctr[0] = pass
129 ctr[1] = 7
130 return gv_verdict("OFFICE-SIGN-GATE" as *u8, ctr, "teeth unchanged; se_catn now composes the shared nxi_buf emitter -- the audit head hash is the byte-identity oracle for that swap" as *u8)
131}