code wiki / _hdl_build / nx_cms_booking.nx
nx_cms_booking.nx source
↩ module page · 82 lines · 5090 B
1// nx_cms_booking.nx -- the consultation-booking BACKEND that finishes the "scheduler that works with the email
2// systems" (the crash-interrupted rung). Composes existing organs, no reinvention:
3// nx_cms_store -- persists the booking as a sovereign record (@name/@phone/@email/@matter/@date/@time/@status)
4// nx_cms_email -- email_addr_valid() gates the client address
5// nx_email_mime -- (format reference) RFC 5322 confirmation message
6// nx_cron -- registers a same-day reminder job (fires once)
7// Defensive at the boundary (Cardinal 12): every web-supplied value is SANITIZED (control chars incl CR/LF
8// stripped) before it enters a record field OR an email header -> header-injection / record-format-break safe.
9// Pure logic (mmap only) -> fully gateable offline; the LIVE rung (daemon POST /schedule -> bk_book + real MTA
10// send via nx_email_send) wires this to andelinwest.com next. license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "nx_cms_store.nx"
13import "nx_cms_email.nx"
14import "nx_cron.nx"
15const K_MAGIC_8192: i64 = 8192
16const K_MAGIC_2000000000: i64 = 2000000000
17
18func bk_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
19func bk_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[off+i]=s[i]; i=i+1 } return off+i }
20// copy s into dst dropping ALL control chars (<32): strips CR(13)/LF(10)/tab(9) -> no header injection, no
21// record-format break. returns new offset.
22func bk_san(dst: *u8, off: i64, s: *u8) -> i64 {
23 var o: i64=off; var i: i64=0
24 while s[i]!=(0 as u8) { let c: i64=s[i] as i64; if c>=32 { dst[o]=s[i]; o=o+1 } i=i+1 }
25 return o
26}
27func bk_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
28
29// build the booking record (nx_cms_store format) into out; status="requested"; return length
30func bk_store(name: *u8, phone: *u8, email: *u8, matter: *u8, date: *u8, time: *u8, out: *u8) -> i64 {
31 var o: i64=0
32 o=bk_cat(out,o,"@name\n" as *u8); o=bk_san(out,o,name); out[o]=10 as u8; o=o+1
33 o=bk_cat(out,o,"@phone\n" as *u8); o=bk_san(out,o,phone); out[o]=10 as u8; o=o+1
34 o=bk_cat(out,o,"@email\n" as *u8); o=bk_san(out,o,email); out[o]=10 as u8; o=o+1
35 o=bk_cat(out,o,"@matter\n" as *u8); o=bk_san(out,o,matter); out[o]=10 as u8; o=o+1
36 o=bk_cat(out,o,"@date\n" as *u8); o=bk_san(out,o,date); out[o]=10 as u8; o=o+1
37 o=bk_cat(out,o,"@time\n" as *u8); o=bk_san(out,o,time); out[o]=10 as u8; o=o+1
38 o=bk_cat(out,o,"@status\nrequested\n" as *u8)
39 return o
40}
41
42// assemble the RFC 5322 confirmation email to the client; return length. Header values sanitized.
43func bk_confirm(name: *u8, email: *u8, matter: *u8, date: *u8, time: *u8, out: *u8) -> i64 {
44 var o: i64=0
45 o=bk_cat(out,o,"From: intake@andelinwest.com\r\nTo: " as *u8); o=bk_san(out,o,email)
46 o=bk_cat(out,o,"\r\nSubject: Your consultation request - " as *u8); o=bk_san(out,o,matter)
47 o=bk_cat(out,o,"\r\n\r\nDear " as *u8); o=bk_san(out,o,name)
48 o=bk_cat(out,o,",\r\n\r\nWe received your consultation request (" as *u8); o=bk_san(out,o,matter)
49 o=bk_cat(out,o,", preferred " as *u8); o=bk_san(out,o,date); out[o]=32 as u8; o=o+1; o=bk_san(out,o,time)
50 o=bk_cat(out,o,"). Our intake team will confirm your appointment shortly. If your matter is urgent, please call (801) 555-0100.\r\n\r\n-- Andelin West, PLLC\r\nintake@andelinwest.com\r\n" as *u8)
51 return o
52}
53
54// register a same-day reminder for this booking via the cron core; return the cron verdict
55func bk_reminder(name: *u8, namelen: i64, fire_at: i64) -> i64 {
56 let jp: *NxCronJob = sys_mmap(256) as *NxCronJob
57 jp.job_name_ptr = name
58 jp.job_name_len = namelen
59 jp.schedule_kind = NX_CRON_KIND_AT_UNIX_ONCE
60 jp.interval_seconds = 0
61 jp.fire_at_unix = fire_at
62 jp.missed_policy = NX_CRON_MISSED_CATCH_UP_ONCE
63 jp.action_kind = NX_CRON_ACTION_PUBLISH
64 jp.action_arg = 1
65 jp.enabled = 1
66 return nx_cron_register_job(jp)
67}
68
69func main() -> i64 {
70 // demo: book a sample consultation -> record + confirmation + reminder
71 let rec: *u8 = sys_mmap(K_MAGIC_8192)
72 let rl: i64 = bk_store("Jane Roe" as *u8, "801-555-1212" as *u8, "jane@example.com" as *u8, "Estate Planning" as *u8, "2026-07-01" as *u8, "Morning (9-12)" as *u8, rec)
73 bk_puts("=== BOOKING RECORD ===\n" as *u8); sys_write(1, rec, rl); bk_puts("\n" as *u8)
74 let msg: *u8 = sys_mmap(K_MAGIC_8192)
75 let ml: i64 = bk_confirm("Jane Roe" as *u8, "jane@example.com" as *u8, "Estate Planning" as *u8, "2026-07-01" as *u8, "Morning (9-12)" as *u8, msg)
76 bk_puts("=== CONFIRMATION EMAIL ===\n" as *u8); sys_write(1, msg, ml); bk_puts("\n" as *u8)
77 let v: i64 = bk_reminder("reminder-jane" as *u8, 13, K_MAGIC_2000000000)
78 bk_puts("reminder cron verdict=" as *u8)
79 let bb: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{bb[0]=48 as u8;k=1}; let t: *u8=sys_mmap(28); while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k)
80 bk_puts("\n" as *u8)
81 sys_exit(0); return 0
82}