implement free plan age verification via Stripe SetupIntent; personalize soul demo greeting with user name and timezone
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m49s
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m49s
This commit is contained in:
+28
-5
@@ -666,10 +666,6 @@ fn handle_request_inner(method: String, path: String, headers: Map, body: String
|
||||
}
|
||||
let timing: String = json_get_string(body, "timing")
|
||||
if str_eq(timing, "") { let timing = "now" }
|
||||
// Free tier: no card required. Return immediately — no Stripe interaction.
|
||||
if str_eq(plan, "free") {
|
||||
return "{\"plan\":\"free\",\"free\":true,\"no_payment_required\":true}"
|
||||
}
|
||||
// Hard cap: block founding checkouts when 1,000 spots are filled
|
||||
if str_eq(plan, "founding") {
|
||||
let current_sold: Int = get_sold()
|
||||
@@ -701,6 +697,25 @@ fn handle_request_inner(method: String, path: String, headers: Map, body: String
|
||||
}
|
||||
}
|
||||
|
||||
// Free tier: creates a SetupIntent for age verification (18+ requirement).
|
||||
// No charge — but the user must provide a valid payment method.
|
||||
if str_eq(plan, "free") {
|
||||
let free_si_body: String = "automatic_payment_methods[enabled]=true"
|
||||
+ "&usage=off_session"
|
||||
+ "&metadata[plan]=free"
|
||||
+ "&metadata[purpose]=age_verification"
|
||||
let free_si_body = if !str_eq(pi_cus_id, "") { free_si_body + "&customer=" + pi_cus_id } else { free_si_body }
|
||||
let free_si_resp: String = http_post_form_auth(
|
||||
"https://api.stripe.com/v1/setup_intents",
|
||||
free_si_body,
|
||||
auth_header)
|
||||
if str_starts_with(free_si_resp, "{") {
|
||||
let inner: String = str_slice(free_si_resp, 1, str_len(free_si_resp))
|
||||
return "{\"setup_mode\":true,\"plan\":\"free\"," + inner
|
||||
}
|
||||
return free_si_resp
|
||||
}
|
||||
|
||||
// Setup-mode path: save payment method, do not charge. Only valid
|
||||
// for Professional (Founding is one-shot lifetime, charges immediately).
|
||||
if str_eq(plan, "professional") && str_eq(timing, "later") {
|
||||
@@ -1390,6 +1405,14 @@ fn handle_request_inner(method: String, path: String, headers: Map, body: String
|
||||
let qrem_safe: String = if str_eq(qrem_str, "") { "10" } else { qrem_str }
|
||||
let is_last_str: String = json_get(body, "is_last_question")
|
||||
let is_last_safe: String = if str_eq(is_last_str, "true") { "true" } else { "false" }
|
||||
let user_name_raw: String = json_get_string(body, "user_name")
|
||||
let user_tz_raw: String = json_get_string(body, "user_timezone")
|
||||
let tod_raw: String = json_get_string(body, "time_of_day")
|
||||
let is_return_raw: String = json_get_string(body, "is_return")
|
||||
let user_name_safe: String = str_replace(str_replace(user_name_raw, "\\", "\\\\"), "\"", "\\\"")
|
||||
let user_tz_safe: String = str_replace(str_replace(user_tz_raw, "\\", "\\\\"), "\"", "\\\"")
|
||||
let tod_safe: String = str_replace(str_replace(tod_raw, "\\", "\\\\"), "\"", "\\\"")
|
||||
let is_return_safe: String = if str_eq(is_return_raw, "true") { "true" } else { "false" }
|
||||
// Look up the configured chat model from public.neuron_config
|
||||
// (Phase 1 runtime config store). 60s TTL caching, falls back
|
||||
// to the hardcoded default on Supabase miss / error.
|
||||
@@ -1398,7 +1421,7 @@ fn handle_request_inner(method: String, path: String, headers: Map, body: String
|
||||
// Build inner content with history and engram context for thread context.
|
||||
// soul-demo unwraps payload from the dharma envelope, then reads
|
||||
// model with json_get(body, "model") - so this propagates end to end.
|
||||
let inner: String = "{\"event_type\":\"chat\",\"payload\":{\"message\":\"" + msg_safe + "\",\"history\":" + hist_safe + ",\"an\":" + an_safe + ",\"ec\":" + ec_safe + ",\"questions_remaining\":" + qrem_safe + ",\"is_last_question\":" + is_last_safe + ",\"model\":\"" + model_safe + "\"}}"
|
||||
let inner: String = "{\"event_type\":\"chat\",\"payload\":{\"message\":\"" + msg_safe + "\",\"history\":" + hist_safe + ",\"an\":" + an_safe + ",\"ec\":" + ec_safe + ",\"questions_remaining\":" + qrem_safe + ",\"is_last_turn\":" + is_last_safe + ",\"model\":\"" + model_safe + "\",\"user_name\":\"" + user_name_safe + "\",\"user_timezone\":\"" + user_tz_safe + "\",\"time_of_day\":\"" + tod_safe + "\",\"is_return\":\"" + is_return_safe + "\"}}"
|
||||
// Escape inner for the outer content field
|
||||
let inner_safe: String = str_replace(str_replace(inner, "\\", "\\\\"), "\"", "\\\"")
|
||||
// Build dharma envelope with per-user channel
|
||||
|
||||
Reference in New Issue
Block a user