Overrun API
API REST Flask con integración a OpenAI/OpenRouter, autenticación JWT + MFA (TOTP), chat streaming SSE, file upload, WebSocket typing indicators, logout real con token blacklist, password reset, y arquitectura limpia.
Stack
| Capa |
Tecnología |
| Framework |
Flask (app factory) |
| ORM |
SQLAlchemy 2.0 |
| DB |
SQLite (dev) / PostgreSQL (prod) |
| Auth |
JWT + MFA TOTP (pyotp) + JTI blacklist + OTP email |
| Validación |
Marshmallow |
| AI Providers |
OpenAI SDK / OpenRouter HTTP / Mock + streaming SSE |
| File Upload |
Multipart, extensiones configurables, ownership checks |
| WebSocket |
SocketIO (typing indicators, opt-in) |
| Security |
Bcrypt, CSP, HSTS, X-Frame-Options, rate limiting |
Arquitectura
graph TD
Client["Cliente"] --> API["REST API /api/v1"]
Client --> WS["WebSocket /socket.io"]
API --> Auth["Auth Routes"]
API --> Chat["Chat Routes"]
API --> Files["File Routes"]
API --> Health["Health Route"]
Auth --> AuthSvc["Auth Service"]
AuthSvc --> UserRepo["User Repository"]
AuthSvc --> OTPSvc["OTP Service"]
AuthSvc --> MFASvc["MFA (TOTP)"]
AuthSvc --> Blacklist["TokenBlacklist"]
Chat --> ConvRepo["Conversation Repository"]
Chat --> MsgRepo["Message Repository"]
Chat --> AISvc["AI Service"]
AISvc --> OpenAI["OpenAI Provider"]
AISvc --> OpenRouter["OpenRouter Provider"]
AISvc --> Mock["Mock Provider"]
Files --> AttachRepo["Attachment Repository"]
Files --> UploadDir[("uploads/")]
WS --> ChatNS["ChatNamespace"]
ChatNS --> ConvRepo
UserRepo --> DB[("SQLite / PostgreSQL")]
OTPSvc --> OTPRepo["OTP Repository"]
OTPRepo --> DB
ConvRepo --> DB
MsgRepo --> DB
Blacklist --> DB
classDef api fill:#2b5797,color:#fff
classDef svc fill:#0078d4,color:#fff
classDef repo fill:#4a4a4a,color:#fff
classDef prov fill:#2e7d32,color:#fff
classDef db fill:#6a1b9a,color:#fff
classDef client fill:#e65100,color:#fff
class API,Auth,Chat,Files,Health api
class AuthSvc,OTPSvc,AISvc,MFASvc svc
class UserRepo,OTPRepo,ConvRepo,MsgRepo,Blacklist,AttachRepo repo
class OpenAI,OpenRouter,Mock prov
class WS,ChatNS client
class UploadDir db
class DB db
class Client client
Quick Start
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# edit .env → set AI_PROVIDER, API keys
python run.py # REST only (dev)
python run_ws.py # REST + WebSocket (dev, gevent)
Endpoints
Auth
| Método |
Ruta |
Descripción |
| POST |
/api/v1/auth/register |
Registrar usuario |
| POST |
/api/v1/auth/login |
Login (username/email/phone) |
| POST |
/api/v1/auth/refresh |
Refrescar access token |
| GET |
/api/v1/auth/me |
Perfil actual |
| PUT |
/api/v1/auth/me |
Editar perfil (username/email/phone) |
| PUT |
/api/v1/auth/me/password |
Cambiar contraseña |
| DELETE |
/api/v1/auth/me |
Eliminar cuenta (soft-delete) |
| POST |
/api/v1/auth/logout |
Logout real (revoca JTI) |
| POST |
/api/v1/auth/otp/send |
Enviar OTP por email |
| POST |
/api/v1/auth/otp/verify-email |
Verificar email con OTP |
| POST |
/api/v1/auth/password-reset/request |
Solicitar reset de contraseña |
| POST |
/api/v1/auth/password-reset/confirm |
Confirmar reset con OTP |
| POST |
/api/v1/auth/mfa/enroll |
Generar secreto TOTP |
| POST |
/api/v1/auth/mfa/verify |
Activar MFA |
| POST |
/api/v1/auth/mfa/verify-login |
Verificar MFA en login |
Chat
| Método |
Ruta |
Descripción |
| GET |
/api/v1/chat/models |
Listar modelos AI disponibles |
| GET |
/api/v1/chat/conversations |
Listar conversaciones |
| POST |
/api/v1/chat/conversations |
Crear conversación |
| GET |
/api/v1/chat/conversations/<id> |
Ver conversación + mensajes |
| PATCH |
/api/v1/chat/conversations/<id> |
Renombrar conversación |
| DELETE |
/api/v1/chat/conversations/<id> |
Eliminar conversación |
| POST |
/api/v1/chat/conversations/<id>/messages |
Enviar mensaje (+ streaming SSE) |
| PATCH |
/api/v1/chat/conversations/<id>/messages/<msg> |
Editar mensaje |
| DELETE |
/api/v1/chat/conversations/<id>/messages/<msg> |
Borrar mensaje |
Files
| Método |
Ruta |
Descripción |
| POST |
/api/v1/files/upload |
Subir archivo (multipart) |
| GET |
/api/v1/files/<id> |
Descargar archivo |
Health
| Método |
Ruta |
| GET |
/api/v1/health |
Features
- Chat streaming SSE — enviar
"stream": true en mensaje para recibir tokens via Server-Sent Events
- File upload — subir archivos (multipart), referenciar por ID al enviar mensajes
- WebSocket typing indicators — opt-in con
USE_WEBSOCKET=true, requiere worker gevent
- Logout real — revoca el JWT via
TokenBlacklist (JTI blacklist), tokens revocados son rechazados
- Password reset — flujo request + confirm via OTP, reusa el sistema de email existente
- Rate limit storage — intercambiable via
RATELIMIT_STORAGE_URL (memory:// por defecto, redis:// para Redis/Valkey)
- Registro bloqueable —
ALLOW_REGISTRATION=false desactiva nuevos registros
Documentación
| Recurso |
Descripción |
sample.http |
Quick start con REST Client (VS Code) |
docs/api-reference.md |
Schemas request/response, errores, seguridad, WebSocket |
docs/auth-flow.md |
Flujo auth: dev vs prod, MFA TOTP, JWT, OTP, password reset |
docs/development.md |
Guía dev: agregar endpoints, providers, WebSocket, convenciones |
docs/openapi.yaml |
OpenAPI 3.1 spec (28 paths, servida en /api/v1/openapi.json) |
Docker
docker compose up -d # PostgreSQL + MailHog + App
docker compose logs -f app
docker compose down
WebSocket en producción: USE_WEBSOCKET=true docker compose up -d
Tests
FLASK_ENV=test python -m pytest tests/ -v
Security (OWASP)
- CSP, HSTS, X-Frame-Options, X-Content-Type-Options en toda respuesta
- Input validation + sanitización (bleach) en toda entrada usuario
- Passwords hasheados con bcrypt
- OTP codes hasheados con SHA-256, max 5 intentos
- Rate limiting: 100 req/hora por IP (configurable)
- JWT en headers, expiración corta, MFA step-up token 5min
- JTI blacklist: tokens revocados en logout son rechazados automáticamente
- CORS restringido a orígenes configurados
License
AGPL-3.0