fix(wave): send users with unverified GitHub emails to a dedicated page - #1956
Merged
Conversation
The wave backend now rejects logins and token refreshes with a 403 carrying code "unverified_email" when the GitHub primary email address is unverified. Match that code on the login callback, the client-side token refresh, and the server-side refresh hook, and route the user to a new /wave/unverified-email page explaining how to verify the address on GitHub.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds explicit frontend handling for Wave backend’s unverified_email 403s so users with unverified GitHub primary emails are routed to a dedicated explanatory page instead of seeing a generic error or being silently logged out.
Changes:
- Introduces
UnverifiedEmailErrorin the Wave API call layer and ensures machine-readable code matching is evaluated before prose keyword matching. - Adds a new
/wave/unverified-emailflow page mirroring the existing suspended flow UX. - Routes all relevant rejection paths (login callback, client refresh, server refresh hook) to
/wave/unverified-email.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/routes/(pages)/wave/(flows)/unverified-email/+page.svelte | New UX page explaining unverified GitHub email requirement and providing a re-login action. |
| src/routes/(pages)/wave/(flows)/login/callback/perform-login.ts | Re-throws UnverifiedEmailError so the callback page can route appropriately. |
| src/routes/(pages)/wave/(flows)/login/callback/+page.svelte | Adds client-side routing to /wave/unverified-email when login exchange fails with UnverifiedEmailError. |
| src/lib/utils/wave/call.ts | Adds UnverifiedEmailError and matches unverified_email before suspended/restricted prose matching in call(). |
| src/lib/utils/wave/auth.ts | Routes client-side token refresh failures with UnverifiedEmailError to /wave/unverified-email after logout. |
| src/hooks.server.ts | Adds SSR refresh handling: clears auth cookies and redirects to /wave/unverified-email when refresh returns unverified_email. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Frontend half of drips-network/wave#791 (backend: drips-network/wave#792).
Problem
The wave backend now rejects logins and token refreshes with a 403 carrying the
machine-readable code
unverified_emailwhen the user's GitHub primary emailaddress is unverified. Without frontend handling, those users would land on the
generic "Something went wrong" screen (login) or be silently logged out
(refresh) with no explanation.
Changes
UnverifiedEmailErrorincall.ts, matched on the backend'sunverified_emailcode. The machine-readable code matches now run before thebare-word
suspended/restrictedmatches so prose can't shadow them. Thecheck is deliberately scoped to
call()— the backend only sets this code onlogin and refresh, and matching it in
authenticatedCall()would turn an SSRload failure into an unhandled 500.
/wave/unverified-emailpage (mirrors/wave/suspended): explains thesituation, links GitHub's "verifying your email address" docs, and offers
"Sign in again".
token refresh (after logout), and the server-side refresh hook (cookies
cleared, 302).
Notes
Recovery is self-healing: the user verifies the address on GitHub and signs in
again — no app-side verification flow needed.