nx_legal_portal_boot.nx source
↩ module page · 112 lines · 4436 B
1// nx_legal_portal_boot.nx -- LEGAL RUNG D8: portal boot-reload (BUILT->LIVE persistence wiring).
2//
3// module: nishi-core.legal.portal_boot
4// capability: LEGAL_PORTAL_BOOT
5//
6// Wires D7 persistence (nx_legal_store) into the D6 portal: a portal daemon can
7// PERSIST a tenant's workflow stores and RELOAD them on boot, so in-flight
8// envelopes/signatures survive a restart instead of vanishing with the in-RAM
9// demo fixture. This is the step that turns the loopback-live portal from
10// "serves over a socket but forgets on restart" into "durable across restarts".
11//
12// lp_boot_save : persist all four per-tenant stores (envelopes, recipients,
13// annotations, vault) to the tenant's files.
14// lp_boot_load : on boot, load all four into fresh arrays, set the pctx
15// counts, and rebuild env_ids from the reloaded envelope store
16// (absent files -> empty, a clean first boot, never garbage).
17//
18// Composes: nx_legal_portal (NxPortalCtx), nx_legal_store (ls_save/load), and the
19// store strides from nx_doc_envelope / nx_doc_annotate / nx_doc_vault.
20// license_tier: ORIGINAL
21// lineage_id: nishi_legal_portal_boot_d8
22import "nx_syscalls.nx"
23import "nx_legal_portal.nx"
24import "nx_legal_store.nx"
25import "nx_doc_envelope.nx"
26import "nx_doc_annotate.nx"
27import "nx_doc_vault.nx"
28const K_MAGIC_8192: i64 = 8192
29const K_MAGIC_16384: i64 = 16384
30
31// persist all four of a tenant's workflow stores. Returns 0, or -1 on bad tenant.
32func lp_boot_save(pctx: *NxPortalCtx, base: *u8, tenant: *u8) -> i64 {
33 let p: *u8 = sys_mmap(512)
34 if ls_path(p, base, tenant, "env" as *u8) < 0 { return 0 - 1 }
35 ls_save(pctx.eflat, pctx.ne, EF_STRIDE, p)
36 ls_path(p, base, tenant, "rcpt" as *u8)
37 ls_save(pctx.rflat, pctx.nr, RF_STRIDE, p)
38 ls_path(p, base, tenant, "ann" as *u8)
39 ls_save(pctx.anflat, pctx.na, NF_STRIDE, p)
40 ls_path(p, base, tenant, "vault" as *u8)
41 ls_save(pctx.vflat, pctx.vc, VF_STRIDE, p)
42 return 0
43}
44
45// load all four stores into the provided fresh arrays + wire them into pctx; an
46// absent store loads as empty (clean first boot). Rebuilds env_ids from eflat.
47func lp_boot_load(pctx: *NxPortalCtx, base: *u8, tenant: *u8,
48 eflat: *i64, ecap: i64, rflat: *i64, rcap: i64,
49 anflat: *i64, ncap: i64, vflat: *i64, vcap: i64, eidbuf: *i64) -> i64 {
50 let p: *u8 = sys_mmap(512)
51 pctx.eflat = eflat
52 pctx.rflat = rflat
53 pctx.anflat = anflat
54 pctx.vflat = vflat
55 if ls_path(p, base, tenant, "env" as *u8) < 0 { return 0 - 1 }
56 var n: i64 = ls_load(eflat, ecap, EF_STRIDE, p)
57 if n < 0 { n = 0 }
58 pctx.ne = n
59 ls_path(p, base, tenant, "rcpt" as *u8)
60 var r: i64 = ls_load(rflat, rcap, RF_STRIDE, p)
61 if r < 0 { r = 0 }
62 pctx.nr = r
63 ls_path(p, base, tenant, "ann" as *u8)
64 var a: i64 = ls_load(anflat, ncap, NF_STRIDE, p)
65 if a < 0 { a = 0 }
66 pctx.na = a
67 ls_path(p, base, tenant, "vault" as *u8)
68 var v: i64 = ls_load(vflat, vcap, VF_STRIDE, p)
69 if v < 0 { v = 0 }
70 pctx.vc = v
71 var ec: i64 = 0
72 var i: i64 = 0
73 while i < pctx.ne {
74 eidbuf[ec] = eflat[i * EF_STRIDE + EF_ENV]
75 ec = ec + 1
76 i = i + 1
77 }
78 pctx.env_ids = eidbuf
79 pctx.env_count = ec
80 return 0
81}
82
83// does the request start with "POST "?
84func lp_is_post(req: *u8, n: i64) -> i64 {
85 if n < 5 { return 0 }
86 if req[0] == 80 { if req[1] == 79 { if req[2] == 83 { if req[3] == 84 { if req[4] == 32 { return 1 } } } } }
87 return 0
88}
89
90// serve one connection with READ + WRITE: GET -> lp_handle; POST -> lp_handle_post then
91// PERSIST the mutation (lp_boot_save) so an interactive change survives a restart. ncap
92// bounds POST annotation adds. The daemon's accept loop calls this.
93func lp_serve_conn_rw(pctx: *NxPortalCtx, ncap: i64, base: *u8, tenant: *u8, cfd: i64) -> i64 {
94 let req: *u8 = sys_mmap(K_MAGIC_8192)
95 let out: *u8 = sys_mmap(K_MAGIC_16384)
96 let rn: i64 = lp_read_request(cfd, req, K_MAGIC_8192)
97 if rn <= 0 { return 0 - 1 }
98 var on: i64 = 0
99 if lp_is_post(req, rn) == 1 {
100 on = lp_handle_post(pctx, ncap, req, rn, out)
101 lp_boot_save(pctx, base, tenant)
102 } else {
103 on = lp_handle(pctx, req, rn, out)
104 }
105 var w: i64 = 0
106 while w < on {
107 let k: i64 = sys_write(cfd, (out as i64 + w) as *u8, on - w)
108 if k <= 0 { return 0 - 1 }
109 w = w + k
110 }
111 return on
112}