Initial commit
This commit is contained in:
11
skills/api-design-standards/reference/INDEX.md
Normal file
11
skills/api-design-standards/reference/INDEX.md
Normal 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
|
||||
24
skills/api-design-standards/reference/authentication.md
Normal file
24
skills/api-design-standards/reference/authentication.md
Normal 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.
|
||||
26
skills/api-design-standards/reference/cors-rate-limiting.md
Normal file
26
skills/api-design-standards/reference/cors-rate-limiting.md
Normal 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.
|
||||
17
skills/api-design-standards/reference/error-handlers.md
Normal file
17
skills/api-design-standards/reference/error-handlers.md
Normal 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)
|
||||
```
|
||||
34
skills/api-design-standards/reference/fastapi-setup.md
Normal file
34
skills/api-design-standards/reference/fastapi-setup.md
Normal 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`
|
||||
17
skills/api-design-standards/reference/openapi.md
Normal file
17
skills/api-design-standards/reference/openapi.md
Normal 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).
|
||||
Reference in New Issue
Block a user