Sign-in: stop telling a fast returning member off for being fast

The email-code endpoint refuses a request that arrives within two seconds of
the page loading, because a script fills a form instantly and a person does
not. A member whose email is already filled in by the browser has nothing to
type, taps straight away, and gets "Give the page a second, then tap again."

The page now waits out the remainder itself and sends when the window has
passed, so the person sees the normal sending state instead of an error.
The server check is untouched, so anything posting at the endpoint without a
page behind it still fails exactly as before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-23 05:50:34 -05:00
parent 286ac9207a
commit 489d832546
17 changed files with 28 additions and 16 deletions
+12
View File
@@ -172,9 +172,21 @@ window.IAP = (function () {
}
armHoneypots(); document.addEventListener('DOMContentLoaded', armHoneypots);
const hpValue = el => (el && el.dataset.touched === '1') ? (el.value || '') : '';
// The server refuses a code request that arrives within a couple of seconds of the page loading,
// because a script fills a form instantly and a person does not. A returning member whose email
// is already autofilled has nothing to type, taps straight away, and gets told off for being
// quick (Marty, 2026-09-23). So the page waits out the remainder itself: the person sees the
// normal sending state, and anything posting at the endpoint without a page behind it still
// fails the same check.
const MIN_FORM_MS = 2400; // the server wants 2000; leave headroom for clock skew in transit
function formSettled() {
const left = MIN_FORM_MS - (Date.now() - FORM_TS);
return left > 0 ? new Promise(r => setTimeout(r, left)) : Promise.resolve();
}
async function requestCode(email, opts) {
const o = opts || {};
let pick = null;
await formSettled();
for (let i = 0; i < 4; i++) {
const r = await (await fetch('/api/auth/email/start', { method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, fts: FORM_TS, hp_field_x9: hpValue(o.honeypot), pick }) })).json();