code wiki / _hdl_build / nx_connect_appd.nx

nx_connect_appd.nx source

↩ module page · 486 lines · 25509 B

1// nx_connect_appd.nx -- the DEPLOYABLE CONNECT app daemon (ops shell around the pure core 2// nx_connect_serve). Binds 0.0.0.0:8032 (LAN: http://192.168.8.227:8032/). Route /connect -> this port 3// on the sovereign edge. Build with --build-only; run deliberately. license_tier: ORIGINAL 4// 5// 2026-07-10 PERSISTENCE + PER-SESSION: anonymous nxc_sess cookie -> an isolated persistent world. 6// 2026-07-25 SHARED CONTENT-BLIND PLANE (E2E): daemon-owned pubkey directory + routed ciphertext, replayed 7// from the append-only connect/shared.cbl at boot. 8// 2026-07-25 REAL LOGIN (the accounts rung -- gates everything): full OPAQUE aPAKE (RFC 9807) via the shared 9// nx_opaque_login seam, in CONNECT's OWN realm (nishi_connect, self-provisioned keys+store). The server 10// stores only an OPAQUE envelope -- NO password-equivalent at rest. A signed session token rides the 11// nxc_auth cookie; each request resolves it via olg_whoami to a stable 32-byte user-id -> the world binds 12// to identity, not to an anonymous cookie. The display handle is resolved from a per-account file the 13// daemon writes at register/login. Crypto lives HERE (the shell); the pure core only renders from the 14// auth slots stamped into ctx. Unifying with one family-wide realm (nishi_site_admin) is the next rung. 15import "nx_connect_accounts.nx" 16import "nx_connect_album.nx" 17import "nx_opaque_login.nx" // olg_ctx_setup_ttl / olg_register / olg_login / olg_whoami + NxAuthContext + NX_MAUTH_OK 18 19const CD_MAGIC_262144: i64 = 262144 20const CD_MAGIC_1048576: i64 = 1048576 21const CD_MAGIC_1024: i64 = 1024 // shared-plane delta-append emit buffer (one row max ~350B) 22 23const CD_PORT: i64 = 0x1f60 // 8032 (8031 = survey lane) 24 25// OPAQUE realm config (data-driven; own realm keeps CONNECT accounts isolated from the family primary store). 26const CD_REALM: *u8 = "nishi_connect" 27const CD_REALM_N: i64 = 13 28const CD_DISP: *u8 = "Nishi Connect" 29const CD_DISP_N: i64 = 13 30const CD_AUTH_KEYS: *u8 = "connect_auth_keys.bin\x00" 31const CD_AUTH_STORE: *u8 = "connect_auth_store.log\x00" 32const CD_SESS_TTL: i64 = 86400 // 24h == NX_MAUTH_HARD_MAX_TTL_S (the modauth hard cap; a longer TTL is 33 // rejected by nx_auth_context_init). Sessions renew on the next sign-in; 34 // a sliding refresh (olg_refresh) past 24h is a follow-on. 35const CD_ARGON_M: i64 = 19456 // 19 MiB argon2id (OWASP 2026 alt profile) -- real KSF, snappy on the NAS 36const CD_ARGON_T: i64 = 2 37const CD_ARGON_P: i64 = 1 38const CD_PW_MIN: i64 = 8 // minimum passphrase length 39const CD_COMPACT_EVERY: i64 = 16 // after this many delete-on-delivery acks, physically compact shared.cbl 40 41func cd_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 42func cd_addr(out: *u8, port: i64) -> i64 { 43 out[0]=2 as u8 44 out[1]=0 as u8 45 out[2]=((port>>8)&0xff) as u8 46 out[3]=(port&0xff) as u8 47 var i: i64=4 48 while i<16 { out[i]=0 as u8; i=i+1 } 49 return 0 50} 51func cd_is_post(req: *u8) -> i64 { 52 if req[0]==(80 as u8) { if req[1]==(79 as u8) { if req[2]==(83 as u8) { if req[3]==(84 as u8) { return 1 } } } } // "POST" 53 return 0 54} 55 56// generic cookie value extractor: find <key> (e.g. "nxc_auth=") in the raw request, copy its value (ends at 57// ';', whitespace, CR or LF) into out (nul-terminated). Returns the value length, 0 if absent. 58func cd_cookie_val(req: *u8, reqlen: i64, key: *u8, keylen: i64, out: *u8, cap: i64) -> i64 { 59 var i: i64=0 60 while i+keylen<=reqlen { 61 var m: i64=1 62 var j: i64=0 63 while j<keylen { if req[i+j]!=key[j] { m=0; j=keylen } else { j=j+1 } } 64 if m==1 { 65 var q: i64=i+keylen 66 var t: i64=0 67 var go: i64=1 68 while go==1 { 69 if q>=reqlen { go=0 } else { 70 let c: i64 = req[q] as i64 & 0xff 71 if c==59 { go=0 } else { if c==32 { go=0 } else { if c==13 { go=0 } else { if c==10 { go=0 } else { 72 if t<cap-1 { out[t]=c as u8; t=t+1 } 73 q=q+1 74 } } } } 75 } 76 } 77 out[t]=0 as u8 78 return t 79 } 80 i=i+1 81 } 82 out[0]=0 as u8 83 return 0 84} 85// extract the request path token (after the method, up to the next space) into out (nul-terminated). 86func cd_req_path(req: *u8, reqlen: i64, out: *u8, cap: i64) -> i64 { 87 var i: i64=0 88 var seen: i64=0 89 while seen==0 { if i>=reqlen { seen=1 } else { if req[i]==(32 as u8) { i=i+1; seen=1 } else { i=i+1 } } } 90 var t: i64=0 91 var go: i64=1 92 while go==1 { 93 if i>=reqlen { go=0 } else { 94 if req[i]==(32 as u8) { go=0 } else { if t<cap-1 { out[t]=req[i]; t=t+1 } i=i+1 } 95 } 96 } 97 out[t]=0 as u8 98 return t 99} 100// lowercase A-Z in place (a form handle may arrive capitalised; the directory is canonical-lowercase). 101func cd_lower(buf: *u8, n: i64) -> i64 { 102 var i: i64=0 103 while i<n { let c: i64 = buf[i] as i64 & 0xff; if c>=65 { if c<=90 { buf[i]=(c+32) as u8 } } i=i+1 } 104 return 0 105} 106// per-account display-handle file: connect/h<acct>.txt (acct = the identity-derived i64; the file just 107// resolves uid->handle for DISPLAY -- identity/authz never trust it). 108func cd_handle_path(acct: i64, out: *u8) -> i64 { 109 var o: i64 = 0 110 let pfx: *u8 = "connect/h" as *u8 111 while pfx[o]!=(0 as u8) { out[o]=pfx[o]; o=o+1 } 112 let t: *u8 = sys_mmap(28) 113 var m: i64 = acct 114 if m<0 { m=0-m } 115 var k: i64=0 116 if m==0 { out[o]=48 as u8; o=o+1 } else { while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } var jj: i64=0; while jj<k { out[o]=t[k-1-jj]; o=o+1; jj=jj+1 } } 117 let ext: *u8 = ".txt\x00" as *u8 118 var e: i64=0 119 while ext[e]!=(0 as u8) { out[o]=ext[e]; o=o+1; e=e+1 } 120 out[o]=0 as u8 121 return o 122} 123func cd_write_handle(acct: i64, handle: *u8, hn: i64) -> i64 { 124 let path: *u8 = sys_mmap(64) 125 cd_handle_path(acct, path) 126 let fd: i64 = sys_openat_wr(path, 0x1a4) 127 if fd<0 { return 0-1 } 128 sys_write(fd, handle, hn) 129 sys_close(fd) 130 return hn 131} 132func cd_read_handle(acct: i64, out: *u8, cap: i64) -> i64 { 133 let path: *u8 = sys_mmap(64) 134 cd_handle_path(acct, path) 135 let fd: i64 = sys_openat_rd(path) 136 if fd<0 { out[0]=0 as u8; return 0 } 137 var t: i64=0 138 var go: i64=1 139 while go==1 { 140 if t>=cap-1 { go=0 } else { 141 let r: i64 = sys_read(fd, (out as i64 + t) as *u8, cap-1-t) 142 if r<=0 { go=0 } else { t=t+r } 143 } 144 } 145 sys_close(fd) 146 // trim trailing whitespace/newlines (defensive; cd_write_handle writes no trailer), then nul-terminate. 147 var trimming: i64=1 148 while trimming==1 { 149 if t<=0 { trimming=0 } else { 150 let c: i64 = out[t-1] as i64 & 0xff 151 if c==10 { t=t-1 } else { if c==13 { t=t-1 } else { if c==32 { t=t-1 } else { trimming=0 } } } 152 } 153 } 154 out[t]=0 as u8 155 return t 156} 157// insert one header line (nul-terminated, already ending in CRLF) right after the response status line. 158func cd_inject_line(resp: *u8, resp_len: i64, line: *u8, out: *u8, cap: i64) -> i64 { 159 var eol: i64 = 0-1 160 var i: i64=0 161 while i+1<resp_len { if resp[i]==(13 as u8) { if resp[i+1]==(10 as u8) { eol=i+2; i=resp_len } } i=i+1 } 162 if eol<0 { var k: i64=0; while k<resp_len { if k<cap { out[k]=resp[k] } k=k+1 } return resp_len } 163 var o: i64=0 164 var a: i64=0 165 while a<eol { if o<cap { out[o]=resp[a] } o=o+1; a=a+1 } 166 var li: i64=0 167 while line[li]!=(0 as u8) { if o<cap { out[o]=line[li] } o=o+1; li=li+1 } 168 var b: i64=eol 169 while b<resp_len { if o<cap { out[o]=resp[b] } o=o+1; b=b+1 } 170 return o 171} 172// build "Set-Cookie: nxc_auth=<val>; Path=/; HttpOnly; SameSite=Lax; Max-Age=<maxage>\r\n" into out(z-term). 173func cd_setcookie(val: *u8, val_len: i64, maxage: i64, out: *u8) -> i64 { 174 var o: i64=0 175 let pre: *u8 = "Set-Cookie: nxc_auth=" as *u8 176 var i: i64=0 177 while pre[i]!=(0 as u8) { out[o]=pre[i]; o=o+1; i=i+1 } 178 var v: i64=0 179 while v<val_len { out[o]=val[v]; o=o+1; v=v+1 } 180 let mid: *u8 = "; Path=/; HttpOnly; SameSite=Lax; Max-Age=" as *u8 181 i=0 182 while mid[i]!=(0 as u8) { out[o]=mid[i]; o=o+1; i=i+1 } 183 let t: *u8 = sys_mmap(28) 184 var m: i64=maxage 185 var k: i64=0 186 if m==0 { out[o]=48 as u8; o=o+1 } else { while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } var jj: i64=0; while jj<k { out[o]=t[k-1-jj]; o=o+1; jj=jj+1 } } 187 out[o]=13 as u8; o=o+1; out[o]=10 as u8; o=o+1 188 out[o]=0 as u8 189 return o 190} 191 192// digits only, bounded by n -- a form field is untrusted input (rule 12) and must not run off its length 193func cd_atoi_n(s: *u8, n: i64) -> i64 { 194 var v: i64=0; var i: i64=0 195 while i<n { let c: i64 = s[i] as i64; if c>=48 { if c<=57 { v=v*10+(c-48) } } i=i+1 } 196 return v 197} 198// wrap a JSON body in a minimal HTTP/1.1 response; returns total bytes, 0 if it will not fit 199func cd_json_resp(body: *u8, bn: i64, out: *u8, cap: i64) -> i64 { 200 if bn<=0 { return 0 } 201 var o: i64=0 202 o = cs_cat(out, o, "HTTP/1.1 200 OK 203Content-Type: application/json 204Cache-Control: no-store 205Content-Length: " as *u8) 206 o = cs_catn(out, o, bn) 207 o = cs_cat(out, o, " 208Connection: close 209 210" as *u8) 211 if o+bn >= cap { return 0 } 212 var i: i64=0 213 while i<bn { out[o+i]=body[i]; i=i+1 } 214 return o+bn 215} 216func main() -> i64 { 217 let ctx: *i64 = cs_world_new() 218 let dir: *u8 = "connect\x00" as *u8 219 sys_mkdir(dir, 0x1ff) 220 // ---- OPAQUE auth context: fail-CLOSED if the realm keys cannot be provisioned (never serve unauthed-broken) ---- 221 let actx: *NxAuthContext = sys_mmap(256) as *NxAuthContext 222 if olg_ctx_setup_ttl(actx, CD_AUTH_KEYS, CD_AUTH_STORE, CD_REALM, CD_REALM_N, CD_DISP, CD_DISP_N, CD_SESS_TTL, CD_ARGON_M, CD_ARGON_T, CD_ARGON_P) != 0 { 223 cd_p("NX-CONNECT-APPD OPAQUE auth ctx FAILED (connect_auth_keys.bin unwritable?) -- fail closed, fail loud\n" as *u8) 224 return 1 225 } 226 // ---- shared content-blind plane: boot = replay the append-only log ---- 227 let sh: *i64 = cs_shared_new() 228 let shlog: *u8 = "connect/shared.cbl\x00" as *u8 229 let shlenp: *i64 = sys_mmap(16) as *i64 230 let shboot: *u8 = sys_read_file(shlog, shlenp) 231 if (shboot as i64)!=0 { cs_sh_replay(sh, shboot, shlenp[0]) } 232 let shline: *u8 = sys_mmap(CD_MAGIC_1024) 233 let shcompact: *u8 = sys_mmap(CD_MAGIC_262144) // compaction rewrite buffer (whole minimal log) 234 let shtmp: *u8 = "connect/shared.cbl.tmp\x00" as *u8 235 var acks_since_compact: i64 = 0 236 let addr: *u8 = sys_mmap(16) 237 cd_addr(addr, CD_PORT) 238 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 239 if lfd<0 { cd_p("NX-CONNECT-APPD socket FAILED\n" as *u8); return 1 } 240 let one: *i64 = (sys_mmap(8)) as *i64 241 one[0]=1 242 sys_setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, one as *u8, 4) 243 if sys_bind(lfd, addr, 16)<0 { cd_p("NX-CONNECT-APPD bind 0.0.0.0:8032 FAILED (port busy?)\n" as *u8); return 1 } 244 if sys_listen(lfd, 16)<0 { cd_p("NX-CONNECT-APPD listen FAILED\n" as *u8); return 1 } 245 cd_p("NX-CONNECT-APPD serving http://0.0.0.0:8032/ (OPAQUE login + per-account worlds + content-blind plane)\n" as *u8) 246 let reqb: *u8 = sys_mmap(CD_MAGIC_262144) 247 let resb: *u8 = sys_mmap(CD_MAGIC_1048576) 248 let resb2: *u8 = sys_mmap(CD_MAGIC_1048576) 249 let cookiebuf: *u8 = sys_mmap(256) 250 let sessbuf: *u8 = sys_mmap(64) 251 // auth per-request scratch (hoisted -- no per-request mmap) 252 let pathbuf: *u8 = sys_mmap(320) 253 let authtok: *u8 = sys_mmap(600) // nxc_auth cookie value (b64 token) 254 let uidbuf: *u8 = sys_mmap(64) // 32-byte user-id from whoami 255 let uidn: *i64 = sys_mmap(16) as *i64 256 let handlebuf: *u8 = sys_mmap(64) // display handle (from form or the per-account file) 257 let fhandle: *u8 = sys_mmap(64) // form handle 258 let fpw: *u8 = sys_mmap(300) // form passphrase 259 let newtok: *u8 = sys_mmap(600) // freshly minted session token (b64) 260 let newtokn: *i64 = sys_mmap(16) as *i64 261 let mnbuf: *u8 = sys_mmap(600) // recovery mnemonic (shown once) 262 let mnn: *i64 = sys_mmap(16) as *i64 263 let ckline: *u8 = sys_mmap(768) // Set-Cookie line 264 var salt: i64 = 0 265 var go: i64=1 266 while go==1 { 267 let cfd: i64 = sys_accept(lfd) // 1-arg accept (the opaque_login syscall set; peer addr not needed) 268 if cfd>=0 { 269 let rn: i64 = cs_read_req(cfd, reqb, CD_MAGIC_262144) 270 if rn>0 { 271 let now: i64 = sys_now_realtime_sec() 272 let is_post: i64 = cd_is_post(reqb) 273 // ---- parse path, strip the /connect edge prefix ---- 274 cd_req_path(reqb, rn, pathbuf, 320) 275 var pp: *u8 = pathbuf 276 if cs_starts(pp, "/connect" as *u8)==1 { pp = (pathbuf as i64 + 8) as *u8 } 277 if pp[0]==(0 as u8) { pp = "/" as *u8 } 278 // strip any query string from pp (so /account?x still matches /account) 279 var qi: i64=0 280 while pp[qi]!=(0 as u8) { if pp[qi]==(63 as u8) { pp[qi]=0 as u8 } qi=qi+1 } 281 282 // ---- resolve current identity from the nxc_auth cookie ---- 283 var authed: i64 = 0 284 handlebuf[0]=0 as u8 285 var acct: i64 = 0 286 var auth_event: i64 = CS_AE_NONE 287 var cookie_action: i64 = 0 // 0 none, 1 set token, 2 clear token 288 var mn_show: i64 = 0 289 let al: i64 = cd_cookie_val(reqb, rn, "nxc_auth=" as *u8, 9, authtok, 600) 290 if al > 0 { 291 if olg_whoami(actx, authtok, al, now, uidbuf, 64, uidn) == NX_MAUTH_OK { 292 authed = 1 293 acct = acc_id_from_range(uidbuf, uidn[0]) 294 cd_read_handle(acct, handlebuf, 64) 295 } 296 } 297 298 // ---- auth POST actions (crypto in the shell) ---- 299 // body = after CRLFCRLF (cs_form_get needs the field at a boundary: body-start or after '&'). 300 var aboff: i64 = rn 301 var aj: i64=0 302 while aj+3<rn { if reqb[aj]==(13 as u8) { if reqb[aj+1]==(10 as u8) { if reqb[aj+2]==(13 as u8) { if reqb[aj+3]==(10 as u8) { aboff=aj+4; aj=rn } } } } aj=aj+1 } 303 let abody: *u8 = (reqb as i64 + aboff) as *u8 304 let ablen: i64 = rn - aboff 305 if is_post==1 { 306 if cs_seq(pp, "/login" as *u8)==1 { 307 let hn: i64 = cs_form_get(abody, ablen, "handle" as *u8, fhandle, 32) 308 let pn: i64 = cs_form_get(abody, ablen, "pw" as *u8, fpw, 256) 309 cd_lower(fhandle, hn) 310 var lhn: i64 = 0; while fhandle[lhn]!=(0 as u8) { lhn=lhn+1 } 311 if olg_login(actx, fhandle, lhn, fpw, pn, newtok, 600, newtokn) == NX_MAUTH_OK { 312 if olg_whoami(actx, newtok, newtokn[0], now, uidbuf, 64, uidn) == NX_MAUTH_OK { 313 authed = 1 314 acct = acc_id_from_range(uidbuf, uidn[0]) 315 cd_write_handle(acct, fhandle, lhn) 316 var w: i64=0; while fhandle[w]!=(0 as u8) { handlebuf[w]=fhandle[w]; w=w+1 } handlebuf[w]=0 as u8 317 cookie_action = 1 318 auth_event = CS_AE_SIGNED_IN 319 } 320 } else { auth_event = CS_AE_LOGIN_FAIL } 321 } 322 else { if cs_seq(pp, "/register" as *u8)==1 { 323 let hn: i64 = cs_form_get(abody, ablen, "handle" as *u8, fhandle, 32) 324 let pn: i64 = cs_form_get(abody, ablen, "pw" as *u8, fpw, 256) 325 cd_lower(fhandle, hn) 326 var lhn: i64 = 0; while fhandle[lhn]!=(0 as u8) { lhn=lhn+1 } 327 if cs_name_ok(fhandle)==0 { auth_event = CS_AE_REG_BAD } 328 else { if pn < CD_PW_MIN { auth_event = CS_AE_REG_BAD } 329 else { 330 let rrc: i64 = olg_register(actx, fhandle, lhn, fpw, pn, mnbuf, 600, mnn) 331 if rrc == NX_MAUTH_OK { 332 if olg_login(actx, fhandle, lhn, fpw, pn, newtok, 600, newtokn) == NX_MAUTH_OK { 333 if olg_whoami(actx, newtok, newtokn[0], now, uidbuf, 64, uidn) == NX_MAUTH_OK { 334 authed = 1 335 acct = acc_id_from_range(uidbuf, uidn[0]) 336 cd_write_handle(acct, fhandle, lhn) 337 var w2: i64=0; while fhandle[w2]!=(0 as u8) { handlebuf[w2]=fhandle[w2]; w2=w2+1 } handlebuf[w2]=0 as u8 338 mnbuf[mnn[0]]=0 as u8 339 mn_show = 1 340 cookie_action = 1 341 auth_event = CS_AE_REGISTERED 342 } 343 } 344 } else { auth_event = CS_AE_REG_TAKEN } 345 } } 346 } 347 else { if cs_seq(pp, "/logout" as *u8)==1 { 348 authed = 0 349 handlebuf[0]=0 as u8 350 cookie_action = 2 351 auth_event = CS_AE_SIGNED_OUT 352 } } } 353 } 354 355 // ---- account_id: authenticated identity, else anonymous nxc_sess ---- 356 var new_sess: i64 = 0 357 var slen: i64 = 0 358 if authed==1 { 359 // acct already set from the uid above 360 cs_world_reset(ctx) 361 acc_load(ctx, acct, dir) 362 } else { 363 let vl: i64 = acc_cookie_get(reqb, rn, cookiebuf, 256) 364 if vl > 0 { acct = acc_id_from_range(cookiebuf, vl) } 365 else { salt = salt + 1; slen = acc_session_mint(salt, sessbuf); acct = acc_id_from_range(sessbuf, slen); new_sess = 1 } 366 cs_world_reset(ctx) 367 acc_load(ctx, acct, dir) 368 } 369 370 // ---- stamp identity into ctx for rendering (survives world_reset because set AFTER it) ---- 371 ctx[CS_AUTH] = authed 372 // stamp the authenticated 32-byte user-id so the /pubkey route can BIND the key to identity 373 // (kills trust-on-first-use). uidbuf holds the whoami hash; 0 for anonymous requests. 374 if authed==1 { ctx[CS_UID] = uidbuf as i64 } else { ctx[CS_UID] = 0 } 375 if authed==1 { ctx[CS_HANDLE] = handlebuf as i64 } else { ctx[CS_HANDLE] = 0 } 376 ctx[CS_AUTH_EVENT] = auth_event 377 if mn_show==1 { ctx[CS_MNEMONIC] = mnbuf as i64 } else { ctx[CS_MNEMONIC] = 0 } 378 ctx[CS_SH] = sh as i64 // the contacts page checks the shared pubkey directory for each contact 379 380 // ---- ALBUM / SHARING API (JSON) -- /connect/album/<verb> ---- 381 // The crypto-and-syscall half lives here in the shell, exactly like auth: nx_connect_serve 382 // is a pure emitter and cannot touch seg_store. `acct` is the OPAQUE-derived account id and 383 // is passed straight through as the actor -- the caller never names themselves, so there is 384 // no identity to forge in the request. Signed-out is actor 0, which every mutating verb in 385 // al_do refuses (album gate T3/T3b). 386 var album_n: i64 = 0 387 let aitem: *u8 = sys_mmap(128) 388 if cs_starts(pp, "/album/" as *u8)==1 { 389 let averb: *u8 = ((pp as i64) + 7) as *u8 390 var asubj: i64 = 0 391 var arid: i64 = 0 392 if is_post==1 { 393 let sn: i64 = cs_form_get(abody, ablen, "subject" as *u8, fhandle, 32) 394 if sn > 0 { asubj = cd_atoi_n(fhandle, sn) } 395 let idn: i64 = cs_form_get(abody, ablen, "id" as *u8, fpw, 32) 396 if idn > 0 { arid = cd_atoi_n(fpw, idn) } 397 // item id for the containment verbs. Untrusted input: bounded, and left EMPTY when 398 // absent so al_do refuses rather than acting on a blank. 399 let itn: i64 = cs_form_get(abody, ablen, "item" as *u8, aitem, 96) 400 if itn <= 0 { aitem[0] = 0 as u8 } 401 } else { aitem[0] = 0 as u8 } 402 var aactor: i64 = 0 403 if authed==1 { aactor = acct } 404 let ajson: *u8 = sys_mmap(CD_MAGIC_1024*8) 405 let ajn: i64 = al_do(CD_SHARE_PREFIX, averb, aactor, asubj, "album" as *u8, arid, aitem, ajson, CD_MAGIC_1024*8) 406 album_n = cd_json_resp(ajson, ajn, resb, CD_MAGIC_1048576) 407 } 408 409 // ---- handle (session plane + shared plane) ---- 410 let np0: i64 = sh[0] 411 let nm0: i64 = sh[1] 412 let pg0: i64 = sh[3] 413 let ag0: i64 = sh[4] 414 var on: i64 = 0 415 if album_n==0 { on = cs_handle2(ctx, sh, reqb, rn, resb, CD_MAGIC_1048576) } 416 if is_post == 1 { 417 if authed==1 { acc_save(ctx, acct, dir) } 418 else { if cookie_action==0 { acc_save(ctx, acct, dir) } } // anon POST persists too (unless logout) 419 // shared plane deltas (append-only) 420 if sh[3]!=pg0 { 421 let af: i64 = sys_openat_append(shlog, 0x1a4) 422 if af>=0 { 423 if sh[0]>np0 { 424 var ai: i64=np0 425 while ai<sh[0] { let an: i64 = cs_sh_emit_pub(sh, ai, shline, 0); sys_write(af, shline, an); ai=ai+1 } 426 } else { 427 if sh[2]>=0 { let au: i64 = cs_sh_emit_pub(sh, sh[2], shline, 0); sys_write(af, shline, au) } 428 } 429 sys_close(af) 430 } 431 } 432 if sh[1]>nm0 { 433 let af2: i64 = sys_openat_append(shlog, 0x1a4) 434 if af2>=0 { 435 var mi: i64=nm0 436 while mi<sh[1] { let mn2: i64 = cs_sh_emit_msg(sh, mi, shline, 0); sys_write(af2, shline, mn2); mi=mi+1 } 437 sys_close(af2) 438 } 439 } 440 // delete-on-delivery: an ack tombstoned a message -> persist a D row so it stays delivered. 441 if sh[4]!=ag0 { 442 if sh[5]>=0 { 443 let af3: i64 = sys_openat_append(shlog, 0x1a4) 444 if af3>=0 { let tn: i64 = cs_sh_emit_tomb(sh, sh[5], shline, 0); sys_write(af3, shline, tn); sys_close(af3) } 445 } 446 // COMPACTION: after enough deliveries, PHYSICALLY rewrite shared.cbl to a minimal log 447 // that drops every tombstoned message -- delivered ciphertext + metadata bytes are then 448 // GONE FROM DISK (delete-on-delivery becomes physical), and the log can't grow unbounded. 449 // Atomic (tmp + rename) so a crash never leaves a torn log; on next boot the compacted 450 // file replays into a clean plane. Runs between requests (single-process accept loop). 451 acks_since_compact = acks_since_compact + 1 452 if acks_since_compact >= CD_COMPACT_EVERY { 453 let cn: i64 = cs_sh_compact_emit(sh, shcompact) 454 let cf: i64 = sys_openat_wr(shtmp, 0x1a4) 455 if cf>=0 { 456 cs_write_all(cf, shcompact, cn) 457 sys_fsync(cf) 458 sys_close(cf) 459 if sys_renameat(shtmp, shlog) >= 0 { acks_since_compact = 0 } 460 } 461 } 462 } 463 } 464 465 // ---- respond (inject the right cookie) ---- 466 if album_n>0 { cs_write_all(cfd, resb, album_n) } else { 467 if cookie_action==1 { 468 cd_setcookie(newtok, newtokn[0], CD_SESS_TTL, ckline) 469 let onx: i64 = cd_inject_line(resb, on, ckline, resb2, CD_MAGIC_1048576) 470 if onx > 0 { cs_write_all(cfd, resb2, onx) } 471 } else { if cookie_action==2 { 472 cd_setcookie("" as *u8, 0, 0, ckline) 473 let onx2: i64 = cd_inject_line(resb, on, ckline, resb2, CD_MAGIC_1048576) 474 if onx2 > 0 { cs_write_all(cfd, resb2, onx2) } 475 } else { if new_sess == 1 { 476 let on2: i64 = acc_inject_cookie(resb, on, sessbuf, slen, resb2, CD_MAGIC_1048576) 477 if on2 > 0 { cs_write_all(cfd, resb2, on2) } 478 } else { 479 if on > 0 { cs_write_all(cfd, resb, on) } 480 } } } } 481 } 482 sys_close(cfd) 483 } 484 } 485 return 0 486}