-- Per-IP flood ceiling for /recover, mirroring the one migration 017 added for /join. -- -- Rationale: /recover is keyed `recover:{ip}:{name}` at 5 per 15 minutes. That is the -- right shape for its actual job — stopping someone who knows a display name (they are -- visible on the feed) from burning the victim's 3-strike PIN counter and locking them -- out repeatedly. But the name is attacker-chosen, so cycling names mints a fresh bucket -- every time and the per-IP cost is unbounded. -- -- Behind that limiter sits a cost-12 bcrypt verify, including an UNCONDITIONAL throwaway -- verify for names that don't exist — deliberately, to close a timing oracle. So an -- unknown name is the cheapest possible way to make the server do ~200ms of hashing. -- Without a ceiling, one client can saturate the box's CPU with a name generator. -- -- 30/min is far above any real recovery attempt (a guest tries their PIN a handful of -- times) while capping a name-cycling flood. The per-(ip, name) bucket is unchanged and -- remains the anti-guessing control. INSERT INTO config (key, value) VALUES ('recover_ip_rate_per_min', '30') ON CONFLICT (key) DO NOTHING;