Resend-confirmation affordance for stored unconfirmed emails #173

Open
opened 2026-08-10 03:16:17 +00:00 by rosa · 0 comments
Owner

Problem Statement

On an email-disabled instance (see #172), a User may set an email that is stored
unconfirmed and inert. When the operator later configures SMTP, that already-stored
email needs a way to become confirmed. #172 assumes this happens through the
ordinary user-initiated confirmation path — but if that path only dispatches a
confirmation when the email changes, a User whose address was stored earlier and
is unchanged has no way to trigger confirmation, leaving their address permanently
unconfirmed even though email now works.

Solution

Give the User an explicit "resend confirmation" affordance in account settings that
mints and dispatches a fresh email confirmation for the currently-stored, still
unconfirmed email — without requiring them to change the address to something else
and back.

Trigger / dependency

This is a contingent follow-up to #172. It only becomes real work if, during or
after #172, the ordinary email-set path is found NOT to reach an already-stored
(previously inert) email. #172's Further Notes carry an explicit check for this.
If the ordinary path already re-confirms an unchanged stored email, close this as
not needed.

User Stories

  1. As a User whose email was stored while the instance was email-disabled, I want a
    "resend confirmation" control in settings, so that I can confirm my unchanged
    address once the operator enables email.
  2. As a User with an unconfirmed email on an email-enabled instance, I want to
    re-request confirmation without editing my address, so that a lost or expired
    confirmation link is recoverable.
  3. As a User, I want the affordance to appear only when I have an email that is not
    yet confirmed, so that it is absent when there is nothing to confirm.
  4. As a User on an email-disabled instance, I want no such affordance shown (or it
    inert), so that I am not offered an action that cannot currently send.

Implementation Decisions

  • Reuses the existing confirmation flow (accounts::Service::send_email_confirmation
    and the email_confirmation job/queue); this issue adds a trigger, not a new
    delivery path.
  • The affordance is gated on the same web-layer email capability introduced by #172:
    hidden/disabled on an email-disabled instance.
  • Shown only when the signed-in User has an email with no email_confirmed_at.
  • Subject to the same enumeration/rate considerations as other confirmation sends;
    reuse existing throttling rather than inventing new limits.

Testing Decisions

  • Primary seam: the crates/server integration harness (test_server), same as
    #172. On an email-enabled server, a User with a stored unconfirmed email hits
    the resend affordance and a new email_confirmation confirmation is minted
    (assert via email_confirmations_for, passkey_test.rs:134).
  • Assert the affordance is absent / inert on an email-disabled test_server.
  • Assert no affordance path mints a confirmation when the User already has a
    confirmed email.

Out of Scope

  • Everything delivered by #172 (making SMTP optional). This issue is only the
    resend trigger.
  • Changing confirmation token lifetime, the SMTP transport, or job retry policy.

Further Notes

Blocked on / informed by #172. Do not start until #172's investigation confirms the
ordinary path does not already cover the unchanged-stored-email case.

## Problem Statement On an email-disabled instance (see #172), a User may set an email that is stored unconfirmed and inert. When the operator later configures SMTP, that already-stored email needs a way to become confirmed. #172 assumes this happens through the ordinary user-initiated confirmation path — but if that path only dispatches a confirmation when the email *changes*, a User whose address was stored earlier and is unchanged has no way to trigger confirmation, leaving their address permanently unconfirmed even though email now works. ## Solution Give the User an explicit "resend confirmation" affordance in account settings that mints and dispatches a fresh email confirmation for the currently-stored, still unconfirmed email — without requiring them to change the address to something else and back. ## Trigger / dependency This is a **contingent follow-up to #172**. It only becomes real work if, during or after #172, the ordinary email-set path is found NOT to reach an already-stored (previously inert) email. #172's Further Notes carry an explicit check for this. If the ordinary path already re-confirms an unchanged stored email, close this as not needed. ## User Stories 1. As a User whose email was stored while the instance was email-disabled, I want a "resend confirmation" control in settings, so that I can confirm my unchanged address once the operator enables email. 2. As a User with an unconfirmed email on an email-enabled instance, I want to re-request confirmation without editing my address, so that a lost or expired confirmation link is recoverable. 3. As a User, I want the affordance to appear only when I have an email that is not yet confirmed, so that it is absent when there is nothing to confirm. 4. As a User on an email-disabled instance, I want no such affordance shown (or it inert), so that I am not offered an action that cannot currently send. ## Implementation Decisions - Reuses the existing confirmation flow (`accounts::Service::send_email_confirmation` and the `email_confirmation` job/queue); this issue adds a trigger, not a new delivery path. - The affordance is gated on the same web-layer email capability introduced by #172: hidden/disabled on an email-disabled instance. - Shown only when the signed-in User has an email with no `email_confirmed_at`. - Subject to the same enumeration/rate considerations as other confirmation sends; reuse existing throttling rather than inventing new limits. ## Testing Decisions - Primary seam: the `crates/server` integration harness (`test_server`), same as #172. On an email-*enabled* server, a User with a stored unconfirmed email hits the resend affordance and a new `email_confirmation` confirmation is minted (assert via `email_confirmations_for`, `passkey_test.rs:134`). - Assert the affordance is absent / inert on an email-disabled `test_server`. - Assert no affordance path mints a confirmation when the User already has a confirmed email. ## Out of Scope - Everything delivered by #172 (making SMTP optional). This issue is only the resend trigger. - Changing confirmation token lifetime, the SMTP transport, or job retry policy. ## Further Notes Blocked on / informed by #172. Do not start until #172's investigation confirms the ordinary path does not already cover the unchanged-stored-email case.
rosa added this to the v0.1 milestone 2026-08-12 03:32:53 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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
rosa/vernier#173
No description provided.