Password reset by email: a single-use link, caught by Mailpit, sent by Resend in production #380
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
spec
wayfinder:grilling
wayfinder:map
wayfinder:prototype
wayfinder:research
wayfinder:task
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
Depends on
#381 Rate limits on sign-up, sign-in and reset requests, with when to try again
amaurycoudr/chess-project
#379 Sign-up and sign-in pages: the navigation names the Account, a refresh keeps it signed in
amaurycoudr/chess-project
Reference
amaurycoudr/chess-project#380
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent
#364
What to build
A Player who forgot their password asks for a reset link at
/forgot-passwordand always gets the same answer. If the email has an Account, a message goes out with a link to/reset-passwordthat holds 256 random bits in the URL fragment. The link is valid one hour and works once. The page reads the token, removes it from the address bar and posts it with the new password. A successful reset deletes every Session and every reset token of the Account, then signs this browser in. An expired, used or unknown link is told so and offered a new one.Mail goes through a mail module with one port. Production sends through Resend over SMTP. Mailpit catches mail in dev (beside the shared dev Postgres), in CI (a service container) and in each preview (a preview-only container behind basic auth, under a path prefix on the preview's host). Tests inject an in-memory outbox. An hourly sweep on the injected clock removes expired Sessions and reset tokens.
The owner runs the Resend and DNS checklist with the
wizardskill before this merges, because the API now refuses to start without its mail settings.Seam:
loadConfig; the RPC wire (with the in-memory outbox and the fake clock); the front views; e2eAcceptance criteria
auth.requestPasswordResetandauth.resetPasswordexist, the latter withRESET_LINK_INVALIDfor unknown, used and expired alikeloadConfigrequires the SMTP URL, the sender address and the public URL, tested beside the existing config testsenv:sync), in CI's e2e job and in each preview, never in production; the preview e2e job passes its URL and credentials to the suite_dmarcrecord atp=noneadded, the SMTP URL stored as a production secret, and one real reset received by the owner with SPF, DKIM and DMARC passingmail/folder is declared in the API's layer order and framework-import rules (the owner ruled on the accounts breakdown that declaring a folder the spec creates counts as the requested lint change; nothing else in lint config changes)mentioned in issue #381
mentioned in issue #364
mentioned in issue #379
marked this issue as related to #364
marked this issue as related to #379
marked this issue as related to #381
mentioned in merge request !523