Launch-week hosting ops: CORS, Nixpacks, lockfile drift, email domain gate

A cluster of small production-wiring commits from nwhitehouse's launch week. Mostly Vercel + Railway + Supabase-specific fixes, with two reusable patterns: a multi-origin CORS function and a DB-enforced email domain whitelist.

infrastructuresecurity

The CORS change is the most broadly useful. The original setup accepted a single FRONTEND_URL env string. The replacement is an origin-function allowlist that covers FRONTEND_URL, any *.vercel.app subdomain (so Vercel preview deploys work automatically), localhost dev ports, and the tryolava.ai apex plus subdomains. A missing entry in the original CORS list was silently turning /user/server-keys into a network error, which caused the frontend to default serverKeys.olava to false and show "API key required" on every chat send - the symptom was far from the cause.

The Nixpacks fix is a common trap: using nixPkgs = ["libreoffice"] replaces Nixpacks's auto-detected build plan rather than extending it, breaking npm ci because Node.js is no longer in the environment. The fix switches to aptPkgs, which is additive.

The email domain whitelist is a BEFORE INSERT trigger on auth.users that rejects emails outside an allowed list (onit.com, mccarthyfinch.com, k1.com). Hard-enforced at the DB, so it applies to direct Supabase API calls and the dashboard - the frontend is covered too, but the trigger is what matters. The frontend mirrors the check client-side for instant feedback, with a code comment noting that the DB trigger is the source of truth.

The dual-lockfile drift is a good cautionary note: canvas@^3.2.3 was added to package.json in the auth-hardening commit but only bun.lock was regenerated. Railway runs npm ci, which failed with "Missing: canvas@3.2.3 from lock file." A follow-up regenerates package-lock.json via npm install --package-lock-only. If your repo uses both bun and npm lockfiles, they will drift silently.

Other commits in this topic are situational: Next.js 16.0.3 → 16.2.4 to clear a Vercel security block, two empty re-trigger commits, and @vercel/analytics in the root layout.

So what The multi-origin CORS function and the email domain whitelist trigger are clean, reusable patterns worth lifting directly. The Nixpacks `aptPkgs` vs `nixPkgs` distinction and the dual-lockfile drift note are situational but document real rough edges. Skip the vendor-specific commits (Vercel analytics, empty re-triggers) unless you're on the same stack.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

11 commits from nwhitehouse/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
076add79 Hosting prep: multi-origin CORS, signup redirect, region env Nick Whitehouse 2026-05-01 ↗ GitHub
commit body
- Backend CORS now accepts FRONTEND_URL + any *.vercel.app preview
  + localhost dev ports via origin function (was a single origin).
- Signup posts emailRedirectTo: window.location.origin so the
  Supabase confirmation link returns users to whichever Vercel host
  they signed up on (production or preview).
- S3 client region is now env-configurable via R2_REGION (default
  "auto" still works for Cloudflare R2; Supabase Storage / MinIO
  need a real region like "us-west-2").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f061f757 Fix Railway build: use aptPkgs for libreoffice so Node.js auto-detection survives Nick Whitehouse 2026-05-01 ↗ GitHub
f3ca06e6 Pin backend Node engine to >=20 (Nixpacks dropped Node 18) Nick Whitehouse 2026-05-01 ↗ GitHub
f4a157ba Frontend: legacy-peer-deps so npm install survives next@16.0.3 / @opennextjs/cloudflare peer mismatch Nick Whitehouse 2026-05-01 ↗ GitHub
a19d145a Trigger Vercel rebuild on latest main Nick Whitehouse 2026-05-01 ↗ GitHub
faaa8458 Re-trigger Vercel after verified-commits override Nick Whitehouse 2026-05-01 ↗ GitHub
58fdae57 Bump Next.js to 16.2.4 (Vercel blocks deploys of vulnerable 16.0.3) Nick Whitehouse 2026-05-01 ↗ GitHub
4d13761c CORS: allow tryolava.ai apex + subdomains Nick Whitehouse 2026-05-01 ↗ GitHub
commit body
Vercel custom domain serves www.tryolava.ai, which the previous CORS allowlist (FRONTEND_URL + *.vercel.app + localhost) rejected. Backend logs were spamming "CORS: origin https://www.tryolava.ai not allowed", which silently turned /user/server-keys into a network error → frontend defaulted serverKeys.olava to false → "API key required" modal on every chat send.

Widened the origin function to also accept the tryolava.ai apex and any subdomain so both www and root work without further FRONTEND_URL juggling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
79b39c9e Email domain whitelist for signups (Onit, McCarthy Finch, K1) Nick Whitehouse 2026-05-01 ↗ GitHub
commit body
- backend/migrations/001_email_domain_whitelist.sql: BEFORE INSERT trigger on auth.users that rejects emails outside the allowed list. Hard-enforced at the DB so it applies to API clients and the Supabase dashboard, not just our frontend
- Mirrored client-side check in signup form for instant UX feedback. To update the list later, edit the array in both places and re-run the SQL

Apply by pasting backend/migrations/001_email_domain_whitelist.sql into Supabase → SQL Editor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0d9be7cb [ops] Regenerate package-lock.json - fixes Railway npm ci failure Nick Whitehouse 2026-05-07 ↗ GitHub
commit body
Lock file was out of sync with package.json. canvas@^3.2.3 was added in
the auth-RLS hardening commit but the lock file wasn't regenerated, so
prod build failed on `npm ci` with "Missing: canvas@3.2.3 from lock file"
plus all of canvas's transitive deps. Local dev worked because bun.lock
is up to date - bun and npm lock files drifted apart silently.

Ran `npm install --package-lock-only` and verified with `npm ci --dry-run`
which now succeeds. No package.json changes; only the lock catches up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c8bbffb8 [chore] Add @vercel/analytics to root layout Nick Whitehouse 2026-05-07 ↗ GitHub
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-114.md from inside the repo you want the changes in.

⬇ Download capture-thread-114.md