nx_intake_handler.nx source
↩ module page · 56 lines · 4695 B
1// nx_intake_handler.nx -- R6 of THE NISHI SITUATION-MANAGEMENT arc: the INTAKE data path. Turns a person's
2// submitted form (a urlencoded POST body from the zero-JS intake form, behind the opaque wall) into a
3// sovereign content-addressed survey record (sv_record) -- so the whole system (climb-out plan, before-you-
4// buy guard, triage, accommodation) runs on THEIR real numbers instead of the demo profile. Reuses the
5// existing nx_http_form_get_field parser (DRY -- the same one the login route uses) + the R0 survey engine.
6// No floats, no hardware writes. The opaque route (POST /finance/intake) calls ih_record then redirects to
7// /finance; that route block is the coordinated deployment hook. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_http_form.nx"
10import "nx_survey.nx"
11import "nx_intake_profile.nx" // ip_put_latest -- record the "latest profile" pointer for the dashboard
12
13func ih_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
14
15// parse one integer field from the urlencoded body (0 if absent/empty). `scratch` is a caller buffer.
16func ih_field(body: *u8, body_n: i64, name: *u8, scratch: *u8, scratch_cap: i64) -> i64 {
17 let vl: *i64 = sys_mmap(16) as *i64
18 vl[0] = 0
19 nx_http_form_get_field(body, body_n, name, ih_len(name), scratch, scratch_cap, vl)
20 if vl[0] <= 0 { return 0 }
21 if vl[0] < scratch_cap { scratch[vl[0]] = 0 as u8 } // NUL-terminate at the parsed length (parser
22 // returns len, not a terminator) so sv_atoi does
23 // not read leftover digits from a prior field
24 return sv_atoi(scratch)
25}
26
27// a MONEY field entered in whole dollars -> stored in cents (the engines are no-float cents).
28func ih_field_cents(body: *u8, body_n: i64, name: *u8, scratch: *u8, scratch_cap: i64) -> i64 {
29 return ih_field(body, body_n, name, scratch, scratch_cap) * 100
30}
31
32// parse the intake POST body into a survey response and record it (content-addressed). out_cid (>=80 bytes)
33// gets the CID. returns 0 ok, negative on store error. Field names ARE the question ids (data-driven).
34func ih_record(prefix: *u8, respondent: *u8, body: *u8, body_n: i64, out_cid: *u8) -> i64 {
35 let qids: *i64 = sys_mmap(8 * 32) as *i64
36 let vals: *i64 = sys_mmap(8 * 32) as *i64
37 let sc: *u8 = sys_mmap(128)
38 var nf: i64 = 0
39 qids[nf] = "income_monthly\x00" as *u8 as i64; vals[nf] = ih_field_cents(body, body_n, "income_monthly\x00" as *u8, sc, 127); nf = nf + 1
40 qids[nf] = "debt_balance\x00" as *u8 as i64; vals[nf] = ih_field_cents(body, body_n, "debt_balance\x00" as *u8, sc, 127); nf = nf + 1
41 qids[nf] = "debt_apr_pct\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "debt_apr_pct\x00" as *u8, sc, 127); nf = nf + 1
42 qids[nf] = "monthly_payment\x00" as *u8 as i64; vals[nf] = ih_field_cents(body, body_n, "monthly_payment\x00" as *u8, sc, 127); nf = nf + 1
43 qids[nf] = "available\x00" as *u8 as i64; vals[nf] = ih_field_cents(body, body_n, "available\x00" as *u8, sc, 127); nf = nf + 1
44 qids[nf] = "hourly_wage\x00" as *u8 as i64; vals[nf] = ih_field_cents(body, body_n, "hourly_wage\x00" as *u8, sc, 127); nf = nf + 1
45 qids[nf] = "buffer_goal\x00" as *u8 as i64; vals[nf] = ih_field_cents(body, body_n, "buffer_goal\x00" as *u8, sc, 127); nf = nf + 1
46 qids[nf] = "behind_mortgage\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "behind_mortgage\x00" as *u8, sc, 127); nf = nf + 1
47 qids[nf] = "medical_debt\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "medical_debt\x00" as *u8, sc, 127); nf = nf + 1
48 qids[nf] = "job_loss_risk\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "job_loss_risk\x00" as *u8, sc, 127); nf = nf + 1
49 qids[nf] = "high_interest_debt\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "high_interest_debt\x00" as *u8, sc, 127); nf = nf + 1
50 qids[nf] = "has_adhd\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "has_adhd\x00" as *u8, sc, 127); nf = nf + 1
51 qids[nf] = "low_energy\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "low_energy\x00" as *u8, sc, 127); nf = nf + 1
52 qids[nf] = "low_vision\x00" as *u8 as i64; vals[nf] = ih_field(body, body_n, "low_vision\x00" as *u8, sc, 127); nf = nf + 1
53 let rc: i64 = sv_record(prefix, respondent, qids, vals, nf, out_cid)
54 if rc == 0 { ip_put_latest(prefix, respondent, out_cid) } // point "latest" at this submission
55 return rc
56}