// In-memory limiter for sign-in style endpoints: 10 FAILED attempts per 15 min, tracked per IP and per // account (key). Successful sign-ins don't count, so a shared IP doesn't lock everyone out. const _failures = new Map(); const FAIL_WINDOW = 15 * 60 * 1000; const FAIL_MAX = 10; setInterval(() => { const now = Date.now(); for (const [k, e] of _failures) if (now > e.resetAt) _failures.delete(k); }, 60 * 60 * 1000).unref(); export function isLimited(...keys) { const now = Date.now(); return keys.some((k) => { const e = _failures.get(k); return e && now <= e.resetAt && e.count >= FAIL_MAX; }); } export function recordFailure(...keys) { const now = Date.now(); for (const k of keys) { const e = _failures.get(k); if (!e || now > e.resetAt) _failures.set(k, { count: 1, resetAt: now + FAIL_WINDOW }); else e.count += 1; } } export function clearFailures(...keys) { keys.forEach((k) => _failures.delete(k)); } export const TOO_MANY = { error: 'Too many attempts. Please wait 15 minutes.' };