Con el CRUD de catálogos y productos del hito 04, la API ya existe y es exactamente la del contrato; lo que falta es rechazar correctamente lo que no admite. Este hito aplica el tema 03 — Validación e invariancias: dos preguntas distintas, respondidas en lugares distintos.
| Pregunta | Dónde se responde | Mecanismo | Respuesta |
|---|---|---|---|
| ¿Cumple la petición el formato del contrato? | La petición de entrada, en la capa de presentación | Jakarta Validation | 400 con campo y motivo |
| ¿El estado propuesto es válido para el negocio? | El dominio | Invariantes en los modelos | Excepción de dominio, mapeada al error del contrato |
openapi.yaml (v0.1.1) con lo que la API admite: los constraints se redactan en el propio documento, porque describen el contrato, no el código.| Esquema | Constraint |
|---|---|
CatalogRequest.name | minLength 1 · maxLength 80 |
CatalogRequest.description | maxLength 240 |
ProductRequest.name | minLength 1 · maxLength 80 |
ProductRequest.description | maxLength 240 |
ProductRequest.price | minimum 0.01 · maximum 999999.99 |
ProductRequest.stock | minimum 0 · maximum 100000 |
ProductRequest.catalogId | minimum 1 |
Problem que el contrato declara, materializado.La petición válida según el contrato puede seguir proponiendo un estado imposible para el negocio: el precio y el stock deben protegerse en el dominio.
domain, según la especificación: Money (precio: decimal mayor que cero, escala de 2) y Stock (entero no negativo). Cada uno valida en su construcción y lanza la excepción de dominio propia.Product pasa a componerse con ellos; la creación y la modificación de productos construyen primero los value objects: si una invariante falla, el estado inválido nunca llega a la persistencia.minimum en el contrato (formato) y la validación del Money (invariante). No es redundancia: protegen fronteras distintas, como explica el tema.Money, no solo para el flujo que llega validado.
Criterios de prueba de este nivel, según el tema: qué probar y qué aislar.
Money y Stock construidos dentro de rango y rechazados fuera; sin Spring, sin base de datos.catalogId desconocido no se llega a crear, y un producto inexistente al modificar o borrar falla con la excepción de dominio correspondiente.Money con precio 0 lanza la excepción de dominio.Problem del contrato.hito-05.Siguiente hito: hito 06 — Módulos: pedidos y API pública.