Skip to content

Moth v2: Production Tambola server rewrite#2

Merged
hashd merged 25 commits into
masterfrom
worktree-moth-v2-rewrite
Apr 9, 2026
Merged

Moth v2: Production Tambola server rewrite#2
hashd merged 25 commits into
masterfrom
worktree-moth-v2-rewrite

Conversation

@hashd
Copy link
Copy Markdown
Owner

@hashd hashd commented Apr 9, 2026

Summary

Full rewrite of the Moth POC into a production-grade Tambola/Housie game server.

  • Game Engine: Supervised GenServer per game under DynamicSupervisor with crash recovery (DB snapshots every 5 picks, write-through for joins/claims)
  • Tambola Mechanics: Board (1-90), ticket generation (3x9, 5 per row), 5 prize types with player-initiated claims and bogey system
  • Player Strike-Out: Players must manually strike numbers on their ticket as called — claims validate against struck numbers, not global picks. Optional auto-strike toggle.
  • Auth: Magic link (Swoosh) + Google OAuth (Ueberauth), dual sessions (cookie for web, bearer token for API)
  • Web UI: Phoenix LiveView — home, magic link flow, game creation, player view (live ticket, claims, chat), host controls (start/pause/resume/end)
  • Mobile API: REST endpoints for auth, games, user profile + authenticated Phoenix Channel for real-time
  • Infrastructure: Bandit HTTP server, ETS rate limiter, CORS, Phoenix Presence, rest_for_one supervision, game monitor (reaps stale lobbies/finished games)

Stats

  • 107 files changed, ~4000 lines added
  • 73 tests (70 unit/integration + 3 property tests), 0 failures
  • 23 commits, clean compilation

Test plan

  • mix test — all 73 tests pass
  • mix ecto.reset && mix phx.server — server starts, home page loads at localhost:4000
  • Magic link flow: request link → check /dev/mailbox → click link → signed in
  • Create game → share code → join as player → host starts → numbers pick on timer
  • Player strikes numbers on ticket → claims prize → bogey on invalid claim
  • Auto-strike toggle works (convenience, opt-in)
  • API: POST /api/auth/magic → POST /api/auth/verify → Bearer token works
  • API: POST /api/games → GET /api/games/:code → POST /api/games/:code/join
  • Host disconnect → 60s auto-pause
  • Pause/resume/end game controls work

hashd added 25 commits April 10, 2026 03:21
Replace plug_cowboy with bandit, add swoosh, tailwind, cors_plug,
stream_data. Remove all old housie/accounts/channel/controller code.
Update config skeleton, endpoint, router, and MothWeb for Phoenix 1.7.
Add error handlers, telemetry, layouts, mailer, and test fixtures.
- Bump elixir constraint from ~> 1.4 to ~> 1.14
- Remove deprecated Mix.compilers() call
- Remove stale .eex templates from lib/moth_web/templates/
- Wire DNSCluster into supervision tree
- Merge split endpoint config blocks in dev.exs
- Move ueberauth OAuth config inside prod guard in runtime.exs
- Remove deprecated Router.Helpers alias from conn_case.ex
Final wiring pass: remove duplicate imports in html_helpers,
fix unused GameComponents import in HostLive, fix unused variable
in PlayLive mount.
- Add API controller tests for auth and game endpoints
- Fix sanitize_state to convert MapSet/Board/Ticket structs to
  JSON-serializable formats
- Update server_test to use list membership check
- Add .formatter.exs with Phoenix/Ecto/LiveView plugins
- Run mix format across entire codebase
- Remove unused aliases in server_test.exs
- All 70 tests passing (67 tests + 3 properties)
Players must manually tap/strike numbers on their ticket as they're
called — claims validate against struck numbers, not global picks.
This preserves the Tambola engagement of paying attention.

- Add struck state per player in Game Server
- Add strike_out/3 to Server, Game context, API, and Channel
- Update ticket_grid component: picked numbers pulse yellow until
  struck, struck numbers show solid green
- Add auto-strike toggle in PlayLive (opt-in convenience)
- Claim validation now uses player's struck set, not board picks
Add missing tailwind.config.js, replace old channel-based app.js with
LiveView socket setup, and update CSS with Tailwind directives. Fix
mix.exs aliases to include tailwind install/build steps.

Remove v1 remnants: Phoenix channels (game_channel, game_socket),
old controller layouts ("Tambola by Funtagious!"), unused HTML view
modules (GameHTML, BaseHTML), stock phoenix.css, channel socket.js,
and channel_case test support. Clean up endpoint.ex and moth_web.ex.
@hashd hashd merged commit 17ea539 into master Apr 9, 2026
@hashd hashd deleted the worktree-moth-v2-rewrite branch April 9, 2026 23:16
hashd added a commit that referenced this pull request Apr 13, 2026
…validation

- Filter struck set per-ticket in prize claims to prevent cross-ticket fraud (#1)
- Filter prize progress per-ticket to prevent cross-ticket info leak (#9)
- Strip join_secret from sanitized state (#2)
- Filter REST show endpoint to only return requesting user's data (#3)
- Filter player_tickets_updated broadcast to target user only (#4)
- Add chat text length limit (500 chars) and validation (#13)
- Add reaction emoji allowlist (#14)
- Add max players per game limit (100) (#11)
- Add input validation for game creation params (#23)
- Remove inspect(reason) from error responses (#22)
- Store rich metadata in Registry for O(1) game listing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant