code wiki / (root) / nx_intake_handler.nx

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}