14 KiB
14 KiB
Golf Card Game - V2 Master Plan
Overview
Transform the current single-server Golf game into a production-ready, hostable platform with:
- Event-sourced architecture for full game replay and audit trails
- User accounts with authentication, password reset, and profile management
- Admin tools for moderation and system management
- Leaderboards with player statistics
- Scalable hosting options (self-hosted or cloud)
- Export/playback for sharing memorable games
Document Structure (VDD)
This plan is split into independent vertical slices. Each document is self-contained and can be worked on by a separate agent.
| Document | Scope | Dependencies |
|---|---|---|
V2_01_EVENT_SOURCING.md |
Event classes, store, state rebuilding | None (foundation) |
V2_02_PERSISTENCE.md |
Redis cache, PostgreSQL, game recovery | 01 |
V2_03_USER_ACCOUNTS.md |
Registration, login, password reset, email | 02 |
V2_04_ADMIN_TOOLS.md |
Admin dashboard, moderation, system stats | 03 |
V2_05_STATS_LEADERBOARDS.md |
Stats aggregation, leaderboard API/UI | 03 |
V2_06_REPLAY_EXPORT.md |
Game replay, export, share links | 01, 02 |
V2_07_PRODUCTION.md |
Docker, deployment, monitoring, security | All |
Current State (V1)
Client (Vanilla JS) <──WebSocket──> FastAPI Server <──> SQLite
│
In-memory rooms
(lost on restart)
What works well:
- Game logic is solid and well-tested
- CPU AI with 8 distinct personalities
- Flexible house rules system (15+ options)
- Real-time multiplayer via WebSockets
- Basic auth system with invite codes
Limitations:
- Single server, no horizontal scaling
- Game state lost on server restart
- Move logging exists but duplicates state
- No persistent player stats or leaderboards
- Limited admin capabilities
- No password reset flow
- No email integration
V2 Target Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ Clients │
│ (Browser / Future: Mobile) │
└───────────────────────────────┬─────────────────────────────────────┘
│ WebSocket + REST API
▼
┌─────────────────────────────────────────────────────────────────────┐
│ FastAPI Application │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Command │ │ Event │ │ State │ │ Query │ │ Auth │ │
│ │ Handler │─► Store │─► Builder │ │ Service │ │ Service │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Admin │ │ Stats │ │ Email │ │
│ │ Service │ │ Worker │ │ Service │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└───────┬───────────────┬───────────────┬───────────────┬────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Redis │ │ PostgreSQL │ │ PostgreSQL │ │ Email │
│ (Live State) │ │ (Events) │ │ (Users/Stats)│ │ Provider │
│ (Pub/Sub) │ │ │ │ │ │ (Resend) │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
Tech Stack
| Layer | Technology | Reasoning |
|---|---|---|
| Web framework | FastAPI (keep) | Already using, async, fast |
| WebSockets | Starlette (keep) | Built into FastAPI |
| Live state cache | Redis | Fast, pub/sub, TTL, battle-tested |
| Event store | PostgreSQL | JSONB, robust, great tooling |
| User database | PostgreSQL | Same instance, keep it simple |
| Background jobs | arq |
Async, Redis-backed, lightweight |
| Resend | Simple API, good free tier, reliable | |
| Containerization | Docker | Consistent deployment |
| Orchestration | Docker Compose | Start simple, K8s if needed |
New Dependencies
# requirements.txt additions
redis>=5.0.0
asyncpg>=0.29.0 # Async PostgreSQL
sqlalchemy>=2.0.0 # ORM for complex queries
alembic>=1.13.0 # Database migrations
arq>=0.26.0 # Background task queue
pydantic-settings>=2.0 # Config management
resend>=0.8.0 # Email service
python-jose[cryptography] # JWT tokens
passlib[bcrypt] # Password hashing
Phases & Milestones
Phase 1: Event Infrastructure (Foundation)
Goal: Emit events alongside current code, validate replay works
| Milestone | Description | Document |
|---|---|---|
| Event classes defined | All gameplay events as dataclasses | 01 |
| Event store working | PostgreSQL persistence | 01 |
| Dual-write enabled | Events emitted without breaking current code | 01 |
| Replay validation | Test proves events recreate identical state | 01 |
| Rate limiting on auth | Brute force protection | 07 |
Phase 2: Persistence & Recovery
Goal: Games survive server restarts
| Milestone | Description | Document |
|---|---|---|
| Redis state cache | Live game state in Redis | 02 |
| Pub/sub ready | Multi-server WebSocket fan-out | 02 |
| Game recovery | Rebuild games from events on startup | 02 |
| Graceful shutdown | Save state before stopping | 02 |
Phase 3a: User Accounts
Goal: Full user lifecycle management
| Milestone | Description | Document |
|---|---|---|
| Email service integrated | Resend configured and tested | 03 |
| Registration with verification | Email confirmation flow | 03 |
| Password reset flow | Forgot password via email token | 03 |
| Session management | View/revoke sessions | 03 |
| Account settings | Profile, preferences, deletion | 03 |
Phase 3b: Admin Tools
Goal: Moderation and system management
| Milestone | Description | Document |
|---|---|---|
| Admin dashboard | User list, search, metrics | 04 |
| User management | Ban, unban, force password reset | 04 |
| Game moderation | View any game, end stuck games | 04 |
| System monitoring | Active games, users online, events/hour | 04 |
| Audit logging | Track admin actions | 04 |
Phase 4: Stats & Leaderboards
Goal: Persistent player statistics
| Milestone | Description | Document |
|---|---|---|
| Stats schema | PostgreSQL tables for aggregated stats | 05 |
| Stats worker | Background job processing events | 05 |
| Leaderboard API | REST endpoints | 05 |
| Leaderboard UI | Client display | 05 |
| Achievement system | Badges and milestones (stretch) | 05 |
Phase 5: Replay & Export
Goal: Share and replay games
| Milestone | Description | Document |
|---|---|---|
| Export API | Download game as JSON | 06 |
| Import/load | Upload and replay | 06 |
| Replay UI | Playback controls, scrubbing | 06 |
| Share links | Public /replay/{id} URLs |
06 |
Phase 6: Production
Goal: Deployable, monitored, secure
| Milestone | Description | Document |
|---|---|---|
| Dockerized | All services containerized | 07 |
| Health checks | /health endpoint with dependency checks |
07 |
| Metrics | Prometheus metrics | 07 |
| Error tracking | Sentry integration | 07 |
| Deployment guide | Step-by-step for VPS/cloud | 07 |
File Structure (Target)
golfgame/
├── client/ # Frontend (enhance incrementally)
│ ├── index.html
│ ├── app.js
│ ├── components/ # New: modular UI components
│ │ ├── leaderboard.js
│ │ ├── replay-controls.js
│ │ └── admin-dashboard.js
│ └── ...
├── server/
│ ├── main.py # FastAPI app entry point
│ ├── config.py # Settings from env vars
│ ├── dependencies.py # FastAPI dependency injection
│ ├── models/
│ │ ├── events.py # Event dataclasses
│ │ ├── user.py # User model
│ │ └── game_state.py # State rebuilt from events
│ ├── stores/
│ │ ├── event_store.py # PostgreSQL event persistence
│ │ ├── state_cache.py # Redis live state
│ │ └── user_store.py # User persistence
│ ├── services/
│ │ ├── game_service.py # Command handling, event emission
│ │ ├── auth_service.py # Authentication, sessions
│ │ ├── email_service.py # Email sending
│ │ ├── admin_service.py # Admin operations
│ │ ├── stats_service.py # Leaderboard queries
│ │ └── replay_service.py # Export, import, playback
│ ├── routers/
│ │ ├── auth.py # Auth endpoints
│ │ ├── admin.py # Admin endpoints
│ │ ├── games.py # Game/replay endpoints
│ │ └── stats.py # Leaderboard endpoints
│ ├── workers/
│ │ └── stats_worker.py # Background stats aggregation
│ ├── middleware/
│ │ ├── rate_limit.py # Rate limiting
│ │ └── auth.py # Auth middleware
│ ├── ai/ # Keep existing AI code
│ │ └── ...
│ └── tests/
│ ├── test_events.py
│ ├── test_replay.py
│ ├── test_auth.py
│ └── ...
├── migrations/ # Alembic migrations
│ ├── versions/
│ └── env.py
├── docker/
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── docker-compose.prod.yml
├── docs/
│ └── v2/ # These planning documents
│ ├── V2_00_MASTER_PLAN.md
│ ├── V2_01_EVENT_SOURCING.md
│ └── ...
└── scripts/
├── migrate.py # Run migrations
├── create_admin.py # Bootstrap admin user
└── export_game.py # CLI game export
Decision Log
| Decision | Choice | Rationale |
|---|---|---|
| Event store DB | PostgreSQL | JSONB support, same DB as users, simpler ops |
| Email provider | Resend | Simple API, good free tier (3k/mo), reliable |
| Background jobs | arq | Async-native, Redis-backed, lightweight |
| Session storage | Redis | Fast, TTL support, already using for state |
| Password hashing | bcrypt | Industry standard, built-in work factor |
| JWT vs sessions | Both | JWT for API, sessions for WebSocket |
Open Questions
-
Guest play vs required accounts?
- Decision: Allow guest play, prompt to register to save stats
- Guest games count for global stats but not personal leaderboards
-
Game history retention?
- Decision: Keep events forever (they're small, ~500 bytes each)
- Implement archival to cold storage after 1 year if needed
-
Replay visibility?
- Decision: Private by default, shareable via link
- Future: Public games opt-in
-
CPU games count for leaderboards?
- Decision: Yes, but separate "vs humans only" leaderboard later
-
Multi-region?
- Decision: Not for V2, single region is fine for card game latency
- Revisit if user base grows significantly
How to Use These Documents
Each V2_XX_*.md document is designed to be:
- Self-contained - Has all context needed to implement that slice
- Agent-ready - Can be given to a Claude agent as the primary context
- Testable - Includes acceptance criteria and test requirements
- Incremental - Can be implemented and shipped independently (respecting dependencies)
Workflow:
- Pick a document based on current phase
- Start a new Claude session with that document as context
- Implement the slice
- Run tests specified in the document
- PR and merge
- Move to next slice
Next Steps
- Review all V2 documents
- Set up PostgreSQL locally for development
- Start with
V2_01_EVENT_SOURCING.md - Implement rate limiting from
V2_07_PRODUCTION.mdearly (security)