# Auditoria READ-ONLY do módulo STA em PRODUÇÃO (2026-07-20)

Escopo: sta-api PROD, fluxo cabine STA ↔ Core (SISBAJUD e CCS), sem nenhuma alteração de estado.
Métodos: ECS describe, CloudWatch Logs Insights, `rpc`/`eval` read-only nos containers vivos (core-api e sta-api), `nats stream` read-only via SSM na EC2 do NATS PROD, evidência das telas do dono (cabine STA + painel STA do BACEN via acesso legado `s-rvulci26`).

## ACHADO CRÍTICO 1 — Remessas SISBAJUD (AJUD301) chegam ZIPADAS e o Core as descarta como "unknown"

**Sintoma relatado pelo dono:** cabine STA mostra AJUD301 "Concluído" em 16/07 20:06 e 17/07 19:40 (BRT), mas a tela SISBAJUD do Core não tem NENHUMA ordem.

**Prova:**
- Logs core-api PROD nos horários exatos dos arquivos da cabine:
  - `[STA Handler] Remessa SISBAJUD enfileirada para ingestão durável (job …)`
  - `[SISBAJUD] arquivo tipo <<3, 4, 20, 0>> (unknown) reconhecido e ACKado SEM processamento`
- `<<3, 4, 20, 0>>` são os bytes 3–6 do cabeçalho ZIP (`PK\x03\x04\x14\x00`). O classificador
  (`core/backend/lib/monetarie/use_cases/regulatory/sisbajud/sisbajud.ex` → `header_tipo_arquivo/1`)
  extrai as posições 3–6 da primeira "linha" esperando o TIPO_ARQUIVO texto (`5301`), mas recebe o ZIP cru.
- Cadeia inteira sem descompactação: `sta_handler.ex` (`maybe_ingest_sisbajud`) passa o base64 como veio;
  `sisbajud_sta_ingest_worker.ex` só decodifica base64; `Sisbajud.ingest/3` classifica o binário cru.
- Banco PROD (rpc read-only): `judicial_orders = 0`, `judicial_blocks = 0`. NUNCA houve ordem ingerida em PROD.
- TODOS os arquivos JUD via STA caem no mesmo buraco (eventos ignorados em 16/07 18:31, 23:06×2; 17/07 01:23,
  08:29, 20:32, 22:40×2; 18/07 01:24; 20/07 08:55 UTC): AJUD301 (remessas!), AJUD303/304 (validações da nossa
  resposta), AJUD305 (varas), AJUD308 (requisição).

**Impacto:** ordens judiciais de bloqueio (AJUD301 de 16/07 e 17/07) estão SEM resposta há 3+ dias — risco de
reapresentação/teimosinha CNJ e descumprimento de prazo legal (24h). A validação (AJUD303 de 17/07 17:32) da
resposta que enviamos também foi descartada.

**Mitigação disponível (sem código):** o conteúdo NÃO se perdeu — o stream `MONETARIE_STA` (NATS PROD) retém
7 dias e tem 98 eventos `file.received` desde 15/07 21:08 UTC; as remessas podem ser recuperadas de lá, ou
re-obtidas no painel STA do BACEN (download), descompactadas e subidas pela tela de Upload Remessa do Core
(caminho manual já existente). ATENÇÃO ao prazo de retenção: eventos de 15-16/07 expiram a partir de 22-23/07.

**Correção de código recomendada (pendente de autorização):** detectar cabeçalho `PK\x03\x04` na ingestão
(no Core, ou na cabine antes de embutir o content) e descompactar, iterando as entradas do ZIP; cobrir também
o caminho das validações e do AJUD305. TDD com um ZIP real do stream.

## ACHADO 2 — O AJUD302 (resposta) FOI enviado e entregue ao CNJ; a cabine só não o exibe

- Cabine (banco `outbound_files`, read-only): `RESP_46026562000105_2026-07-15.zip | PSBA001 | uploaded |
  protocolo 433721199 | 2026-07-16 18:19:26 UTC (=15:19 BRT)`.
- Painel STA BACEN (evidência do dono): protocolo 433721199 transmitido, recebido no BACEN, entregue ao
  destinatário e **download finalizado pelo `ejuez.s-sisbajud` (CNJ) em 16/07 15:30**.
- Por que "não aparece": a tela Arquivos da cabine lista arquivos RECEBIDOS (downloads); uploads vivem em
  `outbound_files` e não têm tela. O card "Arquivos Enviados: 0" do Painel também não reflete o banco
  (métrica em memória zerada no restart do deploy de 16/07 18:02 BRT, posterior ao upload). Defeito de UI/métrica, não de transporte.
- ⚠️ Este RESP é o arquivo com **0 registros** (o "RESP bogus" da saga de 16/07, exclusão abortada porque já
  tinha sido enviado). Único registro em `regulatory_files` de PROD (status `delivered`, record_count 0).
  A resposta VÁLIDA das ordens reais continua devida (depende do Achado 1). O veredito do BACEN/CNJ sobre esse
  RESP provavelmente está no AJUD303 de 17/07 17:32 — também descartado, recuperável no stream.

## ACHADO 3 — CCS: remessas de 17, 18 e 19/07 REJEITADAS (ECCS0003); 20/07 ACEITA

- `ccs_files` PROD: 202607170001 / 202607180001 / 202607190001 = `rejected` ECCS0003 ("Número de remessa
  inválido"); **202607200001 = `confirmed`** (protocolo 434876738) com ACCS003 (0 rejeitos) e ACCS009 aplicados.
- XMLs dos ACCS002 (lidos do banco):
  - 17/07: "o numero correto seria **202607170002**" (Ult=202607170001 — um ACCS002 do próprio BACEN emitido
    às 20:12 BRT de 16/07, na abertura da grade do dia 17, consumiu o 0001; chegou ao Core como
    "ACCS002 sem ACCS001 correspondente — ACK" e o resolvedor de numeração não o considera).
  - 18 e 19/07 (sáb/dom): "o numero correto seria **202607200001**", DtMovto=2026-07-20 — em dia não-útil o
    BACEN desloca o DtMovto para o próximo dia útil e espera a numeração desse dia; nosso job numera pelo dia
    corrente e envia todo dia.
- Deltas de 16 a 19/07 eram todos **0 operações** (ACCS001 vazio obrigatório) → nenhum dado cadastral se perdeu;
  o dia 20 aceito regulariza (cadastro cumulativo). Impacto = formal (3 envios diários rejeitados).
- Correções recomendadas: (a) numeração ciente de dia útil (fim de semana/feriado → numerar pelo próximo dia
  útil ou não enviar); (b) ACCS002 órfão deve alimentar a fonte de numeração (Ult) mesmo sem match.
- Nota: HML não interfere (job gera mas `STA_WORKERS_DISABLED` barra o envio — by design).

## Saúde geral do módulo (sem outros problemas)

- `sta-api` PROD ACTIVE 1/1, task-def `:15` (deploy 16/07 18:02 BRT), rollout COMPLETED. Únicos warnings em 4
  dias: retries transitórios de `list_available_files` (`:closed`/500), todos recuperados no retry.
- Poller inbound vivo (ciclo ~60s); "Found 4 available files" constantes = arquivos já processados que o BACEN
  ainda lista (filtro `Files.protocol_exists?` descarta em silêncio) — comportamento correto.
- Transporte cabine↔Core OK nos dois sentidos (CCS prova o ciclo completo: upload 04:00 UTC, ACCS002/003/009
  baixados e aplicados no Core em segundos).
- NATS PROD: `MONETARIE_STA` 174 msgs/3 réplicas/0 lost; `MONETARIE_DLQ` = 0; `BACEN_DLQ` = 7 (fora do escopo STA, triagem pendente).
- Migration `20260719110000` (CreateCcsScheduleNotifications) rodou em PROD em 19/07 15:30 UTC (deploy de outra
  frente). `[CcsNotifications] … sem destinatarios configurados, pulando` — notificações CCS ativas porém sem
  destinatário configurado.

## RECUPERAÇÃO EXECUTADA (2026-07-20, mesma sessão)

Conteúdos extraídos do stream `MONETARIE_STA` (NATS PROD, via SSM read-only) e validados localmente em
`.scratch/sta-recovery-20260720/` (gitignorado; contém PII judicial). ZIPs íntegros, cabeçalhos conferidos:

| Protocolo | Tipo | Recebido (BRT) | Conteúdo |
|---|---|---|---|
| 433385561 | AJUD301 (5301) | 15/07 19:39 | **3 ordens de bloqueio** |
| 433857962 | AJUD301 (5301) | 16/07 20:06 | **7 ordens de bloqueio** |
| 434339689 | AJUD301 (5301) | 17/07 19:40 | **3 ordens de bloqueio** |
| 433385562 / 433857968 / 434339688 | AJUD308 (5308) | 15–17/07 | 0 solicitações (vazias) |
| 433330886 / 433728772 / 434265590 | AJUD303 (5303) | 15–17/07 | validações sintéticas |
| 432993936 / 433479153 / 433935451 / 434892381 | AJUD304 (5304) | 15–20/07 | validações semanais |
| 432994093 | AJUD331 | 15/07 | validação semanal solicitações |

Total: **13 ordens de bloqueio** aguardando processamento e resposta 5302. AJUD305 (varas, ~550KB) não foram
trazidos (catálogo de referência, não bloqueia resposta; sincronizam após o fix). Arquivos temporários da
extração na EC2 do NATS foram removidos (`/tmp/sta-recovery`).

Descoberta adicional: existe uma TERCEIRA remessa (15/07 19:39, protocolo 433385561) anterior às duas vistas
na tela da cabine — também nunca processada. O RESP vazio de 15/07 (21:48 UTC) coincide com o lote de
arquivos 15/07 (AJUD304/331/305/303) sob o código PRÉ-fix que force-parseava não-remessa como 5301 — origem
provável do "RESP bogus".

Próximo passo operacional (operador, via tela SISBAJUD do Core → Upload Remessa, em ordem cronológica
15/07 → 16/07 → 17/07, usando os TXT extraídos): o processamento congela os valores no TigerBeetle e gera os
5302; revisão e disparo do envio ficam com o operador (auto-send OFF). A identidade única por tipo de ordem
(migration 20260709220000) garante idempotência se o replay pós-fix reencontrar as mesmas ordens.

## FECHAMENTO DA RECUPERAÇÃO (2026-07-20 tarde) — backlog ZERADO

Operador (Eduardo) subiu as 3 remessas pela tela Upload Remessa; verificação final no banco PROD:

- **13/13 ordens ingeridas** (3 de 15/07 + 7 de 16/07 + 3 de 17/07), todas `no_balance` — motor consultou o
  TB vivo, nenhum réu tinha saldo, 0 blocks criados, respostas "02 sem saldo" legítimas.
- **3 respostas 5302 `delivered`**: 435087162 (3 reg, dia 15), 435087274 (7 reg, dia 16), 435111947 (3 reg,
  dia 17); as duas primeiras confirmadas no painel STA do BACEN como disponíveis ao CNJ (`ejuez`).
- Defeito NOVO achado no caminho: **encoding Latin-1** — a remessa de 17/07 tinha nome acentuado
  ("Megawave Indústria…", bytes 0xFA/0xE9/0xE3) e o processamento quebrou com `Jason.EncodeError` ao gravar
  JSONB (500 na tela, rollback completo). Contorno usado: transliteração 1:1 Latin-1→ASCII preservando
  posições de byte (o parser fatia colunas com `binary_part`; converter p/ UTF-8 deslocaria os campos).
  Fix definitivo: transcodificar campo a campo após o extract (`:unicode.characters_to_binary/3`).
- Nota de UX: o PREVIEW filtra contas `active` (`file_processor.ex:311`) e mostrou "0 conta(s)" para réus
  com conta `inactive`; o PROCESSAMENTO real itera todas as contas e decide pelo saldo TB. Comportamentos
  divergem só na exibição — alinhar no fix.

## VALIDAÇÃO LOCAL DO FIX (2026-07-20 tarde) + defeito adicional no Varas.Sync

Ambiente local rebuildado com o código pós-merge (imagens `monetarie-core-api:local-0720` e
`monetarie-core-admin:local-0720`; migrations da main aplicadas no mon_core local; proxy do
core-admin corrigido — apontava para o IP que hoje é do postgres; core-api agora com IP fixo
192.168.155.6 na rede monetarie_default):

- **ZIP original de PROD (`434339689_AJUD301.zip`, com "Megawave Indústria…" em Latin-1)**
  processado fim a fim pela tela local: preview descompacta e parseia as 3 ordens; process
  = 3/3, 0 erros; nome persistido em UTF-8 com acentos. O caso exato do 500 de PROD.
- **Defeito NOVO achado com o AJUD305 REAL** (extraído do stream PROD, 8MB, 12.715 varas):
  `Varas.Sync.upsert_varas` fazia UM `insert_all` com o catálogo inteiro → 76.290 parâmetros
  > teto de 65.535 do protocolo Postgres (`Postgrex.QueryError`). Ia estourar em PROD no
  primeiro 5305 pós-deploy. Fix TDD: upsert em lotes de 5.000 dentro de transação única
  (atômico). Validado vivo local: `upserted: 12715`, catálogo `judicial_courts` populado com
  nomes reais (gabinetes STF/STJ etc.).
- Leiaute best-effort do 5305 CONFERIDO contra o arquivo real: header `005305…`, detalhe
  `02` + código (pos 3-7) + nome (8-207), rodapé com contagem 12715 — posições corretas.
- Nota honesta: a vara `23674` das ordens de 17/07 NÃO consta no catálogo AJUD305 do BACEN
  (busca no arquivo cru = 0 ocorrências) — o "Não catalogada" da tela é fiel ao dado.

## FIX CCS IMPLEMENTADO (2026-07-20 noite) — commit local `96ea7a07`

TDD (9 testes novos + suítes ccs/cadoc/workers/handlers 504/0):

- **ACCS002 órfão persistido** (`ccs_accs002_orphans`, **migration `20260720210000`** — aplicar
  via rpc no deploy) e considerado pelo `next_after_bacen_ult`, com guarda anti-veneno (só 12
  dígitos; Ult com prefixo além do dia de movimento ignorado; MAX capado no SQL). Cobre o caso
  17/07 (Ult=202607170001 descartado → teria calculado ...0002).
- **`CCS.movement_day/1`** (próximo dia útil, calendário de feriados) manda na numeração, no
  `dt_movto` e no XML. Cobre 18-19/07 (fim de semana numera como segunda).
- **Job diário com `plan/1`**: dia não-útil (BRT) → skip logado; segunda consolida o delta de
  sexta+sábado+domingo (coletores de admissão/exclusão por intervalo). Backfill manual explícito
  (`reference_date` nos args) preservado.
- Nota: sem urgência para a noite de 20→21/07 — terça é dia útil e o código antigo enviará
  `202607210001`, que o BCB deve aceitar (como aceitou o de segunda).


## ADOÇÃO DA UI VUE COMO sta-admin-ui OFICIAL (2026-07-20 noite) — pacote local, review formal feito

Decisão do dono: `sta/frontend` (Vue) substitui `sta/admin-portal` (React) como UI oficial. Pacote
completo (36 arquivos, +2199/−1322, local sem commit) com review formal:

- **Contrato de deploy portado e provado**: nginx virou template `${STA_API_HOST}` (mesma env da
  task-def de PROD; ZERO mudança de task-def no deploy — basta trocar o diretório de build para
  `sta/frontend/`), /health desacoplado do backend, index.html no-store, WS `/socket`/`/live`
  proxied, `.dockerignore`. Validado vivo com a env exata de PROD.
- **Defeitos reais do app Vue corrigidos** (nunca tinha rodado contra backend vivo): parse do
  payload de config (`{config}` vs `{data}` — tela nunca carregava), save enviando seção
  somente-leitura (400 sempre), download quebrado nas 2 pontas (frontend esperava JSON `{url}`;
  backend só resolvia outbound — fallback p/ `processed_protocols` com TDD), filtro de data com
  nomes de parâmetro divergentes (ignorado em silêncio), off-by-one nos buckets do timeline
  (excluía a hora/dia corrente — gráfico vivia zerado e caía em MOCK), seletor de sistema
  decorativo (backend ganhou filtro `system` com TDD), WebSocket hardcoded em domínio LEGADO da
  era GCP (`staapi-monetarie.vulci.com.br`), modal de rotas invisível no SAFARI (hack
  inline-block/align-middle → flex centrado, provado no WebKit), Adicionar Rota com `disabled`
  invisível, datepicker com locale string (v14 exige objeto date-fns).
- **Aba Conteúdo real** (era stub) + exemplos; dados fake dos seeds purgados e substituídos pelos
  16 arquivos REAIS de PROD; gráficos/filtros só mostram tipos com movimento.
- **Tradução pt-BR completa** (menus, dropdowns, toasts, gráficos, notificações, logs) via i18n
  nos 3 idiomas; type-check pegou 21 chaves duplicadas do sweep — dedupadas, `vue-tsc` 0 erros.
- **Paridade Configuração**: card Serviço (dado real) + 3 cards condicionais (os do React exibiam
  DEFAULTS INVENTADOS no frontend — aqui só renderizam quando o backend enviar); rotas com CRUD
  completo (editar não existia). PROD: `config_overrides` = 0 → pós-deploy a tela mostra os
  mesmos dados que o React mostra hoje.
- **Gates**: backend 1287 testes (5 falhas pré-existentes provadas com stash: 4 de config/rotas +
  1 flake de timing), 4 testes novos; `vue-tsc` 0 erros; build verde; E2E Chromium + WebKit.

### 🔴 FINDING DE SEGURANÇA (pré-existente, decisão do time)

O escopo `/api/v1/*` do sta_connector (download/upload/delete de arquivos + stats) usa o pipeline
`:api` SEM autenticação — provado vivo (request sem token é processada). O nginx da UI faz proxy
de `/api` ao backend, então quem alcança o host da staadmin acessa a API sem credencial. Em PROD
a exposição é mitigada pela rede interna (ALB interno + VPN), mas com o download agora servindo
conteúdo real (PII judicial), o risco subiu. NÃO alterado unilateralmente: o `/api/v1` é a API
máquina-a-máquina que o core usa para subir CCS (`Monetarie.Sta.Client.upload_file`) — fechar
auth exige credencial m2m coordenada. Recomendação: token de serviço + SsoAuth no escopo v1.

## Prioridades sugeridas

1. **URGENTE (dinheiro/judicial):** recuperar e processar as remessas AJUD301 de 16 e 17/07 (stream NATS ou
   download no painel STA BACEN + unzip + upload manual na tela) e responder ao CNJ. Retenção do stream expira ~22-23/07.
2. Corrigir a ingestão para descompactar ZIP (TDD) — destrava AJUD301/303/304/305/308 automáticos.
3. CCS: numeração por dia útil + considerar ACCS002 órfão no resolvedor.
4. Menores: tela/métrica de uploads na cabine; destinatários das notificações CCS; triagem BACEN_DLQ (7).
