370 Commits

Author SHA1 Message Date
will.anderson 348c81ac7f Merge pull request 'Deploy #154 to stage — analytics CSP fix' (#155) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 8m36s
2026-05-19 17:54:09 +00:00
will.anderson c30e5903a4 Merge pull request 'Allow Google Analytics and Ads domains in CSP' (#154) from fix/csp-analytics into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m5s
2026-05-19 17:53:52 +00:00
will.anderson c526e76d3b Allow Google Analytics and Ads domains in CSP
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m34s
Add to connect-src: analytics.google.com, www.google.com,
www.googletagmanager.com — required for GA event beacons and
Google Ads conversion/remarketing collect endpoints.

Add to script-src: googleads.g.doubleclick.net — required for
Google Ads conversion tag script injection via GTM.
2026-05-19 12:53:36 -05:00
will.anderson a02ad7b61a Merge pull request 'Deploy #152 to stage — SyntaxError fix + CSP expansion' (#153) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 8m8s
2026-05-19 17:13:56 +00:00
will.anderson 6a7b8382ea Merge pull request 'Fix SyntaxError in account-dashboard and expand CSP' (#152) from fix/syntax-error-and-csp into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m7s
2026-05-19 17:13:39 +00:00
will.anderson d2ae0b4b60 Fix SyntaxError in account-dashboard and expand CSP
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m37s
Replace ternary operator in native_js block with explicit if-else —
El's parser chokes on '?' adjacent to single-quoted strings inside
native_js(), causing an Uncaught SyntaxError that prevents the entire
IIFE from running and leaves signInWith undefined.

Add missing CSP entries to all three header functions:
- js.stripe.com → script-src and frame-src (Stripe JS and Elements iframe)
- fonts.googleapis.com → style-src (Google Fonts CSS)
- fonts.gstatic.com → font-src (Google Fonts files)
- static.cloudflareinsights.com → script-src (Cloudflare beacon)
2026-05-19 12:13:05 -05:00
will.anderson 611e43fee1 Merge pull request 'Stage deploy: device count cleanup' (#151) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 8m54s
2026-05-14 16:38:41 +00:00
will.anderson 5c8987ef59 Merge pull request 'Clear hardcoded device count — JS owns it' (#150) from fix/devices-count-v2 into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m35s
2026-05-14 16:38:26 +00:00
will.anderson bfcb325352 Clear hardcoded device count — JS sets it from plan data
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m54s
2026-05-14 11:38:05 -05:00
will.anderson 61c3b1cfe9 Merge pull request 'Stage deploy: device count fix' (#149) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 9m8s
2026-05-14 16:36:35 +00:00
will.anderson 57e9cafc95 Merge pull request 'Fix device count: 1 for free, 2 for professional/founding' (#148) from fix/devices-count into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m13s
2026-05-14 16:36:20 +00:00
will.anderson 632d95000c Fix device count: show 1 for free plan, 2 for professional/founding
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m38s
2026-05-14 11:36:02 -05:00
will.anderson ab83b1653c Merge pull request 'Stage deploy: fix account el_meta SIGSEGV' (#147) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 7m36s
2026-05-13 17:42:07 +00:00
will.anderson 77807d30af Merge pull request 'Fix account SIGSEGV: el_meta 1-arg → 2-arg' (#146) from fix/account-el-meta into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m13s
2026-05-13 17:41:53 +00:00
will.anderson 8f91a80be7 Fix account page SIGSEGV: el_meta extern arity mismatch (1-arg → 2-arg)
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m42s
el_meta was declared as el_meta(attrs) in account.el but the runtime
C implementation expects el_meta(name, content). Same arity crash as
the prior el_img fix — runtime passed garbage on the stack.
2026-05-13 12:41:37 -05:00
will.anderson 752cc415d1 Merge pull request 'Stage deploy: fix account SIGSEGV' (#145) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 7m22s
2026-05-13 17:20:43 +00:00
will.anderson d7bb92c37f Merge pull request 'Fix account page SIGSEGV: el_img extern arity mismatch' (#144) from fix/magic-link-flow into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m20s
2026-05-13 17:20:06 +00:00
will.anderson 4ca793ee2c Fix account page SIGSEGV: el_img extern signature mismatch
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m46s
account.el declared el_img with 1 arg (attrs only) while the runtime
implementation and all other files use 3 args (src, alt, attrs).
The arity mismatch caused the server to crash with signal 11 on every
request — TCP probe passed (bind was fine) but first HTTP hit segfaulted.
2026-05-13 12:19:43 -05:00
will.anderson 0a599ec149 Merge pull request 'Stage deploy: fix free plan payment init' (#143) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 12m58s
Stage deploy: fix free plan payment init
2026-05-13 17:12:52 +00:00
will.anderson 4123f6d5f1 Merge pull request 'Fix free plan checkout: SetupIntent instead of $0 PaymentIntent' (#142) from fix/free-plan-setup-intent into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 1m59s
Fix free plan checkout: SetupIntent instead of $0 PaymentIntent
2026-05-13 17:12:35 +00:00
will.anderson 69f348d48b Fix free plan checkout: use SetupIntent instead of $0 PaymentIntent
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m40s
Stripe rejects amount=0 PaymentIntents. Free plan age verification should
use a SetupIntent (no charge, saves payment method). The JS already handles
setup_mode:true by calling stripe.confirmSetup instead of confirmPayment.
Mirrors the existing professional-later SetupIntent path.
2026-05-13 12:12:10 -05:00
will.anderson 6dedb97719 Merge pull request 'Stage deploy: fix about page El tokenizer rendering' (#141) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 8m15s
Stage deploy: fix about page El tokenizer rendering
2026-05-13 16:46:58 +00:00
will.anderson 3d635505bc Merge pull request 'Fix about page: restore raw string syntax to fix El tokenizer rendering' (#140) from fix/about-rendering into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m17s
Fix about page: restore raw string syntax to fix El tokenizer rendering
2026-05-13 16:46:43 +00:00
will.anderson 675c467a74 Fix about page rendering: restore raw string syntax to fix El tokenizer mangling
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m45s
The El HTML template parser (native { } syntax introduced in 5cb13d6) strips
spaces from text nodes, drops & from HTML entities (' → 39;), and breaks
hyphenated attribute names (aria-label → aria - label). All other component
files were already converted to the extern el_*() function style in 2553a6b
which is immune to this issue. about.el was the only page still using the
broken template syntax. Restoring the raw string return style fixes all
rendering defects on /about.
2026-05-13 11:46:13 -05:00
will.anderson 8528080e85 Merge pull request 'Deploy dev to stage — magic link sign-in fix' (#139) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 7m4s
2026-05-12 19:33:21 +00:00
will.anderson 708dfd06cb Merge pull request 'Fix magic-link sign-in: implicit flow + redirect to /account' (#138) from fix/magic-link-flow into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m14s
2026-05-12 19:33:03 +00:00
will.anderson b6aecd7d89 Fix magic-link sign-in: implicit flow + redirect to /account
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m42s
account-auth.el was using flowType:'pkce' while account-dashboard.el
uses 'implicit'. After the OTP redirect, the dashboard's implicit
client couldn't exchange the PKCE code — so the sign-in silently
failed. Fix: match implicit flow across both clients.

Also adds emailRedirectTo so the link lands on /account instead of
the site root.
2026-05-12 14:32:39 -05:00
will.anderson 3c19f4cf73 Merge pull request 'Deploy dev to stage — Stripe dedup + attestation bypass fix' (#137) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 7m17s
2026-05-12 19:23:54 +00:00
will.anderson bb98f76179 Merge pull request 'Fix duplicate Stripe customers and attestation plan bypass' (#136) from fix/stripe-dedup-attestation into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m4s
2026-05-12 19:23:33 +00:00
will.anderson 0fdbba82e0 Fix duplicate Stripe customers and attestation plan bypass
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m29s
Two bugs:

1. Double-Bearer auth on Stripe customer search. Both checkout paths
   were passing "Bearer sk_..." to http_get_auth(), which prepends
   another "Bearer " — producing "Bearer Bearer sk_..." which Stripe
   rejects as 401. Customer lookup always failed, so a new Stripe
   customer was created on every checkout page load. Fix: pass the
   raw key to http_get_auth(), letting it handle the prefix.

2. /api/attest blindly wrote whatever plan the client submitted to
   the waitlist, letting anyone POST plan=founding and get founding
   member access without paying. Fix: server ignores the client-
   submitted plan and always writes plan=waitlist. Founding access
   requires Stripe payment — the attestation form is waitlist-only.
2026-05-12 14:10:04 -05:00
will.anderson b5285ccb74 Merge pull request 'Deploy dev to stage — webhook user_metadata fix, textarea, initStripe' (#135) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 8m13s
2026-05-12 17:50:07 +00:00
will.anderson 9e0451be41 Merge pull request 'Fix initStripe load order, subscription webhook email, chat textarea' (#134) from fix/webhook-initstripe-textarea into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m11s
Merge PR #134: Fix initStripe load order, webhook user_metadata, chat textarea
2026-05-12 17:49:26 +00:00
will.anderson 99ed8b85f7 Fix webhook failing to update plan for pre-existing Supabase users
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m17s
supabase_admin_invite re-sends a magic link for users who already have
an account (e.g. signed up via attestation before paying) but does not
touch their user_metadata — leaving plan as "free" after purchase.

Fix: add supabase_admin_update_user (PUT /auth/v1/admin/users/{id})
and call it after every invite so user_metadata is always stamped with
the correct plan, name, and stripe_customer_id. Idempotent for new and
returning users.

Also fix waitlist_upsert to use on_conflict=email,plan so the upsert
works for users who already have a waitlist row from attestation,
rather than silently failing on duplicate key.
2026-05-12 12:31:45 -05:00
will.anderson c72127032e Fix initStripe load order, subscription webhook email extraction, chat textarea UX
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m18s
- checkout.el: swap stripe_el_script before auth_script so initStripe is
  defined when Supabase auth fires onAuthStateChange on page load
- main.el: fix Stripe webhook email extraction for checkout.session.completed
  (subscription) events — customer_details is nested at data.object level,
  not at root; previous code only worked for payment_intent.succeeded
- page_close.c: replace <input type="text"> with <textarea rows="1"> in
  the chat widget input row so long questions are visible as you type
- page_css.c: update #neuron-demo-text CSS for textarea (resize:none,
  overflow:hidden, min/max-height, align-items:flex-end on row)
- chat-widget.el: add auto-resize event listener (grows up to ~4 lines),
  reset height to auto on send
2026-05-12 12:22:59 -05:00
will.anderson ba776153a9 Merge pull request 'dev → stage' (#133) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 7m48s
2026-05-12 14:03:42 +00:00
will.anderson 869dcec0bb Merge pull request 'Fix intro greeting and load history on return visits' (#132) from fix/greeting-history-load into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m8s
2026-05-12 14:03:11 +00:00
will.anderson 1786aeeff6 Fix intro greeting tone and load history on return visits
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m36s
- soul-demo.c: rewrite intro system prompt — remove 'to see if you are real'
  and 'say something true about who you are' which were producing alive/sentient
  language. New prompt: friendly hello, ask how they're doing, explicitly no
  alive/sentient/experiencing anything lines.
- chat-widget: Turnstile callback now replays existing session history instead
  of always firing a new greeting — returning users within the same day see
  their conversation, not a duplicate hello.
2026-05-12 09:02:55 -05:00
will.anderson 853d73855d Merge pull request 'dev → stage' (#131) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 8m26s
2026-05-12 13:53:31 +00:00
will.anderson e938cb69fc Merge pull request 'Fix question counter, rate-limit timer, admin reset API, pricing clarity' (#130) from fix/question-timer-pricing-clarity into dev
Dev — Build & local smoke test / build-smoke (push) Failing after 1m12s
2026-05-12 13:53:04 +00:00
will.anderson 4f6df973cb Fix question counter daily reset, rate-limit timer, and founding member pricing clarity
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 2m0s
- chat-widget: session.count now resets on new UTC day (keeps client in sync with server's daily quota reset)
- chat-widget: fix rate-limit timer — wrong element IDs (neuron-demo-msgs → neuron-demo-messages) and wrong class (.neuron-msg-ai → .demo-msg-ai) meant the countdown never updated
- chat-widget: remove btn.disabled=false that immediately re-enabled the send button after rate-limiting
- main.el: add POST /api/admin/reset-rate-limits endpoint (requires NEURON_ADMIN_TOKEN, deletes all demo_rate_limits rows)
- pricing.el: clarify founding member card — software updates are free forever, inference is pay-per-use at founding member rate
2026-05-12 08:52:34 -05:00
will.anderson 3ed43c0037 Merge pull request 'dev → stage: binary assets, payment fix, checkout layout' (#129) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 7m4s
2026-05-12 01:11:23 +00:00
will.anderson be849c608e Merge pull request 'fix: binary asset serving + checkout centering' (#128) from fix/binary-assets-checkout-layout into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m7s
2026-05-12 01:10:58 +00:00
will.anderson 5ce5f4a8be fix: binary asset serving + checkout centering
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m34s
el_runtime: http_response() JSON-encoded the body via jb_emit_escaped(),
which stops at the first null byte. PNG/binary files contain null bytes
at byte 8 (IHDR chunk length), so only 8 bytes were served — browsers
received a corrupt/truncated image and showed broken icons.

Fix: when _tl_fs_read_len > 0 (binary fs_read), copy raw bytes into a
thread-local side-channel (_tl_binary_body/_tl_binary_size) and write
the sentinel "__el_binary__" into the envelope body field. http_send_response()
detects the sentinel and substitutes the real bytes for sending.

checkout.el: .checkout-shell, .checkout-summary, and .checkout-form-wrap
had no CSS, leaving the page left-aligned and single-column. Added grid
layout (2-col desktop, 1-col mobile), max-width centering, and sticky
order summary.
2026-05-11 20:10:19 -05:00
will.anderson 6e425da63e Merge pull request 'fix: remove setup_future_usage from $0 PaymentIntent' (#127) from fix/zero-pi-setup-future-usage into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m2s
2026-05-12 00:55:56 +00:00
will.anderson 37c7dca30d Fix $0 PaymentIntent: remove setup_future_usage (invalid with amount=0)
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m32s
2026-05-11 19:55:44 -05:00
will.anderson 69ae0ca891 Merge pull request 'dev → stage: free plan $0 PaymentIntent' (#126) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 7m25s
2026-05-12 00:46:14 +00:00
will.anderson 73c435eb90 Merge pull request 'fix: free plan $0 PaymentIntent for age verification' (#125) from fix/free-plan-payment-intent into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m14s
2026-05-12 00:46:01 +00:00
will.anderson 7be2b49300 Free plan: use $0 PaymentIntent instead of SetupIntent for age verification
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m45s
All plans now use the same payment intent flow. Free creates a $0 PI
with payment_method_types[]=card and setup_future_usage=off_session.
No charge, card saved. Removes setup_mode=true for free plan.

Fix submit button label: show 'Verify age & get started' for free
instead of 'Complete purchase'. Retire checkout-free.el.
2026-05-11 19:45:39 -05:00
will.anderson 876f2afe27 Merge pull request 'dev → stage: free checkout Stripe fix + copy updates' (#124) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 6m51s
2026-05-12 00:16:26 +00:00
will.anderson e5c05cbece Merge branch 'dev' of git.neuralplatform.ai:neuron-technologies/neuron-web into dev 2026-05-11 19:16:18 -05:00