0017 — Contrato de erro único {code, message}¶
Decisão obsoleta — superada pela decisão 0021
Status: Obsoleto · Responsável: Gustavo Madruga · Atualizado em: 2026-06-19 · Decidido em: 2026-06-17
Superada pela decisão 0021: o app alinhou ao default da casa (RFC 7807). O contrato de erro hoje é
application/problem+json.
Contexto¶
A API tinha três formatos de corpo de erro convivendo: o Hateoas default do
Micronaut ({message, _links, _embedded}) nas HttpStatusException; um envelope
ad-hoc {error, message} no login; e o status-no-corpo do /processar
(ProcessamentoResponse.httpStatus). Não havia ponto único de tradução, nem
Bean Validation — toda validação era if manual. Cliente recebia formato
diferente conforme o endpoint.
Decisão¶
- Corpo de erro único
{code, message}(ErrorResponse), renderizado num ponto só peloUnifiedErrorResponseProcessor(@ReplacesdoHateoasErrorResponseProcessor). CobreHttpStatusException, falhas de validação, 404 de rota e parse de JSON.codeé estável/legível por máquina (ex.:CONFLICT); o status HTTP vai na resposta. OAuthExceptionganha umExceptionHandler(rede de segurança). - Bean Validation ativado nos pontos limpos (
@Positivenowait_secs,@Sizenomotivo). A trilha de segurança do login (CSRF constant-time, limite de token) fica manual de propósito: convertê-la em constraints reordenaria a sequência de checagem (CSRF-first) e genericizaria os códigos estáveis (csrf_mismatch,token_too_large). Migra junto do login no micronaut-security.
Consequências¶
- Contrato de erro consistente e descobrível; um teste fixa o
{code, message}em 404/400 (não existia teste de corpo de erro antes). - O corpo público do
/processarfoi preservado (status2xxmantém o corpo de negócio, nunca ocode; ohttpStatussegue interno, nunca serializado) — nenhum cliente quebra. - Validação declarativa onde cabe; o resto (parse de data/hora, segurança) permanece manual por ser parse de formato ou ordem-sensível.
Alternativas consideradas¶
- RFC 7807 / ProblemDetail: mais completo, mas o
{code, message}já unifica e reaproveita ocodeestável que o login expunha. Descartado por simplicidade. - Push completo de Bean Validation (inclusive login): descartado — degrada a trilha de segurança sem ganho real (ver acima).