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¶
- Abrir uma Análise de Crédito (ou um Inquilino) cujo locatário principal tenha consulta de bureau concluída com
status: SUCCESSe nenhuma pendência financeira, protesto ou cheque sem fundo. -
Observar o cabeçalho do painel "Consulta de crédito": fundo, título e selo "SEM RESTRIÇÃO" em verde (
theme.palette.success). -
Ambiente: qualquer (local, dev-remote, produção) — é estilo estático, não depende de dado além do estado "sem restrição".
- Superfície: desktop e mobile — a cor vem do mesmo cálculo de
tonenos dois viewports; não é layout, é token de cor. - Dados/pré-condições: usuário com acesso ao painel (garantidora, não
AGENCY_USER— ver a nota de identidade emBureauInquiryPanel.tsx:63-69), consulta comstatus: SUCCESSe 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:305Esseconst tone: "success" | "error" | "secondary" = pending || failed ? "secondary" : (temRestricao ? "error" : "success");tonealimenta o fundo do cabeçalho (:376), a cor doSectionLabel(:382) e a cor do selo (:394), todos viatheme.palette[tone].main. -
O mecanismo: quando a consulta termina sem restrição,
tonerecebe"success", que resolve paratheme.palette.success.main(#2E7D32no tema claro — verapps/web/src/design-system/theme/palette.ts:60). O tokenfeedback.successdo 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 alteracredit_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 oBureauInquiryPanelé usado sem variação nas duas telas que o exibem —apps/web/src/pages/credit-analyses/show.tsx:1137eapps/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 detone) 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 detone(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 detonepara incluir"info".theme.palette.infojá 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
SUCCESSe 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 selorgb(0, 172, 240)=#00ACF0=feedback.info, nos dois viewports. Print emdocs/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 detonesó mudou o ramosem restrição; os ramoserror/secondarynão foram tocados, e os 6 casos doBureauInquiryPanel.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/showusa o mesmo componente compartilhado com o mesmotone, 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), mastheme.palette.infoexiste nos dois modos (palette.ts:66,100), mesmo padrão desuccess/errorjá 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"emBureauInquiryPanel.tsx(linha 305) e no tipo detone. - [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) eARQ=src/pages/renters/show.test.tsx(7 verdes) — nenhum caso quebrou. - [x]
make lint(tsc) sem apontamento novo —npx tsc --noEmitlimpo.
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.