code wiki / _hdl_build / nx_legal_portal_live_gate.nx
nx_legal_portal_live_gate.nx source
↩ module page · 206 lines · 9629 B
1// nx_legal_portal_live_gate.nx -- LIVE LOOPBACK proof for the legal portal.
2//
3// The same fork pattern as nx_email_live_gate: parent = the portal server
4// (sys_accept -> lp_serve_conn over the real router), child = a real HTTP client
5// that connects over 127.0.0.1 and asserts the response BYTES came back over the
6// wire. This lifts the portal from "pure handler proven in-process" to "served
7// correctly over a real socket" -- WITHOUT any production deploy (loopback only,
8// the process exits; pointing a public daemon at it is a separate operator step).
9//
10// conn 1: GET /portal/envelopes -> 200 + "env 9601 status SENT" over the wire
11// conn 2: GET /portal/doc?id=8601 -> 200 + the document body BYTE-EXACT over
12// the socket (binary integrity end-to-end).
13// GREEN iff the child asserts both and exits 0.
14//
15// Evidence -> knowledge/status/legal_portal_live.log
16// license_tier: ORIGINAL
17import "nx_legal_portal.nx"
18import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
19import "nx_doc_envelope.nx"
20import "nx_doc_serve.nx"
21import "nx_doc_annotate.nx"
22import "nx_doc_vault.nx"
23import "nx_doc_seal.nx"
24import "nx_legal_compliance.nx"
25import "nx_syscalls.nx"
26
27const LPL_PORT: i64 = 0x2560 // 9568, loopback
28const LPL_LOG: *u8 = "knowledge/status/legal_portal_live.log"
29
30func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
31func g_addr(out: *u8, port: i64) -> i64 {
32 out[0] = 2 as u8; out[1] = 0 as u8
33 out[2] = ((port >> 8) & 0xff) as u8; out[3] = (port & 0xff) as u8
34 out[4] = 127 as u8; out[5] = 0 as u8; out[6] = 0 as u8; out[7] = 1 as u8
35 var i: i64 = 8
36 while i < 16 { out[i] = 0 as u8; i = i + 1 }
37 return 0
38}
39func g_starts(buf: *u8, n: i64, s: *u8) -> i64 {
40 let sn: i64 = slen(s)
41 if n < sn { return 0 }
42 var i: i64 = 0
43 while i < sn { if buf[i] != s[i] { return 0 } i = i + 1 }
44 return 1
45}
46func g_contains(hay: *u8, n: i64, needle: *u8) -> i64 {
47 let nn: i64 = slen(needle)
48 if nn == 0 { return 1 }
49 var i: i64 = 0
50 while i + nn <= n {
51 var m: i64 = 1
52 var j: i64 = 0
53 while j < nn { if hay[i + j] != needle[j] { m = 0; break } j = j + 1 }
54 if m == 1 { return 1 }
55 i = i + 1
56 }
57 return 0
58}
59func g_read_all(fd: i64, buf: *u8, cap: i64) -> i64 {
60 var n: i64 = 0
61 while n < cap {
62 let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - n)
63 if r <= 0 { return n }
64 n = n + r
65 }
66 return n
67}
68// one client request/response cycle over a fresh connection; returns response len.
69func g_client_once(addr: *u8, reqline: *u8, resp: *u8, rcap: i64) -> i64 {
70 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
71 if cfd < 0 { return 0 - 1 }
72 if nx_connect_bounded(cfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(cfd); return 0 - 1 }
73 let rl: i64 = slen(reqline)
74 var w: i64 = 0
75 while w < rl {
76 let k: i64 = sys_write(cfd, (reqline as i64 + w) as *u8, rl - w)
77 if k <= 0 { sys_close(cfd); return 0 - 1 }
78 w = w + k
79 }
80 let n: i64 = g_read_all(cfd, resp, rcap)
81 sys_close(cfd)
82 return n
83}
84func mk_seal(s: *NxSeal, dt: i64, ewills: i64, signer: *u8, ts: i64,
85 intent: i64, consent: i64, attribution: i64, retainable: i64,
86 witnesses: i64, notarized: i64) -> i64 {
87 s.doc_type = dt; s.e_wills_allowed = ewills
88 s.intent = intent; s.consent = consent; s.attribution = attribution
89 s.retainable = retainable; s.witnesses = witnesses; s.notarized = notarized
90 s.signer_id = signer; s.signer_id_len = slen(signer); s.ts = ts
91 return nx_seal_create(s)
92}
93func lpl_log(green: i64) -> i64 {
94 let fd: i64 = sys_openat_append(LPL_LOG, 420)
95 if fd < 0 { return 0 }
96 sys_write(fd, "LEGALPORTALLIVEGATE authored=organ live=loopback-http " as *u8, slen("LEGALPORTALLIVEGATE authored=organ live=loopback-http " as *u8))
97 if green == 1 { sys_write(fd, "envelopes_over_wire=PASS doc_byteexact_over_wire=PASS verdict=GREEN\n" as *u8, slen("envelopes_over_wire=PASS doc_byteexact_over_wire=PASS verdict=GREEN\n" as *u8)) }
98 else { sys_write(fd, "verdict=RED\n" as *u8, slen("verdict=RED\n" as *u8)) }
99 sys_close(fd)
100 return 0
101}
102
103func main() -> i64 {
104 // ---- RFC 8032 test-1 keypair ----
105 let priv: *u8 = sys_mmap(64)
106 priv[0]=0x9d; priv[1]=0x61; priv[2]=0xb1; priv[3]=0x9d; priv[4]=0xef; priv[5]=0xfd; priv[6]=0x5a; priv[7]=0x60
107 priv[8]=0xba; priv[9]=0x84; priv[10]=0x4a; priv[11]=0xf4; priv[12]=0x92; priv[13]=0xec; priv[14]=0x2c; priv[15]=0xc4
108 priv[16]=0x44; priv[17]=0x49; priv[18]=0xc5; priv[19]=0x69; priv[20]=0x7b; priv[21]=0x32; priv[22]=0x69; priv[23]=0x19
109 priv[24]=0x70; priv[25]=0x3b; priv[26]=0xac; priv[27]=0x03; priv[28]=0x1c; priv[29]=0xae; priv[30]=0x7f; priv[31]=0x60
110 let pub: *u8 = sys_mmap(64)
111 pub[0]=0xd7; pub[1]=0x5a; pub[2]=0x98; pub[3]=0x01; pub[4]=0x82; pub[5]=0xb1; pub[6]=0x0a; pub[7]=0xb7
112 pub[8]=0xd5; pub[9]=0x4b; pub[10]=0xfe; pub[11]=0xd3; pub[12]=0xc9; pub[13]=0x64; pub[14]=0x07; pub[15]=0x3a
113 pub[16]=0x0e; pub[17]=0xe1; pub[18]=0x72; pub[19]=0xf3; pub[20]=0xda; pub[21]=0xa6; pub[22]=0x23; pub[23]=0x25
114 pub[24]=0xaf; pub[25]=0x02; pub[26]=0x1a; pub[27]=0x68; pub[28]=0xf7; pub[29]=0x07; pub[30]=0x51; pub[31]=0x1a
115 let dh: *u8 = sys_mmap(64)
116 var di: i64 = 0
117 while di < 32 { dh[di] = ((di * 7 + 3) & 0xff) as u8; di = di + 1 }
118 let s: *NxSeal = sys_mmap(256) as *NxSeal
119 s.doc_hash = dh; s.doc_hash_len = 32; s.priv = priv; s.canon = sys_mmap(512); s.sig = sys_mmap(128)
120
121 // ---- one tenant's stores: a SENT 1-of-2-signed contract + a vault doc ----
122 let ecap: i64 = 8
123 let rcap: i64 = 16
124 let ncap: i64 = 8
125 let vcap: i64 = 8
126 let eflat: *i64 = sys_mmap(ecap * EF_STRIDE * 8) as *i64
127 let rflat: *i64 = sys_mmap(rcap * RF_STRIDE * 8) as *i64
128 let anflat: *i64 = sys_mmap(ncap * NF_STRIDE * 8) as *i64
129 let vflat: *i64 = sys_mmap(vcap * VF_STRIDE * 8) as *i64
130 var ne: i64 = 0
131 var nr: i64 = 0
132 var na: i64 = 0
133 var vc: i64 = 0
134 ne = nx_env_create(eflat, ne, ecap, 9601, 8601, "Services Agreement" as *u8, 1, 1000)
135 nr = nx_env_add_recipient(rflat, nr, rcap, 9601, 101, ROLE_SIGNER, 1)
136 nr = nx_env_add_recipient(rflat, nr, rcap, 9601, 102, ROLE_SIGNER, 2)
137 nx_env_send(eflat, ne, rflat, nr, 9601)
138 let cs: i64 = mk_seal(s, DT_CONTRACT, 1, "client1@andelinwest.com" as *u8, 1100, 1, 1, 1, 1, 0, 0)
139 nx_env_sign(eflat, ne, rflat, nr, 9601, 101, s, pub)
140 vc = nx_vault_add(vflat, vc, vcap, 8601, 5001, 64, 1000)
141
142 let docb: *u8 = sys_mmap(64)
143 docb[0]=37; docb[1]=80; docb[2]=68; docb[3]=70; docb[4]=13; docb[5]=10; docb[6]=0; docb[7]=88
144 let doclen: i64 = 8
145 let eidbuf: *i64 = sys_mmap(32) as *i64
146 eidbuf[0] = 9601
147
148 let ctx: *NxPortalCtx = sys_mmap(256) as *NxPortalCtx
149 ctx.user_level = 1
150 ctx.eflat = eflat; ctx.ne = ne
151 ctx.rflat = rflat; ctx.nr = nr
152 ctx.anflat = anflat; ctx.na = na
153 ctx.vflat = vflat; ctx.vc = vc
154 ctx.doc_id = 8601; ctx.doc_bytes = docb; ctx.doc_len = doclen; ctx.doc_fmt = DF_PDF
155 ctx.env_ids = eidbuf; ctx.env_count = 1
156
157 // ---- bind + listen on loopback ----
158 let addr: *u8 = sys_mmap(16)
159 g_addr(addr, LPL_PORT)
160 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
161 if lfd < 0 { lpl_log(0); sys_exit(91); return 91 }
162 let opt: *u8 = sys_mmap(4); opt[0] = 1 as u8; sys_setsockopt(lfd, 1, 2, opt, 4) // SO_REUSEADDR: re-runnable across TIME_WAIT
163 if sys_bind(lfd, addr, 16) < 0 { lpl_log(0); sys_exit(92); return 92 }
164 if sys_listen(lfd, 8) < 0 { lpl_log(0); sys_exit(93); return 93 }
165
166 let pid: i64 = sys_fork()
167 if pid < 0 { lpl_log(0); sys_exit(94); return 94 }
168 if pid == 0 {
169 // child: the HTTP client
170 var spin: i64 = 0
171 while spin < 400000 { spin = spin + 1 }
172 var cok: i64 = 1
173 let resp1: *u8 = sys_mmap(16384)
174 let n1: i64 = g_client_once(addr, "GET /portal/envelopes HTTP/1.1\r\nHost: x\r\n\r\n" as *u8, resp1, 16384)
175 if g_starts(resp1, n1, "HTTP/1.1 200" as *u8) != 1 { cok = 0 }
176 if g_contains(resp1, n1, "env 9601 status SENT" as *u8) != 1 { cok = 0 }
177 let resp2: *u8 = sys_mmap(16384)
178 let n2: i64 = g_client_once(addr, "GET /portal/doc?id=8601 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8, resp2, 16384)
179 if g_starts(resp2, n2, "HTTP/1.1 200" as *u8) != 1 { cok = 0 }
180 if nx_doc_serve_roundtrip_ok(resp2, n2, docb, doclen) != 1 { cok = 0 }
181 if cok == 1 { sys_exit(0); return 0 }
182 sys_exit(7); return 7
183 }
184
185 // parent: serve the two connections through the real router
186 let s1: i64 = sys_accept(lfd)
187 if s1 >= 0 { lp_serve_conn(ctx, s1); sys_close(s1) }
188 let s2: i64 = sys_accept(lfd)
189 if s2 >= 0 { lp_serve_conn(ctx, s2); sys_close(s2) }
190
191 let status: *i64 = sys_mmap(8) as *i64
192 sys_wait4(pid, status, 0)
193 let child_code: i64 = (status[0] >> 8) & 0xff
194
195 var green: i64 = 0
196 if child_code == 0 { green = 1 }
197
198 sys_write(1, "LEGALPORTALLIVEGATE authored=organ live=loopback-http child_code=" as *u8, slen("LEGALPORTALLIVEGATE authored=organ live=loopback-http child_code=" as *u8))
199 let nb: *u8 = sys_mmap(8); nb[0] = (48 + (child_code % 10)) as u8; sys_write(1, nb, 1)
200 if green == 1 { sys_write(1, " envelopes+doc_over_wire=PASS verdict=GREEN\n" as *u8, slen(" envelopes+doc_over_wire=PASS verdict=GREEN\n" as *u8)) }
201 else { sys_write(1, " verdict=RED\n" as *u8, slen(" verdict=RED\n" as *u8)) }
202 lpl_log(green)
203
204 if green == 1 { sys_exit(0); return 0 }
205 sys_exit(1); return 1
206}