Replace zod with valibot; misc fixes - #48
Conversation
The z namespace import is not tree-shakeable (importing it pulls in roughly the whole builder API), costing ~29 KB gzip in the shared schemas chunk for five small form schemas. Valibot's per-function imports tree-shake to actual usage, cutting that chunk to ~14 KB gzip. Also fills e2e/unit test gaps found while verifying the resolver swap: forgotSchema had no test at all, and the forgot-password/OTP forms' valibotResolver wiring had no e2e coverage. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
send-verification-otp is unauthenticated and never checked the target's emailVerified state before mailing a fresh code. Combined with autoSignInAfterVerification, this meant anyone who could read a single OTP email for an existing, already-verified user got a full session as that user, indefinitely, not just during the signup window most apps restrict this shortcut to. Brute-forcing the code itself isn't practical (3 attempts per code, 10-minute expiry, fresh code per resend), but reading one email is enough on its own. Verified against the real dev server: with the guard removed, a second send-verification-otp call for an already-verified address mails another code (proving the exploit); restoring the guard blocks it. An automated e2e regression was attempted but dropped: the endpoint shares a tight 3-per-60s rate-limit bucket with every real signup in the suite, and adding another live call to it destabilized unrelated tests under full parallelism. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both docs' layout sections had drifted from src/worker/'s actual contents (missing better-auth.ts, guards.ts, org-role.ts, rate-limit.ts, session.ts, clicks.ts, workflows.ts). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
|
Warning Review limit reached
Next review available in: 20 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?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 reviews. How do review 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 refer docs for additional details. 📝 WalkthroughWalkthroughThe pull request replaces Zod with Valibot across schemas and form resolvers, adds client and worker handling for verified accounts, changes local Cloudflare simulation to use an unset token, updates repository metadata, and removes several operational documents. ChangesValibot validation migration
Verified-account OTP guard
Cloudflare local-mode configuration
Repository maintenance
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/worker/better-auth.ts`:
- Around line 111-120: Move the existing emailVerified lookup out of the
sendVerificationOTP callback and perform it before dispatching the OTP. Update
the relevant authenticated and unauthenticated route/client flows around
sendVerificationOTP to return and handle an explicit EMAIL_VERIFIED result,
avoiding the code screen for verified accounts while preserving OTP sending for
unverified emails.
- Around line 111-120: Update the unauthenticated email-verification flow around
the existing emailVerified lookup and early return to use waitUntil() so
verified and unverified requests have indistinguishable response timing. For
verified accounts, discard the usable OTP while still publishing the appropriate
non-sign-in confirmation event; preserve normal OTP delivery for unverified
accounts.
- Around line 116-120: Close the race between the emailVerified check and OTP
issuance in the verification flow around sendEmail. Coordinate code
creation/sending with the verification-state update so concurrent verification
cannot issue a stale OTP, or record the verification completion boundary and
make autoSignInAfterVerification reject codes issued before it. Preserve the
existing early return for already-verified users.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 6dc032a5-8b0d-4d7c-ae6c-743acf969f56
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (18)
.codegraph/.gitignoreAGENTS.mdREADME.mddocs/click-ingestion.mddocs/rate-limiting.mddocs/storage-recovery.mdpackage.jsonsrc/app/components/link-editor.tsxsrc/app/components/no-org.tsxsrc/app/lib/schemas.tssrc/app/routes/auth.tsxsrc/app/routes/dashboard.tsxsrc/app/routes/domains.tsxsrc/app/routes/members.tsxsrc/app/routes/settings.tsxsrc/worker/better-auth.tstests/e2e/auth.pw.tstests/schemas.test.ts
💤 Files with no reviewable changes (3)
- docs/click-ingestion.md
- docs/storage-recovery.md
- docs/rate-limiting.md
Also widens the fake's issuing_tls window (5s-20s, was 5s-8s) so it's visible in a browser or e2e run, and fixes a stale comment claiming domain reads advance the activation pipeline (a background Workflow does that now). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…llback better-auth swallows whatever sendVerificationOTP returns or throws and always answers the client with a generic success, so skipping the send for an already-verified email there left resend/verify flows stuck on a code screen waiting for a code that would never arrive. Move the check into hooks.before (same pattern as the sign-up duplicate-email guard), where a thrown APIError actually reaches the client as EMAIL_VERIFIED, and have the client bounce back to the login form on that code. Split the before hook into guardVerificationOTPSend/guardSignUp to keep its complexity within the fallow health baseline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Line 82: Update the README statement about unset CF_API_TOKEN to remove the
inaccurate “activate instantly on Check status” claim. Describe that local
custom domains use stubbed Cloudflare status and become ready after the
simulated DNS and TLS delays, using short, direct wording.
In `@src/worker/routes/domains.ts`:
- Line 63: Update the domain workflow around the Cloudflare credential check to
fail closed when CF_API_TOKEN or CF_ZONE_ID is missing, preventing fake domain
IDs from reaching activation, deletion, or re-add paths. If local fake behavior
is required, gate it behind an explicit test-only flag rather than the absence
of credentials; otherwise reject the operation before activation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 06347ffa-1e91-4f95-90fe-2d857cef7d7a
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (11)
.dev.vars.example.dev.vars.playwrightAGENTS.mdREADME.mdpackage.jsonsrc/app/lib/hooks.tssrc/app/routes/auth.tsxsrc/worker/better-auth.tssrc/worker/env.tssrc/worker/routes/domains.tstests/worker/domains.worker.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- package.json
It doesn't activate "instantly": the stub delays DNS ~5s and TLS ~20s so the checking_dns/issuing_tls states are visible in a browser or e2e run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Tip For best results, initiate chat on the files or code changes.
|
Summary
Test plan
bun run checkbunx tsc -p tsconfig.worker.json --noEmitbun run test🤖 Generated with Claude Code
Summary by CodeRabbit
Improvements
CF_API_TOKEN.Documentation
Tests