Commit Graph

51 Commits

Author SHA1 Message Date
cottongin
171303a6f9 fix: enforce single playing game and clean up stale shard monitors
Mark games as 'played' when shard detects game.ended or room_closed.
Stop old shard monitors before demoting previous playing games on new
game add or status change. Sync frontend playingGame state with the
games list on every refresh to prevent stale UI. Use terminate() for
probe connections to prevent shard connection leaks.

Made-with: Cursor
2026-03-20 23:34:22 -04:00
cottongin
4999060970 fix: periodic player count refresh via probe shard connection
Some Jackbox games (e.g. Trivia Murder Party 2) do not send
client/connected events to shard connections and lack textDescriptions,
leaving the player count stuck at 0 if the shard connects before
players join. Fix by opening a lightweight probe shard every 20s to
read the fresh here map. Also fix bc:room entity lookup in
handleWelcome and a WebSocket close handler race condition.

Made-with: Cursor
2026-03-20 21:29:58 -04:00
cottongin
34637d6d2c feat: add periodic game.status broadcast and live status REST endpoint
Add 20-second game.status WebSocket heartbeat from active shard monitors
containing full game state, and GET /status-live REST endpoint for on-demand
polling. Fix missing token destructuring in SessionInfo causing crash.
Relax frontend polling from 3s to 60s since WebSocket events now cover
real-time updates. Bump version to 0.6.0.

Made-with: Cursor
2026-03-20 21:05:19 -04:00
cottongin
a7bd0650eb docs: update ecast API reference with connection roles and shard details
Add Connection Roles table documenting host, player, shard, audience,
observer, and moderator roles with their capabilities and slot impact.
Add shard client/welcome capture and passive room monitoring section.

Made-with: Cursor
2026-03-20 11:47:47 -04:00
cottongin
65036a4e1b fix: Picker WebSocket auth, event handling, and status display
- Authenticate with JWT before subscribing to session events
- Use message.type instead of message.event (matches server format)
- Handle all new shard monitor events (room.connected, lobby.*,
  game.started, game.ended, room.disconnected)
- Replace never-set 'waiting' status with 'monitoring'
- Show monitoring indicator with live player count

Made-with: Cursor
2026-03-20 11:47:19 -04:00
cottongin
336ba0e608 docs: update websocket event reference with new shard monitor events
Add room.connected, lobby.player-joined, lobby.updated, game.started,
game.ended, room.disconnected events. Clarify player-count.updated as
manual-override only. Update complete example with new event handlers.

Made-with: Cursor
2026-03-20 11:35:29 -04:00
cottongin
03f79422af fix: clean up activeShards on reconnection failure
Remove stale entries from the activeShards map when
reconnectWithBackoff exhausts all attempts or detects room closure.

Made-with: Cursor
2026-03-20 11:34:15 -04:00
cottongin
2503c3fc09 chore: remove Puppeteer and old room-monitor/player-count-checker modules
Made-with: Cursor
2026-03-20 11:29:01 -04:00
cottongin
9c9927218a feat: wire graceful shutdown for shard connections on SIGTERM/SIGINT
Made-with: Cursor
2026-03-20 11:27:58 -04:00
cottongin
3c1d5b2224 refactor: rewire sessions routes to use ecast shard client
Made-with: Cursor
2026-03-20 11:27:54 -04:00
cottongin
1c4c8bc19c feat: add startMonitor, stopMonitor, cleanupAllShards module exports 2026-03-20 11:25:01 -04:00
cottongin
de395d3a28 feat: add reconnection logic with exponential backoff to shard client 2026-03-20 11:24:48 -04:00
cottongin
3f21299720 feat: add event broadcasting and entity update handlers to shard client
Made-with: Cursor
2026-03-20 11:19:57 -04:00
cottongin
516db57248 feat: add EcastShardClient with connection, welcome parsing, and player counting
Made-with: Cursor
2026-03-20 11:09:05 -04:00
cottongin
0fc2ddbf23 feat: add getRoomInfo to jackbox-api for full room data including host
Made-with: Cursor
2026-03-20 11:04:54 -04:00
cottongin
7712ebeb04 Add implementation plan for ecast shard monitor
10-task TDD plan covering: jackbox-api extension, EcastShardClient
class, event broadcasting, reconnection, route rewiring, graceful
shutdown, old module removal, doc updates, and manual smoke test.

Made-with: Cursor
2026-03-20 10:53:19 -04:00
cottongin
002e1d70a6 Add design doc for ecast shard monitor replacing Puppeteer audience approach
Replaces room-monitor.js (REST polling) and player-count-checker.js
(Puppeteer/CDP audience join) with a single EcastShardClient that
connects as a shard via direct WebSocket. Defines new event contract,
integration points, error handling, and reconnection strategy.

Made-with: Cursor
2026-03-20 10:42:33 -04:00
cottongin
e6198181f8 docs: reframe player counting as slot-based (not a limitation)
Occupied slots = effective player count since held reconnection slots
are unavailable to new players. connections - 1 = player count,
maxPlayers - (connections - 1) = available slots. Clean and simple.

Made-with: Cursor
2026-03-20 09:56:58 -04:00
cottongin
7b0dc5c015 docs: major corrections to ecast API docs from second round of testing
Key corrections based on testing with fresh room SCWX:
- connections count includes ALL ever-joined players, not just active ones
  (slots persist for reconnection, count never decreases)
- here field also includes disconnected players (slot reservation model)
- client/connected and client/disconnected confirmed as NOT delivered to
  player connections after extensive testing
- Jackbox has no concept of "leaving" — player disconnect is invisible
  to the API
- Added reconnection URL format (secret + id query params)
- Added error code 2027 (REST/WebSocket state divergence)
- Added ws-lifecycle-test.js for systematic protocol testing

Made-with: Cursor
2026-03-20 09:51:24 -04:00
cottongin
af5e8cbd94 docs: comprehensive Jackbox ecast API reverse engineering
Adds complete documentation of the ecast platform covering:
- REST API (8 endpoints including newly discovered /connections, /info, /status)
- WebSocket protocol (connection, message format, 40+ opcodes)
- Entity model (room, player, audience, textDescriptions)
- Game lifecycle (lobby → start → gameplay → end)
- Player/room management answers (counting, join/leave detection, etc.)

Also adds scripts/ws-probe.js utility for direct WebSocket probing.

Made-with: Cursor
2026-03-20 09:39:17 -04:00
cottongin
e5ba43bcbb Add design doc for Jackbox ecast API reverse engineering
Defines scope, methodology (REST probing + WebSocket interception),
and documentation structure for comprehensive API documentation effort.

Made-with: Cursor
2026-03-20 09:18:55 -04:00
cottongin
35617268e9 fix: upgrade Docker to Node 22, add vote persistence diagnostics and e2e tests
- Bump Dockerfile base image from node:18-alpine to node:22-alpine to
  fix build failure (better-sqlite3@12.8.0 requires Node 20+)
- Add post-transaction verification logging in POST /api/votes/live to
  detect live_votes insertion failures in production
- Add direct DB assertion to regression test for live_votes population
- Add end-to-end integration tests covering the full vote flow: POST
  vote -> GET /api/sessions/:id/votes -> GET /api/votes -> direct DB

Made-with: Cursor
2026-03-16 20:53:32 -04:00
cottongin
0d0d20161b docs: update remaining docs with vote tracking API changes
Update README.md, docs/api/README.md, session-lifecycle guide,
webhooks-and-events guide, and archive docs (BOT_INTEGRATION,
API_QUICK_REFERENCE) with new endpoints and vote.received event.

Made-with: Cursor
2026-03-15 19:21:35 -04:00
cottongin
3ed3af06ba docs: add vote tracking endpoints to API documentation
Update REST endpoint docs (votes.md, sessions.md), WebSocket protocol
(websocket.md), OpenAPI spec, and voting guide with the new
GET /api/votes, GET /api/sessions/:id/votes, and vote.received event.

Made-with: Cursor
2026-03-15 19:16:23 -04:00
cottongin
e9add95efa feat: add vote.received WebSocket event on live votes
Made-with: Cursor
2026-03-15 19:08:00 -04:00
cottongin
83b274de79 feat: add GET /api/votes endpoint with filtering and pagination
Made-with: Cursor
2026-03-15 19:00:00 -04:00
cottongin
264953453c test: regression tests for WebSocket events
Made-with: Cursor
2026-03-15 18:55:55 -04:00
cottongin
56adbe7aa2 test: regression tests for GET /api/sessions endpoints
Made-with: Cursor
2026-03-15 18:53:32 -04:00
cottongin
8ddbd1440f test: regression tests for POST /api/votes/live
Made-with: Cursor
2026-03-15 18:53:25 -04:00
cottongin
19c4b7dc37 test: regression tests for GET /api/games vote fields
Made-with: Cursor
2026-03-15 18:53:07 -04:00
cottongin
8e8e6bdf05 fix: upgrade better-sqlite3 for Node 24 compat, add --forceExit to jest
Made-with: Cursor
2026-03-15 18:51:50 -04:00
cottongin
84b0c83409 test: add jest/supertest infrastructure and make server.js testable
Made-with: Cursor
2026-03-15 18:40:44 -04:00
cottongin
81fcae545e docs: vote tracking API implementation plan
TDD plan with 9 tasks: test infrastructure, regression tests
(4 files), and 3 feature implementations with full test code.

Made-with: Cursor
2026-03-15 18:24:50 -04:00
cottongin
4bf41b64cf docs: vote tracking API design (REST + WebSocket)
Covers WebSocket vote.received event, GET /api/sessions/:id/votes
breakdown, GET /api/votes paginated history, and two-phase TDD
testing strategy with regression tests before implementation.

Made-with: Cursor
2026-03-15 18:18:26 -04:00
cottongin
8ba32e128c docs: comprehensive API documentation from source code
Replace existing docs with fresh documentation built entirely from source
code analysis. OpenAPI 3.1 spec as source of truth, plus human-readable
Markdown with curl examples, response samples, and workflow guides.

- OpenAPI 3.1 spec covering all 42 endpoints (validated against source)
- 7 endpoint reference docs (auth, games, sessions, picker, stats, votes, webhooks)
- WebSocket protocol documentation (auth, subscriptions, 4 event types)
- 4 guide documents (getting started, session lifecycle, voting, webhooks)
- API README with overview, auth docs, and quick reference table
- Old docs archived to docs/archive/

Made-with: Cursor
2026-03-15 16:44:53 -04:00
cottongin
505c335d20 Decouple room monitoring from player count, fix Jackbox API fetch
Extracts checkRoomStatus into shared jackbox-api.js with proper
User-Agent header (bare fetch was silently rejected by Jackbox API)
and always-on error logging (previously gated behind DEBUG flag).

Splits room-start detection (room-monitor.js) from audience-based
player counting (player-count-checker.js) to eliminate circular
dependency and allow immediate game.started detection. Room monitor
now polls immediately instead of waiting 10 seconds for first check.

Made-with: Cursor
2026-03-08 18:25:52 -04:00
cottongin
4747aa9632 Fix game.started not firing when Jackbox room is full
The waitForGameStart() function checked roomStatus.full before
roomStatus.locked, causing it to short-circuit when a room was full
but the game hadn't started yet. This meant game.started was never
broadcast and watchGameAsAudience() was never called for full games.

Now only locked=true triggers game start detection. When full=true
but locked=false, the poller continues until the game actually starts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-15 22:46:16 -05:00
cottongin
52e00e56f6 Add audience.joined and game.started WebSocket events, reduce poll interval
Broadcast audience.joined when the audience client receives its first
client/welcome frame. Broadcast game.started when the room lock is
detected. Reduced initial wait and poll interval from 30s to 10s for
faster feedback.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-07 14:09:37 -05:00
cottongin
84398ebdd0 Reorganize project: move docs to docs/ and test scripts to tests/
Moved 9 documentation .md files from root into docs/.
Moved 4 test scripts from root into tests/.
Updated cross-references in README.md and docs to reflect new paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-07 14:07:39 -05:00
cottongin
974f0e4a67 Harden secret handling: remove weak fallback defaults, fail fast on missing env vars
JWT_SECRET and ADMIN_KEY no longer fall back to insecure defaults.
The app will throw at startup if these env vars are not set.
docker-compose.yml now uses :? syntax to require them.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-07 14:07:09 -05:00
cottongin
5cf5901001 tweaks 2025-11-03 18:38:27 -05:00
cottongin
f52754ac87 done 2025-11-03 17:56:15 -05:00
cottongin
140988d01d initial actual player count implementation 2025-11-03 13:57:26 -05:00
cottongin
2a75237e90 IDK, it's working and we're moving on 2025-11-02 16:06:31 -05:00
cottongin
6308d99d33 first release! 0.3.6 2025-10-30 19:27:23 -04:00
cottongin
47db3890e2 pretty much ready to 'ship'.3 2025-10-30 17:52:44 -04:00
cottongin
1a74b4d777 pretty much ready to 'ship'.2 2025-10-30 17:34:44 -04:00
cottongin
8f3a12ad76 pretty much ready to 'ship' 2025-10-30 17:18:30 -04:00
cottongin
7bb3aabd72 wow, chrome-extension MUCH improved - websockets 2025-10-30 15:17:15 -04:00
cottongin
db2a8abe66 we're about to port the chrome-extension. everything else mostly works 2025-10-30 13:27:55 -04:00