# 0004. Phase 2 Implementation Decisions Date: 2024-11-20 ## Status Accepted ## Context The Developer has raised 8 categories of implementation questions for Phase 2 that require architectural decisions. These decisions need to balance simplicity with functionality while providing clear direction for implementation. ## Decisions ### 1. Rate Limiting Implementation **Decision**: Implement actual rate limiting with in-memory storage in Phase 2. **Rationale**: Security features should be real from the start, not stubs. In-memory is simplest. **Implementation**: - Use a simple dictionary with domain as key, list of timestamps as value - Clean up old timestamps on each check (older than 1 hour) - Store in `RateLimiter` service as instance variable - No persistence needed - resets on restart is acceptable ### 2. Authorization Code Metadata Structure **Decision**: Use Phase 1's `CodeStorage` service with complete structure from the start. **Rationale**: Reuse existing infrastructure, avoid future migrations. **Implementation**: - Include `used` field (boolean, default False) even though Phase 3 consumes it - Store epoch integers for timestamps (simpler than datetime objects) - Use same `CodeStorage` from Phase 1 with authorization code keys ### 3. HTML Template Implementation **Decision**: Use Jinja2 templates with separate template files. **Rationale**: Jinja2 is standard, maintainable, and allows for future template customization. **Implementation**: - Templates in `src/gondulf/templates/` - Create `base.html` for shared layout - Individual templates: `verify_email.html`, `verify_totp.html`, `authorize.html`, `error.html` - Pass minimal context to templates ### 4. Database Migration Timing **Decision**: Apply migration 002 immediately as part of Phase 2 setup. **Rationale**: Keep database schema current with code expectations. **Implementation**: - Run migration before any Phase 2 code execution - New code assumes 'two_factor' column exists - Migration updates existing rows (if any) to have 'two_factor' = false ### 5. Client Validation Helper Functions **Decision**: Implement as standalone functions in a shared utility module. **Rationale**: Functions over classes when no state is needed. Simpler to test and understand. **Implementation**: - Create `src/gondulf/utils/validation.py` - Functions: `mask_email()`, `validate_redirect_uri()`, `normalize_client_id()` - Full subdomain validation now (not a stub) - security should be complete ### 6. Error Response Format Consistency **Decision**: Use format appropriate to the endpoint type. **Rationale**: Follow OAuth 2.0 patterns and user experience expectations. **Implementation**: - Verification endpoints (`/verify/email`, `/verify/totp`): JSON responses, always 200 OK - Authorization endpoint errors before user interaction: HTML error page - Authorization endpoint errors after client validation: OAuth redirect with error - Token endpoint (Phase 3): Always JSON ### 7. Dependency Injection Pattern **Decision**: Create `dependencies.py` with singleton services instantiated at startup. **Rationale**: Simpler than per-request instantiation, consistent with Phase 1 pattern. **Implementation**: - All services instantiated once in `dependencies.py` - Services read configuration at instantiation - FastAPI dependency injection provides same instance to all requests - Pattern: `get_code_storage()`, `get_rate_limiter()`, etc. ### 8. Test Organization for Authorization Endpoint **Decision**: Separate test files per major endpoint with shared fixtures module. **Rationale**: Easier to navigate and maintain as tests grow. **Implementation**: - `tests/test_verification_endpoints.py` - email and TOTP verification - `tests/test_authorization_endpoint.py` - authorization flow - `tests/conftest.py` - shared fixtures for common scenarios - Test complete flows, not sub-endpoints in isolation ## Consequences ### Positive - Clear, consistent patterns across the codebase - Real security from the start (no stubs) - Reuse of existing Phase 1 infrastructure - Standard, maintainable template approach - Simple service architecture ### Negative - Slightly more upfront work than stub implementations - In-memory rate limiting loses state on restart - Templates add a dependency (Jinja2) ### Neutral - Following established patterns from other web frameworks - Committing to specific implementation choices early