code wiki / _hdl_build / nx_email_invite.nx
nx_email_invite.nx source
↩ module page · 61 lines · 2950 B
1// nx_email_invite.nx -- CLI: mint ONE mailbox invite for a domain's email portal (the provisioning
2// seam of nx_email_portal_daemon: registration is invite-gated, so "create a new email address" =
3// mint an invite + hand it to the person; they self-register with their OWN passphrase -- the
4// operator never knows or sets user secrets, OPAQUE end-to-end).
5// Designed to run as a capability-gated MCP tool with a FULLY PINNED allowlist row per domain
6// (store+realm+level+ttl pinned server-side -> the caller's cap can only ever mint for ITS domain;
7// that IS the per-site-admin delegation, enforced by construction).
8// nx_email_invite <invites_store_path> <realm> <level> <ttl_s>
9// prints: INVITE token=<64-hex> realm=<realm> level=<n> ttl_s=<n>
10// Composes the proven nx_invite_token store (inv_issue; sha256-keyed, append-only, fail-closed).
11// license_tier: ORIGINAL
12import "nx_invite_token.nx"
13import "nx_syscalls.nx"
14
15func ei_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
16func ei_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
17func ei_putn(v: i64) -> i64 {
18 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
19 var m: i64 = v
20 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
21 let t: *u8 = sys_mmap(24); var k: i64 = 0
22 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
23 let o: *u8 = sys_mmap(24); var w: i64 = 0; var q: i64 = k - 1
24 while q >= 0 { o[w] = t[q]; w = w + 1; q = q - 1 }
25 sys_write(1, o, w); return 0
26}
27func ei_atoi(s: *u8) -> i64 {
28 var v: i64 = 0; var i: i64 = 0
29 while s[i] != (0 as u8) {
30 let c: i64 = s[i] as i64
31 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } }
32 i = i + 1
33 }
34 return v
35}
36
37func main(argc: i64, argv: *i64) -> i64 {
38 if argc < 5 {
39 ei_puts("usage: nx_email_invite <invites_store_path> <realm> <level> <ttl_s>\n" as *u8)
40 ei_puts(" mints one self-registration invite for the domain portal bound to (store, realm).\n" as *u8)
41 sys_exit(2); return 2
42 }
43 let store: *u8 = argv[1] as *u8
44 let realm: *u8 = argv[2] as *u8
45 let level: i64 = ei_atoi(argv[3] as *u8)
46 let ttl: i64 = ei_atoi(argv[4] as *u8)
47 let tok: *u8 = sys_mmap(80)
48 let rc: i64 = inv_issue(store, realm, ei_slen(realm), level, ttl, sys_now_realtime_sec(), tok)
49 if rc != NX_INV_OK {
50 ei_puts("INVITE-FAIL rc=" as *u8); ei_putn(rc)
51 ei_puts(" (bad input, csprng, or store io; store must be creatable/appendable)\n" as *u8)
52 sys_exit(1); return 1
53 }
54 ei_puts("INVITE token=" as *u8)
55 sys_write(1, tok, 64)
56 ei_puts(" realm=" as *u8); ei_puts(realm)
57 ei_puts(" level=" as *u8); ei_putn(level)
58 ei_puts(" ttl_s=" as *u8); ei_putn(ttl)
59 ei_puts("\n register at the domain's mail portal: handle + passphrase + THIS invite code.\n" as *u8)
60 sys_exit(0); return 0
61}