code wiki / (root) / nx_legal_portal_boot.nx

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}