code wiki / _hdl_build / nx_email_portal_daemon.nx
nx_email_portal_daemon.nx
buildroot/runtime/_hdl_build/nx_email_portal_daemon.nx
about
nx_email_portal_daemon.nx -- the mail.<domain> EMAIL-PORTAL daemon on the CANONICAL ecosystem auth
(the SAME Modern Auth the doc portal / status use: OPAQUE-3DH + Argon2id + NO-COOKIE Ed25519 session).
Replaces the demo-grade nx_email_webmail_daemon (hardcoded single mailbox, NO auth) with a real
multi-user, per-domain portal:
GET / -> login + register + mail SPA shell (public)
POST /mail/register -> invite-gated OPAQUE self-registration (handle -> <handle>@<domain>)
POST /mail/login -> handle+passphrase -> 200 {"token":...} | 401
* /mail/* (token) -> X-Nishi-Session validates -> the mailbox is derived ONLY from the
session handle (per-user isolation BY CONSTRUCTION -- no request
parameter can address another user's mailbox):
GET /mail/inbox -> HTML fragment: newest-first message list (Subject/From, escaped)
GET /mail/msg?n=K -> HTML fragment: the raw message, HTML-escaped
POST /mail/del?n=K -> soft-delete (seg_store tombstone; history preserved, rule 13)
POST /mail/send -> to/subject/body form: rcpt@<domain> -> REAL local delivery into the
rcpt mailbox (same store the data-driven MTA delivers into, so real
inbound mail appears here the moment MX/relay is armed);
foreign rcpt -> appended to relay-queue@<domain> + an HONEST
"QUEUED-EXTERNAL (relay not armed)" receipt -- never a fake send.
GET /mail/whoami -> {"handle":...,"mailbox":...}
Loopback HTTP daemon behind the SNI router's mail.<d> row (sites.elf reverse-proxies; TLS terminates
at sites.elf with the per-domain wildcard). Every response carries Content-Length (the buffered-proxy
contract). Pure router epd_handle = bytes-in/bytes-out (the gate drives it in-process, no socket).
license_tier: ORIGINAL
dependencies 6 imports · 1 importers
imports: nx_status_daemon.nxnx_modern_auth_flow.nxnx_syscalls.nxnx_invite_token.nxnx_opaque_login.nxnx_email_webmail.nx
imported by: nx_email_portal_gate.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 30 | const EPD_MAGIC_1024: i64 = 1024 |
| 31 | const EPD_MAGIC_8192: i64 = 8192 |
| 33 | const EPD_REQCAP: i64 = 65536 |
| 34 | const EPD_OUTCAP: i64 = 262144 |
| 35 | const EPD_BODYCAP: i64 = 131072 |
| 36 | const EPD_MSGCAP: i64 = 24576 // assembled outbound message cap |
| 37 | const EPD_SHOWCAP: i64 = 16384 // per-message render cap (truncated view beyond) |
| 38 | const EPD_INBOX_PAGE: i64 = 50 // newest-first page size |
functions
| 42 | func epd_handle_ok(h: *u8, n: i64) -> i64 |
| 65 | func epd_hex32(src: *u8, out: *u8) -> i64 |
| 77 | func epd_mailmap_path(ctx: *NxAuthContext, out: *u8) -> i64 |
| 88 | func epd_map_put(path: *u8, hexuid: *u8, h: *u8, hn: i64) -> i64 |
| 105 | func epd_map_get(path: *u8, hexuid: *u8, out: *u8, cap: i64) -> i64 |
| 137 | func epd_ci_eq(h: *u8, hn: i64, lit: *u8) -> i64 |
| 154 | func epd_mailbox(h: *u8, hn: i64, domain: *u8, out: *u8) -> i64 |
| 166 | func epd_resp(out: *u8, status: *u8, ctype: *u8, body: *u8, blen: i64) -> i64 called by 7: epd_shellepd_landing_mailepd_inbox_pageepd_read_pageepd_write_pageepd_sent_page+1 calls 2: sd_catsd_catn |
| 181 | func epd_qn(path: *u8, pn: i64) -> i64 called by 1: epd_handle |
| 213 | func epd_shell(domain: *u8, out: *u8) -> i64 |
| 243 | func epd_inbox_frag(prefix: *u8, mailbox: *u8, body: *u8) -> i64 called by 1: epd_handle calls 7: nx_mbox_countsd_catsys_mmapnx_mbox_get_nnx_mime_header_findsd_catn+1 |
| 285 | func epd_assemble(fromb: *u8, tob: *u8, tn: i64, subjb: *u8, sn: i64, bodyb: *u8, bn: i64, msg: *u8) -> i64 |
| 309 | func epd_qs_mailbox(ctx: *NxAuthContext, domain: *u8, path: *u8, pn: i64, now: i64, shand: *u8, shn_p: *i64, mbox: *u8) -> i64 called by 1: epd_handle calls 7: sys_mmapnx_sa_validate_qsepd_hex32epd_mailmap_pathepd_map_getepd_handle_ok+1 |
| 329 | func epd_splice(body: *u8, b: i64, sraw: *u8, srn: i64) -> i64 |
| 337 | func epd_landing_mail(out: *u8, b64: *u8, b64n: i64) -> i64 |
| 347 | func epd_inbox_page(prefix: *u8, mbox: *u8, sraw: *u8, srn: i64, out: *u8) -> i64 called by 1: epd_handle calls 9: sys_mmapsd_catepd_splicenx_mbox_countnx_mbox_get_nnx_mime_header_find+3 |
| 391 | func epd_read_page(prefix: *u8, mbox: *u8, idx: i64, sraw: *u8, srn: i64, out: *u8) -> i64 |
| 416 | func epd_write_page(domain: *u8, sraw: *u8, srn: i64, out: *u8) -> i64 |
| 433 | func epd_deliver(domain: *u8, prefix: *u8, shand: *u8, tob: *u8, sub: *u8, bod: *u8, lens: *i64, rmsg: *u8) -> i64 |
| 474 | func epd_sent_page(rmsg: *u8, rlen: i64, sraw: *u8, srn: i64, out: *u8) -> i64 |
| 488 | func epd_handle(ctx: *NxAuthContext, domain: *u8, prefix: *u8, req: *u8, req_n: i64, out: *u8) -> i64 called by 2: mainmain calls 41: sys_mmapsd_find_pathsd_startssys_now_realtime_secepd_qs_mailboxnx_sa_qs_raw+35 |
| 913 | func main(argc: i64, argv: *i64) -> i64 |