Notas de la review del PR #338 (mergeado, cierra #296). Ninguna era bloqueante; se registran aquí para no perderlas.
Contexto
El #338 añadió localizeBackendError (apps/web/src/lib/backend-error-messages.ts), que mapea mensajes de error del backend a copy localizado matcheando por substring/prefijo del texto en inglés de las excepciones de dominio. En la review verifiqué que los 12 patrones actuales casan con un mensaje real de apps/api — hoy funciona. El problema es la fragilidad del acoplamiento a futuro.
Problema
El contrato entre apps/api (mensaje) y apps/web (patrón) es texto libre en inglés, sin nada que los enlace:
- Si alguien reescribe el
.message de una excepción en apps/api (o añade una nueva), la web se degrada en silencio al mensaje genérico.
- Los tests de
backend-error-messages.test.ts hardcodean las mismas cadenas, así que pasan aunque el backend haya divergido → no detectan el drift.
Propuesta (por orden de preferencia)
Nota menor (UX, opcional)
Criterios de aceptación
- El mapeo de errores 4xx deja de depender de coincidencia por prosa, o bien existe un test que falla si el texto del backend cambia.
Referencias
Notas de la review del PR #338 (mergeado, cierra #296). Ninguna era bloqueante; se registran aquí para no perderlas.
Contexto
El #338 añadió
localizeBackendError(apps/web/src/lib/backend-error-messages.ts), que mapea mensajes de error del backend a copy localizado matcheando por substring/prefijo del texto en inglés de las excepciones de dominio. En la review verifiqué que los 12 patrones actuales casan con un mensaje real deapps/api— hoy funciona. El problema es la fragilidad del acoplamiento a futuro.Problema
El contrato entre
apps/api(mensaje) yapps/web(patrón) es texto libre en inglés, sin nada que los enlace:.messagede una excepción enapps/api(o añade una nueva), la web se degrada en silencio al mensaje genérico.backend-error-messages.test.tshardcodean las mismas cadenas, así que pasan aunque el backend haya divergido → no detectan el drift.Propuesta (por orden de preferencia)
codeestable en las excepciones de dominio (p.ej.NeedResourceNotInEmergencyError.code = 'resource_not_in_emergency') y devolverlo en el filtro de excepciones NestJS ({ statusCode, code, message }). La web mapea porcodeen vez de por prosa. Elimina el drift de raíz.apps/apiy afirme que su.messagesigue casando cada patrón deKNOWN_BACKEND_ERRORS, para que un cambio de texto en el backend rompa el build en vez de degradar silenciosamente en producción.offer_items_required(único sin cobertura enbackend-error-messages.test.ts).Nota menor (UX, opcional)
InventoryField/SupplyLineList) usa elinvalidRowdel último submit; si el usuario añade/elimina filas por encima antes de reenviar, el índice se desalinea y el borde rojo señala otra fila. Se autocorrige al reenviar. Se podría limpiar el resaltado en el primeronChangetras el error.Criterios de aceptación
Referencias