fix(auth): await welcome email inline so it lands before verify on signup #304

Merged
vas2000-work merged 1 commit from fix/BUNYIP-296-welcome-before-verify into main 2026-07-01 07:13:32 +02:00
Owner

Both mails around registration are dispatched via tokio::spawn today, so their SMTP submission order depends on scheduler timing. register spawns send_account_created and returns 201; bunyip-web redirects to /onboarding; the onboarding GET auto-fires POST /v1/users/me/email/verify, which spawns send_email_verify. Both spawned tasks race, and the verify request reliably lands within ~50-200 ms of the register response - well inside the window a slow welcome mail can lose to. The user then sees "Verify your email" before "Welcome to Bunyip", which reads as a broken sequence for the very first two mails they will ever get from us.

Move the welcome dispatch to an inline .await inside register. The send stays best-effort (a mail failure logs and continues, because register has already committed the row and dashboard access does not depend on a delivered welcome), but the response only returns after the welcome is on the SMTP wire. The onboarding page's auto-verify (which runs in the browser only AFTER it has received the register response and navigated) cannot fire earlier than the welcome by construction.

Cost: the register response is delayed by SMTP submission latency (typically 50-500 ms on a warm connection). Acceptable because the perceived latency of the register flow is dominated by the redirect to /onboarding and its render, not by the 201, and the SMTP timeout in EmailService bounds worst-case hang.

Same inline-await applied to the MagicLinkResult::Success new-user branch for stylistic uniformity. Magic-link signup verifies the email as part of the flow itself, so no verify message follows and the ordering-race concern does not apply there; the change is cosmetic parity between the two signup paths, not a correctness fix at that call site.

Out of scope: POST /v1/users/me/email/verify still tokio::spawns its send. Templates + copy are BUNYIP-288's; the onboarding auto-send + VERIFY_SENT_COOKIE cookie gate are unchanged.

#BUNYIP-296

Both mails around registration are dispatched via `tokio::spawn` today, so their SMTP submission order depends on scheduler timing. `register` spawns `send_account_created` and returns 201; bunyip-web redirects to /onboarding; the onboarding GET auto-fires `POST /v1/users/me/email/verify`, which spawns `send_email_verify`. Both spawned tasks race, and the verify request reliably lands within ~50-200 ms of the register response - well inside the window a slow welcome mail can lose to. The user then sees "Verify your email" before "Welcome to Bunyip", which reads as a broken sequence for the very first two mails they will ever get from us. Move the welcome dispatch to an inline `.await` inside `register`. The send stays best-effort (a mail failure logs and continues, because register has already committed the row and dashboard access does not depend on a delivered welcome), but the response only returns after the welcome is on the SMTP wire. The onboarding page's auto-verify (which runs in the browser only AFTER it has received the register response and navigated) cannot fire earlier than the welcome by construction. Cost: the register response is delayed by SMTP submission latency (typically 50-500 ms on a warm connection). Acceptable because the perceived latency of the register flow is dominated by the redirect to /onboarding and its render, not by the 201, and the SMTP timeout in `EmailService` bounds worst-case hang. Same inline-await applied to the `MagicLinkResult::Success` new-user branch for stylistic uniformity. Magic-link signup verifies the email as part of the flow itself, so no verify message follows and the ordering-race concern does not apply there; the change is cosmetic parity between the two signup paths, not a correctness fix at that call site. Out of scope: `POST /v1/users/me/email/verify` still `tokio::spawn`s its send. Templates + copy are BUNYIP-288's; the onboarding auto-send + `VERIFY_SENT_COOKIE` cookie gate are unchanged. #BUNYIP-296
fix(auth): await welcome email inline so it lands before verify on signup
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 22s
Check / fmt + clippy + build + tests (pull_request) Successful in 10m20s
31384bdae4
Both mails around registration are dispatched via `tokio::spawn` today, so their SMTP submission order depends on scheduler timing. `register` spawns `send_account_created` and returns 201; bunyip-web redirects to /onboarding; the onboarding GET auto-fires `POST /v1/users/me/email/verify`, which spawns `send_email_verify`. Both spawned tasks race, and the verify request reliably lands within ~50-200 ms of the register response - well inside the window a slow welcome mail can lose to. The user then sees "Verify your email" before "Welcome to Bunyip", which reads as a broken sequence for the very first two mails they will ever get from us.

Move the welcome dispatch to an inline `.await` inside `register`. The send stays best-effort (a mail failure logs and continues, because register has already committed the row and dashboard access does not depend on a delivered welcome), but the response only returns after the welcome is on the SMTP wire. The onboarding page's auto-verify (which runs in the browser only AFTER it has received the register response and navigated) cannot fire earlier than the welcome by construction.

Cost: the register response is delayed by SMTP submission latency (typically 50-500 ms on a warm connection). Acceptable because the perceived latency of the register flow is dominated by the redirect to /onboarding and its render, not by the 201, and the SMTP timeout in `EmailService` bounds worst-case hang.

Same inline-await applied to the `MagicLinkResult::Success` new-user branch for stylistic uniformity. Magic-link signup verifies the email as part of the flow itself, so no verify message follows and the ordering-race concern does not apply there; the change is cosmetic parity between the two signup paths, not a correctness fix at that call site.

Out of scope: `POST /v1/users/me/email/verify` still `tokio::spawn`s its send. Templates + copy are BUNYIP-288's; the onboarding auto-send + `VERIFY_SENT_COOKIE` cookie gate are unchanged.

#BUNYIP-296
vas2000-work force-pushed fix/BUNYIP-296-welcome-before-verify from 31384bdae4
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 22s
Check / fmt + clippy + build + tests (pull_request) Successful in 10m20s
to f9ca921df1
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 1m4s
Check / fmt + clippy + build + tests (pull_request) Successful in 9m37s
Create release / Create release from merged PR (pull_request) Has been skipped
2026-07-01 06:55:24 +02:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!304
No description provided.