# SISBAJUD — Conformidade do módulo vs leiaute oficial v1.11 (2026-07-08)

Fonte de verdade: **"SISBAJUD 2.0 — Layout dos arquivos trocados com as
instituições participantes, versão 1.11"** (CNJ, 38 págs). Este documento
cruza o leiaute oficial com o código da Monetarie
(`core/backend/lib/monetarie/use_cases/regulatory/sisbajud/` + `judicial/`)
e serve de referência para o enriquecimento do módulo.

Contexto: o módulo foi portado do Cecresa contra o layout **v1.8** (ver
`test/fixtures/sisbajud/5301_remessa/basic_block.meta.yml`), com fixtures
truncadas (344 chars em vez dos 410 oficiais) e campos-chave em branco — por
isso vários gaps de conformidade nunca foram exercitados pelos testes.

## Fatos gerais confirmados (código OK)

- Remessa: registro de 410 chars; resposta: 125 chars. ResponseBuilder emite
  125 ✓.
- Campos monetários (tipo V): 19 dígitos, 2 decimais implícitos, zeros à
  esquerda ✓.
- ISO 8859-1 (mas ver gap de conversão na saída, auditoria anterior).
- TIPO_ARQUIVO: remessa 5301 (homolog 5311); resposta 5302 (homolog 5312) ✓.
- VERSAO_LAYOUT: **remessa = "05", resposta = "04"** — divergência INTENCIONAL
  (cada arquivo tem versão própria, §1). O ResponseBuilder emite "04" ✓.

## Gaps SUSPEITOS que o leiaute REFUTA (não mexer)

1. **"Bloqueio parcial deveria ser código 02, não 03"** — REFUTADO. Tabela
   oficial 3.3.1: **`03` = "Cumprida parcialmente por insuficiência de saldo"**
   (VALOR > 0 e < solicitado); **`02` = "Réu/executado sem saldo positivo"**
   (não preenche valor). O `"partial" -> "03"` do `determine_block_response_code`
   está CORRETO. (Bater com o manual de homologação do CNJ que dizia "03 =
   cumprida parcialmente".)
2. **"Versão de layout divergente 05 vs 04"** — REFUTADO, é intencional (acima).

## Gaps CONFIRMADOS pelo leiaute (corrigir)

### 🔴 Crítico — conformidade legal / rejeição BACEN

- **Conta-salário usa T/F, não S/N.** Remessa registro 03, campo
  `INDICADOR_BLOQUEIO_CONTA_SALARIO` (pos 249): valores oficiais **"T"**
  (pode atingir conta-salário) / **"F"** (não deve). Resposta registro 03,
  `INDICADOR_CONTA_SALARIO` (pos 045): **"T"/"F"**.
  Código atual: `normalize_salary_indicator/1` só reconhece `"S"/"N"` →
  retorna `nil` para T/F reais (file_processor.ex:454-456); e
  `derive_indicador_conta_salario/1` EMITE `"S"/"N"` (file_processor.ex:446-447).
  **Impacto:** com dados reais do BCB (T/F), a proteção de impenhorabilidade
  (art. 833 CPC) nunca dispara — conta-salário seria bloqueada — e a resposta
  sai malformada. Correção: aceitar T/F (e S/N por retrocompat) na entrada;
  emitir T/F na saída.
- **UNBLOCK referencia o bloqueio anterior — hoje nunca executa.** Registro 05
  (desbloqueio, §2.4) NÃO carrega CPF/processo/vara: a chave é
  `PROTOCOLO + SEQUENCIAL_BLOQUEIO + REITERACAO_BLOQUEIO + SEQUENCIAL_DESBLOQUEIO
  + REITERACAO_DESBLOQUEIO`. `process_unblock` monta a ordem com
  `document_number=""`/`court_code=""` → `validate_required` falha → responde
  "00". Correção: resolver a ordem de bloqueio original pela chave
  (protocolo+seq+reit) para obter CPF/vara e liberar só aquele bloqueio.

### 🟠 Alto

- **ORDEM_CANCELADA usa T/F, não S.** Registro 03, campo `ORDEM_CANCELADA`
  (pos 250): **"T"** = cancelada, **"F"** = reiterada. `cancellation_requested?/1`
  só reconhece `"S"/"s"` (file_processor.ex:246-252) → cancelamento do BCB (T)
  vira bloqueio novo em vez de liberação.
- **Falta o código 02 (cliente sem saldo).** `determine_block_response_code/1`
  (file_processor.ex:931-938) mapeia só `executed→01, partial→03, _→00`. Quando
  o réu É cliente mas sem saldo positivo, cai no catch-all `_→00` (que informa
  "não é cliente"). O correto é **02** ("réu sem saldo positivo"). Distinguir
  "conta encontrada mas saldo 0" de "conta não encontrada".
- **Resposta de UNBLOCK hardcoded.** `process_unblock` emite `codigo_resposta:
  "01"` fixo e `valor_desbloqueado: 0` (file_processor.ex:506-507); o leiaute
  (resposta §3.4) exige CODIGO_RESPOSTA real e VALOR_DESBLOQUEADO +
  SALDO_BLOQUEADO_REMANESCENTE_TOTAL/CONTA_SALARIO.

## Tabelas oficiais de códigos de resposta (v1.11)

- **Bloqueio (3.3.1):** 00 negativa (não-cliente) · 01 integral · **02 sem saldo
  positivo** · 03 parcial · 05 sem saldo por bloqueio anterior · 08 não-titular
  da conta · 09 agência/conta inválida · 12 integral em depósito a prazo · 13
  parcial em prazo/títulos · 15 valor reservado (depósito judicial na
  transferência) · 16 integral em outra instituição do agrupamento · 17 integral
  com bloqueio parcial nesta IF · 18 idem afetando prazo · 20 só ativos em
  garantia · 21 ativo indivisível · 22/23/24 parciais com ativo
  indivisível/garantia · 25 ativo escriturado · 26 baixa liquidez · 27 ativo não
  precificado · 28 ativos de ente público (não liquida via SISBAJUD).
- **Cancelamento (3.3.2, ORDEM_CANCELADA="T"):** só 01.
- **Desbloqueio (3.4.1):** 01 cumprida · 07 operação fora do Sisbajud.
- **Transferência (3.5.1):** 01 recebida · 07 fora do Sisbajud · 11 banco/agência
  destino inválido · 42 sem resgate por baixa liquidez · 43 resgate parcial ·
  47 fora do Sisbajud (juízo comunicado em 30 dias).
- **Notificação de recebimento (3.6.1):** só 01.
- **Uso exclusivo BCB (3.7):** 93 cooperativa Capital&Empréstimo (não capta) ·
  94 não-participante · 95 destino inativo/liquidação · 96 respondida por outra
  IF do agrupamento · 97 não encaminhada · 98 não-resposta · 99 destino em
  intervenção/liquidação.

O `CodeDispatcher` (code_dispatcher.ex) tem 24 códigos de bloqueio, mas o caminho
comum `determine_block_response_code` usa só 00/01/03 (dualidade Gap #8). Unificar
para o CodeDispatcher cobrindo 02/05/08/09 etc.

## Arquivos de retorno do BCB (fecham o ciclo — hoje ausentes)

Além do 5302, o BCB devolve validações que a IF precisa consumir:
- **5303/5313** — resultado da validação SINTÁTICA (§4): rejeita o arquivo
  inteiro se houver erro; a IF deve reenviar.
- **validação SEMÂNTICA** (§5) na consolidação.
Isso é a contraparte do "recebimento do ASPB009" que a auditoria de fluxo
apontou como fio solto — sem consumir 5303, a IF não sabe se a resposta foi
aceita.

## ✅ Implementado nesta sessão (conformidade ao leiaute v1.11)

- **Conta-salário T/F** (entrada + saída) via módulo puro `WireEnums`: a entrada
  aceita T/F oficial + S/N legado; a saída emite T/F. Representação interna S/N
  preservada (CodeDispatcher intacto). ⚠️ validar em homologação real (comentário
  legado afirmava S/N — reversão de 1 linha se o BCB rejeitar T/F).
- **ORDEM_CANCELADA "T"**: `WireEnums.cancellation?/1` reconhece "T" (v1.11) e "S".
- **Código 02**: novo status `no_balance` (réu É cliente, sem saldo) →
  `FileProcessor.block_response_code/1` mapeia para "02", distinto de "00"
  (not_found = não-cliente).
- **UNBLOCK que executa**: `process_unblock` resolve o bloqueio original por
  `Processor.find_block_order_by_reference/3` (protocolo+seq+reit), herda
  document/court, libera só aquele bloqueio (espelha o CANCEL) e responde com
  código/valor reais. Cobertura: resolução testada com DB; liberação TB no
  caminho de integração (excluído por falta de harness de mock TB).

Testes: 321 SISBAJUD/judicial verdes. Follow-ups: desbloqueio PARCIAL por
VALOR_DESBLOQUEIO (hoje libera total); harness de mock TB para exercitar o
congelamento/liberação real.

## Ordem recomendada de enriquecimento

1. **T/F conta-salário** (entrada+saída) — conformidade legal, corrige risco de
   penhora indevida de salário. + **código 02**.
2. **UNBLOCK que executa** — resolver bloqueio original pela chave; resposta real.
3. **ORDEM_CANCELADA "T"** — detectar cancelamento.
4. **Bloqueio permanente + valor mínimo R$ 50** (Portaria 3/2024 — ver manual
   básico) e janelas de cron (13h/20h → 19h/12h).
5. **Consumo do 5303** (validação sintática) + ingestão automática do 5301 via
   STA — fecha o ciclo nas duas pontas.

Já entregue nesta sessão (fora deste doc): envio do 5302 ao BCB via STA a partir
do sistema + idempotência de re-upload (impede duplo congelamento).
