Pular para conteúdo

0019 — O painel de Consulta de crédito usa a cor de aprovação para um resultado que não aprova nada

Status CORRIGIDO
Branch fix/0019-cor-verde-painel-consulta-credito
Aberto em 2026-09-07
Severidade BAIXA
Apps afetados web
Revisão do diagnóstico —
Revisão da correção —

Status: RASCUNHO → DIAGNOSTICADO → EM CORREÇÃO → CORRIGIDO

1. Sintoma

No painel "Consulta de crédito" (BureauInquiryPanel, spec 0050) — mostrado na tela de Análise de Crédito (/credit-analyses/:id) e na do Inquilino (/renters/:id) — quando a consulta automática ao bureau termina sem nenhuma restrição encontrada, o cabeçalho, o título e o selo ("SEM RESTRIÇÃO") aparecem em verde. O usuário aponta que essa cor lê como "aprovado", quando o painel é só informativo e não decide nada sobre a análise.

2. Reprodução

  1. Abrir uma Análise de Crédito (ou um Inquilino) cujo locatário principal tenha consulta de bureau concluída com status: SUCCESS e nenhuma pendência financeira, protesto ou cheque sem fundo.
  2. Observar o cabeçalho do painel "Consulta de crédito": fundo, título e selo "SEM RESTRIÇÃO" em verde (theme.palette.success).

  3. Ambiente: qualquer (local, dev-remote, produção) — é estilo estático, não depende de dado além do estado "sem restrição".

  4. Superfície: desktop e mobile — a cor vem do mesmo cálculo de tone nos dois viewports; não é layout, é token de cor.
  5. Dados/pré-condições: usuário com acesso ao painel (garantidora, não AGENCY_USER — ver a nota de identidade em BureauInquiryPanel.tsx:63-69), consulta com status: SUCCESS e sem restrições.

3. Esperado × Atual

  • Esperado: a cor do estado "sem restrição" deveria comunicar "dado neutro, informativo" — coerente com o que o próprio componente documenta sobre si mesmo (RN8: só informa, não decide) — não "aprovado".
  • Atual: o estado "sem restrição" usa o token semântico success, que no design system do app tem significado próprio e documentado de aprovação (contrato ativo), não de informação neutra.

4. Causa raiz

  • Onde: apps/web/src/components/shared/BureauInquiryPanel.tsx:305

    const tone: "success" | "error" | "secondary" =
      pending || failed ? "secondary" : (temRestricao ? "error" : "success");
    
    Esse tone alimenta o fundo do cabeçalho (:376), a cor do SectionLabel (:382) e a cor do selo (:394), todos via theme.palette[tone].main.

  • O mecanismo: quando a consulta termina sem restrição, tone recebe "success", que resolve para theme.palette.success.main (#2E7D32 no tema claro — ver apps/web/src/design-system/theme/palette.ts:60). O token feedback.success do design system tem semântica documentada e específica: "aprovação, contrato ativo" (docs/design-tokens.md:70) — não "dado neutro". O próprio comentário do componente (BureauInquiryPanel.tsx:88-90) afirma que o painel "é só informativo (RN8, spec 0050)" e que "não altera credit_recommendation" — a decisão de crédito continua sendo de quem analisa. Ou seja: o código já sabe, por escrito, que este painel não aprova nada, mas pinta o resultado mais favorável com o token reservado para aprovação. É essa divergência entre o que a cor diz e o que o sistema faz que produz o sintoma relatado.

O design system já tem o token certo para este caso: feedback.info (ciano, #00ACF0), documentado como "dado e informação neutra" / "dado, aviso neutro (severidade padrão)" (docs/design-tokens.md:41,55,73), disponível no tema como theme.palette.info.main (apps/web/src/design-system/theme/palette.ts:66,100, presente nos dois modos). O próprio BureauInquiryPanel já usa a variante deste token para texto/ícone (theme.garantora.infoInk) no círculo do diálogo de explicação (:209-212) — é o mesmo vocabulário de cor que o painel usa em outro lugar para dizer "isto é informação".

  • O alcance: o tone é calculado uma vez e consumido pelas três referências citadas acima, dentro do mesmo componente compartilhado. Como o BureauInquiryPanel é usado sem variação nas duas telas que o exibem — apps/web/src/pages/credit-analyses/show.tsx:1137 e apps/web/src/pages/renters/show.tsx:290 —, a mesma causa produz o mesmo sintoma nas duas, e a correção num único ponto (a expressão de tone) resolve as duas. Não há terceiro consumidor: os únicos dois usos do componente no repositório são estes. O estado "com restrição" (error, vermelho) não é afetado — é sinal de risco real, e o usuário confirmou que o escopo é só o estado "sem restrição".

5. Revisão do diagnóstico

Preenchido pelo laço do /fix new, rubrica .claude/rubrics/diagnostico.md. Registrar todas as rodadas, inclusive as reprovadas.

Rodada Critical Important Minor Veredicto
1 0 0 0 Aprovado (nota 10/10)

Resultado: aprovado na rodada 1.

Pendências aceitas: nenhuma.

6. Correção

apps/api

Sem impacto — o backend não tem noção de cor; bureau_inquiry/credit_bureau chega ao front só com os dados (score, pendências, etc.), sem campo de apresentação.

apps/web

  • Onde: apps/web/src/components/shared/BureauInquiryPanel.tsx — expressão de tone (linha ~305) e o tipo da constante.
  • O quê: trocar "success" por "info" no ramo "sem restrição" (mantendo "error" para "com restrição" e "secondary" para pendente/falha), e ajustar o tipo de tone para incluir "info". theme.palette.info já existe nos dois modos de tema — não precisa de token novo.
  • data-testid: nenhum novo — é troca de cor, não de estrutura.
  • Responsividade & PWA: é token de cor lido pelo tema; vale igual em qualquer viewport. Como o app é PWA, a validação em ambiente com service worker exige reabrir a tela instalada para não medir o bundle antigo em cache.

apps/e2e

Sem impacto de asserção nova — nenhum spec hoje afirma a cor do selo por classe ou estilo computado (conferido em apps/e2e/tests/e2e/analise-credito-boavista.spec.ts, que verifica texto e presença/ausência do painel, não cor).

7. Risco / impacto colateral

Mudança isolada a um token de apresentação, sem lógica de negócio, sem cálculo e sem permissão envolvidos. O único risco é visual: confirmar que o ciano de feedback.info mantém contraste adequado como fundo tingido a 8% (mesma fórmula alpha(...) já usada para os outros tons) e que o texto/selo em info.main permanece legível nos dois temas — o próprio componente já usa esse ciano em outro elemento (círculo do diálogo de explicação), então não é uma cor nova na tela.

8. Critérios de aceite

  • [x] CA1. Numa Análise de Crédito ou Inquilino com bureau SUCCESS e sem restrição, o cabeçalho, o título e o selo "SEM RESTRIÇÃO" do painel aparecem em ciano (feedback.info), não em verde. Verificado contra o dev-remote (renter real, dado migrado): cor computada do selo rgb(0, 172, 240) = #00ACF0 = feedback.info, nos dois viewports. Print em docs/fixes/assets/0019-cor-verde-painel-consulta-credito/.
  • [x] CA2. O estado "com restrição" continua vermelho (feedback.error), e os estados "consultando"/"não concluída" continuam neutros (secondary) — inalterados. Não há registro real com restrição na base do dev-remote (modo sandbox devolve sempre o mesmo resultado fixo, sem restrição) — verificado por leitura do diff: a expressão de tone só mudou o ramo sem restrição; os ramos error/secondary não foram tocados, e os 6 casos do BureauInquiryPanel.test.tsx (que cobrem PENDING/SUCCESS/FAILED) continuam verdes.
  • [x] CA3. A mudança vale nas duas telas que usam o componente (Análise de Crédito e Inquilino). Verificado via renters/show (dado real); credit-analyses/show usa o mesmo componente compartilhado com o mesmo tone, sem variação — e o teste unitário daquela tela (13 casos) segue verde. Desktop (1440px) e mobile (375px) verificados; tema escuro não testado ao vivo (o dev-remote não tem toggle de tema nesta sessão), mas theme.palette.info existe nos dois modos (palette.ts:66,100), mesmo padrão de success/error já em uso.

9. Plano

  • [x] Não há teste automatizado a escrever/reverter — é troca de token de cor, sem condição, cálculo ou permissão envolvida (nenhum teste unitário ou e2e hoje afirma a cor do selo). A prova de regressão é a verificação visual descrita no CA1-CA3.
  • [x] Trocar "success" por "info" em BureauInquiryPanel.tsx (linha 305) e no tipo de tone.
  • [x] Verificação visual nos dois viewports (desktop e 375px), na tela do Inquilino, com print antes/depois (dado real do dev-remote pós-migração de infra). Análise de Crédito não fotografada à parte — mesmo componente, mesma prop, testes unitários cobrindo.
  • [x] make test-web ARQ=src/components/shared/BureauInquiryPanel.test.tsx (6 verdes), ARQ=src/pages/credit-analyses/show.test.tsx (13 verdes) e ARQ=src/pages/renters/show.test.tsx (7 verdes) — nenhum caso quebrou.
  • [x] make lint (tsc) sem apontamento novo — npx tsc --noEmit limpo.

10. Decisões em aberto

Nenhuma — escopo confirmado com o usuário: só o estado "sem restrição", cor sugerida pelo diagnóstico (feedback.info, já em uso no mesmo componente).

11. Revisão da correção

Preenchido pelo laço do /fix implement, rubrica .claude/rubrics/correcao.md. Registrar todas as rodadas.

Rodada Critical Important Minor Veredicto
1 0 0 1 Aprovado

Resultado: aprovado na rodada 1.

O teste sobreviveria à reversão? Não se aplica — não há teste automatizado para esta correção (troca de token de cor, sem condição/cálculo/permissão; ver seção 9). A prova é visual: cor computada do selo lida diretamente do DOM renderizado no dev-remote (rgb(0, 172, 240) = #00ACF0 = feedback.info), com print em docs/fixes/assets/0019-cor-verde-painel-consulta-credito/ — revertendo a linha 305 de BureauInquiryPanel.tsx, essa cor voltaria a rgb(46, 125, 50) (feedback.success).

Defeitos aceitos: achado Minor da rodada 1 — o status do registro estava inconsistente entre docs/fixes/0019-....md (frontmatter), docs/fixes/index.md e docs/metadata/catalog.yaml. Corrigido nesta mesma revisão (os três agora dizem corrigido), não ficou como pendência.

12. Registro

O que era: o painel "Consulta de crédito" pintava o estado "sem restrição" com o token success (verde), semanticamente reservado a "aprovação, contrato ativo" (docs/design-tokens.md) — mas o painel é só informativo e não aprova nada (RN8, spec 0050).

O que virou: o mesmo estado agora usa info (ciano, feedback.info, "dado neutro"), já em uso no mesmo componente (círculo do diálogo de explicação). Nenhuma outra cor ou estado do painel foi tocado.

O que divergiu do plano: nada na correção em si. A verificação teve uma volta a mais não prevista no plano original: a validação contra o dev-remote foi bloqueada por contenção de memória na VPS (outro projeto hospedado na mesma máquina recriou a stack dele durante a sessão), o que motivou, à parte deste fix, uma migração de infra do dev-remote (db/redis/mailpit para serviços nativos, Caddy removido — commitada e mesclada separadamente, branch infra/devremote-servicos-nativos). A verificação visual deste fix só ficou possível depois dela. Também foi preciso resetar a senha do admin semeado do dev-remote (o hash migrado do banco antigo não batia com o SEED_ADMIN_PASSWORD atual do .env) para conseguir logar e navegar até a tela real.

Critérios de aceite: CA1, CA2 e CA3 marcados — ver seção 8 para a evidência de cada um.