328 lines
14 KiB
Markdown
328 lines
14 KiB
Markdown
# 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 |
|
|
| **Email** | Resend | Simple API, good free tier, reliable |
|
|
| **Containerization** | Docker | Consistent deployment |
|
|
| **Orchestration** | Docker Compose | Start simple, K8s if needed |
|
|
|
|
### New Dependencies
|
|
|
|
```txt
|
|
# 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
|
|
|
|
1. **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
|
|
|
|
2. **Game history retention?**
|
|
- Decision: Keep events forever (they're small, ~500 bytes each)
|
|
- Implement archival to cold storage after 1 year if needed
|
|
|
|
3. **Replay visibility?**
|
|
- Decision: Private by default, shareable via link
|
|
- Future: Public games opt-in
|
|
|
|
4. **CPU games count for leaderboards?**
|
|
- Decision: Yes, but separate "vs humans only" leaderboard later
|
|
|
|
5. **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:
|
|
|
|
1. **Self-contained** - Has all context needed to implement that slice
|
|
2. **Agent-ready** - Can be given to a Claude agent as the primary context
|
|
3. **Testable** - Includes acceptance criteria and test requirements
|
|
4. **Incremental** - Can be implemented and shipped independently (respecting dependencies)
|
|
|
|
**Workflow:**
|
|
1. Pick a document based on current phase
|
|
2. Start a new Claude session with that document as context
|
|
3. Implement the slice
|
|
4. Run tests specified in the document
|
|
5. PR and merge
|
|
6. Move to next slice
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
1. Review all V2 documents
|
|
2. Set up PostgreSQL locally for development
|
|
3. Start with `V2_01_EVENT_SOURCING.md`
|
|
4. Implement rate limiting from `V2_07_PRODUCTION.md` early (security)
|