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>