From 1a46d611a0f4bd69b9067e7293ee69629c87938c Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Tue, 10 Nov 2026 21:30:43 -0500 Subject: [PATCH] The template's lost-seat search has a limit of its own Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx --- template/server/src/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/template/server/src/index.ts b/template/server/src/index.ts index 4ddbcd6..61ca325 100644 --- a/template/server/src/index.ts +++ b/template/server/src/index.ts @@ -97,6 +97,8 @@ const galleryVoices = new RateLimit(30, 10 * 60 * 1000); const bells = new RateLimit(3, 60 * 60 * 1000); /** Claims on transfer phrases: a phrase is guessed, not brute-forced. */ const claims = new RateLimit(10, 10 * 60 * 1000); +/** Searches for lost seats: each reads every table written to lately, and a person loses their seats rarely. */ +const searches = new RateLimit(5, 10 * 60 * 1000); const MAX_AUDIENCE = 30; /** How often each socket is asked to answer; one silent through a whole round is a browser gone, and is closed. */ const PING_MS = Number(process.env.PING_MS ?? 30_000); @@ -109,6 +111,7 @@ setInterval(() => { galleryVoices.prune(); bells.prune(); claims.prune(); + searches.prune(); if (n) console.log(`evicted ${n} idle room${n === 1 ? '' : 's'} from memory; ${rooms.loaded} loaded`); }, 60 * 60 * 1000).unref(); @@ -347,7 +350,7 @@ async function handle(req: IncomingMessage, res: ServerResponse): Promise return send(res, 200, { seats }); } if (parts[2] === 'find' && parts.length === 3) { - if (!claims.allow(clientOf(req))) throw new RoomError('Too many searches from here just now; try again later.', 429); + if (!searches.allow(clientOf(req))) throw new RoomError('Too many searches from here just now; try again later.', 429); const found = rooms.findSeats(String(body.name ?? ''), addrOf(req), typeof body.roomId === 'string' ? body.roomId : undefined); // The seats given back are banked at once, so the cookie and the browser agree. if (found.seated.length) bankSeats(req, res, provenBank(req, found.seated, []));