code wiki / _hdl_build / nx_email_invite_gate.nx
nx_email_invite_gate.nx source
↩ module page · 106 lines · 5145 B
1// nx_email_invite_gate.nx -- MEASURED gate for the invite-mint provisioning seam (nx_email_invite's
2// core = inv_issue composed against the SAME inv_check/inv_consume the live portal registration
3// runs). Proves the full lifecycle offline against a scratch store:
4// T1 mint -> NX_INV_OK + 64 lowercase-hex token
5// T2 accept -> inv_check(same realm, fresh) returns the minted level
6// T3 realm-bind -> inv_check(WRONG realm) = 0 (an andelinwest invite can never register on
7// another domain's portal -- the per-domain delegation boundary)
8// T4 single-use -> inv_consume then inv_check = 0 (no replay)
9// T5 expiry -> ttl=1 token checked at now+5 = 0 (fail-closed)
10// GREEN iff 5/5. Appends knowledge/status/email_invite_gate.log. license_tier: ORIGINAL
11import "nx_invite_token.nx"
12import "nx_g_puts_lib.nx"
13import "nx_syscalls.nx"
14
15func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
16func g_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
17func g_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}
27
28func main() -> i64 {
29 g_puts("=== EMAIL INVITE GATE: mint->accept->realm-bind->single-use->expiry (the portal's own check path) ===\n" as *u8)
30 let store: *u8 = "knowledge/status/email_invite_gate.invites" as *u8
31 // reset the scratch store (idempotent gate, rule 10)
32 let rfd: i64 = sys_openat_wr(store, 0x1a4)
33 if rfd >= 0 { sys_close(rfd) }
34 let realm: *u8 = "mailgate-realm" as *u8
35 let wrong: *u8 = "other-realm" as *u8
36 let now: i64 = sys_now_realtime_sec()
37 var pass: i64 = 0
38
39 // T1 mint
40 let tok: *u8 = sys_mmap(80)
41 let rc: i64 = inv_issue(store, realm, g_slen(realm), 3, 3600, now, tok)
42 var t1: i64 = 0
43 if rc == NX_INV_OK {
44 var hexok: i64 = 1
45 var i: i64 = 0
46 while i < 64 {
47 let c: i64 = tok[i] as i64
48 var ok: i64 = 0
49 if c >= 48 { if c <= 57 { ok = 1 } }
50 if c >= 97 { if c <= 102 { ok = 1 } }
51 if ok == 0 { hexok = 0 }
52 i = i + 1
53 }
54 if hexok == 1 { t1 = 1 }
55 }
56 pass = pass + t1
57 g_puts(" T1 mint 64-hex: " as *u8); if t1 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
58
59 // T2 accept (same realm, fresh)
60 let lvl: i64 = inv_check(store, tok, 64, realm, g_slen(realm), now + 1)
61 var t2: i64 = 0
62 if lvl == 3 { t2 = 1 }
63 pass = pass + t2
64 g_puts(" T2 accept level==3 (got " as *u8); g_putn(lvl); g_puts("): " as *u8); if t2 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
65
66 // T3 realm binding
67 let lw: i64 = inv_check(store, tok, 64, wrong, g_slen(wrong), now + 1)
68 var t3: i64 = 0
69 if lw == 0 { t3 = 1 }
70 pass = pass + t3
71 g_puts(" T3 wrong-realm rejected: " as *u8); if t3 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
72
73 // T4 single-use
74 inv_consume(store, tok, 64, now + 2)
75 let lc: i64 = inv_check(store, tok, 64, realm, g_slen(realm), now + 3)
76 var t4: i64 = 0
77 if lc == 0 { t4 = 1 }
78 pass = pass + t4
79 g_puts(" T4 consumed no-replay: " as *u8); if t4 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
80
81 // T5 expiry fail-closed
82 let tok2: *u8 = sys_mmap(80)
83 let rc2: i64 = inv_issue(store, realm, g_slen(realm), 1, 1, now, tok2)
84 var t5: i64 = 0
85 if rc2 == NX_INV_OK {
86 let le: i64 = inv_check(store, tok2, 64, realm, g_slen(realm), now + 5)
87 if le == 0 { t5 = 1 }
88 }
89 pass = pass + t5
90 g_puts(" T5 expired rejected: " as *u8); if t5 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
91
92 g_puts("----\nEMAIL-INVITE rows=5 pass=" as *u8); g_putn(pass); g_puts("\n" as *u8)
93 let lg: i64 = sys_openat_append("knowledge/status/email_invite_gate.log" as *u8, 0x1a4)
94 if lg >= 0 {
95 g_w(lg, "INVITEGATE mint_hex=" as *u8); if t1 == 1 { g_w(lg, "1" as *u8) } else { g_w(lg, "0" as *u8) }
96 g_w(lg, " accept=" as *u8); if t2 == 1 { g_w(lg, "1" as *u8) } else { g_w(lg, "0" as *u8) }
97 g_w(lg, " realm_bind=" as *u8); if t3 == 1 { g_w(lg, "1" as *u8) } else { g_w(lg, "0" as *u8) }
98 g_w(lg, " single_use=" as *u8); if t4 == 1 { g_w(lg, "1" as *u8) } else { g_w(lg, "0" as *u8) }
99 g_w(lg, " expiry=" as *u8); if t5 == 1 { g_w(lg, "1" as *u8) } else { g_w(lg, "0" as *u8) }
100 if pass == 5 { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) }
101 sys_close(lg)
102 }
103 if pass == 5 { g_puts("EMAIL-INVITE GREEN (the provisioning seam is measured end-to-end)\n" as *u8); sys_exit(0); return 0 }
104 g_puts("EMAIL-INVITE RED\n" as *u8)
105 sys_exit(1); return 1
106}