fix(signin): key the resend cooldown to the address it was set for (#20)
The email-step Send button disabled on any running cooldown, so a merchant who mistyped their address was locked out of sending to the corrected one for the rest of the 60s window — a guard the server never had: request_code enforces the cooldown per address (SD-0001 INV-3 -> PUC-2c). Track which address the running cooldown belongs to (cooldownFor) and gate the email-step button through cooldownAppliesTo(), which blocks only while the countdown runs AND the input normalizes (strip+lowercase, mirroring normalize_email / INV-2) to that address. Same address still shows the honest 'Resend in Ns'; any other address sends immediately. The code-step resend is unchanged. Verified in the live UI (wrong address -> Wrong address? -> corrected address sends at once). package-lock.json: sync recorded version with package.json (0.4.0). Closes #20 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
// Resend-cooldown keying (SD-0001 §5.2, INV-3; bug #20). The server's cooldown is
|
||||
// per-address, so the client countdown must be too: it blocks sending only while it
|
||||
// is running AND the current input is the address it was set for. Normalization
|
||||
// mirrors the backend's normalize_email (lowercase + strip, INV-2).
|
||||
|
||||
function normalize(email: string): string {
|
||||
return email.trim().toLowerCase();
|
||||
}
|
||||
|
||||
export function cooldownAppliesTo(
|
||||
input: string,
|
||||
cooldownEmail: string | null,
|
||||
secondsLeft: number,
|
||||
): boolean {
|
||||
if (secondsLeft <= 0 || cooldownEmail === null) return false;
|
||||
return normalize(input) === normalize(cooldownEmail);
|
||||
}
|
||||
Reference in New Issue
Block a user