Files
Gondulf/docs/decisions/0004-phase-2-implementation-decisions.md
Phil Skentelbery 6f06aebf40 docs: add Phase 2 domain verification design and clarifications
Add comprehensive Phase 2 documentation:
- Complete design document for two-factor domain verification
- Implementation guide with code examples
- ADR for implementation decisions (ADR-0004)
- ADR for rel="me" email discovery (ADR-008)
- Phase 1 impact assessment
- All 23 clarification questions answered
- Updated architecture docs (indieauth-protocol, security)
- Updated ADR-005 with rel="me" approach
- Updated backlog with technical debt items

Design ready for Phase 2 implementation.

Generated with Claude Code https://claude.com/claude-code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 13:05:09 -07:00

4.3 KiB

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