Skip to content

v0.1.17

Choose a tag to compare

@github-actions github-actions released this 18 Mar 14:31

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.cookies from mangling commas (\054) and breaking client-side JSON.parse().
  • NeedsNewTokens query string preservation: The token-refresh redirect now uses str(request.url) instead of request.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