code wiki / _hdl_build / nx_capability_route.nx
nx_capability_route.nx source
↩ module page · 51 lines · 3064 B
1// nx_capability_route.nx -- THE GLOBAL FUNCTIONALITY SPLIT (operator 2026-06-28: "global capabilities like mail or
2// admin live on the .xxx.com [subdomain] ... the site visitors contents live on the forward slash off the root
3// domain"). A PURE host-header classifier (NO syscalls, NO imports -> unit-gateable offline against crafted host
4// strings, exactly like nx_sni_route): given a request Host, decide whether it is a CAPABILITY subdomain
5// (mail.<d> / admin.<d> = the GLOBAL machinery, SAME for every domain) or CONTENT (<d> / www.<d> = the per-domain
6// public site, served by PATH). The TLS-terminating front (the sites daemon) calls cr_capability per request:
7// CR_CONTENT -> serve the per-domain docroot via the content router (nx_host_router hr_serve3), path-routed
8// CR_ADMIN/MAIL -> reverse-proxy to the loopback capability daemon (the SAME pattern by which the sites daemon
9// already reverse-proxies nx_status_daemon)
10// Data-driven prefix table (Cardinal 11: add a capability = add a prefix row, no logic change). The actual
11// reverse-proxy wiring into the sites daemon + running the loopback daemons + the *.<d> cert SANs are the
12// operator-gated DEPLOY step; this is the routing DECISION, sovereign + proven. license_tier: ORIGINAL
13
14const CR_CONTENT: i64 = 0 // <d> / www.<d> -> per-domain public site content (path-routed visitor content)
15const CR_ADMIN: i64 = 1 // admin.<d> -> the document-portal admin daemon (nx_docportal_admin_daemon)
16const CR_MAIL: i64 = 2 // mail.<d> -> the webmail daemon (nx_email_webmail_daemon)
17
18// loopback ports the TLS front reverse-proxies a capability subdomain to (CONTENT is served in-process, not proxied)
19const CR_PORT_ADMIN: i64 = 8456
20const CR_PORT_MAIL: i64 = 8457
21
22// leading-label prefix match: does host[0..hn) begin with prefix[0..pn), case-insensitive? The prefix INCLUDES the
23// dot ("admin."), so "administrative.com" is NOT admin -- only the real leading label "admin." matches.
24func cr_starts(host: *u8, hn: i64, prefix: *u8, pn: i64) -> i64 {
25 if hn < pn { return 0 }
26 var i: i64 = 0
27 while i < pn {
28 var c: i64 = host[i] as i64
29 if c >= 65 { if c <= 90 { c = c + 32 } }
30 var p: i64 = prefix[i] as i64
31 if p >= 65 { if p <= 90 { p = p + 32 } }
32 if c != p { return 0 }
33 i = i + 1
34 }
35 return 1
36}
37
38// classify a (lowercased-or-not) Host into a capability. www. is CONTENT (the bare site). Default = CONTENT.
39// GLOBAL: the same rule for every domain -- admin.andelinwest.com and admin.nishifamily.com both -> CR_ADMIN.
40func cr_capability(host: *u8, hn: i64) -> i64 {
41 if cr_starts(host, hn, "admin." as *u8, 6) == 1 { return CR_ADMIN }
42 if cr_starts(host, hn, "mail." as *u8, 5) == 1 { return CR_MAIL }
43 return CR_CONTENT
44}
45
46// the loopback backend port for a capability, or 0 for CONTENT (served in-process by the front, not proxied).
47func cr_backend_port(cap: i64) -> i64 {
48 if cap == CR_ADMIN { return CR_PORT_ADMIN }
49 if cap == CR_MAIL { return CR_PORT_MAIL }
50 return 0
51}