# Auditoria do frontend SPB

Data: 23/07/2026

## Escopo e evidência

- Projeto auditado: `spb/frontend-vue` (Vue 3, Vite, Vuetify, Vue Router, Pinia).
- Inventário: 60 declarações de rota Admin, 77 declarações de rota Operador e 108 views/componentes de tela.
- Automação executada: `pnpm test:unit -- --run`, `pnpm type-check` e `pnpm build-only`.
- Resultado: 6 arquivos de teste, 38 testes, 0 falhas; type-check verde; build verde.
- O build emite warning de chunks acima de 500 kB; o maior bundle JS produzido tem aproximadamente 963 kB antes de gzip.
- Esta etapa ainda não constitui prova funcional de todas as páginas em HML: não foram usados usuários reais nem executadas todas as ações destrutivas/configuráveis.

## Pendências encontradas

### SPB-FE-001 — Token JWT em query string entre módulos — alta

`src/components/layout/Header.vue` monta a navegação inter-módulos com `?token=<JWT>`. Tokens em URL podem aparecer em histórico, logs de proxy, ferramentas de observabilidade e cabeçalho Referer. O backend do módulo destino precisa migrar para troca de código de uso único, cookie seguro compartilhado com escopo controlado ou outro SSO sem transportar JWT na URL.

### SPB-FE-002 — Refresh de token explicitamente não implementado — alta

`src/stores/auth.ts` contém `throw new Error("Token refresh not implemented")`. Embora o interceptor tenha refresh opt-in, o contrato de sessão precisa ser validado ponta a ponta: expiração, aviso, logout, retorno 401 e renovação autorizada. Não se deve considerar a sessão resiliente enquanto o caminho suportado não estiver coberto por teste e HML.

### SPB-FE-003 — Fallbacks de API/WebSocket para localhost — média

`src/stores/entities.ts` usa `http://localhost:4000` como fallback de API e `src/composables/useWebSocket.ts` usa `ws://localhost:4000/socket`. Em configuração de produção ausente ou incorreta, o frontend tenta falar com a máquina do operador. Deve haver configuração obrigatória por ambiente, validação no build e falha explícita, sem fallback local em artefato de HML/PRD.

### SPB-FE-004 — 10 chaves de tradução ausentes em EN-US e ZH-CN — média

Comparação estrutural dos catálogos encontrou ausência, em `en-US.json` e `zh-CN.json`, das chaves `monitoring.detail.coaReceived`, `codReceived`, `r1Received`, `r2Received`, `r3Settled`, `operationId`, `responseCode`, `responseContent`, `outboundWireHex` e `inboundWireHex`. A interface pode exibir a chave técnica ou fallback inadequado nessas localidades.

### SPB-FE-005 — Strings visíveis hardcoded fora do i18n — média

Há textos de tela e ações diretamente em templates, confirmados em views como `PaymentsView.vue`, `BacenMessagesView.vue`, `DdaPcrAuditView.vue`, `DdaPcrMovementsView.vue`, `ExternalEntityStatusView.vue`, `ReturnAlertsView.vue`, `TransactionsView.vue` e várias telas de configuração. Exemplos: `Fechar`, `Cancelar`, `Excluir`, títulos e mensagens operacionais. O catálogo PT-BR não é a fonte única e EN/ZN não conseguem traduzir integralmente essas telas.

### SPB-FE-006 — Dados/defaults operacionais hardcoded — média

Foram encontrados defaults e listas literais em views, incluindo `Todos`, domínios, papéis, sistemas e códigos de exemplo. Alguns são rótulos de UI aceitáveis, mas precisam ser classificados: catálogo regulatório e opções operacionais devem vir do backend ou de constantes tipadas centralizadas; exemplos e placeholders devem ser explicitamente marcados como exemplo.

### SPB-FE-007 — Documentação da API renderiza localhost — baixa/média

`src/views/APIDocsView.vue` monta exemplos como `http://localhost:<port>`. Isso é útil apenas para desenvolvimento e pode induzir operação incorreta em HML/PRD. A documentação deve derivar o host do ambiente ou mostrar claramente placeholder não executável.

### SPB-FE-008 — Escopo de testes de interface insuficiente — alta

Existem apenas 6 arquivos de teste unitário para 108 views inventariadas. Não há evidência automatizada equivalente para cada rota, guarda de papel, carregamento vazio/erro, paginação, filtros, formulários, ações de alteração/exclusão, exportações, tabs e diálogos. É necessário criar matriz de cobertura e testes Playwright em HML por perfil, sem executar ações financeiras destrutivas.

### SPB-FE-009 — Componentes de template inicial ainda presentes — baixa

`src/components/HelloWorld.vue` e `TheWelcome.vue` permanecem no produto e contêm links/textos do template Vue/Vite. Mesmo que não estejam roteados, devem ser removidos ou comprovadamente excluídos do bundle para evitar conteúdo de scaffold.

## Rotas e segurança observadas

- O router aplica `requiresAuth` aos grupos Admin, Operador e telas auxiliares.
- Admin e Operador possuem metadados de papel; a guarda usa `roleCanAccess` e redireciona papel incompatível.
- A autorização efetiva não pode depender somente da guarda: cada mutação deve continuar sendo validada pelo backend. Isso deve ser comprovado em HML com tentativa de acesso cruzado.
- O token é mantido em `localStorage`; isso aumenta o impacto de XSS. Deve permanecer pendente uma decisão arquitetural sobre cookie HttpOnly/BFF ou controles equivalentes, especialmente junto da remoção do JWT da query string.
- O WebSocket inclui token na query string (`monitoringSocket.ts`), criando o mesmo risco de exposição e exigindo desenho específico de autenticação do canal.

## Plano de validação HML

1. Gerar matriz completa de rotas por perfil Admin, Operador, auditor/consulta e usuário sem sessão.
2. Executar cada rota em HML e registrar HTTP, erros de console, requests 4xx/5xx, telas vazias e chaves i18n não resolvidas.
3. Para cada view, catalogar campos, tabs, filtros, paginação, estados loading/empty/error, submit, edição, exclusão, exportação e confirmação.
4. Validar autorização negativa: URL direta, API direta, mudança de papel e tentativa de mutação sem permissão.
5. Validar WebSocket, expiração, logout, SSO e troca de módulos sem expor token.
6. Corrigir primeiro os itens de segurança alta, depois i18n/hardcodes e, por fim, performance do bundle.

## Critério de encerramento

Uma pendência só será encerrada com evidência reproduzível: teste automatizado ou captura/log de HML, rota/perfil identificado, resultado esperado e resultado observado. Nenhuma validação nesta etapa alterou PRD.

## Primeira execução funcional em HML — 23/07/2026

Ambiente: `http://spbadmin-h.monetarie.internal`, acessado pela VPN HML. O login usou o segredo administrativo mantido no AWS Secrets Manager; nenhuma credencial foi gravada na evidência.

Rotas críticas capturadas com sessão autenticada: `/admin/dashboard`, `/admin/messages`, `/admin/transactions`, `/admin/operations`, `/admin/entities`, `/admin/reports`, `/admin/system-date`, `/operator/dashboard`, `/operator/payments`, `/operator/bacen-messages`, `/operator/balances` e `/operator/schedule`, além de `/login`.

Resultado observado em todas as 13 rotas:

- HTTP `200` e permanência na rota esperada;
- zero erro de console, erro JavaScript ou request falho;
- telas com conteúdo visível, controles e dados renderizados;
- tabelas críticas com linhas carregadas nas consultas de mensagens, transações, operações, pagamentos, BACEN, saldos e agenda;
- login administrativo concluído (`loginOk=true`).

Evidência detalhada: `docs/reports/screenshots/2026-07-23-spb-hml-audit/logs/screenshot-metadata.json` e as capturas no mesmo diretório.

Limitação: essa rodada validou carregamento, renderização e integridade básica da navegação. Ainda falta executar cada campo, aba, filtro, paginação, exportação, confirmação, mutação e matriz negativa de autorização. Os itens `SPB-FE-001` a `SPB-FE-009` permanecem abertos até essa segunda etapa.

### Varredura de todos os links do menu

O `Sidebar.vue` foi extraído e executado contra HML com sessão administrativa: 121 links únicos, incluindo `/login`, Admin e Operador. Todos retornaram HTTP 200, permaneceram na rota solicitada e produziram conteúdo visível. Não houve tela vazia nem falha de navegação.

Foram observados 9 `net::ERR_ABORTED` em requests iniciados pela tela anterior durante a navegação imediata para a próxima rota. Esses abortos são compatíveis com cancelamento de requests em troca rápida de página e não foram tratados como erro de backend sem reprodução isolada. A exceção real foi:

- **SPB-FE-010 — `message-groups` quebra com erro JavaScript — alta:** HML registrou `TypeError: Cannot read properties of undefined (reading 'length')` em `MessageGroupEditorView`. A resposta de grupos contém itens sem `messageTypes`, enquanto a view acessava esse campo diretamente.

Correção preparada na fonte: normalização de `messageTypes`/campos snake_case, contagem defensiva e falha explícita nas operações de criar/editar/excluir, sem alterar estado local quando a API falhar. Type-check e os 38 testes unitários passaram após a correção. O item só será encerrado após publicar a nova imagem SPB em HML e repetir a rota isoladamente.
