Arquitectura · A2 · Contrato y tipos
El bug más común de un front y un back separados es que sus tipos se desincronizan. Acá no puede pasar: el backend define el contrato una vez, y el tipado del frontend se genera solo. Nadie escribe un tipo de cliente a mano.
Un tipo nace una vez, en Pydantic, y desciende hasta los componentes sin intervención manual. Cada flecha es automática.
generated/schema.ts. La única excepción son los tipos puramente del cliente (estado de UI, props internas).Los tipos generados garantizan la estructura, pero no validan valores en runtime (rangos, regex). Para eso, un espejo en Zod al lado de cada formulario.
El Zod es UX, no seguridad: da feedback inmediato en el form antes de enviar. Si Zod y Pydantic divergen, el server rechaza igual y el frontend muestra el error — el backend nunca confía en la validación del cliente. Sus reglas deben espejar los Field(...) del Pydantic.
Un comando regenera todo el puente; el compilador de TypeScript hace de red de seguridad.
El JSON y el schema.ts viajan en el repo: los revisores ven los cambios de API en el diff y el CI no necesita levantar el backend para chequear tipos. Un cambio de contrato que olvide regenerar rompe el build — no llega a producción.
La misma idea de fuente única aplicada al texto visible: el backend nunca devuelve frases traducidas, devuelve códigos, y el catálogo del frontend es el dueño de las etiquetas.
ES es el default; ES/EN se soportan por cookie, sin el idioma en la URL. Las dos catálogos deben tener exactamente las mismas keys — una key faltante en en.json mostraría la key cruda al usuario. Nada de texto visible hardcodeado en el JSX: si se tipea una frase, va al catálogo.
La API está versionada (/api/v1). Qué se puede cambiar sin romper, y qué obliga a migrar.
| Cambio | Requiere |
|---|---|
| Non-breaking — agregar endpoint, o campo opcional con default | Nada. Va directo. |
| Breaking — renombrar/eliminar campo o endpoint, cambiar tipo o significado | Plan de migración o /api/v2. |
En pre-producción, sin clientes externos todavía, está OK romper v1 — pero se documenta en el commit. La disciplina no es burocracia: es lo que permite que el frontend confíe ciegamente en los tipos generados.
Viene de A1 (forma y stack). Sigue en A3: la separación dominio/servicio que hace cada cálculo una unidad aislada.
Fuente: webapp/ARCHITECTURE.md §3 (SSOT schemas), §4 (versionado), §7 (i18n).