feat(dev): DEV_AUTH_BYPASS flag to skip guest gates for headless testing - #555
Conversation
Headless API/Playwright testing of guest flows (collect/join/kiosk submit, vote,
profile) is blocked by the human-verification (wrzdj_human cookie) and email-
verification gates, which the external test suites can't easily satisfy. Turnstile
already self-disables in dev; these two gates had no dev escape hatch.
Add DEV_AUTH_BYPASS (default off). When set in a non-production env, the three guest
gates (require_verified_human, require_verified_human_soft, require_email_verified)
resolve a real guest identity (the request's wrzdj_guest cookie if present, else a
stable lazily-created dev guest) and skip the cookie/email checks — so tests need no
cookies at all.
Prod-safe by construction: the auth_bypass_enabled property gates on `not
is_production` (inert if the flag ever leaks into prod), AND validate_settings
refuses to boot (SystemExit) if it is set with ENV=production. A loud warning is
logged when it is active in dev.
Tests: property matrix (dev-active / prod-inert / off-by-default), prod refuses to
boot + clean prod still boots + dev warns, and a live integration check that a hard-
gated endpoint (GET /collect/{code}/profile) is 403 without the bypass and 200 with
it. 8 new tests; no regression across the gate suites (104 passing).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 29 minutes and 26 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The first cut only bypassed the gate dependencies, but several guest endpoints (vote, public.py, guest.py, events.py) resolve identity INLINE via get_guest_id and raise their own 401 — so they still blocked under the bypass. Move the dev-guest get-or-create into get_guest_id (the single identity chokepoint the gates AND the inline routes share) so DEV_AUTH_BYPASS covers every guest page. Same prod-safety: the new branch is gated on the identical auth_bypass_enabled (inert in production), and with the flag off behavior is unchanged. Adds a vote regression test for the inline-resolution path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adversarial review found the bypass FLAG was prod-safe, but the dev guest ROW it creates was a latent backdoor: a fixed public token (dev-auth-bypass-guest) + a pre-set verified_email. If that row ever reached a prod DB (staging->prod promotion, backup restore, dev dump), an attacker could present `Cookie: wrzdj_guest= dev-auth-bypass-guest` — the NORMAL cookie lookup resolved it before any bypass check — solve a public Turnstile, and pass require_email_verified (row pre-verified) to reach email-gated guest actions with no OTP. Two independent barriers: 1. get_guest_id rejects the reserved dev token outright when the bypass is off, so a leaked row is unresolvable in production regardless of the flag. 2. The dev guest is no longer pre-verified (no verified_email) — the email gate is opened by the explicit require_email_verified bypass, so the row never needs a pre-verified identity that could be abused if it leaked. Regression tests: leaked dev token rejected with bypass off, resolves with bypass on, normal tokens unaffected, dev guest not pre-verified. Codex separately confirmed no other prod bypass path (flag inert in prod + boot-abort, no runtime toggle, no effect on JWT/rate-limit/IDOR/kiosk/owner checks). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-review found the reserved-token defense was incomplete: /guest/identify does NOT go through get_guest_id, so it could still accept the reserved-token cookie, let an attacker write their fingerprint onto a leaked dev guest row, and after the quiet period have reconciliation rotate it to a fresh random token — escaping the reserved-token check. Extract the rule into a single source of truth (rate_limit.is_inert_dev_token: the reserved token with the bypass OFF) and apply it at BOTH guest-identity entry points — get_guest_id and the /guest/identify endpoint (drop the token so identity resolves as cookieless). The dev row is created with no fingerprint, so reconciliation-by- fingerprint can't reach it once the cookie path is closed. Regression test: /identify with the reserved cookie + bypass off neither claims the dev row nor writes the attacker fingerprint onto it. Codex re-confirmed no prod-bypass path otherwise (flag inert + boot-abort, no runtime toggle, JWT/rate-limit/IDOR/kiosk untouched). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adversarial security review (Codex GPT-5.5 xhigh) — 3 passes to convergencePer the requirement that this dev flag cannot weaken production hardening via any path:
Prod-safety invariant: inert in production by construction ( 🤖 Reviewed via Codex (GPT-5.5 xhigh, 3 passes) + manual analysis. |
Why
Headless testing of guest flows (collect/join/kiosk submit, vote, profile) is blocked by the human-verification (
wrzdj_humancookie) and email-verification gates — the external API suite and Playwright can't easily mint those. Turnstile already self-disables in dev; these two gates had no dev escape hatch. (This is exactly what blocked 16 checks in the~/wrzdj-testingsuite — all 401/403 gate rejections.)What
Adds
DEV_AUTH_BYPASS(default off). When set in a non-production env, the three guest gates (require_verified_human,require_verified_human_soft,require_email_verified) resolve a real guest identity — the request'swrzdj_guestcookie if present, else a stable lazily-created dev guest — and skip the cookie/email checks. So tests need no cookies at all. Admin/DJ auth is unchanged (JWT).Prod-safety (by construction)
auth_bypass_enabledgates onnot is_production→ inert even if the flag leaks into a prod environment.validate_settingsrefuses to boot (SystemExit(1)) ifDEV_AUTH_BYPASSis set withENV=production.WARNINGis logged whenever it's active in dev.Testing
GET /collect/{code}/profile(hard gate) → 403 without bypass, 200 with it🤖 Co-authored by Claude Opus 4.8.