Hashed seat tokens, ledgered inputs, refusable moves, disk-checked codes, host-only bots, and a drift script

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
This commit is contained in:
Eric Wagoner
2026-09-23 12:07:53 -04:00
co-authored by Claude Fable 5.1
parent ddb18cb08a
commit c934bbe434
12 changed files with 173 additions and 47 deletions
+5 -5
View File
@@ -3,7 +3,7 @@
//
// POST /api/rooms {name, size?} create a room and take seat A
// POST /api/rooms/:id/join {name} take the next seat
// POST /api/rooms/:id/bot {token} seat a bot (any seated player may, before the game begins)
// POST /api/rooms/:id/bot {token} the host seats a bot, before the game begins
// POST /api/rooms/:id/begin {token} the host begins with the players seated so far
// POST /api/rooms/:id/unseat {token, seat} the host sends a bot away before the game begins
// GET /api/rooms/:id?token= the view for that seat; without a token, the gallery's view
@@ -171,8 +171,8 @@ async function handle(req: IncomingMessage, res: ServerResponse): Promise<void>
if (parts.length === 2 && req.method === 'POST') {
if (!doors.allow(clientOf(req))) throw new RoomError('Too many rooms opened from here just now; try again later.', 429);
const body = await readBody(req);
const { room, seat } = rooms.create(String(body.name ?? ''), Number(body.size ?? game.minSeats));
return send(res, 201, { seat: seat.id, token: seat.token, view: rooms.view(room, seat.id) });
const { room, seat, token } = rooms.create(String(body.name ?? ''), Number(body.size ?? game.minSeats));
return send(res, 201, { seat: seat.id, token, view: rooms.view(room, seat.id) });
}
const room = rooms.get(parts[2] ?? '');
@@ -187,8 +187,8 @@ async function handle(req: IncomingMessage, res: ServerResponse): Promise<void>
const token = typeof body.token === 'string' && body.token ? body.token : undefined;
if (action === 'join') {
if (!doors.allow(clientOf(req))) throw new RoomError('Too many seats taken from here just now; try again later.', 429);
const seat = rooms.join(room, String(body.name ?? ''));
return send(res, 200, { seat: seat.id, token: seat.token, view: rooms.view(room, seat.id) });
const { seat, token: minted } = rooms.join(room, String(body.name ?? ''));
return send(res, 200, { seat: seat.id, token: minted, view: rooms.view(room, seat.id) });
}
if (action === 'bot') {
rooms.addBot(room, token);