askill
backend-api

backend-apiSafety --Repository

Load when editing Python files in backend/, api/, routes/, services/, models/, websocket files, or alembic/. Provides FastAPI, async SQLAlchemy, WebSocket, Authentication, and Database Migration patterns.

0 stars
1.2k downloads
Updated 2/6/2026

Package Files

Loading files...
SKILL.md

Backend API

Merged Skills

  • authentication: JWT tokens, session management, OAuth flows
  • security: Input sanitization, CORS, rate limiting, XSS/CSRF protection
  • monitoring: Structured logging, metrics, tracing, health checks
  • websocket-realtime: ConnectionManager, broadcast, room management

⚠️ Critical Gotchas

CategoryPatternSolution
JSONBNested object won't saveUse flag_modified(obj, 'field') before commit
Auth401 errors on frontendCall logout() from authStore for redirect
MigrationsModel changes not appliedRun alembic upgrade head after changes
WebSocketConnection drops silentlyAlways handle WebSocketDisconnect exception
SecurityToken bypassValidate tokens server-side, never trust client
InputInjection attacksSanitize inputs, use parameterized queries
LoggingMissing contextUse structured logging with request context

Rules

RulePattern
Layer separationEndpoint → Service → Model
Type safetyAlways response_model=Schema
Async I/Oawait all DB/network calls
Auth dependencyDepends(get_current_user)
WebSocketUse ConnectionManager pattern
JSONB mutationsAlways flag_modified() after update

Avoid

❌ Bad✅ Good
DB logic in routesService layer
Mutable defaultsField(default_factory=list)
Missing typesresponse_model=Schema
Sync DB callsawait db.execute()
Direct JSONB mutationflag_modified() after change

Patterns

# Pattern 1: CRUD endpoint with proper typing
@router.get("/{id}", response_model=ItemResponse)
async def get_item(id: int, db: AsyncSession = Depends(get_db)):
    result = await db.execute(select(Item).where(Item.id == id))
    if not (item := result.scalar_one_or_none()):
        raise HTTPException(404, "Not found")
    return item

# Pattern 2: JSONB mutation (CRITICAL - must flag_modified)
from sqlalchemy.orm.attributes import flag_modified

agent.agent_metadata['key'] = value
flag_modified(agent, 'agent_metadata')  # REQUIRED
await db.commit()

# Pattern 3: WebSocket with proper disconnect handling
@router.websocket("/ws/{id}")
async def ws_endpoint(ws: WebSocket, id: str):
    await manager.connect(ws, id)
    try:
        while True:
            data = await ws.receive_json()
            await process_message(data)
    except WebSocketDisconnect:
        manager.disconnect(id)

# Pattern 4: JWT token creation
from datetime import datetime, timedelta
import jwt

def create_access_token(data: dict) -> str:
    expire = datetime.utcnow() + timedelta(minutes=15)
    return jwt.encode({**data, "exp": expire}, SECRET_KEY, algorithm="HS256")

# Pattern 5: Service layer pattern
class ItemService:
    def __init__(self, db: AsyncSession):
        self.db = db
    
    async def create(self, data: ItemCreate) -> Item:
        item = Item(**data.dict())
        self.db.add(item)
        await self.db.commit()
        return item

Alembic Migrations

TaskCommand
Create migrationalembic revision --autogenerate -m "description"
Apply migrationsalembic upgrade head
Rollback onealembic downgrade -1
View historyalembic history
Current versionalembic current

Commands

TaskCommand
Run servercd backend && uvicorn app.main:app --reload
Run testscd backend && pytest -v
Create migrationcd backend && alembic revision --autogenerate -m "msg"
Apply migrationscd backend && alembic upgrade head
Enter containerdocker exec -it nop-backend bash

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

AI review pending.

Metadata

Licenseunknown
Version-
Updated2/6/2026
Publishergoranjovic55

Tags

apici-cdobservabilitysecuritytesting