Commit Graph

281 Commits

Author SHA1 Message Date
will.anderson de9bf25437 Merge pull request 'dev → stage: fix CI migration heredoc YAML parse error' (#98) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 23s
Merge PR #98 from dev into stage
2026-05-11 18:34:15 +00:00
will.anderson b3ce6c3e64 Merge pull request 'Fix CI migration step: script file instead of heredoc' (#97) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m3s
Merge PR #97
2026-05-11 18:34:01 +00:00
will.anderson adbdfd3e90 Fix CI migration step: extract Python to scripts/run_migrations.py
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m36s
go-yaml (Gitea's parser) mishandles << inside block scalars, treating the
bash heredoc delimiter as a YAML merge key. Move the migration logic to a
standalone script called via python3 scripts/run_migrations.py.
2026-05-11 13:33:44 -05:00
will.anderson a59fdf4baa Merge pull request 'dev → stage: fix supabase-config null-origin CORS bug' (#96) from dev into stage
Merge PR #96 from dev into stage
2026-05-11 18:31:00 +00:00
will.anderson dd5fd2b3ce Merge pull request 'Fix supabase-config CORS: treat absent Origin as allowed' (#95) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 1m59s
Merge PR #95
2026-05-11 18:30:44 +00:00
will.anderson 617916134f Fix supabase-config CORS: treat absent Origin header as allowed
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m30s
map_get returns null (0) for missing headers. str_eq(null, "") is false
because EL_CSTR(0) is NULL != "". Same-origin browser fetches don't send
Origin at all, so the missing-origin case was incorrectly being denied.

Fix: use str_starts_with(req_origin, "http") to detect a present origin.
If no origin header (null first arg → str_starts_with returns false),
origin_present is false and the request is allowed unconditionally.
2026-05-11 13:30:22 -05:00
will.anderson ae633d3f71 Merge pull request 'dev → stage: wire Supabase migrations into CI/CD' (#94) from dev into stage
Merge PR #94 from dev into stage
2026-05-11 18:22:17 +00:00
will.anderson 924c0804e7 Merge pull request 'Wire Supabase migrations into CI/CD' (#93) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m0s
Merge PR #93
2026-05-11 18:22:01 +00:00
will.anderson 4a915c1a11 Wire Supabase migrations into CI/CD
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m30s
Adds a "Run database migrations" step to both stage.yaml and deploy.yaml.
Uses the Supabase Management API (access token from GCP Secret Manager)
to apply pending migrations tracked in a schema_migrations table.
Migrations run unconditionally before every deploy — asset-only or full.

Also adds migrations/** to paths filter so a migrations-only commit
triggers the pipeline.
2026-05-11 13:21:42 -05:00
will.anderson 43b5286fd5 Merge pull request 'dev → stage: pricing buttons, API keys, enterprise contacts' (#92) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 7m55s
Merge dev into stage
2026-05-11 18:06:02 +00:00
will.anderson 4a3ede98f7 Merge pull request 'Stage: pricing buttons, API keys, reasoning note, enterprise contacts' (#91) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m19s
Merge PR #91: dev stage batch
2026-05-11 18:05:33 +00:00
will.anderson a6b75b9abf Add direct sales and security contact block to enterprise section
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m45s
Two-card grid above the enterprise box — sales (enterprise@) and
security (security@) — with email links and one-line descriptions.
Visible without filling out the form, which is what enterprise and
security teams look for first.
2026-05-11 12:58:25 -05:00
will.anderson 21a7c07547 Add reasoning model recommendation to API Keys card
Callout above the provider list recommends o4-mini/o3, Claude Sonnet 4,
Gemini 2.5 Pro, or Grok-3 for best performance, notes that model choice
happens in the app, and points to Neuron Inference launching Q3 2026.
2026-05-11 12:54:28 -05:00
will.anderson 04641ed1a3 Merge pull request 'Stage: CI fixes, pricing buttons, API key provisioning' (#90) from fix/stage-ci-paths into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 10s
2026-05-11 17:49:37 +00:00
will.anderson 756f1f955e Add per-provider key provisioning instructions to API Keys card
Each provider row now has a collapsible details panel with accurate
step-by-step instructions and a direct link to the key creation page.
Includes billing notes for OpenAI and Anthropic (easy to miss gotchas),
free tier note for Gemini, and credits note for Grok.
2026-05-11 12:47:12 -05:00
will.anderson 18350761c5 Add API key provisioning to accounts page 2026-05-11 12:24:05 -05:00
will.anderson f22d90ac6f Make Free and Professional pricing buttons solid blue
All three pricing CTA buttons now share the same solid navy background,
white text, and blue hover state. Previously only anchor-element rules
existed for the solid variant; the button elements had no explicit
background so all three appeared unstyled.
2026-05-11 12:19:19 -05:00
will.anderson 2b8915bd60 Fix JS syntax errors and stage supabase-config CORS in CI
chat-widget.el: apostrophe in El native_js double-quoted strings caused
the El compiler to drop the backslash, producing broken JS single-quoted
strings. Switched those four string literals to double-quoted JS strings
using \" escaping so the compiled output is valid.

main.el: /api/supabase-config was returning 403 for all stage Cloud Run
origins. Added marketing-stage-* prefix to the allowed list so the
checkout page can initialise Supabase during CI E2E runs.
2026-05-11 12:15:18 -05:00
will.anderson f4a202e220 Merge pull request 'dev → stage: CSP unsafe-eval fix' (#89) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 7m59s
Merge dev into stage
2026-05-11 16:45:12 +00:00
will.anderson acca3cfddf Merge pull request 'add unsafe-eval to CSP (El native_js compatibility)' (#88) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 3m15s
Merge fix/stage-ci-paths into dev
2026-05-11 16:44:54 +00:00
will.anderson 90f7c3655e add unsafe-eval to CSP for El runtime native_js() compatibility
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 3m9s
El's native_js() compiles to eval(). checkout-auth.el uses native_js()
to embed the auth logic, so all window globals (showSignIn, initStripe,
etc.) live inside an eval call. Stage CSP was blocking it, leaving the
page with no auth functions defined.
2026-05-11 11:40:05 -05:00
will.anderson 3482e7e0f5 Merge pull request 'dev → stage: remove --obfuscate (CSP/eval fix)' (#87) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 2m31s
2026-05-11 16:11:58 +00:00
will.anderson 6d3c7e2bcd Merge pull request 'remove --obfuscate from elc JS compile step' (#86) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m54s
2026-05-11 16:11:33 +00:00
will.anderson 637b05af98 remove --obfuscate from elc JS compile step
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 2m8s
Stage CSP blocks 'unsafe-eval' which javascript-obfuscator introduces.
checkout-auth.js IIFE was crashing before assigning window globals,
causing all checkout E2E tests to fail.
2026-05-11 11:11:11 -05:00
will.anderson beee0f99a7 Merge pull request 'Stage: fix Stripe CDN mock + free-plan waitForLoadState sync' (#85) from dev into stage
Stage: fix Stripe CDN mock + free-plan waitForLoadState sync
2026-05-11 15:36:35 +00:00
will.anderson d90e8d1668 Merge pull request 'Fix Stripe CDN mock override and free-plan sync guards in E2E tests' (#84) from fix/stage-ci-paths into dev
Fix Stripe CDN mock override and free-plan sync guards in E2E tests
2026-05-11 15:36:21 +00:00
will.anderson 4b70e8c186 Merge pull request 'Fix Stripe CDN mock override and free-plan sync guards in E2E tests' (#83) from fix/stage-ci-paths into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 11s
Fix Stripe CDN mock override and free-plan sync guards in E2E tests
2026-05-11 14:55:22 +00:00
will.anderson c6fd06b3de Fix Stripe CDN mock override and free-plan sync guards in E2E tests
- Block real Stripe CDN (js.stripe.com) in injectMockStripe() so the
  addInitScript mock is never overwritten by the async-loaded SDK
- Replace waitForFunction(signUpWithEmail) with waitForLoadState in
  all 8 free-plan auth tests; defer scripts run before DOMContentLoaded
  so the function is guaranteed present without polling for it
2026-05-11 09:54:55 -05:00
will.anderson f9a5f93070 Merge pull request 'Stage: fix CI JS corruption from obfuscator stdout + flaky test guards' (#82) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 20m46s
Stage: fix CI JS corruption + flaky test guards
2026-05-11 14:16:48 +00:00
will.anderson 91ecdaf3a5 Merge pull request 'Fix CI JS corruption from obfuscator stdout; clean up flaky test guards' (#81) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Failing after 1m53s
Merge fix/stage-ci-paths: fix CI JS corruption + flaky test guards
2026-05-11 14:16:29 +00:00
will.anderson 61f006f62d Fix CI JS corruption from obfuscator stdout; clean up flaky test guards
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m54s
- Strip [javascript-obfuscator-cli] progress line from elc --obfuscate
  output before writing to dist/js/ (was prepended to every compiled JS
  file, causing browser parse errors on stage)
- Remove spurious waitForFunction(signUpWithEmail) guards from
  buyer-name and buyer-email structural tests (pure DOM tests, no auth)
- Switch chat.spec.ts beforeEach to domcontentloaded (SSR elements
  present at DOM ready; networkidle caused cold-start timeouts)
2026-05-11 08:19:30 -05:00
will.anderson 8e2deab5cb Merge pull request 'Stage: free plan age verification + soul demo personalization' (#80) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 23m41s
Stage: free plan age verification + soul demo personalization
2026-05-11 07:05:52 +00:00
will.anderson 48ba7716b8 Merge pull request 'Free plan Stripe age verification + soul demo personalization' (#79) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m25s
Merge free plan age verification + soul demo personalization into dev
2026-05-11 07:05:35 +00:00
will.anderson c966f2b455 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
2026-05-11 02:03:39 -05:00
will.anderson ddeca2250e Merge pull request 'dev → stage: CI paths + comprehensive checkout tests' (#78) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Failing after 20m10s
2026-05-11 06:21:21 +00:00
will.anderson 74e84da41a Merge pull request 'Add tests/** to stage CI paths filter' (#77) from fix/stage-ci-paths into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m26s
2026-05-11 06:21:04 +00:00
will.anderson ac2d00d653 Add tests/** + playwright.config.ts to stage CI paths filter
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m52s
2026-05-11 01:20:43 -05:00
will.anderson d228701828 Merge pull request 'dev → stage: comprehensive checkout + Stripe tests' (#76) from dev into stage
Merge: dev into stage — comprehensive checkout + Stripe tests
2026-05-11 06:19:33 +00:00
will.anderson c0e6b40a5a Merge pull request 'Comprehensive checkout + Stripe payment flow tests' (#75) from feat/checkout-comprehensive-tests into dev
Merge: Comprehensive checkout + Stripe payment flow tests
2026-05-11 06:19:19 +00:00
will.anderson dbb8035698 Add comprehensive checkout + Stripe payment flow tests
- checkout-flows.spec.ts: 60 tests covering all 3 plan variants (free/
  professional/founding), auth section visibility, form validation,
  sign-in/sign-up toggle, mocked Supabase auth flows (sign-up, email-
  confirm-required, existing session, sign-in error), DOM transitions
  (auth-section → payment-section, free-success panel), auth badge
  content + email pre-fill, /api/checkout and /api/supabase-config
  endpoint contracts, CORS enforcement

- checkout-stripe.spec.ts: 45 tests covering Stripe.js presence,
  NEURON_CFG shape, submit-btn disabled state, founding attestation
  checkbox + attest-warn guard, professional charge timing radios,
  setup_mode label, mocked full Stripe payment flow via addInitScript +
  /api/payment-intent intercept, submit validation (name/email),
  decline handling, sold-out guard, /api/payment-intent /api/link-
  customer /api/attest /api/founding-count endpoint contracts, and
  live test-card flows (skipped unless STRIPE_LIVE=1)

Mocking strategy: page.route() for /api/supabase-config + Supabase
auth endpoints; addInitScript() for window.Stripe mock; localStorage
pre-seeding for existing-session tests.
2026-05-11 01:18:37 -05:00
will.anderson 41f27e83aa Merge pull request 'test: full Playwright + API test suite for stage' (#74) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 6m43s
Merge dev into stage
2026-05-11 05:29:33 +00:00
will.anderson 83aa7ad64f Merge pull request 'test: full Playwright + API test suite for stage' (#73) from fix/checkout-auth-reveal into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m59s
Merge fix/checkout-auth-reveal into dev
2026-05-11 05:29:16 +00:00
will.anderson cac7bd5727 test: full Playwright + API test suite for stage
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m52s
159 tests across three Playwright projects (api, chromium, mobile):
- tests/api/security.test.ts: security headers, CORS on /api/supabase-config
  (origin allowlist enforced), auth gate on /api/demo, Stripe webhook
  signature enforcement, source file leakage, path traversal, input
  validation (8000-char message cap)
- tests/api/endpoints.test.ts: /api/health, /api/founding-count shape
  invariants, /api/supabase-config JWT shape, sitemap.xml, robots.txt,
  /llms.txt, /api/soul-health internal gate, 404 for unknown routes
- tests/e2e/landing.spec.ts: title, h1 count, meta description, OG tags,
  canonical (no stage leak), JSON-LD schema, demo widget DOM presence,
  JS error filtering (known GTM/CSP noise excluded)
- tests/e2e/seo.spec.ts: per-page title patterns, noindex on checkout,
  canonical URLs, sitemap production-URL enforcement
- tests/e2e/checkout.spec.ts: all three plan variants, auth section, payment
  element, canonical
- tests/e2e/chat.spec.ts: widget DOM structure, auth gate (send button
  disabled without session), API-level auth rejection
- tests/e2e/navigation.spec.ts: all public routes return 200, 404s for
  removed/old paths (/terms, /enterprise-terms, /gallery), static files

All 159 pass against stage. CI step added to stage.yaml after smoke test.
2026-05-11 00:28:33 -05:00
will.anderson 533436e2c2 Merge pull request 'security: pentest fixes — deploy to stage' (#70) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 3m32s
security: pentest fixes — deploy to stage
2026-05-11 04:57:20 +00:00
will.anderson e914704d86 Merge pull request 'security: pentest fixes — webhook sig, CORS, soul-health gate, asset headers' (#69) from fix/checkout-auth-reveal into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m31s
security: pentest fixes — webhook sig, CORS, soul-health gate, asset headers
2026-05-11 04:57:02 +00:00
will.anderson 43e1245306 seo: full audit fixes — meta, og, schema, canonical, sitemap, headings, alts
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m57s
- Per-page title/description/canonical/OG tags: about, checkout (per-plan),
  terms, enterprise-terms, success all get unique SEO blocks
- Homepage title updated to em-dash form; meta description adds CTA
- og:site_name added to all pages
- noindex/nofollow on checkout, success, account pages
- Sitemap (/sitemap.xml) with all public pages; robots.txt updated with
  Sitemap directive and Disallow for private paths
- Schema: WebSite type added, Organization gains logo ImageObject, SoftwareApplication
  gains url field, billingIncrement corrected to billingPeriod (ISO 8601 P1M),
  sameAs gains x.com/neurontechai alongside GitHub
- marked.min.js given defer attribute (was render-blocking)
- page_head refactored into page_head_base + page_seo_block + page_open_seo
  for clean inner-page overrides without duplicating the CSS/script block
2026-05-10 23:56:40 -05:00
will.anderson 3f3c5cf149 security: penetration test fixes — headers, cors, path traversal, info leakage
- Switch to http_serve_v2/http_set_handler_v2 so request headers are available
  to El handler code (prerequisite for all header-based security checks)

- Stripe webhook (CVE-class): add HMAC-SHA256 signature verification against
  Stripe-Signature header using STRIPE_WEBHOOK_SECRET env var. Previously any
  unauthenticated POST could forge a payment_intent.succeeded event and
  increment the founding counter or trigger Supabase account provisioning for
  arbitrary emails.

- CORS on /api/supabase-config: restrict to neurontechnologies.ai and localhost
  origins only. Cross-origin requests now get 403.

- /api/soul-health: require X-Internal: true header; otherwise return 404.
  Endpoint was publicly accessible and leaked internal soul service URL,
  network topology, and raw probe responses.

- Static asset / JS headers: add X-Frame-Options, Referrer-Policy,
  Permissions-Policy, and Content-Security-Policy to static_asset_headers_json
  and js_headers_json. These were only present on HTML/API responses before.

- Fix state key bug: share_card_page read state_get("__neuron_origin__") but
  the key registered at startup is "__origin__", causing empty base URLs in
  share card og: meta tags.
2026-05-10 23:56:31 -05:00
will.anderson aeea037e6f Merge pull request 'feat: auth-gate demo chat + budget circuit breaker' (#68) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 3m53s
feat: auth-gate demo chat + budget circuit breaker
2026-05-11 04:45:56 +00:00
will.anderson bdff0ad153 Merge pull request 'feat: auth-gate demo chat + budget circuit breaker' (#67) from fix/checkout-auth-reveal into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m27s
feat: auth-gate demo chat + budget circuit breaker
2026-05-11 04:45:36 +00:00
will.anderson fe418bf3f7 feat: auth-gate demo chat + budget circuit breaker
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 2m10s
Gate the demo chat behind Supabase auth: the widget now fetches Supabase
config on open, shows a compact sign-in pane (Google OAuth or email/password)
when the user is unauthenticated, and passes the access_token to /api/demo.
The server verifies the token via supabase_auth_user() before any processing
and uses the verified user ID as the rate-limit key.

Add a budget kill switch: a demo_config table in Supabase holds a
demo_enabled flag that /api/demo polls every 60s (cached, fails open).
A Cloud Function (demo-budget-guard) is triggered by a GCP Pub/Sub budget
alert and sets demo_enabled = 'false' when spend crosses 90% of the $150
daily budget. Budget and topic are provisioned; function is live in
us-central1.
2026-05-10 23:44:54 -05:00