v0.1.17
Summary
- Multi-email system: Users can add a secondary email (max 2), verify it via an emailed link, promote it to primary, or remove it. The old single-email update flow (
EmailUpdateToken,/request_email_update,/confirm_email_update) has been removed. - Account recovery: When a sensitive email change occurs (primary swap or email removal), the affected email receives a notification with a tokenized recovery link. Clicking it restores the victim's email as primary, purges attacker emails, revokes all sessions, and forces a password reset.
- Password reset auto-login: After resetting a password, the user is automatically logged in and redirected to the dashboard — no redundant login step.
- Flash cookie encoding fix: URL-encode the JSON cookie value before setting it, preventing Python's
http.cookiesfrom mangling commas (\054) and breaking client-sideJSON.parse(). - NeedsNewTokens query string preservation: The token-refresh redirect now uses
str(request.url)instead ofrequest.url.path, preserving query parameters for GET routes.
QA checklist
Add and verify a secondary email
- Log in and navigate to profile page
- Add a secondary email address via the form
- Verify a "Verification email sent" toast appears
- Note: "Add email" field/button should clear/disable after submission
- Check the secondary email inbox to verify verification link was sent
- Click the verification link
- Verify redirect to login page with success toast
- After login, verify the new email appears on the profile page as verified (non-primary)
- Verify the primary email received a "New email added" notification
Promote a secondary email to primary
- From profile page, click "Make Primary" on the verified secondary email
- Verify a "Primary email updated" toast appears
- Verify the profile page now shows the new primary email
- Note: Primary email should move to top row rather than just swapping labels
- Check the OLD primary email inbox for a "Primary Email Changed" notification
- Verify the notification contains a "Recover Your Account" button/link (not just "change your password")
Remove a secondary email
- Add and verify a secondary email, then click "Remove"
- Verify a "Email address removed" toast appears
- Check the REMOVED email inbox for an "Email Address Removed" notification
- Verify the notification contains a "Recover Your Account" button/link
Account recovery (after primary swap)
- With a promoted secondary email as primary, click the recovery link sent to the old primary
- Verify redirect to the password reset page with "Account recovered. Please set a new password." toast
- Submit a new password
- Verify auto-login: redirected to dashboard with "Password reset successfully." toast (no manual login required)
- Navigate to profile and verify the original email is restored as the sole primary email
- Verify the attacker's email has been removed from the account
Account recovery (after email removal)
- Remove a secondary email, then click the recovery link sent to that email
- Verify the same recovery flow as above works (redirect to reset, auto-login, email restored)
Recovery edge cases
- Click an expired recovery link (>7 days) — should see an error, not a crash
- Click a used recovery link — should see an error
- Click a recovery link with a bogus token — should see an error
Standard password reset (regression check)
- Use "Forgot Password" flow to reset password
- Verify auto-login after reset (redirect to dashboard, not login page)
- Verify "Password reset successfully." toast appears on the dashboard
Flash toast visibility (regression check)
- Verify toasts appear on all redirect flows above (not silently swallowed)
- Specifically test with both fresh sessions and expired sessions
🤖 Generated with Claude Code