mantimon-tcg/backend/PROJECT_PLAN_MASTER.json
Cal Corum 58349c126a Phase 3: Collections + Decks - Services and DI architecture
Implemented with Repository Protocol pattern for offline fork support:
- CollectionService with PostgresCollectionRepository
- DeckService with PostgresDeckRepository
- DeckValidator with DeckConfig + CardService injection
- Starter deck definitions (5 types: grass, fire, water, psychic, lightning)
- Pydantic schemas for collection and deck APIs
- Unit tests for DeckValidator (32 tests passing)

Architecture follows pure dependency injection - no service locator patterns.
Added CLAUDE.md documenting DI requirements and patterns.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 11:27:14 -06:00

263 lines
8.6 KiB
JSON

{
"meta": {
"version": "1.0.0",
"created": "2026-01-27",
"lastUpdated": "2026-01-28",
"planType": "master",
"projectName": "Mantimon TCG - Backend Services",
"description": "Live service backend for play.mantimon.com - server-authoritative multiplayer TCG with campaign mode, free-play, and F2P monetization",
"totalPhases": 6,
"completedPhases": 3,
"status": "Phases 0-2 complete, Phase 3 (Collections + Decks) up next"
},
"architectureDecisions": {
"deployment": "Online-first live service at play.mantimon.com",
"database": "PostgreSQL 15+ for durable storage",
"cache": "Redis 7+ for game state, matchmaking, sessions",
"gameState": "Redis primary (fast), Postgres write-behind at turn boundaries",
"api": "FastAPI REST + python-socketio WebSocket",
"auth": "OAuth 2.0 (Google, Discord) with JWT sessions",
"cardData": "Bundled JSON in repo, loaded at runtime",
"offlineSupport": "Core engine forkable, full offline mode deferred",
"replayData": "Capture from start for future replay feature"
},
"businessRules": {
"monetization": {
"model": "F2P with optional purchases",
"fullCollectionF2P": true,
"premiumFeatures": ["cosmetics", "convenience", "battle_pass"],
"premiumDuration": "time-limited (subscription style)",
"noPay2Win": true
},
"currency": {
"name": "Mantibucks",
"symbol": "₼"
},
"deckLimits": {
"free": 5,
"premium": "unlimited"
},
"starterDecks": {
"count": 5,
"types": ["grass", "fire", "water", "psychic", "lightning"],
"rotation": "Two deck types rotate with current set releases",
"classic": ["grass", "fire", "water"],
"rotating": ["psychic", "lightning"]
},
"boosterPacks": {
"structure": "X slots per pack, each slot has individual rarity probabilities",
"acquisition": ["campaign_wins", "daily_rewards", "purchases"]
},
"energyDeck": {
"default": true,
"configurable": true,
"note": "Mantimon house rules default, standard Pokemon TCG supported"
},
"deckValidation": {
"campaign": "Requires card ownership",
"freeplay": "Full collection unlocked"
}
},
"phases": [
{
"id": "PHASE_0",
"name": "Core Game Engine",
"status": "COMPLETE",
"description": "Pure game logic - GameEngine, models, effects, validation, turn management",
"planFile": "PROJECT_PLAN.json",
"deliverables": [
"GameEngine orchestrator",
"RulesConfig system",
"All action types and validation",
"Effect handler system with 12 built-in handlers",
"Turn manager with status conditions",
"Win condition checker",
"Visibility filter (hidden info security)",
"Card scraper with 372 cards + images",
"Engine validation script (29 test scenarios)",
"833 initial tests (now 1072 total with all phases)"
],
"completedDate": "2026-01-27"
},
{
"id": "PHASE_1",
"name": "Database + Infrastructure",
"status": "COMPLETE",
"description": "PostgreSQL models, Redis caching, CardService, environment config",
"planFile": "project_plans/PHASE_1_DATABASE.json",
"dependencies": ["PHASE_0"],
"deliverables": [
"SQLAlchemy async models (User, GameHistory, OAuthLinkedAccount)",
"Alembic migrations",
"Redis connection utilities",
"GameStateManager (Redis + Postgres write-behind)",
"CardService (JSON → CardDefinition)",
"Environment config (dev/staging/prod)",
"Docker compose for local dev"
],
"completedDate": "2026-01-27"
},
{
"id": "PHASE_2",
"name": "Authentication",
"status": "COMPLETE",
"description": "OAuth login, JWT sessions, user management",
"planFile": "project_plans/PHASE_2_AUTH.json",
"dependencies": ["PHASE_1"],
"deliverables": [
"OAuth integration (Google, Discord)",
"JWT token management with refresh tokens",
"User creation/login endpoints",
"FastAPI auth dependencies (CurrentUser, DbSession)",
"Account linking (multiple providers per user)",
"Premium tier with expiration tracking",
"98 new tests, 1072 total tests"
],
"completedDate": "2026-01-28"
},
{
"id": "PHASE_3",
"name": "Collections + Decks",
"status": "NOT_STARTED",
"description": "Card ownership, deck building, starter deck selection",
"planFile": "project_plans/PHASE_3_COLLECTION_DECKS.json",
"estimatedWeeks": "1-2",
"dependencies": ["PHASE_2"],
"deliverables": [
"CollectionService (owned cards CRUD)",
"DeckService (create, edit, validate, delete)",
"Mode-aware deck validation (owned vs full collection)",
"Deck slot limits (free vs premium)",
"Starter deck selection flow",
"5 starter deck definitions",
"REST endpoints"
]
},
{
"id": "PHASE_4",
"name": "Game Service + WebSocket",
"status": "NOT_STARTED",
"description": "Real-time gameplay, reconnection, turn timeouts",
"planFile": "project_plans/PHASE_4_GAME_SERVICE.json",
"estimatedWeeks": "2-3",
"dependencies": ["PHASE_3"],
"deliverables": [
"WebSocket connection manager",
"Message protocol specification",
"GameService (create, execute, persist, resume)",
"Turn-boundary persistence to Postgres",
"Reconnection handling",
"Turn timeout system",
"Replay data capture",
"Spectator mode (optional)"
]
},
{
"id": "PHASE_5",
"name": "Campaign Mode",
"status": "NOT_STARTED",
"description": "Single-player experience with NPCs, progression, rewards",
"planFile": "project_plans/PHASE_5_CAMPAIGN.json",
"estimatedWeeks": "3-4",
"dependencies": ["PHASE_4"],
"deliverables": [
"Club and NPC data structures",
"CampaignService (progression, save/load)",
"AI system (RuleBasedAI, DifficultyScaledAI)",
"NPC deck definitions",
"Reward system (medals, booster packs, Mantibucks)",
"Booster pack opening with slot-based rarities",
"Campaign REST endpoints"
]
},
{
"id": "PHASE_6",
"name": "Free-Play Multiplayer",
"status": "NOT_STARTED",
"description": "PvP matchmaking, custom rules, ranked mode",
"planFile": "project_plans/PHASE_6_MULTIPLAYER.json",
"estimatedWeeks": "2-3",
"dependencies": ["PHASE_4"],
"deliverables": [
"Matchmaking queue (Redis-backed)",
"Invite link system (private games)",
"RulesConfig customization API",
"Match history",
"Ranked mode with Elo/MMR (optional)",
"Leaderboards (optional)"
]
}
],
"futurePhases": [
{
"id": "FUTURE_P2P",
"name": "P2P Multiplayer",
"description": "Peer-to-peer for offline/LAN play (host-authoritative)",
"priority": "nice-to-have"
},
{
"id": "FUTURE_REPLAYS",
"name": "Replay System",
"description": "Playback recorded games (data captured from Phase 4)",
"priority": "nice-to-have"
},
{
"id": "FUTURE_ML_AI",
"name": "ML-Based AI",
"description": "Neural network opponents",
"priority": "nice-to-have"
},
{
"id": "FUTURE_OFFLINE",
"name": "Offline Fork",
"description": "Standalone offline package with SQLite",
"priority": "nice-to-have"
},
{
"id": "FUTURE_TRADING",
"name": "Trading System",
"description": "Player-to-player card trading",
"priority": "nice-to-have"
},
{
"id": "FUTURE_TOURNAMENTS",
"name": "Tournament Mode",
"description": "Organized competitive events",
"priority": "nice-to-have"
}
],
"infrastructure": {
"required": {
"postgresql": "15+",
"redis": "7+",
"python": "3.11+"
},
"development": {
"docker": "Docker compose for local Postgres + Redis",
"testing": "pytest-asyncio, testcontainers"
},
"production": {
"deployment": "Kubernetes (future)",
"cdn": "Card images served via CDN",
"monitoring": "TBD"
}
},
"securityConsiderations": [
"All game logic server-authoritative",
"Hidden information never sent to clients (from Phase 0)",
"OAuth tokens never stored, only OAuth IDs",
"JWT tokens short-lived with refresh mechanism",
"Rate limiting on all endpoints",
"Action validation on every request (from Phase 0)"
],
"totalEstimatedWeeks": "12-17",
"criticalPath": ["PHASE_1", "PHASE_2", "PHASE_3", "PHASE_4", "PHASE_5"]
}