# 0001. Python Framework Selection for IndieAuth Server Date: 2025-11-20 ## Status Proposed ## Context We need to select a Python web framework for implementing the IndieAuth server. The requirements are: 1. Must support OAuth 2.0/IndieAuth protocol implementation 2. Must be simple and maintainable (avoiding Django per user requirement) 3. Must handle async operations efficiently 4. Must have good security features 5. Must be production-ready and well-maintained 6. Must not add unnecessary complexity We evaluated several Python web frameworks considering our core value of simplicity. ## Decision **Recommended Stack:** ### Web Framework: FastAPI FastAPI is the recommended framework for this project. **Rationale:** - **Simplicity with Power**: Clean, Pythonic API design that doesn't hide complexity - **Type Hints**: Native support for Python type hints with automatic validation - **OAuth 2.0 Ready**: Built-in OAuth 2.0 support that we can adapt for IndieAuth - **Async First**: Native async/await support for better performance - **Automatic Documentation**: OpenAPI/Swagger documentation generated automatically - **Modern Python**: Requires Python 3.10+ which aligns with our standards - **No Magic**: Explicit routing and dependency injection, no hidden behavior - **Production Ready**: Used by Microsoft, Netflix, Uber - battle-tested ### Data Storage: SQLite with SQLAlchemy Core **Rationale:** - **Simplicity**: SQLite for single-admin use case is perfect - **SQLAlchemy Core**: Direct SQL-like interface without ORM complexity - **No Migrations Needed Initially**: Simple schema we can manage directly - **Upgrade Path**: Can switch to PostgreSQL later if needed without code changes ### Additional Libraries: - **python-jose[cryptography]**: For JWT token handling if needed - **python-multipart**: For form data handling - **httpx**: For HTTP client operations (fetching client metadata) - **pydantic**: Data validation (comes with FastAPI) - **python-dotenv**: Environment variable management - **uvicorn**: ASGI server for running FastAPI ## Alternatives Considered ### Flask - **Pros**: Minimal, mature, extensive ecosystem - **Cons**: Requires many extensions, no native async, more boilerplate for our needs ### Starlette (FastAPI's base) - **Pros**: Even more minimal than FastAPI - **Cons**: Would need to build too much ourselves, against our simplicity principle ### Tornado - **Pros**: Good async support, mature - **Cons**: Older patterns, less modern Python features, smaller ecosystem ### aiohttp - **Pros**: Excellent async support - **Cons**: Lower-level, would require more custom code for OAuth flows ## Consequences ### Positive Consequences 1. **Rapid Development**: FastAPI's automatic validation and documentation saves time 2. **Type Safety**: Type hints catch errors early 3. **Clear Architecture**: Explicit dependency injection makes data flow obvious 4. **Good Testing**: FastAPI has excellent testing support with TestClient 5. **Performance**: Async support handles concurrent requests efficiently 6. **Maintainability**: Clear, explicit code that's easy to understand ### Negative Consequences 1. **Newer Framework**: FastAPI is newer than Flask (but very stable) 2. **Async Complexity**: Developers need to understand async/await 3. **Fewer Examples**: Fewer IndieAuth examples in FastAPI than Flask ### Mitigation Strategies 1. Use sync functions where async isn't needed - FastAPI supports both 2. Provide clear documentation and examples 3. Start with simple synchronous code, add async where beneficial ## Implementation Plan ### Basic Application Structure ```python from fastapi import FastAPI, Depends, HTTPException from fastapi.security import OAuth2AuthorizationCodeBearer app = FastAPI(title="IndieAuth Server") # Authorization endpoint @app.get("/auth") async def authorization_endpoint( response_type: str, client_id: str, redirect_uri: str, state: str, code_challenge: Optional[str] = None, code_challenge_method: Optional[str] = None ): """Handle IndieAuth authorization requests.""" pass # Token endpoint @app.post("/token") async def token_endpoint( grant_type: str, code: str, client_id: str, redirect_uri: str, code_verifier: Optional[str] = None ): """Exchange authorization code for access token.""" pass # Client registration endpoint @app.post("/client/register") async def client_registration_endpoint( client_name: str, redirect_uris: List[str] ): """Allow clients to self-register.""" pass ``` This structure is clean, explicit, and follows the IndieAuth specification closely. ## Recommendation FastAPI provides the best balance of simplicity, modern features, and production-readiness for our IndieAuth server implementation. It aligns perfectly with our core value of simplicity while providing all necessary features for a compliant implementation.