Commit Graph

127 Commits

Author SHA1 Message Date
syntaxbullet
25a0bd3431 Sign panel sessions and isolate test runs
Some checks failed
Deploy to Production / test (push) Failing after 29s
- Replace in-memory auth sessions with signed cookies and signed OAuth state
- Add auth route coverage and update panel/web server wiring
- Switch test script to per-file Bun processes and clean up type checks
2026-04-09 21:44:05 +02:00
syntaxbullet
6abbd4652a Refresh repository documentation
Some checks failed
Deploy to Production / test (push) Failing after 33s
- Rewrite AGENTS and README files to match the current app layout
- Document API routes, trivia UI, and the active panel design language
2026-04-09 21:10:10 +02:00
syntaxbullet
034f2ead1c fix: correct blackjack PnL calculation and enhance UI
Some checks failed
Deploy to Production / test (push) Failing after 35s
- Fix incorrect PnL calculations where multipliers were treated as amounts
- Add proper net profit calculation: (multiplier × bet) - bet
- Update UI with gradient backgrounds, icons, and improved animations
- Add slide-in and pulse-slow keyframe animations
- Enhance dealer area with status-based styling
- Improve action buttons with colored gradients and hover effects
- Revise round result banner with better visual hierarchy
2026-04-06 15:11:47 +02:00
syntaxbullet
06c3891045 fix: Correct PnL calculation by using betAmount in net profit computation
Some checks failed
Deploy to Production / test (push) Failing after 34s
- Add betAmount field to BlackjackState to track the base bet
- Fix finishPlayerTurns: multiply hand.bet by state.betAmount for actual money bets
- Fix GameServer: roundPayouts are already gross payouts (not multipliers)
- Update cumulative PnL calculation to correctly subtract actual bet amount
- Add betAmount support to riggedState test helper
2026-04-06 14:50:40 +02:00
syntaxbullet
966bad98d3 Add cumulative PnL tracking to Blackjack game
Some checks failed
Deploy to Production / test (push) Failing after 32s
- Added cumulativePnl field to PlayerSeat and PlayerSeatView types
- Added myCumulativePnl to PlayerView for UI display
- Track net profit/loss across rounds in the game state
- Update round result banner to show both round net and total balance
- Add player seat PnL indicator with color coding (green/red)
- Preserve cumulativePnl when players stay seated through rounds
- Initialize new players with cumulativePnl = 0
- Added comprehensive tests for cumulative PnL tracking
2026-04-06 14:31:58 +02:00
syntaxbullet
2b89fb7ede docs: rename CLAUDE.md to AGENTS.md across the project
Some checks failed
Deploy to Production / test (push) Failing after 34s
2026-04-06 14:18:56 +02:00
syntaxbullet
a36c05994c feat(games): refactor blackjack for continuous play, split/double, and table UI
Some checks failed
Deploy to Production / test (push) Failing after 32s
Transform blackjack from single-round to continuous-play table sessions with
round lifecycle (betting → playing → resolved → betting), split/double down
actions, per-hand bet tracking, leave/join table mid-session, and a responsive
felt-style table UI with arc-positioned player seats.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:41:49 +02:00
syntaxbullet
ef78a85b9c feat(games): implement blackjack game plugin with manual start and custom payouts
Some checks failed
Deploy to Production / test (push) Failing after 39s
Adds a full blackjack game with dealer AI, hit/stand/double-down actions,
and per-player payout multipliers (house-edge model). Extends the game
framework with manualStart support and a START_GAME WebSocket message so
hosts can begin when ready. Generalizes bet settlement transaction
descriptions from chess-specific to game-agnostic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:48:25 +02:00
syntaxbullet
f368da9e73 feat(games): add solo mode to room creation and AU currency betting
Some checks failed
Deploy to Production / test (push) Failing after 31s
Solo mode is now a toggle in the chess room creation modal, available
to all users instead of admin-only. Betting lets players wager AU on
games with preset amounts, async deduction on game start, and automatic
payout/refund on game end.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:09:03 +02:00
syntaxbullet
12809623c1 fix(games): fix chess piece interaction and solo mode
Some checks failed
Deploy to Production / test (push) Failing after 32s
Two bugs fixed:
- Piece <img> elements were intercepting pointer events, preventing
  dnd-kit drag handlers and square click handlers from firing. Added
  pointerEvents: "none" so events pass through to the board framework.
- Solo test mode (fillRoom with duplicate player IDs) always resolved
  to "white" in colorOfPlayer, making black moves impossible. Now
  detects duplicate IDs and returns the current turn's color instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:23:16 +02:00
syntaxbullet
a29bb63a1d feat(games): implement chess game plugin with full UI
Some checks failed
Deploy to Production / test (push) Failing after 32s
Add chess as the first game plugin using the existing multiplayer framework.
Server-side game logic uses chess.js with server-authoritative clock management.
Client uses react-chessboard v5 with cburnett piece set, drag-and-drop + click-to-move,
configurable time controls (bullet/blitz/rapid/classical/none), draw offers,
resignation, and timeout detection. Extends the game framework with room creation
options to support per-game configuration. Includes 57 tests covering all code paths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:59:26 +02:00
syntaxbullet
56db5bc998 refactor(games): rework room lifecycle events and remove chess plugin
Consolidate room leave/delete event handling into RoomManager emitter,
remove redundant PLAYER_LEFT publishes from GameServer, and delete the
chess game plugin (board, types, tests) in favor of the new plugin
architecture. Add per-module CLAUDE.md files for leveling, guild-settings,
feature-flags, db, api, and panel to improve agent navigability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 15:19:51 +02:00
syntaxbullet
70a149ab82 refactor(games): overhaul WS game system with improved UX and solo test support
Some checks failed
Deploy to Production / test (push) Failing after 35s
Backend:
- Fix session never being attached to ws.data at upgrade time
- Add GameServer class: connection registry, per-connection room tracking,
  automatic room cleanup on disconnect via ws.data.rooms
- Replace ws-handler.ts with typed event-driven architecture using mitt
- Remove redundant subscription tracking from RoomManager
- Add JOIN_RESULT with player/spectator lists replacing error-as-control-flow
- Add SESSION_REPLACED for multi-tab same-account detection
- Add FILL_ROOM command for admin solo testing (fills empty slots with host)
- Fix dual-schema routing; remove game types from WsMessageSchema
- Per-player personalized views sent directly after each action

Chess plugin:
- Allow same-player (solo) mode: skip color/turn ownership checks
- Fix forfeit and disconnect handling in solo mode (winner: null)

Frontend:
- Click-to-move with legal move dots and last-move highlight
- Auto-scroll move history, forfeit confirmation, turn-reactive board border
- JOIN_RESULT initialises player/spectator lists immediately on join
- Contextual connecting state, player slot cards in waiting room
- Copy-invite button with Copied! flash, Back to Lobby CTA on finish
- Session-replaced warning banner with Rejoin here action
- Lobby passes preferAs intent through route state
- Admin waiting room shows Start Solo Test button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 16:41:13 +02:00
syntaxbullet
26a0e532f6 fix(chess): prevent duplicate players and fix move detection
Some checks failed
Deploy to Production / test (push) Failing after 38s
- Prevent same player from joining as both white and black
- Add validation to reject duplicate players in RoomManager
- Fix spectator status not resetting when joining as player
- Use ref to track latest chess state in ChessBoard for accurate move validation
2026-04-02 15:36:05 +02:00
syntaxbullet
0dadc82f84 feat(chess): replace custom engine with chess.js and react-chessboard
Some checks failed
Deploy to Production / test (push) Failing after 39s
Swap the custom move validation and Unicode piece grid for chess.js
(full rules engine with check/checkmate/castling/en passant/promotion)
and react-chessboard (drag-and-drop SVG board). Board styled to match
the purple dark theme and auto-orients to the player's color.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 14:22:27 +02:00
syntaxbullet
55df982a0b feat(games): implement chess plugin with tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:25:54 +02:00
syntaxbullet
db10ebe220 feat(games): add room types and game WS message schemas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:23:11 +02:00
syntaxbullet
a5478dce2b feat(games): add GamePlugin interface and registry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:22:48 +02:00
syntaxbullet
5bd390b4ee docs: add JSDoc to service public methods
One-line JSDoc on 82 methods across 11 service files for quick
scanning without reading full implementations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:36:18 +02:00
syntaxbullet
5f8819bb46 docs: add subdirectory CLAUDE.md files for key domain modules
Provide non-obvious business rules and constraints for economy,
inventory, quest, moderation, trade, and trivia modules to reduce
context-gathering overhead for AI tools.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:36:12 +02:00
syntaxbullet
5188d86d61 fix(inventory): address code review findings
Some checks failed
Deploy to Production / test (push) Failing after 31s
- Replace setTimeout race in use-item flow with explicit Back button
- Fix collector end handler to re-render current view instead of blanking
- Add appendUseBackButton helper to attach navigation to use results
- Remove unused isInventoryInteraction import
- Fix rarity test type assertions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:49:12 +01:00
syntaxbullet
fa09ef25e2 feat(inventory): add squareEmoji to RARITY_CONFIG
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 17:04:07 +01:00
syntaxbullet
21b5fedfc9 chore: add migration for quest config column
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:29:42 +01:00
syntaxbullet
912ce5b942 feat: enforce active quest limit in assignQuest
Adds a limit check to assignQuest that reads maxActiveQuests from game
settings and throws a UserError when the user has reached their active
quest limit. Completed quests are excluded from the count.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 15:39:23 +01:00
syntaxbullet
4ead7e60b1 feat: wire QuestConfig into game settings service 2026-03-28 15:37:38 +01:00
syntaxbullet
e64ffdc4cb feat: add QuestConfig interface and column to game settings schema 2026-03-28 15:36:43 +01:00
syntaxbullet
1d601febcf fix: wire quest progress tracking for transfer, daily, trivia, and exam events
Some checks failed
Deploy to Production / test (push) Failing after 31s
These domain events were only connected to dashboard recording but never
called questService.handleEvent(), so quests with triggers TRANSFER_OUT,
DAILY_REWARD, TRIVIA_WIN, and EXAM_REWARD never tracked progress. Added
userId and tx to event payloads and switched from emit to emitAsync for
transaction atomicity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:24:30 +01:00
syntaxbullet
782a138fd8 fix: strip query params from asset URLs before filesystem lookup
All checks were successful
Deploy to Production / test (push) Successful in 36s
Icon URLs stored with cache-busting query params (e.g. ?v=123) caused
existsSync to fail, preventing Discord attachment fallback and leaving
unresolvable localhost URLs as thumbnails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:48:19 +01:00
syntaxbullet
602147e961 feat: cap daily reward at 500 AU
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:21:01 +01:00
syntaxbullet
9e6bb8b148 fix: add non-null assertion for default rarity config fallback
All checks were successful
Deploy to Production / test (push) Successful in 35s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:15:53 +01:00
syntaxbullet
86142cba6c feat: rewrite lootbox pull results with Components V2 and separate icon/image URLs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 21:51:28 +01:00
syntaxbullet
0517cd638c fix: add JSDoc header and null input test for rarity config 2026-03-18 21:49:10 +01:00
syntaxbullet
b8303a7e28 feat: add shared rarity config and helpers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 21:46:21 +01:00
syntaxbullet
5d832c9601 fix: update trivia test to mock events instead of dashboardService
All checks were successful
Deploy to Production / test (push) Successful in 38s
The trivia service now emits domain events via systemEvents instead
of directly calling dashboardService.recordEvent. Updated the test
mock and assertions to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:37:31 +01:00
syntaxbullet
2bddab001a fix: verify receiver has no transaction records in insufficient funds test
Some checks failed
Deploy to Production / test (push) Failing after 9s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:26:50 +01:00
syntaxbullet
fc058effd5 feat: add integration test for economy transfer flow
Tests the full transfer cycle against a real database: debit/credit,
transaction records, insufficient funds rejection, self-transfer
rejection, non-positive amounts, and sequential transfers.

Uses *.integration.test.ts convention — excluded from default test
runs, included with --integration flag in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:24:49 +01:00
syntaxbullet
3f99a77446 test: add integration test for economy transfer flow
Covers the critical financial transfer path against a real database,
catching schema mismatches, constraint violations, and transaction
atomicity bugs that mocked unit tests cannot detect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 13:21:31 +01:00
syntaxbullet
abe25e0ceb refactor: extract Discord.js code from shared services into bot layer
Move terminal.service.ts and prune.service.ts entirely to bot/modules/
since they are Discord-specific. Split lootdrop.service.ts: pure logic
(activity tracking, DB ops, claim) stays in shared/, Discord operations
(message sending, channel interactions) move to bot/modules/economy/
lootdrop.handler.ts. Move effect registry/handlers/types from bot/ to
shared/modules/inventory/ since they contain no Discord.js imports and
are needed by inventory.service.ts in shared.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:15:29 +01:00
syntaxbullet
5a20ed23f4 fix: guard against undefined username in trivia won event
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:06:33 +01:00
syntaxbullet
0142508eb5 fix: add type safety and error handling to event bus
- Add DomainEventPayloads interface to events.ts for typed event payloads
- Wrap dashboard listeners with fireAndForget() to prevent unhandled promise rejections
- Type all listener parameters explicitly using DomainEventPayloads
- Add idempotency guard to registerDomainEventListeners to prevent double registration on hot-reload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 13:04:32 +01:00
syntaxbullet
5863418ae9 refactor: replace dynamic imports with event bus pattern
Replace 12 dynamic `await import()` calls with domain events emitted
through the existing systemEvents bus, breaking circular dependencies
between services (economy/inventory/leveling -> quest, * -> dashboard).

- Add `emitAsync` to SystemEventEmitter for sequential listener awaiting,
  preserving DB transaction atomicity for quest progress tracking
- Add DOMAIN event constants (BALANCE_CHANGED, XP_GAINED, ITEM_COLLECTED,
  ITEM_USED, TRANSFER_COMPLETED, DAILY_CLAIMED, TRIVIA_*, EXAM_PASSED)
- Create shared/lib/eventWiring.ts to register all domain event listeners
- Convert quest event calls to `await systemEvents.emitAsync()` (5 calls)
- Convert dashboard event calls to `systemEvents.emit()` fire-and-forget (5 calls)
- Convert exam.service.ts userService import to static import (1 call)
- Convert dashboard.service.ts events import to static import (1 call)
- Leave inventory.service.ts validateAndExecuteEffect import unchanged (Task 3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:59:15 +01:00
syntaxbullet
a96c6caa49 fix: standardize error classes in shared service modules
Replace raw `Error` with `UserError` for user-facing conditions (invalid trade state, user not found, permission/channel type checks) and `SystemError` for internal failures (DB insert failures, external API errors, missing config). Improves Discord UX by ensuring user-facing errors are surfaced cleanly via withCommandErrorHandling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 12:51:16 +01:00
syntaxbullet
2381f073ba feat: add admin panel with Discord OAuth and dashboard
Some checks failed
Deploy to Production / test (push) Failing after 37s
Adds a React admin panel (panel/) with Discord OAuth2 login,
live dashboard via WebSocket, and settings/management pages.
Includes Docker build support, Vite proxy config for dev,
game_settings migration, and open-redirect protection on auth callback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 20:27:14 +01:00
syntaxbullet
121c242168 fix: handle permission denied on backup directory
All checks were successful
Deploy to Production / test (push) Successful in 35s
The backups directory may have been created by Docker/root, making it
unwritable by the deploy user. The script now detects this and attempts
to fix permissions automatically (chmod, then sudo chown as fallback).

Also added shared/db/backups to .gitignore.
2026-02-13 14:48:06 +01:00
syntaxbullet
942875e8d0 fix: replace 'source .env' with safe env loader in all scripts
All checks were successful
Deploy to Production / test (push) Successful in 34s
The raw 'source .env' pattern breaks when values contain special bash
characters like ) in passwords or database URLs. This caused deploy:remote
to fail with 'syntax error near unexpected token )'.

Changes:
- Created shared/scripts/lib/load-env.sh: reads .env line-by-line with
  export instead of source, safely handling special characters
- Updated db-backup.sh, db-restore.sh, deploy-remote.sh, remote.sh to
  use the shared loader
- Reordered deploy-remote.sh: git pull now runs first (step 1) so the
  remote always has the latest scripts before running backup (step 2)
2026-02-13 14:46:30 +01:00
syntaxbullet
aca5538d57 chore: improve DX scripts, fix test suite, and harden tooling
All checks were successful
Deploy to Production / test (push) Successful in 32s
Scripts:
- remote.sh: remove unused open_browser() function
- deploy-remote.sh: add DB backup before deploy, --skip-backup flag, step numbering
- db-backup.sh: fix macOS compat (xargs -r is GNU-only), use portable approach
- db-restore.sh: add safety backup before restore, SQL file validation, file size display
- logs.sh: default to no-follow with --tail=100, order-independent arg parsing
- docker-cleanup.sh: add Docker health check, colored output
- test-sequential.sh: exclude *.integration.test.ts by default, add --integration flag
- simulate-ci.sh: pass --integration flag (has real DB)

Tests:
- db.test.ts: fix mock path from ./DrizzleClient to @shared/db/DrizzleClient
- server.settings.test.ts: rewrite mocks for gameSettingsService (old config/saveConfig removed)
- server.test.ts: add missing config.lootdrop and BotClient mocks, complete DrizzleClient chain
- indexes.test.ts: rename to indexes.integration.test.ts (requires live DB)

Config:
- package.json: test script uses sequential runner, add test:ci and db:restore aliases
- deploy.yml: use --integration flag in CI (has Postgres service)
2026-02-13 14:39:02 +01:00
syntaxbullet
0c67a8754f refactor: Implement Zod schema validation for inventory effect payloads and enhance item route DTO type safety.
Some checks failed
Deploy to Production / test (push) Failing after 38s
2026-02-13 14:12:46 +01:00
syntaxbullet
099601ce6d refactor: convert ModerationService and PruneService from classes to singleton objects
- Convert ModerationService class to moderationService singleton
- Convert PruneService class to pruneService singleton
- Update all command files to use new singleton imports
- Update web routes to use new singleton imports
- Update tests for singleton pattern
- Remove getNextCaseId from tests (now private module function)
2026-02-13 13:33:58 +01:00
syntaxbullet
55d2376ca1 refactor: convert LootdropService from class to singleton object pattern
- Move instance properties to module-level state (channelActivity, channelCooldowns)
- Convert constructor cleanup interval to module-level initialization
- Export state variables for testing
- Update tests to use direct state access instead of (service as any)
- Maintains same behavior while following project service pattern

Closes #4
2026-02-13 13:28:46 +01:00
syntaxbullet
6eb4a32a12 refactor: consolidate config types and remove file-based config
Tickets: #2, #3

- Remove duplicate type definitions from shared/lib/config.ts
- Import types from schema files (game-settings.ts, guild-settings.ts)
- Add GuildConfig interface to guild-settings.ts schema
- Rename ModerationConfig to ModerationCaseConfig in moderation.service.ts
- Delete shared/config/config.json and shared/scripts/migrate-config-to-db.ts
- Update settings API to use gameSettingsService exclusively
- Return DB format (strings) from API instead of runtime BigInts
- Fix moderation service tests to pass config as parameter

Breaking Changes:
- Removes legacy file-based configuration system
- API now returns database format with string values for BigInt fields
2026-02-13 13:24:02 +01:00