Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:29:15 +08:00
commit be476a3fea
76 changed files with 12812 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
# API Design Reference Index
**All reference files are under 500 lines for optimal loading.**
## Available References
- **[fastapi-setup.md](fastapi-setup.md)** - Main FastAPI configuration
- **[openapi.md](openapi.md)** - OpenAPI customization
- **[error-handlers.md](error-handlers.md)** - Exception handlers
- **[authentication.md](authentication.md)** - JWT configuration
- **[cors-rate-limiting.md](cors-rate-limiting.md)** - CORS and rate limiting

View File

@@ -0,0 +1,24 @@
# Authentication Configuration
**JWT setup with bcrypt password hashing.**
```python
# app/core/auth.py
import jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
import os
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY")
JWT_ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(user_id: str, tenant_id: str) -> str:
expire = datetime.utcnow() + timedelta(minutes=30)
return jwt.encode({"sub": user_id, "tenant_id": tenant_id, "exp": expire}, JWT_SECRET_KEY, algorithm=JWT_ALGORITHM)
def hash_password(password: str) -> str:
return pwd_context.hash(password)
```
**Doppler:** `JWT_SECRET_KEY` must be set in Doppler secrets.

View File

@@ -0,0 +1,26 @@
# CORS and Rate Limiting
**CORS middleware and Upstash Redis rate limiter.**
## CORS
```python
allowed_origins = os.getenv("CORS_ALLOWED_ORIGINS", "").split(",")
app.add_middleware(CORSMiddleware, allow_origins=allowed_origins, allow_credentials=True)
```
**Doppler:** `CORS_ALLOWED_ORIGINS="https://app.example.com"`
## Rate Limiting
See [../templates/rate-limiter.py](../templates/rate-limiter.py) for full implementation.
```python
from app.core.rate_limit import rate_limit_normal
@router.get("", dependencies=[Depends(rate_limit_normal)])
async def list_users():
pass # Rate limited to 100 req/min
```
**Doppler:** `REDIS_URL` must be set for Upstash Redis.

View File

@@ -0,0 +1,17 @@
# Error Handlers
**Complete exception handler configuration.**
See [../templates/error-handler.py](../templates/error-handler.py) for full implementation.
```python
async def http_exception_handler(request, exc):
return JSONResponse(status_code=exc.status_code, content={"error": exc.detail, "status_code": exc.status_code})
async def validation_exception_handler(request, exc):
errors = [{"field": ".".join(str(loc) for loc in e["loc"]), "message": e["msg"], "code": e["type"]} for e in exc.errors()]
return JSONResponse(status_code=422, content={"error": "Validation error", "detail": errors, "status_code": 422})
app.add_exception_handler(HTTPException, http_exception_handler)
app.add_exception_handler(RequestValidationError, validation_exception_handler)
```

View File

@@ -0,0 +1,34 @@
# FastAPI Setup
**Complete main application configuration.**
```python
# app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import os
app = FastAPI(
title="Grey Haven API",
description="RESTful API for multi-tenant SaaS",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
)
# CORS
allowed_origins = os.getenv("CORS_ALLOWED_ORIGINS", "").split(",")
app.add_middleware(CORSMiddleware, allow_origins=allowed_origins, allow_credentials=True)
# Exception handlers (see error-handlers.md)
# app.add_exception_handler(...)
# Include routers
app.include_router(users.router)
@app.get("/health")
async def health_check():
return {"status": "healthy"}
```
**Doppler config:** `doppler run --config dev -- uvicorn app.main:app --reload`

View File

@@ -0,0 +1,17 @@
# OpenAPI Customization
**Custom OpenAPI schema with security.**
```python
def custom_openapi(app):
openapi_schema = get_openapi(title=app.title, version=app.version, routes=app.routes)
openapi_schema["components"]["securitySchemes"] = {
"BearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}
}
openapi_schema["security"] = [{"BearerAuth": []}]
return openapi_schema
app.openapi = lambda: custom_openapi(app)
```
Access docs at `/docs` (Swagger UI) or `/redoc` (ReDoc).