Harden OAuth callback base: fail closed in production

↗ view on GitHub · sloth-ninja · 2026-08-04 · 6fc6afa6

Incident 03/08/2026: the deployed backend minted Clio authorize URLs with
redirect_uri=http://127.0.0.1:3001/... because neither API_PUBLIC_URL nor
BACKEND_URL was set on Fly, so clioBackendBaseUrl() fell through to its dev
literal. A pilot solicitor's consent succeeded at Clio then bounced to
127.0.0.1 (ERR_CONNECTION_REFUSED). Fixed operationally by setting
API_PUBLIC_URL; this makes the failure loud and early instead of silent.

- clio/config.ts: new productionCallbackBaseMissing() - in NODE_ENV=production
  when the resolved base is the 127.0.0.1 fallback, clioConfigured() returns
  false (same state as missing credentials), so the start route returns the
  fixed "not configured" error and never mints a localhost redirect. A redacted
  safeErrorLog fires once per boot naming API_PUBLIC_URL. Dev/test unchanged.
- MCP checked: the interactive authorize redirect derives from the Host header
  (routes/user.ts backendPublicUrl) - different fallback class, unaffected on
  Fly, left unchanged. The refresh-path helper mcpOAuthCallbackUrl() shares the
  localhost fallback but is covered by API_PUBLIC_URL being required in prod.
- .env.example + CLAUDE.md env registry: API_PUBLIC_URL/BACKEND_URL documented
  as REQUIRED in production for OAuth callback flows (Clio + MCP).
- DURABLE_LESSONS: env-derived callback bases degrade silently; guard fails
  closed; OAuth deploy verification needs a real round-trip from a non-dev
  machine. Includes the debugging signature.
- Tests: 4 guard cases (prod+fallback -> not configured/no URL; prod+base ->
  normal; dev+fallback -> unchanged). Backend vitest 604/604, tsc + prettier
  clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Repository Sloth-ninja/JessicaOSS
Author sloth-ninja <ezanahaddis@gmail.com>
Authored
Parents df1ec415
Stats 6 files changed , +200 , -4
Part of OAuth callback-base hardening

Capture this commit into my fork

Download a Markdown prompt that tells Claude how to port this exact commit into your working tree. Run it via claude -p < capture-commit-6fc6afa6.md from inside the repo you want the change in.

⬇ Download capture-commit-6fc6afa6.md