diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 92039c3..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,369 +0,0 @@ -# Know Foolery - Claude Code Project Guide - -## Project Overview - -Know Foolery is a cross-platform quiz game with a Go microservices backend and React/React Native frontend using Gluestack UI. This document provides guidance for future Claude Code sessions. - -## Project Structure - -``` -knowfoolery/ -├── docs/ # Project documentation -│ ├── architecture.md # System architecture -│ ├── api-specs.md # API specifications -│ └── deployment.md # Deployment guides -├── backend/ # Go microservices -│ ├── services/ # Individual microservices -│ │ ├── game-service/ # Game logic and session management -│ │ ├── question-service/ # Question CRUD operations -│ │ ├── user-service/ # User management -│ │ ├── leaderboard-service/ # Score and ranking logic -│ │ ├── session-service/ # Session and timer management -│ │ ├── admin-service/ # Admin panel backend -│ │ └── gateway-service/ # API gateway -│ ├── shared/ # Shared Go packages -│ │ ├── auth/ # JWT middleware and Zitadel integration -│ │ ├── database/ # Ent database client -│ │ ├── observability/ # Metrics and tracing -│ │ └── security/ # Security utilities -│ └── scripts/ # Build and deployment scripts -├── frontend/ # Cross-platform frontend -│ ├── packages/ # Shared packages -│ │ ├── ui-components/ # Gluestack UI components -│ │ ├── shared-logic/ # Business logic -│ │ └── shared-types/ # TypeScript types -│ ├── web/ # React web application -│ ├── mobile/ # React Native mobile app -│ └── desktop/ # Electron desktop app (future) -├── infrastructure/ # Infrastructure as code -│ ├── docker/ # Docker configurations -│ ├── kubernetes/ # K8s manifests -│ └── monitoring/ # Observability configs -├── tests/ # Testing utilities -│ ├── e2e/ # End-to-end tests -│ ├── load/ # Performance tests -│ └── security/ # Security tests -├── requirements.md # Project requirements -└── README.md # Setup and development guide -``` - -## Technology Stack - -### Backend (Go) -- **Framework**: Fiber for HTTP routing -- **Database ORM**: Ent with PostgreSQL -- **Authentication**: Zitadel OAuth 2.0/OIDC -- **Observability**: Prometheus metrics, OpenTelemetry tracing -- **Communication**: gRPC for inter-service communication -- **Testing**: Go testing + testcontainers -- **Security**: Comprehensive input validation, JWT middleware - -### Frontend (TypeScript) -- **Web**: React 18 with TypeScript -- **Mobile**: React Native with TypeScript -- **UI Framework**: Gluestack UI with NativeWind/Tailwind CSS -- **State Management**: React Context + useReducer -- **Testing**: Jest + React Testing Library + Playwright - -### Database & Infrastructure -- **Primary Database**: PostgreSQL with Ent ORM -- **Cache**: Redis for sessions and performance -- **Authentication**: Self-hosted Zitadel -- **Deployment**: Docker + Kubernetes -- **Monitoring**: Prometheus + Grafana + Jaeger - -## Key Architectural Decisions - -### 1. Database Strategy -- **Development**: SQLite for fast local development -- **Testing**: PostgreSQL with testcontainers -- **Production**: PostgreSQL with high availability -- **ORM**: Ent (Facebook) for type-safe database operations -- **No Repository Pattern**: Direct Ent usage except for external APIs - -### 2. Authentication Strategy -- **Local Development**: Mock JWT service -- **Production**: Self-hosted Zitadel -- **Repository Pattern**: Only for external integrations (Zitadel) -- **Security**: MFA required for admin accounts - -### 3. Cross-Platform UI Strategy -- **Design System**: Gluestack UI for consistent components -- **Styling**: NativeWind/Tailwind CSS for utility-first styling -- **Code Sharing**: Same components work on web and mobile -- **Performance**: Native performance on mobile, optimized for web - -## Development Guidelines - -### Code Organization -```go -// Backend service structure -services/ -├── game-service/ -│ ├── cmd/main.go # Service entry point -│ ├── internal/ -│ │ ├── handlers/ # HTTP handlers -│ │ ├── services/ # Business logic -│ │ └── models/ # Ent models -│ ├── api/ # API definitions -│ └── tests/ # Service tests -``` - -```typescript -// Frontend component structure -packages/ui-components/ -├── src/ -│ ├── GameCard/ -│ │ ├── GameCard.tsx # Main component -│ │ ├── GameCard.test.tsx # Tests -│ │ └── index.ts # Exports -│ └── index.ts # Package exports -``` - -### Naming Conventions -- **Go**: PascalCase for exported, camelCase for unexported -- **TypeScript**: PascalCase for components, camelCase for functions -- **Files**: kebab-case for directories, PascalCase for components -- **Database**: snake_case for tables and columns - -### Testing Standards -- **Unit Tests**: Required for all business logic -- **Integration Tests**: Required for database operations -- **E2E Tests**: Required for critical user journeys -- **Security Tests**: Required for all input validation -- **Performance Tests**: Required for high-load scenarios - -## Security Requirements - -### Critical Security Measures (Implemented Early) -1. **Input Validation**: All user inputs sanitized and validated -2. **SQL Injection Prevention**: Ent parameterized queries only -3. **XSS Protection**: HTML escaping and CSP headers -4. **Authentication**: JWT validation with secure middleware -5. **Rate Limiting**: Per-user and global rate limits -6. **HTTPS**: TLS encryption for all communications -7. **CORS**: Strict cross-origin policies - -### Game Integrity -- **Server-Side Validation**: All game logic on backend -- **Score Verification**: Server calculates all scores -- **Session Security**: Tamper-proof session management -- **Anti-Cheating**: Multiple validation layers - -## Common Commands - -### Backend Development -```bash -# Start all services locally -docker-compose up -d - -# Run specific service -cd ~/Projects/go/src/knowfoolery/backend/services/game-service -go run cmd/main.go - -# Run tests with coverage -go test -v -cover ./... - -# Generate Ent code -cd ~/Projects/go/src/knowfoolery/database/ent -go run -mod=mod entgo.io/ent/cmd/ent describe ./schema - -# Update database schema description from Ent code -cd ~/Projects/go/src/knowfoolery/database/ent -go run -mod=mod entgo.io/ent/cmd/ent describe ./schema > ./schema/schema.md -``` - -### Frontend Development -```bash -# Install dependencies -npm install - -# Start web development -cd ~/Projects/go/src/knowfoolery/frontend/web -npm run dev - -# Start mobile development -cd ~/Projects/go/src/knowfoolery/frontend/mobile -npm run ios # or npm run android - -# Run tests -npm test - -# Build for production -npm run build -``` - -### Database Operations -```bash -# Run migrations -go run ~/Projects/go/src/knowfoolery/backend/scripts/migrate.go - -# Reset database (development only) -go run ~/Projects/go/src/knowfoolery/backend/scripts/reset-db.go - -# Seed test data -go run ~/Projects/go/src/knowfoolery/backend/scripts/seed.go -``` - -## Environment Configuration - -### Development (.env.dev) -```bash -# Database -DATABASE_URL=sqlite://./dev.db -REDIS_URL=redis://localhost:6379 - -# Authentication -JWT_SECRET=dev-secret-key -ZITADEL_URL=http://localhost:8080 - -# Observability -PROMETHEUS_PORT=9090 -JAEGER_ENDPOINT=http://localhost:14268 -``` - -### Production (.env.prod) -```bash -# Database -DATABASE_URL=postgres://user:pass@db:5432/knowfoolery -REDIS_URL=redis://redis:6379 - -# Authentication -JWT_SECRET=${JWT_SECRET} -ZITADEL_URL=${ZITADEL_URL} - -# Observability -PROMETHEUS_PORT=9090 -JAEGER_ENDPOINT=${JAEGER_ENDPOINT} -``` - -## Development Workflow - -### 1. Feature Development -1. Create feature branch from main -2. Implement domain model changes -3. Add comprehensive tests for domain model -3. Implement database and ORM changes -3. Add comprehensive tests for domain model -2. Implement backend service changes -3. Add comprehensive tests -4. Implement frontend components -5. Test cross-platform compatibility -6. Update documentation -7. Create pull request - -### 2. Testing Checklist -- [ ] Unit tests pass -- [ ] Integration tests pass -- [ ] Security tests pass -- [ ] E2E tests pass -- [ ] Cross-platform UI tests pass -- [ ] Performance tests pass - -### 3. Deployment Process -1. Merge to main branch -2. Automated CI/CD pipeline -3. Deploy to staging environment -4. Run smoke tests -5. Deploy to production -6. Monitor metrics and alerts - -## Troubleshooting - -### Common Issues - -#### Database Connection Errors -```bash -# Check database status -docker-compose ps - -# Reset database connection -docker-compose restart postgres - -# Check logs -docker-compose logs postgres -``` - -#### Authentication Issues -```bash -# Verify JWT token -curl -H "Authorization: Bearer $TOKEN" localhost:8080/api/health - -# Check Zitadel status -curl localhost:8080/.well-known/openid_configuration -``` - -#### Frontend Build Issues -```bash -# Clear node modules -rm -rf node_modules package-lock.json -npm install - -# Clear build cache -npm run clean -npm run build -``` - -## Performance Optimization - -### Backend Optimization -- Use Ent query optimization -- Implement Redis caching -- Profile with pprof -- Monitor with Prometheus - -### Frontend Optimization -- Bundle size analysis -- React Native performance profiling -- Gluestack UI optimization -- Image and asset optimization - -## Security Checklist - -### Before Each Release -- [ ] Security dependencies updated -- [ ] Vulnerability scan passed -- [ ] Penetration testing completed -- [ ] Security headers configured -- [ ] Input validation tested -- [ ] Authentication flows verified -- [ ] Rate limiting tested -- [ ] Audit logs reviewed - -## Monitoring and Alerts - -### Key Metrics to Watch -- **Response Times**: API endpoint performance -- **Error Rates**: Application stability -- **Authentication**: Success/failure rates -- **Game Metrics**: Session duration, completion rates -- **Security Events**: Failed logins, rate limit hits - -### Alert Conditions -- API response time > 500ms -- Error rate > 1% -- Authentication failure rate > 5% -- Database connection issues -- Security events detected - -## Future Development Notes - -### Mobile App Considerations -- Platform-specific optimizations needed -- App store submission requirements -- Push notification integration -- Offline capability planning - -### Desktop App Considerations -- Electron performance optimization -- Native OS integration -- Auto-update mechanism -- Platform-specific packaging - -### Scalability Planning -- Horizontal scaling strategies -- Database sharding considerations -- CDN integration for global reach -- Microservice boundaries refinement - -This guide should be updated as the project evolves and new decisions are made. \ No newline at end of file diff --git a/claude-plan-phase-1.md b/claude-plan-phase-1.md deleted file mode 100644 index 56ad52d..0000000 --- a/claude-plan-phase-1.md +++ /dev/null @@ -1,392 +0,0 @@ -# Progressive Phase 1 Implementation Plan: Incremental Infrastructure Setup - -## Overview -Instead of setting up all infrastructure at once, we'll progressively build Phase 1 in three distinct sub-phases, allowing for thorough testing and validation at each layer before adding complexity. - -## Phase 1A: Backend + Database Foundation (5-7 days) - -### Core Infrastructure Setup -**Dependencies: None** - -**1A.1 Go Project Structure & Basic Services** -- Create complete Go module structure for all microservices -- Implement basic Fiber apps with health endpoints for each service -- Set up shared packages structure (auth, database, observability, security) -- Create basic service discovery and configuration management -- Add graceful shutdown and signal handling - -**1A.2 Database Layer with Ent** -- Define complete Ent schemas (Question, GameSession, QuestionAttempt) -- Set up dual database configuration (SQLite for dev, PostgreSQL for testing) -- Create migration scripts and database initialization -- Implement basic CRUD operations for each entity -- Add database connection pooling and health checks - -**1A.3 Mock Authentication System** -- Create simple JWT-based mock authentication (no external calls) -- Implement basic role-based access control (player/admin) -- Add middleware for token validation using local secret -- Create user context propagation through services -- Add basic security headers and CORS - -**1A.4 Basic Docker Environment** -- Create `docker-compose.basic.yml` with only PostgreSQL -- Add database initialization and seeding containers -- Create health check scripts for database connectivity -- Set up volume management for persistent data - -**1A.5 Integration Testing Framework** -- Set up testcontainers for PostgreSQL integration tests -- Create test utilities for database seeding and cleanup -- Implement service-level integration tests -- Add API endpoint testing with mock authentication -- Create test data factories and fixtures - -**Success Criteria for 1A:** -- All services start and respond to health checks -- Database migrations run successfully -- Mock authentication validates tokens correctly -- Integration tests pass with PostgreSQL container -- Services can perform basic CRUD operations -- Docker environment runs consistently - ---- - -## Phase 1B: Add Redis Layer (2-3 days) - -### Redis Integration -**Dependencies: Phase 1A complete** - -**1B.1 Redis Configuration & Connection** -- Add Redis client to shared package with connection pooling -- Create Redis health checks and monitoring -- Implement connection retry logic and circuit breaker -- Add Redis configuration management (cluster vs single instance) - -**1B.2 Session Management with Redis** -- Migrate session storage from in-memory to Redis -- Implement session middleware with Redis backend -- Add session invalidation and cleanup routines -- Create session security (encryption, tampering protection) - -**1B.3 Caching Layer Implementation** -- Create cache abstraction layer for future use -- Add caching for frequently accessed data (questions, leaderboards) -- Implement cache invalidation strategies -- Add cache performance metrics - -**1B.4 Update Development Environment** -- Extend `docker-compose.basic.yml` to include Redis -- Create `docker-compose.redis.yml` configuration -- Update health check scripts to verify Redis connectivity -- Add Redis monitoring and debugging tools - -**1B.5 Redis Integration Testing** -- Extend integration tests to include Redis functionality -- Test session persistence across service restarts -- Validate cache behavior and invalidation -- Test Redis failover scenarios -- Add performance testing for cache operations - -**Success Criteria for 1B:** -- Redis connects reliably with proper failover -- Sessions persist correctly in Redis -- Cache operations perform as expected -- Integration tests pass with Redis + PostgreSQL -- Services handle Redis connectivity issues gracefully - ---- - -## Phase 1C: Add Zitadel Authentication (3-4 days) - -### External Authentication Integration -**Dependencies: Phase 1B complete** - -**1C.1 Zitadel Repository Implementation** -- Implement full ZitadelRepository interface with HTTP client -- Add JWT token validation with Zitadel public keys -- Create token refresh and user management functionality -- Implement circuit breaker for external API calls -- Add proper error handling and retry logic - -**1C.2 Replace Mock Authentication** -- Migrate from mock JWT to real Zitadel integration -- Update middleware to validate tokens against Zitadel -- Implement proper role and permission mapping -- Add MFA validation for admin endpoints -- Create user context enrichment from Zitadel claims - -**1C.3 Complete Docker Environment** -- Add Zitadel container to Docker Compose setup -- Create `docker-compose.yml` with full infrastructure stack -- Configure Zitadel with proper OAuth applications -- Set up development user accounts and roles -- Add monitoring for all services - -**1C.4 Observability Foundation** -- Add Prometheus metrics collection to all services -- Create basic Grafana dashboards -- Implement distributed tracing preparation -- Add structured logging across services -- Create alerting for critical failures - -**1C.5 End-to-End Integration Testing** -- Create full authentication flow tests -- Test token validation and refresh cycles -- Validate role-based access control -- Test multi-service communication with real auth -- Add performance testing under load - -**Success Criteria for 1C:** -- Zitadel authentication works end-to-end -- All services integrate properly with real JWT validation -- Role-based access control functions correctly -- Integration tests pass with full infrastructure stack -- System handles authentication failures gracefully -- Basic observability provides useful insights - ---- - -## Progressive Testing Strategy - -### Phase 1A Testing Focus -- Database operations and data consistency -- Service startup and health check reliability -- Mock authentication token flows -- Basic API functionality - -### Phase 1B Testing Focus -- Redis connectivity and session persistence -- Cache performance and invalidation -- Service behavior with Redis failures -- Session security and tampering protection - -### Phase 1C Testing Focus -- External authentication integration -- Token validation and refresh flows -- Role-based access across services -- System resilience under auth failures -- End-to-end user workflows - -## Benefits of Progressive Approach - -1. **Incremental Complexity**: Each phase adds one major component -2. **Isolation of Issues**: Problems can be traced to specific layers -3. **Thorough Testing**: Each layer gets comprehensive validation -4. **Rollback Capability**: Can revert to previous working state -5. **Learning Curve**: Understand each technology deeply before combining -6. **Debugging Ease**: Fewer variables when troubleshooting -7. **Confidence Building**: Success at each phase builds momentum - -## Deliverables Timeline - -- **Week 1**: Phase 1A - Backend + Database foundation -- **Week 2**: Phase 1B - Redis integration and testing -- **Week 2-3**: Phase 1C - Zitadel integration and full stack testing - -This progressive approach ensures solid foundations at each layer before adding the next level of complexity, making the overall implementation more reliable and maintainable. - ---- - -## Detailed Implementation Steps for Phase 1A - -### Step 1A.1: Create Go Project Structure - -#### Root Go Module Setup -```bash -# Initialize main go.mod -go mod init knowfoolery -go mod tidy -``` - -#### Directory Structure Creation -``` -knowfoolery/ -├── backend/ -│ ├── services/ -│ │ ├── game-service/ -│ │ │ ├── cmd/main.go -│ │ │ ├── internal/ -│ │ │ │ ├── handlers/ -│ │ │ │ ├── services/ -│ │ │ │ ├── middleware/ -│ │ │ │ └── models/ -│ │ │ ├── config/ -│ │ │ ├── tests/ -│ │ │ └── go.mod -│ │ ├── question-service/ -│ │ ├── user-service/ -│ │ ├── leaderboard-service/ -│ │ ├── session-service/ -│ │ ├── admin-service/ -│ │ └── gateway-service/ -│ ├── shared/ -│ │ ├── auth/ -│ │ ├── database/ -│ │ ├── observability/ -│ │ ├── security/ -│ │ └── utils/ -│ └── scripts/ -└── infrastructure/ - └── docker/ -``` - -### Step 1A.2: Define Ent Schemas - -#### Question Schema -```go -// backend/shared/database/ent/schema/question.go -package schema - -import ( - "time" - "entgo.io/ent" - "entgo.io/ent/schema/field" - "entgo.io/ent/schema/index" -) - -type Question struct { - ent.Schema -} - -func (Question) Fields() []ent.Field { - return []ent.Field{ - field.String("id").Unique(), - field.String("theme").NotEmpty(), - field.Text("text").NotEmpty(), - field.String("answer").NotEmpty(), - field.Text("hint").Optional(), - field.Enum("difficulty").Values("easy", "medium", "hard").Default("medium"), - field.Bool("is_active").Default(true), - field.Time("created_at").Default(time.Now), - field.Time("updated_at").Default(time.Now).UpdateDefault(time.Now), - } -} - -func (Question) Indexes() []ent.Index { - return []ent.Index{ - index.Fields("theme"), - index.Fields("difficulty"), - index.Fields("is_active"), - index.Fields("created_at"), - } -} -``` - -### Step 1A.3: Basic Service Implementation - -#### Game Service Main -```go -// backend/services/game-service/cmd/main.go -package main - -import ( - "log" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/middleware/cors" - "github.com/gofiber/fiber/v2/middleware/logger" -) - -func main() { - app := fiber.New(fiber.Config{ - AppName: "Know Foolery Game Service", - }) - - // Middleware - app.Use(logger.New()) - app.Use(cors.New()) - - // Health endpoint - app.Get("/health", func(c *fiber.Ctx) error { - return c.JSON(fiber.Map{ - "status": "healthy", - "service": "game-service", - }) - }) - - log.Println("Game Service starting on :3001") - log.Fatal(app.Listen(":3001")) -} -``` - -### Step 1A.4: Docker Compose Basic Setup - -#### Basic Docker Compose -```yaml -# infrastructure/docker/docker-compose.basic.yml -version: '3.8' - -services: - postgres: - image: postgres:15-alpine - environment: - POSTGRES_DB: knowfoolery - POSTGRES_USER: knowfoolery - POSTGRES_PASSWORD: dev-password - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql - healthcheck: - test: ["CMD-SHELL", "pg_isready -U knowfoolery"] - interval: 10s - timeout: 5s - retries: 5 - -volumes: - postgres_data: -``` - -### Step 1A.5: Integration Test Framework - -#### Test Utilities -```go -// backend/shared/database/testutil/testutil.go -package testutil - -import ( - "context" - "testing" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" -) - -func SetupTestDB(t *testing.T) (*ent.Client, func()) { - ctx := context.Background() - - postgresContainer, err := postgres.RunContainer(ctx, - testcontainers.WithImage("postgres:15-alpine"), - postgres.WithDatabase("testdb"), - postgres.WithUsername("test"), - postgres.WithPassword("test"), - ) - if err != nil { - t.Fatal(err) - } - - // Get connection string and create Ent client - // ... implementation details - - cleanup := func() { - postgresContainer.Terminate(ctx) - } - - return client, cleanup -} -``` - -## Current Phase 1A Implementation Checklist - -- [ ] Create complete Go project structure -- [ ] Initialize all service modules with basic Fiber apps -- [ ] Define and generate all Ent schemas -- [ ] Set up database connection and migration utilities -- [ ] Implement mock JWT authentication -- [ ] Create Docker Compose basic environment -- [ ] Set up integration testing framework -- [ ] Add health checks and basic monitoring -- [ ] Create database seeding scripts -- [ ] Validate all services start and communicate properly - -This detailed plan provides clear, actionable steps for implementing Phase 1A while maintaining the progressive approach that allows for thorough testing at each layer. \ No newline at end of file diff --git a/claude-plan.md b/claude-plan.md deleted file mode 100644 index 487fe43..0000000 --- a/claude-plan.md +++ /dev/null @@ -1,157 +0,0 @@ -# Know Foolery - Claude Implementation Plan - -## Project Overview - -**Know Foolery** is a comprehensive quiz game application based on the French game "Déconnaissance". The project implements a cross-platform solution with web, mobile (iOS/Android), and desktop applications, featuring secure authentication, microservices architecture, and comprehensive observability. - -## Technology Stack - -- **Backend**: Go with Fiber framework, microservices architecture -- **Database**: PostgreSQL (production), SQLite (development) -- **ORM**: Ent for type-safe database operations -- **Cache**: Redis for session management and caching -- **Authentication**: Self-hosted Zitadel (OAuth 2.0/OIDC) -- **Frontend**: React (web), React Native (mobile), Wails (desktop) -- **UI Framework**: Gluestack UI for cross-platform consistency -- **Styling**: NativeWind/Tailwind CSS -- **Monitoring**: Prometheus, Grafana, Jaeger -- **Containerization**: Docker with Docker Compose - -## Implementation Phases - -### Phase 0: Documentation & Planning ✅ COMPLETED -- [x] Create requirements.md with complete application requirements -- [x] Create CLAUDE.md project guidance file -- [x] Document game mechanics and scoring system -- [x] Document technical requirements and architecture decisions -- [x] Create architecture documentation with Zitadel integration -- [x] Document development guidelines and coding standards -- [x] Document observability strategy -- [x] Document security requirements -- [x] Document cross-platform UI strategy with Gluestack UI - -**Completion Date**: Phase 0 completed successfully with comprehensive documentation covering all aspects of the project. - -### Phase 1: Project Setup & Core Security Infrastructure -- [ ] Initialize Go project structure with microservices architecture -- [ ] Set up Ent schema definitions for core entities (User, Quiz, Question, etc.) -- [ ] Create ZitadelRepository interface for external auth integration -- [ ] Set up development environment with Docker Compose -- [ ] Initialize Gluestack UI setup with theme configuration -- [ ] Implement core security middleware and input validation -- [ ] Set up Prometheus metrics collection foundation -- [ ] Create basic CI/CD pipeline structure - -### Phase 2: Authentication & User Management -- [ ] Implement Zitadel integration with repository pattern -- [ ] Create JWT validation middleware with circuit breaker -- [ ] Build user registration and profile management -- [ ] Implement role-based access control (player/admin) -- [ ] Add MFA requirements for admin access -- [ ] Create secure token storage for each platform -- [ ] Implement comprehensive authentication testing - -### Phase 3: Core Game Engine -- [ ] Implement quiz engine with theme and difficulty support -- [ ] Create question management system with validation -- [ ] Build scoring system with anti-cheating measures -- [ ] Implement session management (30-minute time limits) -- [ ] Add hint system with progressive revelation -- [ ] Create leaderboard functionality -- [ ] Implement comprehensive game testing - -### Phase 4: Cross-Platform Frontend -- [ ] Build React web application with Gluestack UI -- [ ] Create React Native mobile applications -- [ ] Develop Wails desktop application -- [ ] Implement shared authentication flows -- [ ] Create responsive game interface components -- [ ] Add platform-specific optimizations -- [ ] Implement comprehensive frontend testing - -### Phase 5: Admin Panel & Content Management -- [ ] Build secure admin dashboard -- [ ] Create question management interface -- [ ] Implement user administration tools -- [ ] Add analytics and reporting features -- [ ] Create content import/export functionality -- [ ] Implement admin-specific security measures -- [ ] Add comprehensive admin testing - -### Phase 6: Performance & Optimization -- [ ] Implement Redis caching strategy -- [ ] Add database query optimization -- [ ] Create CDN integration for assets -- [ ] Implement API rate limiting -- [ ] Add frontend performance optimization -- [ ] Create load testing and benchmarks - -### Phase 7: Monitoring & Observability -- [ ] Complete Prometheus metrics implementation -- [ ] Set up Grafana dashboards -- [ ] Implement distributed tracing with Jaeger -- [ ] Add comprehensive logging strategy -- [ ] Create alerting and notification system -- [ ] Implement health checks and monitoring - -### Phase 8: Security Hardening -- [ ] Conduct comprehensive security audit -- [ ] Implement advanced anti-cheating measures -- [ ] Add security monitoring and incident response -- [ ] Create backup and disaster recovery procedures -- [ ] Implement data encryption at rest -- [ ] Add comprehensive security testing - -### Phase 9: Production Deployment -- [ ] Set up production infrastructure -- [ ] Configure CI/CD for production deployment -- [ ] Implement monitoring and alerting in production -- [ ] Create deployment documentation -- [ ] Conduct production readiness review -- [ ] Implement production security measures - -### Phase 10: Launch & Post-Launch -- [ ] Conduct final testing and quality assurance -- [ ] Deploy to production environment -- [ ] Monitor launch metrics and performance -- [ ] Address any post-launch issues -- [ ] Gather user feedback and analytics -- [ ] Plan future feature development - -## Key Architectural Decisions - -1. **Repository Pattern**: Used only for external API integrations (Zitadel), direct Ent client usage for database operations -2. **Security First**: Critical vulnerabilities addressed in early phases (1-3), enhancements in Phase 8 -3. **Cross-Platform UI**: Gluestack UI for consistent design across web, mobile, and desktop -4. **Microservices**: Go with Fiber framework for high-performance, maintainable services -5. **Self-Hosted Auth**: Zitadel for complete control over authentication and user data -6. **Comprehensive Testing**: Unit and integration testing after each implementation phase - -## Current Status - -**Phase 0 Complete**: All documentation has been created and is ready for implementation. The project has comprehensive documentation covering: - -- Complete requirements and specifications -- Technical architecture with microservices design -- Security requirements and implementation strategy -- Cross-platform UI strategy with Gluestack UI -- Development guidelines and coding standards -- Observability and monitoring strategy -- Game mechanics and anti-cheating measures -- Zitadel authentication integration - -**Next Steps**: Ready to begin Phase 1 (Project Setup & Core Security Infrastructure) upon approval to proceed with implementation. - -## Files Created - -1. `/requirements.md` - Complete project requirements and specifications -2. `/CLAUDE.md` - Project guidance for future Claude Code sessions -3. `/docs/game-mechanics.md` - Game flow, scoring, and anti-cheating measures -4. `/docs/technical-architecture.md` - System architecture and service design -5. `/docs/zitadel-integration.md` - Authentication architecture and implementation -6. `/docs/development-guidelines.md` - Coding standards and patterns -7. `/docs/observability-strategy.md` - Monitoring and metrics strategy -8. `/docs/security-requirements.md` - Security strategy and requirements -9. `/docs/gluestack-ui-strategy.md` - Cross-platform UI implementation strategy - -All documentation includes comprehensive code examples, implementation details, and best practices for building a secure, scalable quiz game application. \ No newline at end of file diff --git a/docs/2_architecture/security-architecture.md b/docs/2_architecture/security-architecture.md index 86e3819..f7711cd 100644 --- a/docs/2_architecture/security-architecture.md +++ b/docs/2_architecture/security-architecture.md @@ -110,3 +110,21 @@ Zitadel serves as the self-hosted OAuth 2.0/OpenID Connect authentication provid │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` +### Authentication Flow +```mermaid +sequenceDiagram + participant C as Client + participant G as API Gateway + participant Z as Zitadel + participant S as Service + + C->>G: Request with credentials + G->>Z: Validate credentials + Z->>G: Return JWT token + G->>C: Return token + user info + C->>G: API request with JWT + G->>G: Validate JWT signature + G->>S: Forward request with user context + S->>G: Return response + G->>C: Return response +``` diff --git a/docs/2_architecture/technical-architecture.md b/docs/2_architecture/technical-architecture.md index a36adc3..7ffc769 100644 --- a/docs/2_architecture/technical-architecture.md +++ b/docs/2_architecture/technical-architecture.md @@ -8,19 +8,24 @@ Know Foolery follows a microservices architecture with clear separation between ## Technical Architecture ### Frontend Architecture -- **Web Application**: React with TypeScript -- **Mobile Applications**: React Native for iOS and Android -- **Desktop Applications**: Wails for macOS, Windows, and Linux +- **Web Application**: React with TypeScript, vite and React Native Web +- **Mobile Applications**: React Native with Expo for iOS and Android +- **Desktop Applications**: Wails for macOS, Windows, and Linux, with the web application packaged for the deployement in the Wails app - **UI Framework**: Gluestack UI for consistent cross-platform design -- **Styling**: NativeWind/Tailwind CSS for utility-first styling ### Backend Architecture +- **Business Logic**: Domain Driven Design approach - **Microservices**: Go-based services with clear domain boundaries - **API Gateway**: Centralized routing, authentication, and rate limiting - **Database ORM**: Ent for type-safe database operations - **Communication**: gRPC for inter-service communication - **External APIs**: Repository pattern for external integrations +### Domain Design +- **Aggregates**: User, Theme, Question, GameSession +- **Value Objects**: Hint, Attempt, Answer, Score +- **Domain Services**: Scoring + ### Microservices Design #### Core Services @@ -29,31 +34,33 @@ Know Foolery follows a microservices architecture with clear separation between 3. **User Service**: Player registration and profile management 4. **Leaderboard Service**: Score calculations, rankings, statistics 5. **Session Service**: Timer management, session state persistence -6. **Admin Service**: Question management with OAuth protection +6. **Admin Service**: Question and user management with OAuth protection 7. **Gateway Service**: API routing, authentication, rate limiting #### External Services 1. **Zitadel**: Self-hosted OAuth 2.0/OIDC authentication -2. **PostgreSQL**: Primary database for application data -3. **Redis**: Session state and caching layer +2. **PostgreSQL**: Primary database for production application data +3. **sqlite**: Database for test application data +4. **Redis**: Session state and caching layer ### Database Design #### Core Entities -- **Questions**: ID, theme, text, answer, hint, metadata -- **GameSessions**: ID, player_name, score, start_time, end_time, is_active - **Users**: ID, name, created_at (minimal player data) +- **Themes**: ID, theme, metadata +- **Questions**: ID, ID of theme, text, answer, hint, metadata +- **GameSessions**: ID, ID of user, score, start_time, end_time, is_active +- **Attempts**: ID, ID of GameSession, answer - **Leaderboard**: Aggregated scores and rankings - **AuditLogs**: Admin actions and security events #### Data Relationships - Questions belong to themes -- GameSessions track multiple question attempts +- GameSessions track multiple question attempts for a user - Leaderboard aggregates from GameSessions - AuditLogs reference users and actions - ## Deployment & Infrastructure ### Development Environment @@ -70,8 +77,7 @@ Know Foolery follows a microservices architecture with clear separation between ### Cross-Platform Deployment - **Web**: Standard web application deployment - **Mobile**: iOS App Store and Google Play Store distribution -- **Desktop**: Electron applications for major operating systems - +- **Desktop**: Wails applications for major operating systems ## System Architecture Diagram @@ -79,10 +85,10 @@ Know Foolery follows a microservices architecture with clear separation between ``` ┌────────────────────────────────────────────────────────────────────────────┐ │ Client Layer │ -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ -│ │ Web App │ │ Mobile iOS │ │ Mobile Androi│ │ Desktop ctr│ │ -│ │ (React) │ │(React Native)│ │(React Native)│ │ (Wails) │ │ -│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ ┌─────────────┐ │ +│ │ Web App │ │ Mobile iOS │ │ Mobile Android│ │ Desktop │ │ +│ │ (React) │ │(React Native)│ │(React Native) │ │ (Wails) │ │ +│ └──────────────┘ └──────────────┘ └───────────────┘ └─────────────┘ │ └────────────────────────────────────────────────────────────────────────────┘ │ HTTPS/WSS @@ -125,6 +131,10 @@ Know Foolery follows a microservices architecture with clear separation between ``` ## Technology Stack +- **Web Application**: React with TypeScript, vite and React Native Web +- **Mobile Applications**: React Native with Expo for iOS and Android +- **Desktop Applications**: Wails for macOS, Windows, and Linux, with the web application packaged for the deployement in the Wails app +- **UI Framework**: Gluestack UI for consistent cross-platform design ### Frontend Technologies ```yaml @@ -132,7 +142,7 @@ Web Application: Framework: React 18.2+ Language: TypeScript 5.0+ Build Tool: Vite 4.0+ - UI Library: Gluestack UI + UI Library: Gluestack UI (React Native Web) Styling: NativeWind/Tailwind CSS 3.0+ State Management: React Context + useReducer Testing: Jest + React Testing Library + Playwright @@ -141,7 +151,7 @@ Mobile Applications: Framework: React Native 0.81+ Language: TypeScript 5.9+ UI Library: Gluestack UI (Native) - Navigation: React Navigation 6+ + Navigation: Expo 54+ State Management: React Context + useReducer Testing: Jest + React Native Testing Library @@ -214,15 +224,6 @@ CI/CD: #### 1. Game Service ```go -// Responsibilities -type GameService struct { - // Core game logic and session management - SessionManager *SessionManager - ScoreCalculator *ScoreCalculator - AttemptTracker *AttemptTracker - TimerManager *TimerManager -} - // API Endpoints POST /api/v1/game/start // Start new game session GET /api/v1/game/session/{id} // Get session details @@ -234,49 +235,32 @@ GET /api/v1/game/status/{id} // Get session status #### 2. Question Service ```go -// Responsibilities -type QuestionService struct { - QuestionRepo *QuestionRepository - ThemeManager *ThemeManager - Randomizer *QuestionRandomizer - Validator *AnswerValidator -} - // API Endpoints -GET /api/v1/questions/random // Get random question -GET /api/v1/questions/{id} // Get specific question -GET /api/v1/questions/themes // List available themes -POST /api/v1/questions // Create question (admin) -PUT /api/v1/questions/{id} // Update question (admin) -DELETE /api/v1/questions/{id} // Delete question (admin) +GET /api/v1/questions/themes/random/{id} // Get random question in a theme +GET /api/v1/questions/random // Get random question in a theme +GET /api/v1/questions/{id} // Get specific question +GET /api/v1/questions/themes // List available themes +POST /api/v1/questions // Create question (admin) +PUT /api/v1/questions/{id} // Update question (admin) +DELETE /api/v1/questions/{id} // Delete question (admin) +GET /api/v1/questions // List all questions (admin) +POST /api/v1/questions/bulk // Bulk question import (admin) ``` #### 3. User Service ```go -// Responsibilities -type UserService struct { - UserRepo *UserRepository - ProfileManager *ProfileManager - SessionTracker *SessionTracker -} - // API Endpoints POST /api/v1/users/register // Register new player GET /api/v1/users/profile // Get user profile PUT /api/v1/users/profile // Update profile GET /api/v1/users/sessions // Get session history DELETE /api/v1/users/profile // Delete account (GDPR) +GET /api/v1/users // List all users (admin) +DELETE /api/v1/users // Delete user (admin) ``` #### 4. Leaderboard Service ```go -// Responsibilities -type LeaderboardService struct { - ScoreAggregator *ScoreAggregator - RankingEngine *RankingEngine - StatsCalculator *StatsCalculator -} - // API Endpoints GET /api/v1/leaderboard/top10 // Get top 10 scores GET /api/v1/leaderboard/stats // Get game statistics @@ -286,13 +270,6 @@ POST /api/v1/leaderboard/update // Update scores (internal) #### 5. Session Service ```go -// Responsibilities -type SessionService struct { - SessionStore *SessionStore - TimerManager *TimerManager - StateManager *StateManager -} - // API Endpoints POST /api/v1/sessions // Create session GET /api/v1/sessions/{id} // Get session @@ -303,20 +280,9 @@ GET /api/v1/sessions/{id}/timer // Get timer status #### 6. Admin Service ```go -// Responsibilities -type AdminService struct { - AuthManager *AuthManager - QuestionMgmt *QuestionManagement - UserMgmt *UserManagement - AuditLogger *AuditLogger -} - // API Endpoints POST /api/v1/admin/auth // Admin authentication GET /api/v1/admin/dashboard // Dashboard data -GET /api/v1/admin/questions // List all questions -POST /api/v1/admin/questions/bulk // Bulk question import -GET /api/v1/admin/users // User management GET /api/v1/admin/audit // Audit logs ``` @@ -364,544 +330,4 @@ service LeaderboardService { } ``` -## Database Architecture - -### Data Model Design - -#### Core Entities (Ent Schemas) -```go -// Question Entity -type Question struct { - ent.Schema -} - -func (Question) Fields() []ent.Field { - return []ent.Field{ - field.String("theme").NotEmpty(), - field.Text("text").NotEmpty(), - field.String("answer").NotEmpty(), - field.Text("hint").Optional(), - field.Enum("difficulty").Values("easy", "medium", "hard").Default("medium"), - field.Bool("is_active").Default(true), - field.Time("created_at").Default(time.Now), - field.Time("updated_at").Default(time.Now).UpdateDefault(time.Now), - } -} - -func (Question) Indexes() []ent.Index { - return []ent.Index{ - index.Fields("theme"), - index.Fields("difficulty"), - index.Fields("is_active"), - index.Fields("created_at"), - } -} - -// GameSession Entity -type GameSession struct { - ent.Schema -} - -func (GameSession) Fields() []ent.Field { - return []ent.Field{ - field.String("player_name").NotEmpty(), - field.Int("total_score").Default(0), - field.Int("questions_asked").Default(0), - field.Int("questions_correct").Default(0), - field.Int("hints_used").Default(0), - field.Time("start_time").Default(time.Now), - field.Time("end_time").Optional().Nillable(), - field.Enum("status").Values("active", "completed", "timeout", "abandoned").Default("active"), - field.String("current_question_id").Optional(), - field.Int("current_attempts").Default(0), - } -} - -func (GameSession) Edges() []ent.Edge { - return []ent.Edge{ - edge.To("attempts", QuestionAttempt.Type), - edge.To("current_question", Question.Type).Unique().Field("current_question_id"), - } -} - -// QuestionAttempt Entity -type QuestionAttempt struct { - ent.Schema -} - -func (QuestionAttempt) Fields() []ent.Field { - return []ent.Field{ - field.String("session_id"), - field.String("question_id"), - field.Int("attempt_number"), - field.String("submitted_answer"), - field.Bool("is_correct"), - field.Bool("used_hint"), - field.Int("points_awarded"), - field.Time("submitted_at").Default(time.Now), - field.Duration("time_taken"), - } -} - -func (QuestionAttempt) Edges() []ent.Edge { - return []ent.Edge{ - edge.From("session", GameSession.Type).Ref("attempts").Unique().Field("session_id"), - edge.To("question", Question.Type).Unique().Field("question_id"), - } -} -``` - -#### Database Performance Optimization -```sql --- Indexes for optimal query performance -CREATE INDEX idx_questions_theme_active ON questions(theme, is_active); -CREATE INDEX idx_sessions_status_start_time ON game_sessions(status, start_time); -CREATE INDEX idx_attempts_session_question ON question_attempts(session_id, question_id); -CREATE INDEX idx_leaderboard_score_time ON game_sessions(total_score DESC, end_time ASC) WHERE status = 'completed'; - --- Partitioning for large datasets (future scaling) -CREATE TABLE game_sessions_y2024m01 PARTITION OF game_sessions - FOR VALUES FROM ('2024-01-01') TO ('2024-02-01'); -``` - -### Database Connection Management -```go -// Database configuration -type DatabaseConfig struct { - Primary DatabaseInstance - Replicas []DatabaseInstance - Pool PoolConfig -} - -type DatabaseInstance struct { - Host string - Port int - Database string - Username string - Password string - SSLMode string -} - -type PoolConfig struct { - MaxOpenConns int // 25 - MaxIdleConns int // 5 - ConnMaxLifetime time.Duration // 30 minutes - ConnMaxIdleTime time.Duration // 15 minutes -} - -// Connection pooling with read/write splitting -func NewDatabaseClient(config DatabaseConfig) (*ent.Client, error) { - primaryDSN := formatDSN(config.Primary) - - // Primary database for writes - primaryDB, err := sql.Open("postgres", primaryDSN) - if err != nil { - return nil, err - } - - configurePools(primaryDB, config.Pool) - - // Create Ent client with instrumented driver - drv := entsql.OpenDB("postgres", primaryDB) - return ent.NewClient(ent.Driver(drv)), nil -} -``` - -## Security Architecture - -### Authentication Flow -```mermaid -sequenceDiagram - participant C as Client - participant G as API Gateway - participant Z as Zitadel - participant S as Service - - C->>G: Request with credentials - G->>Z: Validate credentials - Z->>G: Return JWT token - G->>C: Return token + user info - C->>G: API request with JWT - G->>G: Validate JWT signature - G->>S: Forward request with user context - S->>G: Return response - G->>C: Return response -``` - -### Authorization Strategy -```go -// Role-based access control -type Role string - -const ( - RolePlayer Role = "player" - RoleAdmin Role = "admin" -) - -type Permissions struct { - CanPlayGame bool - CanViewScores bool - CanManageQuestions bool - CanViewAuditLogs bool - CanManageUsers bool -} - -var RolePermissions = map[Role]Permissions{ - RolePlayer: { - CanPlayGame: true, - CanViewScores: true, - }, - RoleAdmin: { - CanPlayGame: true, - CanViewScores: true, - CanManageQuestions: true, - CanViewAuditLogs: true, - CanManageUsers: true, - }, -} - -// JWT middleware with role checking -func AuthMiddleware() fiber.Handler { - return func(c *fiber.Ctx) error { - token := extractToken(c.Get("Authorization")) - - claims, err := validateJWT(token) - if err != nil { - return c.Status(401).JSON(fiber.Map{"error": "Invalid token"}) - } - - c.Locals("user_id", claims.Subject) - c.Locals("user_role", claims.Role) - c.Locals("permissions", RolePermissions[Role(claims.Role)]) - - return c.Next() - } -} - -func RequirePermission(permission func(Permissions) bool) fiber.Handler { - return func(c *fiber.Ctx) error { - perms := c.Locals("permissions").(Permissions) - if !permission(perms) { - return c.Status(403).JSON(fiber.Map{"error": "Insufficient permissions"}) - } - return c.Next() - } -} -``` - -### Input Validation & Security -```go -// Comprehensive input validation -type InputValidator struct { - maxAnswerLength int - maxNameLength int - allowedChars *regexp.Regexp -} - -func NewInputValidator() *InputValidator { - return &InputValidator{ - maxAnswerLength: 500, - maxNameLength: 50, - allowedChars: regexp.MustCompile(`^[a-zA-Z0-9\s\-_.]+$`), - } -} - -func (v *InputValidator) ValidateAnswer(answer string) error { - if len(answer) == 0 { - return errors.New("answer cannot be empty") - } - - if len(answer) > v.maxAnswerLength { - return errors.New("answer too long") - } - - // Sanitize HTML and potential XSS - clean := html.EscapeString(strings.TrimSpace(answer)) - if clean != answer { - return errors.New("invalid characters in answer") - } - - return nil -} - -func (v *InputValidator) ValidatePlayerName(name string) error { - if len(name) < 2 || len(name) > v.maxNameLength { - return errors.New("name must be 2-50 characters") - } - - if !v.allowedChars.MatchString(name) { - return errors.New("name contains invalid characters") - } - - return nil -} - -// Rate limiting implementation -type RateLimiter struct { - redis *redis.Client - limits map[string]RateLimit -} - -type RateLimit struct { - Requests int // Number of requests - Window time.Duration // Time window -} - -func (rl *RateLimiter) Allow(key string, limit RateLimit) bool { - current, err := rl.redis.Incr(key).Result() - if err != nil { - return false // Fail closed - } - - if current == 1 { - rl.redis.Expire(key, limit.Window) - } - - return current <= int64(limit.Requests) -} - -// Usage in middleware -func RateLimitMiddleware() fiber.Handler { - limiter := NewRateLimiter() - - return func(c *fiber.Ctx) error { - userID := c.Locals("user_id").(string) - clientIP := c.IP() - - // Per-user rate limiting - userKey := fmt.Sprintf("rate_limit:user:%s", userID) - if !limiter.Allow(userKey, RateLimit{Requests: 60, Window: time.Minute}) { - return c.Status(429).JSON(fiber.Map{"error": "Rate limit exceeded"}) - } - - // Per-IP rate limiting - ipKey := fmt.Sprintf("rate_limit:ip:%s", clientIP) - if !limiter.Allow(ipKey, RateLimit{Requests: 100, Window: time.Minute}) { - return c.Status(429).JSON(fiber.Map{"error": "Rate limit exceeded"}) - } - - return c.Next() - } -} -``` - -## Cross-Platform Frontend Architecture - -### Gluestack UI Integration -```typescript -// Shared component library structure -// packages/ui-components/src/index.ts - -export { GameCard } from './GameCard' -export { Leaderboard } from './Leaderboard' -export { Timer } from './Timer' -export { ScoreDisplay } from './ScoreDisplay' -export { AdminPanel } from './AdminPanel' - -// Component example with Gluestack UI -// packages/ui-components/src/GameCard/GameCard.tsx -import { - Card, - VStack, - HStack, - Text, - Input, - Button, - Badge, - Progress, - Box -} from '@gluestack-ui/themed' - -export interface GameCardProps { - question: string - theme: string - timeRemaining: number - attemptsLeft: number - currentScore: number - onSubmitAnswer: (answer: string) => void - onRequestHint: () => void - isLoading?: boolean -} - -export const GameCard: React.FC = ({ - question, - theme, - timeRemaining, - attemptsLeft, - currentScore, - onSubmitAnswer, - onRequestHint, - isLoading = false -}) => { - const [answer, setAnswer] = useState('') - - const handleSubmit = () => { - if (answer.trim()) { - onSubmitAnswer(answer.trim()) - setAnswer('') - } - } - - return ( - - - {/* Header with theme and timer */} - - - - {theme} - - - - - ⏱️ {Math.floor(timeRemaining / 60)}:{(timeRemaining % 60).toString().padStart(2, '0')} - - - - - {/* Progress indicator */} - - - - - {/* Question */} - - - {question} - - - - {/* Answer input */} - - - - - {/* Game stats */} - - - Attempts left: {attemptsLeft}/3 - - - Score: {currentScore} points - - - - {/* Action buttons */} - - - - - - - ) -} -``` - -### Platform-Specific Adaptations -```typescript -// Platform detection and adaptation -// packages/shared-logic/src/platform.ts - -export interface PlatformCapabilities { - hasTouch: boolean - hasKeyboard: boolean - hasCamera: boolean - canVibrate: boolean - supportsNotifications: boolean - isOfflineCapable: boolean -} - -export const getPlatformCapabilities = (): PlatformCapabilities => { - // Web platform - if (typeof window !== 'undefined') { - return { - hasTouch: 'ontouchstart' in window, - hasKeyboard: true, - hasCamera: !!navigator.mediaDevices?.getUserMedia, - canVibrate: !!navigator.vibrate, - supportsNotifications: 'Notification' in window, - isOfflineCapable: 'serviceWorker' in navigator - } - } - - // React Native platform - if (typeof require !== 'undefined') { - try { - const { Platform } = require('react-native') - return { - hasTouch: true, - hasKeyboard: Platform.OS === 'ios' || Platform.OS === 'android', - hasCamera: true, - canVibrate: true, - supportsNotifications: true, - isOfflineCapable: true - } - } catch { - // Fallback for other environments - } - } - - // Default capabilities - return { - hasTouch: false, - hasKeyboard: true, - hasCamera: false, - canVibrate: false, - supportsNotifications: false, - isOfflineCapable: false - } -} - -// Responsive design utilities -export const useResponsiveValue = (values: { - mobile: T - tablet: T - desktop: T -}) => { - const [screenSize, setScreenSize] = useState<'mobile' | 'tablet' | 'desktop'>('desktop') - - useEffect(() => { - const updateScreenSize = () => { - const width = window.innerWidth - if (width < 768) { - setScreenSize('mobile') - } else if (width < 1024) { - setScreenSize('tablet') - } else { - setScreenSize('desktop') - } - } - - updateScreenSize() - window.addEventListener('resize', updateScreenSize) - return () => window.removeEventListener('resize', updateScreenSize) - }, []) - - return values[screenSize] -} -``` - This technical architecture provides a solid foundation for building a scalable, secure, and maintainable quiz game platform with cross-platform capabilities. \ No newline at end of file diff --git a/docs/3_guidelines/development-guidelines.md b/docs/3_guidelines/development-guidelines.md index 2b4009e..b679296 100644 --- a/docs/3_guidelines/development-guidelines.md +++ b/docs/3_guidelines/development-guidelines.md @@ -28,13 +28,14 @@ This document establishes coding standards, development practices, and guideline ``` knowfoolery/ ├── backend/ -│ ├── services/ # Microservices +│ ├── Domain/ # Domain logic (aggregates, value objects, repositories, services from Domain Driven Design) +│ ├── services/ # Microservices │ │ ├── {service-name}/ │ │ │ ├── cmd/ │ │ │ │ └── main.go # Service entry point │ │ │ ├── internal/ │ │ │ │ ├── handlers/ # Fiber HTTP handlers -│ │ │ │ ├── services/ # Business logic +│ │ │ │ ├── app/ # Business logic (commands, queries) │ │ │ │ ├── middleware/ # Service-specific middleware │ │ │ │ └── models/ # Ent models and schemas │ │ │ ├── api/ # API definitions (OpenAPI/gRPC) @@ -45,6 +46,7 @@ knowfoolery/ │ │ └── shared/ # Shared packages │ │ ├── auth/ # JWT middleware & Zitadel integration │ │ ├── database/ # Ent database client +│ │ │ │ └── schema/ # Ent models and schemas │ │ ├── observability/ # Metrics and tracing │ │ ├── security/ # Security utilities │ │ └── utils/ # Common utilities @@ -54,11 +56,15 @@ knowfoolery/ │ │ ├── shared-logic/ # Business logic │ │ ├── shared-types/ # TypeScript types │ │ └── shared-utils/ # Utility functions -│ ├── apps/ -│ │ ├── web/ # React web app -│ │ ├── mobile/ # React Native app -│ │ └── desktop/ # Wails desktop app +│ └── apps/ +│ ├── web/ # React web app +│ ├── mobile/ # React Native app +│ └── desktop/ # Wails desktop app └── infrastructure/ # DevOps and deployment + ├── dev/ # Development setup + │ ├── docker-compose.yml # dev stack (hot reload, mounts) + │ └── api.env # dev env vars + └── prod/ # Production setup ``` ### Naming Conventions diff --git a/docs/3_guidelines/security-guidelines.md b/docs/3_guidelines/security-guidelines.md index e4d5a6b..df61efd 100644 --- a/docs/3_guidelines/security-guidelines.md +++ b/docs/3_guidelines/security-guidelines.md @@ -3,178 +3,7 @@ ## Authentication & Authorization ### OAuth 2.0/OIDC Implementation - -#### Zitadel Authentication Flow -```go -// Secure authentication implementation -package auth - -import ( - "context" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/pem" - "fmt" - "time" - - "github.com/golang-jwt/jwt/v5" - "golang.org/x/crypto/argon2" -) - -type SecureAuthService struct { - zitadelRepo ZitadelRepository - keyStore *KeyStore - sessionManager *SessionManager - auditLogger *AuditLogger - rateLimiter *RateLimiter -} - -type AuthClaims struct { - jwt.RegisteredClaims - Email string `json:"email"` - Name string `json:"name"` - Roles []string `json:"urn:zitadel:iam:org:project:roles"` - MFAVerified bool `json:"amr"` - SessionID string `json:"sid"` - DeviceID string `json:"device_id,omitempty"` - IPAddress string `json:"ip_address,omitempty"` -} - -// Token validation with comprehensive security checks -func (s *SecureAuthService) ValidateToken(ctx context.Context, tokenString string, clientIP string) (*AuthClaims, error) { - // Rate limiting check - if !s.rateLimiter.Allow(fmt.Sprintf("token_validation:%s", clientIP)) { - s.auditLogger.LogSecurityEvent("rate_limit_exceeded", "", clientIP, "warning", map[string]interface{}{ - "operation": "token_validation", - }) - return nil, fmt.Errorf("rate limit exceeded") - } - - // Parse and validate JWT structure - token, err := jwt.ParseWithClaims(tokenString, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) { - // Verify signing algorithm - if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - - // Get key ID from header - keyID, ok := token.Header["kid"].(string) - if !ok { - return nil, fmt.Errorf("missing key ID in token header") - } - - // Retrieve public key - return s.keyStore.GetPublicKey(keyID) - }) - - if err != nil { - s.auditLogger.LogSecurityEvent("invalid_token", "", clientIP, "warning", map[string]interface{}{ - "error": err.Error(), - }) - return nil, fmt.Errorf("token validation failed: %w", err) - } - - if !token.Valid { - return nil, fmt.Errorf("invalid token") - } - - claims, ok := token.Claims.(*AuthClaims) - if !ok { - return nil, fmt.Errorf("invalid token claims") - } - - // Additional security validations - if err := s.validateTokenClaims(claims, clientIP); err != nil { - s.auditLogger.LogSecurityEvent("token_validation_failed", claims.Subject, clientIP, "warning", map[string]interface{}{ - "error": err.Error(), - }) - return nil, err - } - - // Check if session is still valid - if !s.sessionManager.IsValidSession(claims.SessionID, claims.Subject) { - s.auditLogger.LogSecurityEvent("invalid_session", claims.Subject, clientIP, "warning", map[string]interface{}{ - "session_id": claims.SessionID, - }) - return nil, fmt.Errorf("session no longer valid") - } - - // Log successful validation - s.auditLogger.LogSecurityEvent("token_validated", claims.Subject, clientIP, "info", map[string]interface{}{ - "session_id": claims.SessionID, - "roles": claims.Roles, - }) - - return claims, nil -} - -func (s *SecureAuthService) validateTokenClaims(claims *AuthClaims, clientIP string) error { - now := time.Now() - - // Check expiration - if claims.ExpiresAt != nil && claims.ExpiresAt.Time.Before(now) { - return fmt.Errorf("token expired") - } - - // Check not before - if claims.NotBefore != nil && claims.NotBefore.Time.After(now) { - return fmt.Errorf("token not yet valid") - } - - // Check issued at (prevent future tokens) - if claims.IssuedAt != nil && claims.IssuedAt.Time.After(now.Add(5*time.Minute)) { - return fmt.Errorf("token issued in the future") - } - - // Validate audience - expectedAudience := "knowfoolery-quiz-game" - if !contains(claims.Audience, expectedAudience) { - return fmt.Errorf("invalid audience") - } - - // Validate issuer - expectedIssuer := "https://auth.knowfoolery.com" - if claims.Issuer != expectedIssuer { - return fmt.Errorf("invalid issuer") - } - - // IP address validation (if configured) - if claims.IPAddress != "" && claims.IPAddress != clientIP { - return fmt.Errorf("IP address mismatch") - } - - return nil -} - -// Multi-Factor Authentication enforcement -func (s *SecureAuthService) RequireMFA(userID string, roles []string) bool { - // Admin users always require MFA - for _, role := range roles { - if role == "admin" { - return true - } - } - - // Check if user has high-value permissions - return s.hasHighValuePermissions(roles) -} - -func (s *SecureAuthService) hasHighValuePermissions(roles []string) bool { - highValueRoles := []string{"moderator", "question_manager", "user_manager"} - - for _, userRole := range roles { - for _, hvRole := range highValueRoles { - if userRole == hvRole { - return true - } - } - } - - return false -} -``` +- See [Zitadel Integration Guidelines](zitadel-guidelines.md) ### Session Management ```go diff --git a/docs/3_guidelines/zitadel-guidelines.md b/docs/3_guidelines/zitadel-guidelines.md index e14205b..bdb6f27 100644 --- a/docs/3_guidelines/zitadel-guidelines.md +++ b/docs/3_guidelines/zitadel-guidelines.md @@ -381,6 +381,179 @@ func (cb *CircuitBreaker) setState(state CircuitState) { ## Authentication Flows + +### Zitadel Authentication Flow +```go +// Secure authentication implementation +package auth + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "fmt" + "time" + + "github.com/golang-jwt/jwt/v5" + "golang.org/x/crypto/argon2" +) + +type SecureAuthService struct { + zitadelRepo ZitadelRepository + keyStore *KeyStore + sessionManager *SessionManager + auditLogger *AuditLogger + rateLimiter *RateLimiter +} + +type AuthClaims struct { + jwt.RegisteredClaims + Email string `json:"email"` + Name string `json:"name"` + Roles []string `json:"urn:zitadel:iam:org:project:roles"` + MFAVerified bool `json:"amr"` + SessionID string `json:"sid"` + DeviceID string `json:"device_id,omitempty"` + IPAddress string `json:"ip_address,omitempty"` +} + +// Token validation with comprehensive security checks +func (s *SecureAuthService) ValidateToken(ctx context.Context, tokenString string, clientIP string) (*AuthClaims, error) { + // Rate limiting check + if !s.rateLimiter.Allow(fmt.Sprintf("token_validation:%s", clientIP)) { + s.auditLogger.LogSecurityEvent("rate_limit_exceeded", "", clientIP, "warning", map[string]interface{}{ + "operation": "token_validation", + }) + return nil, fmt.Errorf("rate limit exceeded") + } + + // Parse and validate JWT structure + token, err := jwt.ParseWithClaims(tokenString, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) { + // Verify signing algorithm + if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + + // Get key ID from header + keyID, ok := token.Header["kid"].(string) + if !ok { + return nil, fmt.Errorf("missing key ID in token header") + } + + // Retrieve public key + return s.keyStore.GetPublicKey(keyID) + }) + + if err != nil { + s.auditLogger.LogSecurityEvent("invalid_token", "", clientIP, "warning", map[string]interface{}{ + "error": err.Error(), + }) + return nil, fmt.Errorf("token validation failed: %w", err) + } + + if !token.Valid { + return nil, fmt.Errorf("invalid token") + } + + claims, ok := token.Claims.(*AuthClaims) + if !ok { + return nil, fmt.Errorf("invalid token claims") + } + + // Additional security validations + if err := s.validateTokenClaims(claims, clientIP); err != nil { + s.auditLogger.LogSecurityEvent("token_validation_failed", claims.Subject, clientIP, "warning", map[string]interface{}{ + "error": err.Error(), + }) + return nil, err + } + + // Check if session is still valid + if !s.sessionManager.IsValidSession(claims.SessionID, claims.Subject) { + s.auditLogger.LogSecurityEvent("invalid_session", claims.Subject, clientIP, "warning", map[string]interface{}{ + "session_id": claims.SessionID, + }) + return nil, fmt.Errorf("session no longer valid") + } + + // Log successful validation + s.auditLogger.LogSecurityEvent("token_validated", claims.Subject, clientIP, "info", map[string]interface{}{ + "session_id": claims.SessionID, + "roles": claims.Roles, + }) + + return claims, nil +} + +func (s *SecureAuthService) validateTokenClaims(claims *AuthClaims, clientIP string) error { + now := time.Now() + + // Check expiration + if claims.ExpiresAt != nil && claims.ExpiresAt.Time.Before(now) { + return fmt.Errorf("token expired") + } + + // Check not before + if claims.NotBefore != nil && claims.NotBefore.Time.After(now) { + return fmt.Errorf("token not yet valid") + } + + // Check issued at (prevent future tokens) + if claims.IssuedAt != nil && claims.IssuedAt.Time.After(now.Add(5*time.Minute)) { + return fmt.Errorf("token issued in the future") + } + + // Validate audience + expectedAudience := "knowfoolery-quiz-game" + if !contains(claims.Audience, expectedAudience) { + return fmt.Errorf("invalid audience") + } + + // Validate issuer + expectedIssuer := "https://auth.knowfoolery.com" + if claims.Issuer != expectedIssuer { + return fmt.Errorf("invalid issuer") + } + + // IP address validation (if configured) + if claims.IPAddress != "" && claims.IPAddress != clientIP { + return fmt.Errorf("IP address mismatch") + } + + return nil +} + +// Multi-Factor Authentication enforcement +func (s *SecureAuthService) RequireMFA(userID string, roles []string) bool { + // Admin users always require MFA + for _, role := range roles { + if role == "admin" { + return true + } + } + + // Check if user has high-value permissions + return s.hasHighValuePermissions(roles) +} + +func (s *SecureAuthService) hasHighValuePermissions(roles []string) bool { + highValueRoles := []string{"moderator", "question_manager", "user_manager"} + + for _, userRole := range roles { + for _, hvRole := range highValueRoles { + if userRole == hvRole { + return true + } + } + } + + return false +} +``` + ### Player Authentication Flow (Web/Mobile) ```typescript // Frontend authentication service diff --git a/docs/index.md b/docs/index.md index 9f006e8..0cad608 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,6 +23,22 @@ Know Foolery is a quiz game inspired by the French game "Déconnaissance" (https - **Leaderboard**: Display top 10 scores accessible to all players - **Themes**: Questions are categorized by themes (Geography, History, Science, etc.) +### Documentation + +#### Detailed requirements +- [Functional](1_requirements/functional-requirements.md) +- [Non Functional](1_requirements/non-functional-requirements.md) + +#### Architecture +- [Technical](2_architecture/technical-architecture.md) +- [Security](2_architecture/security-architecture.md) +- [Observability](2_architecture/observability-architecture.md) + +#### Guidelines +- [Development](3_guidelines/development-guidelines.md) +- [Security](3_guidelines/security-guidelines.md) +- [Observability](3_guidelines/observability-guidelines.md) + ### Future Enhancements #### Planned Features diff --git a/go.mod b/go.mod deleted file mode 100644 index e5e190f..0000000 --- a/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module knowfoolery - -go 1.25.0 - -require github.com/stretchr/testify v1.10.0 // indirect diff --git a/go.sum b/go.sum deleted file mode 100644 index 7bfdabe..0000000 --- a/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=