Saltar a contenido

Stack de la vertical y cumplimiento de los estándares

Qué prescriben SV Backend §1 y SV Frontend §1, qué adopta de verdad el monorepo, y qué adopta muebles. Medido contra los 17 workspaces el 2026-08-29.

El hallazgo

Los estándares prescriben un stack de ~30 tecnologías por capa. Medido contra el código real, se parte en tres niveles muy distintos, y tratarlos igual es cómo se acaba adoptando un broker de mensajes para servir un catálogo.


Nivel A — Universal. Innegociable, se adopta entero

Adoptado por las tres verticales de producción. No hay discusión ni ADR posible.

Capa Tecnología Adopción
Lenguaje Python 3.13+ 3/3
Gestor de paquetes uv + uv.lock 10 lockfiles en el repo
Framework FastAPI 3/3
ORM SQLAlchemy 2.0 async, sintaxis select() 3/3 · cero db.query() legacy
Driver asyncpg 3/3
Migraciones Alembic + migration-cycle en CI 3/3
Validación Pydantic v2 + pydantic-settings 3/3
Caché / rate limit Redis 7 (redis-py async) + slowapi 3/3
Logging structlog JSON 3/3
Linter Ruff 3/3
Tipado mypy --strict en CI 3/3
SAST Bandit + pip-audit 3/3
Testing pytest + pytest-asyncio + httpx 3/3 · 1.497 pruebas
Contenedor Docker multistage 3/3
Proxy Traefik 3/3
CI GitHub Actions 20 workflows

Muebles adopta los 16.


Nivel B — Adoptado por los buenos, no por todos

Aquí es donde se separa una vertical seria de una que solo funciona.

Tecnología Adopción ¿Muebles?
OpenTelemetry + Sentry 8 de 9 backends — falta en Events ✅ desde el primer commit
Testcontainers 5 pyproject ✅ pruebas contra Postgres real
respx (mocks HTTP) 4 pyproject ✅ la pasarela de crédito se prueba sin red
react-hook-form + Zod 13 package.json — el más adoptado
Vitest 11
Playwright (E2E) 8
nuqs (estado en URL) 7 ✅ el filtro del catálogo vive en la URL o no se comparte
MSW 5
Storybook 5 ✅ el catálogo es un design system
Radix UI 4 ✅ el selector de variantes necesita teclado resuelto
XState 4 ⚠️ solo si el separado supera 3 estados
openapi-ts 2 ✅ — ver abajo

La regla más incumplida y más valiosa

El estándar dice: «HTTP client generado desde OpenAPI. Cero código manual de fetching.» Solo 2 de 8 frontends lo hacen.

Para muebles no es opcional. El contrato del catálogo —producto, variantes, tipos de opción, medidas, materiales, financiación— es el payload más grande del monorepo. Escribirlo a mano en TypeScript garantiza que se desincronice del backend. Y el gate de deriva de OpenAPI ya existe en CI: se genera el cliente desde el mismo openapi.json que CI verifica con git diff --exit-code.


Nivel C — Prescrito y adoptado por nadie

Cero adopción en 17 workspaces. No es descuido: es que el monorepo no ha necesitado ninguna.

Tecnología Adopción Veredicto para muebles
NATS / RabbitMQ 0 No. Un catálogo no tiene eventos de dominio entre servicios. Adoptarlo sería sobreingeniería con nombre de estándar
Celery 0 · ARQ 1 No. El patrón de la casa es background_tasks.py de Travel, con referencia fuerte para que el GC no mate la task a medias
Temporal 0 No. No hay sagas
Granian 0 No. Uvicorn, como todos
Vault / Infisical / Doppler 0 ⚠️ Brecha real de todo el monorepo. Todo secreto vive en .env. Muebles no lo resuelve sola, pero tampoco lo empeora: pydantic-settings con SecretStr, listo para migrar

Regla que dejo escrita: una tecnología de Nivel C solo entra con ADR que demuestre la necesidad. Estar en la tabla del estándar no es justificación.


El apéndice del estándar está vencido

SV_Standard_Frontend Apéndice A se titula «Q2 2026» y el repo ya lo superó:

Paquete Dice el apéndice Corre el repo
Vite ^6.0.0 8.x
Next.js 15 16.3
Zod ^3.24.0 4.x
TypeScript ^5.7.0 6.0
Storybook ^8.5.0 9.x

Muebles sigue las versiones del repo, no las del apéndice. Nacer con Vite 6 sería nacer con dos majors de retraso para cumplir un documento vencido. Queda anotado en TECH_DEBT.md del monorepo que el apéndice necesita refresco trimestral, que es lo que él mismo exige.


Stack final de muebles

Backend: Python 3.13 · FastAPI · SQLAlchemy 2.0 async · asyncpg · Alembic · Pydantic v2 · Redis + slowapi · structlog · OTEL + Sentry · aioboto3 (R2) · Pillow · uv con pyproject.toml como fuente única (sin requirements.txt) · ruff · mypy strict · bandit · pip-audit · pytest + asyncio + httpx + Testcontainers + respx + schemathesis.

Frontend admin: Vite 8 · React 19 · TS 6 · Tailwind 4 · TanStack Query 5 · Zustand · RHF + Zod 4 · Radix · nuqs · Vitest + MSW + Playwright · Storybook.

Frontend showroom: Next.js 16 App Router · el mismo núcleo · cliente HTTP generado desde OpenAPI.

Toda desviación exige ADR. Y lo que no está aquí no se instala «porque el estándar lo menciona».