Files
resolutionflow/backend/.env.example
Michael Chihlas 8494366ec6
Some checks failed
Mirror to GitHub / mirror (push) Successful in 5s
CI / e2e (pull_request) Failing after 1m57s
CI / frontend (pull_request) Failing after 2m35s
CI / backend (pull_request) Successful in 9m46s
feat(billing): add INTERNAL_TESTER_EMAILS allowlist for self-serve soft cutover
Phase O Task 46 needs internal validation of the full self-serve flow
against the prod backend before flipping SELF_SERVE_ENABLED public. This
adds the per-email allowlist that bypasses the global flag for specific
authenticated users.

- INTERNAL_TESTER_EMAILS: comma-separated list, parsed by a Pydantic
  field_validator into a normalized lowercase list. Settings.is_internal_tester
  and Settings.is_self_serve_active_for centralize the allowlist + global-flag
  check; both endpoints below call the latter.
- New get_current_user_optional dep — best-effort auth that returns None
  on missing/invalid token instead of 401. Used by /config/public so the
  same endpoint serves anonymous public callers and authenticated allowlist
  members.
- /config/public now accepts optional auth and returns self_serve_enabled=True
  for authenticated allowlist members even when the global flag is off.
  Anonymous callers always see the global flag.
- /auth/register replaces the SELF_SERVE_ENABLED check with the helper so a
  registering email on the allowlist can join without an invite code.
  Non-allowlist emails still 400 when self-serve is off.
- docker-compose.dev.yml passes SELF_SERVE_ENABLED + INTERNAL_TESTER_EMAILS
  through; backend/.env.example documents both.

Tests cover: allowlisted authenticated user sees true, non-allowlisted
authenticated user sees the global flag, anonymous calls ignore the
allowlist, allowlisted email registers without invite code, non-allowlisted
email still blocked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:57:25 -04:00

42 lines
1.4 KiB
Plaintext

# Application
APP_NAME=ResolutionFlow
DEBUG=true
# Database
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/resolutionflow
DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/resolutionflow
# JWT Settings - CHANGE THESE IN PRODUCTION
# Generate with: openssl rand -hex 32
SECRET_KEY=your-super-secret-key-change-this-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=15
REFRESH_TOKEN_EXPIRE_DAYS=7
# CORS
CORS_ORIGINS=["http://localhost:3000","http://localhost:5173"]
# Anthropic API Key
ANTHROPIC_API_KEY=
VOYAGE_API_KEY=
# ConnectWise PSA Integration
CW_CLIENT_ID=<CONNECTWISE CLIENT ID>
# Stripe
# Test keys from Stripe Dashboard → Developers → API keys (with Test mode toggled on).
# Webhook secret for local dev: from `stripe listen --forward-to localhost:8000/api/v1/webhooks/stripe`.
# When unset, app/core/config.py:stripe_enabled returns False and Stripe code paths short-circuit.
STRIPE_SECRET_KEY=sk_test_
STRIPE_PUBLISHABLE_KEY=pk_test_
STRIPE_WEBHOOK_SECRET=whsec_
# Self-serve cutover
# SELF_SERVE_ENABLED is the master switch for the public self-serve signup
# flow (pricing page, invite-code-optional registration). Default is false
# until Phase O cutover.
# INTERNAL_TESTER_EMAILS is a comma-separated allowlist that bypasses the
# global flag for specific users — used for prod test-mode validation
# before the public flip. Empty by default.
SELF_SERVE_ENABLED=false
INTERNAL_TESTER_EMAILS=