# Relatório de carga v2: ETL completo do legado PIX/SPB (backups AB/GX/MGI)

Data da execução: 2026-07-01 (rodadas finais às 20:31 e 20:35 BRT; os carimbos do banco aparecem em UTC, 23:31/23:35)
Design de referência: `docs/plans/2026-07-01-etl-completo-legado-pix-spb-design.md`
Script: `etl/legacy_pix_spb/load_legacy_pix_spb.py` (comandos `setup`, `stage --profile all`, `project`, `fix-spb`, `verify`)
Ambiente: exclusivamente os containers locais `monetarie-bak-mssql` (SQL Server, leitura) e `monetarie-postgres-1` (bancos `cc_pix` e `cc_spb`, schemas `cecresa_*` e `legacy_ab_*`). Nenhum acesso a AWS, Aurora ou HML. Nenhum comando `aws` executado.

Todos os números deste relatório foram revalidados por SELECT direto no banco local em 2026-07-01, depois da segunda rodada de idempotência. Nenhum número foi copiado de log sem conferência.

## 1. Resumo executivo

A carga v2 fecha o que o design de 2026-07-01 pediu: staging completo dos 16 backups (com exclusões justificadas), projeções de negócio PIX (ordens, histórico de status, anotações de crédito, bloqueios, devoluções, infrações e MED), correção integral do acervo SPB (tipo real, direção real, estado canônico, valor via catálogo, eventos de timeline) e prova de idempotência com delta zero.

Resultados principais, todos conferidos no banco:

- Staging PIX: 3.373.971 linhas em 210 fontes (`legacy_ab_pix.source_rows`). Staging SPB: 2.003.396 linhas em 55 fontes (`legacy_ab_spb.source_rows`). O `stage --profile all` processou 265 tabelas com 0 erros no log.
- Tabelas sensíveis no staging: 0 linhas (as 9 exclusões da seção 3 valem nas duas cabines).
- PIX: 4.391 ordens de pagamento projetadas em `cecresa_spi.transactions` (settled 4.255, rejected 116, cancelled 19, accepted 1) mais 54 exceções contadas, totalizando as 4.445 ordens do staging. Conciliação ao centavo com o extrato: R$ 163.295.572,53 (settled) + R$ 3.580.073,14 (49 EFETIVADA excluídas, valoradas pelo extrato via E2E) = R$ 166.875.645,67, exatamente a soma dos 4.304 movimentos D/SUCESSO do extrato.
- PIX: 8.761 anotações de crédito (R$ 159.722.913,42, soma exata do staging), 4.392 bloqueios (R$ 168.935.505,42, soma exata do staging), 488 devoluções, 390 relatos de infração (+1 exceção), 205 MED.
- SPB: 14.101 `bacen_messages` e 10.591 `spb_operations` com tipo real extraído do XML (`message_type = 'LEGACY'` zerado no nível de mensagem), direção real, estado canônico, `operation_id` 100% preenchido e 10.591 eventos de timeline.
- Idempotência provada: a segunda rodada completa de `project` + `fix-spb` teve inserts e updates iguais a 0 em todas as 22 tabelas destino; contagens antes e depois idênticas (diff vazio).
- A projeção destrutiva de `cecresa_spi.balances` ficou atrás do gate `--allow-balance-overwrite` e foi PULADA com aviso explícito nas rodadas da v2 (audit = 0).

O escopo permaneceu 100% local (laboratório). A promoção a HML é um pacote separado que exige aprovação do dono (seção 11).

## 2. Escopo, ambiente e linha do tempo

Ordem executada (conforme seção 6 do design): `setup` -> `stage --profile all` -> `project` -> `verify` -> `project` de novo (delta zero). A linha do tempo real, lida de `legacy_ab_*.load_audit` e `legacy_ab_*.projection_audit` (horários UTC do banco):

| Hora (UTC) | Evento | Evidência |
|---|---|---|
| 14:43 a 14:48 | Carga anterior do dia (pré-gate): projeções base PIX/SPB da primeira leva, incluindo a única linha de `balances` que existe hoje | `projection_audit` das duas cabines |
| 22:39 | Projeções PIX v2 inseridas: transactions 4.391, status history 13.153, credit_notifications 8.761, balance_blocks 4.392, returns 488, infrações 390, MED 205, XMLs de ordem 4.373 | `legacy_ab_pix.projection_audit` |
| 22:55 | `fix-spb` primeira passada: 10.456 operações e 14.101 mensagens atualizadas (tipo real, direção, estado, valor), 10.591 `operation_events`, flags O->E 33 e I->R 18 | `legacy_ab_spb.projection_audit` |
| 23:01 | `fix-spb` relink dos 5 pares cruzados de NUMCTRLSPB duplicado (mais 5 ops/msgs convergidas) | `legacy_ab_spb.projection_audit` |
| 23:22 a 23:28 | `stage --profile all` PIX: 210 tabelas, 3.373.971 linhas lidas | `legacy_ab_pix.load_audit` |
| 23:28 a 23:30 | `stage --profile all` SPB: 55 tabelas, 2.003.396 linhas lidas | `legacy_ab_spb.load_audit` |
| 23:31 | `project` + `fix-spb` rodada 1 pós-stage: TODOS os inserts/updates = 0 | audits das duas cabines |
| 23:35 | `project` + `fix-spb` rodada 2 (prova de idempotência): TODOS os inserts/updates = 0 | audits das duas cabines |

O `verify` integral da rodada 1 foi capturado em `etl_verify_run1.log` (scratchpad da sessão): 42 itens PIX + 55 itens SPB.

## 3. Staging completo

Contagens finais conferidas no banco:

| Cabine | Tabela de staging | Linhas | Fontes distintas |
|---|---|---:|---:|
| PIX (`cc_pix`) | `legacy_ab_pix.source_rows` | 3.373.971 | 210 |
| SPB (`cc_spb`) | `legacy_ab_spb.source_rows` | 2.003.396 | 55 |

Estrutura por linha: `source_db`, `source_table`, `source_pk` (PK natural quando existe, senão `sha256:` do JSON), `row_hash`, `row_data` JSONB completo, `loaded_at`. O merge é upsert por PK composta, então repetir o `stage` não duplica nada.

Exclusões aplicadas (contagem no staging = 0, conferida por SELECT com a lista completa):

| Tabela excluída | Motivo |
|---|---|
| `CERTIFICADOS`, `PARAMETROS`, `PARAMETROS_MQ`, `PARAMETROS_SEGURANCA` | segredos e runtime (exclusão original de design) |
| `THUMBPRINT_SITE`, `THUMBPRINT_SITE_HISTORICO`, `THUMBPRINT_CERTIFICADO`, `DOWNLOAD_CERTIFICADOS_SITE` | material de certificado, coerência com a exclusão de `CERTIFICADOS` |
| `TESTE_CONECTIVIDADE` | healthcheck puro (122 mil linhas, 480 MB, sem valor de negócio) |

`MSG_ENDERECAMENTO_ENVIADA/RECEBIDA` (tráfego DICT bruto) ENTRARAM no staging local, conforme decisão do design (seção 3): trilha de auditoria DICT do participante, sem projeção, tratadas integralmente como PII em container local gitignorado.

## 4. Mapa oficial de status aplicado (contagens reais obtidas)

As tabelas abaixo reproduzem as seções 4.1 a 4.7 do design com as contagens REAIS conferidas no banco após a carga.

### 4.1 PIX, ordens de pagamento (saída)

Terminal de `STATUS_ORDEM_PAGAMENTO` por ordem (staging, 4.445 ordens):

| Terminal legado | Qtde no staging | Destino `transactions.status` | Projetadas | Exceções |
|---|---:|---|---:|---:|
| EFETIVADA | 4.304 | `settled` | 4.255 | 49 (sem bloqueio) |
| RECUSADA | 120 | `rejected` | 116 | 3 (sem bloqueio) + 1 (sem identidade de contraparte) |
| ERRO | 19 | `cancelled` | 19 | 0 |
| ICOM | 1 | `accepted` | 1 | 0 |
| AGENDADA | 1 | `pending` | 0 | 1 (sem bloqueio) |
| Total | 4.445 | | 4.391 | 54 |

`reason_code` das rejeitadas extraído do prefixo de `INFORMACAO_ADICIONAL` (AM04, DS04, AB11, CH16, AC06, FRAD, AB09, AB03, AC03). Valor da ordem vem de `BLOQUEIO_ORDEM_PAGAMENTO.VALOR`; ordem sem bloqueio não tem identidade financeira completa e vira exceção contada (nunca inventada).

### 4.2 PIX, anotações de crédito (entrada)

Terminal de `STATUS_ANOTACAO_CREDITO` por `END_TO_END`:

| Terminal | Destino `credit_notifications` | Obtido |
|---|---|---:|
| EFETIVADO | `processed = true` | 8.071 |
| CANCELADO | `processed = false` (motivo `INFO_ERROS` + `COD_DEVOLUCAO_PACS004` preservados na descrição) | 690 |
| Total | | 8.761 |

### 4.3 PIX, bloqueios (hold da ordem)

Terminal de `STATUS_BLOQUEIO_ORDEM_PAGAMENTO` por `END_TO_END`:

| Terminal | Destino `balance_blocks.status` | Obtido |
|---|---|---:|
| APROVADO | `confirmed` | 4.255 |
| RECUSADO | `released` | 117 |
| ERRO | `cancelled` | 20 |
| Total | | 4.392 |

A paridade 1:1 entre bloqueios `confirmed` (4.255) e transações `settled` (4.255) confirma o mapa.

### 4.4 PIX, extrato (já projetado na v1, sem mudança de dados)

`statement_entries` legadas: 13.250, sendo `booked` (SUCESSO) 12.424 e `legacy_erro` (ERRO, audit-only, jamais sensibiliza saldo) 826. Populações críticas do design conferidas via `transaction_returns`: devoluções com ERRO 396 (R$ 18.495.831,97) e devoluções com SUCESSO 92 (R$ 2.969.402,37).

### 4.5 PIX, devoluções, infrações e MED

| Projeção | Regra | Obtido |
|---|---|---:|
| `cecresa_spi.transaction_returns` | extrato `INDDEVOLUCAO=1` + vínculos de `ANOTACAO_DEVOLUCAO`; SUCESSO -> `completed`, ERRO -> `rejected` | 488 (completed 92, rejected 396) |
| `cecresa_dict.infraction_reports` | `RELATO_DE_INFRACAO`, enum DICT as-is | 390 (CLOSED 382, CANCELLED 8) + 1 exceção |
| `cecresa_dict.refund_requests` (MED) | `SOLICITACAO_DEVOLUCAO`, CLOSED -> `COMPLETED`, resultado preservado em `reason` | 205 |
| `cecresa_spi_msg.xml_messages` (faixa 1,1e12) | `ORDEM_PAGAMENTO_MENSAGEM` | 4.373 |

O total de 488 devoluções está dentro da faixa esperada de 488 a 507 (as 19 `ANOTACAO_DEVOLUCAO` adicionais só entram quando não existe movimento correspondente no extrato; todas tinham correspondência).

### 4.6 PIX, o que NÃO projeta (acervo em VIEW tipada)

| View | Conteúdo | Obtido |
|---|---|---:|
| `legacy_ab_pix.v_dict_keys` | `ENDERECAMENTO` (chaves DICT históricas; `cecresa_dict.keys` é do sync CID vivo) | 303 |
| `legacy_ab_pix.v_movimentos_contabeis` | `MOVIMENTOS_CONTABEIS_CONTAPI_*` (projeção contábil depende de `chart_of_accounts`, vazio na cabine) | 794 |
| `legacy_ab_pix.v_saldo_conta_pi` | `SALDO_CONTA_PI` | 215 |

`cecresa_spi.balances`: GATE ativo. Sem `--allow-balance-overwrite` a projeção é pulada com aviso explícito no stderr. Nas duas rodadas da v2 o audit registrou `cecresa_spi.balances = 0` (23:31:41 e 23:35:06 UTC). Trilha completa do gate no audit: as inserções com valor 1 são da carga pré-gate da manhã (14:43 a 14:48 UTC) e de um teste de fase 3 com a flag ativa (22:40 UTC, upsert convergente da mesma linha única); todas as rodadas sem flag (22:39, 23:02, 23:07, 23:18, 23:19, 23:31, 23:35 UTC) registraram 0.

### 4.7 SPB, mapa composto (STATUSSGR / STATUSSTR / SITUACAO) com contagens reais

Distribuição real do staging aplicada pelo `fix-spb`. `TRANS_INTERF_PASS` (10.461 linhas):

| Chave legada | Obtido | Estado canônico |
|---|---:|---|
| 5 / 02 / A com origem SPB (inbound) | 6.816 | `confirmed` |
| 5 / 04 ou 05 / A | 20 | `r1_rejected` |
| 5 / 06 / A | 5 | `processing` |
| 3 / vazio / A | 102 | `created` |
| 1 ou 2 / vazio | 1 | `created` |
| 9 / * / * | 3 | `r1_rejected` |
| * / * / C | 23 | `cancelled` |
| vazio / vazio (origem SPB, recebida da rede) | 3.491 | `confirmed` |

`TRANS_SISTEMAS` (130 linhas, sem XML): 5/02 -> `r1_confirmed` 126; 5/04-05 -> `r1_rejected` 4.

Direção: `CODSISTEMA_O = 'SPB'` -> `inbound`; origem EB/GI/SGR -> `outbound`. Nenhuma linha caiu no fallback `processing` por status desconhecido (contador de exceção `state_fallback_processing` = 0 nas rodadas finais).

## 5. Projeções PIX: contagens finais e conciliação ao centavo

Contagens finais legadas conferidas no `cc_pix` (idênticas antes e depois da rodada 2):

| Tabela destino | Legadas | Detalhe |
|---|---:|---|
| `cecresa_spi.transactions` | 4.391 | settled 4.255, rejected 116, cancelled 19, accepted 1 |
| `cecresa_spi.transaction_status_history` | 13.153 | staging tem 13.262; a diferença de 109 são exatamente os status das 54 ordens excluídas (comprovado por query: as 54 ordens têm 109 linhas de status) |
| `cecresa_spi.credit_notifications` | 8.761 | processed=true 8.071, processed=false 690 |
| `cecresa_spi.balance_blocks` | 4.392 | confirmed 4.255, released 117, cancelled 20 |
| `cecresa_spi.transaction_returns` | 488 | completed 92, rejected 396 |
| `cecresa_dict.infraction_reports` | 390 | CLOSED 382, CANCELLED 8 |
| `cecresa_dict.refund_requests` | 205 | todas CLOSED -> COMPLETED, resultado preservado |
| `cecresa_spi_msg.xml_messages` | 30.569 + 4.373 | faixas 9e11/1e12 (MENSAGEM_BACEN_PSP e RESPOSTA) + faixa 1,1e12 (ORDEM_PAGAMENTO_MENSAGEM); maior id vivo na faixa BACEN/PSP: 1.000.000.008.761 |
| `cecresa_spi.bacen_inbound` | 8.761 | respostas BACEN/PSP |
| `cecresa_spi.bacen_outbound` | 21.808 | mensagens BACEN/PSP |
| `cecresa_spi.statements` | 2.280 | extrato agregado por ISPB/conta/dia |
| `cecresa_spi.statement_entries` | 13.250 | booked 12.424, legacy_erro 826 |
| `cecresa_dict.parameters` | 36 | parâmetros de balde DICT |
| `cecresa_spi.balances` | 1 | linha pré-gate remanescente (ver seção 10) |
| `legacy_ab_pix.final_links` | 36.153 | transactions 4.391, status_history 13.153, credit_notifications 8.761, balance_blocks 4.392, returns 488, infractions 390, refunds 205, xml_opm 4.373 |

Conciliações ao centavo (todas conferidas por SELECT nesta validação):

1. Ordens efetivadas x extrato de débito: `transactions` settled soma R$ 163.295.572,53; as 49 EFETIVADA sem bloqueio (não projetadas) somam R$ 3.580.073,14 quando valoradas pelo extrato via E2E (49 de 49 encontradas). Soma: R$ 166.875.645,67 = soma exata dos 4.304 movimentos D/SUCESSO do extrato. Contagem: 4.255 + 49 = 4.304. Fecha ao centavo.
2. Anotações de crédito: soma das 8.761 `credit_notifications` legadas = R$ 159.722.913,42 = soma exata de `ANOTACAO_CREDITO.VALOR` no staging. Fecha ao centavo.
3. Bloqueios: soma dos 4.392 `balance_blocks` legados = R$ 168.935.505,42 = soma exata de `BLOQUEIO_ORDEM_PAGAMENTO.VALOR` no staging. Fecha ao centavo.

## 6. Correção do acervo SPB (fix-spb)

Contagens finais conferidas no `cc_spb`:

`bacen_messages` legadas (source = `legacy_ab_spb`): 14.101.

- `message_type = 'LEGACY'` restante: 0 (tipo real extraído do `<CodMsg>` do XML em 100% das mensagens).
- Direção: inbound 7.134, outbound 6.967.
- Estados: confirmed 13.939, created 103, cancelled 31, r1_rejected 23, processing 5. `legacy_imported` restante: 0.
- `operation_id` preenchido: 14.101 de 14.101 (backfill via `final_links`).
- Valor: 9.798 mensagens com valor extraído do XML via `value_tag` do catálogo; 4.038 sem `value_tag` no catálogo (ficam 0, contadas); 135 com tag ausente no XML (ficam 0, contadas).

Top 10 tipos reais em `bacen_messages`:

| Tipo | Qtde |
|---|---:|
| STR0008 | 5.398 |
| STR0008R2 | 2.973 |
| STR0008R1 | 2.681 |
| LPI0001 | 458 |
| LPI0003 | 296 |
| STR0006R2 | 286 |
| LPI0004 | 280 |
| LPI0002 | 271 |
| LPI0006 | 270 |
| LPI0001R1 | 226 |

(O STR0008 = 5.398 decompõe em 2.699 corpos de `CORPO_TRANS_INTERF_PASS` + 2.699 de `CORPO_TRANS_INTERF_USMSG_PASS`, conferido no staging.)

`spb_operations` legadas (created_by = `legacy_ab_spb`): 10.591.

- Estados: confirmed 10.307, r1_confirmed 126, created 103, r1_rejected 27, cancelled 23, processing 5. `legacy_imported` restante: 0.
- Direção: inbound 6.844, outbound 3.747 (há menos operações que mensagens porque respostas R1/R2 compartilham a operação da mensagem original).
- `error_code` preenchido: 17 (os estados raros com erro do design: EGEN1102, CODREJEICAO 99, EGEN0300, 03, EGEN1009).
- `message_type = 'LEGACY'` restante: 130, TODAS de `AB_MGI.TRANS_SISTEMAS` (sem XML), exceção declarada no design (seção 4.7: acervo auditável sem derivação).
- Top 10 tipos: STR0008 2.699, STR0008R2 2.695, STR0008R1 2.681, STR0006R2 277, LPI0006 270, LPI0001 256, LPI0001R1 226, LPI0003 188, LPI0002 156, LPI0004 156.

Complementos aplicados e conferidos:

- `operation_events` com `event_type = 'legacy_import'`: 10.591 (exatamente 1 por operação legada; timeline não renderiza vazia).
- `control_number_clearing` das inbound legadas com prefixo `LEGACY-` (não colide com o índice único parcial do fluxo vivo).
- `message_type_config`: 1.766 no total; `direction_flag` O/I = 0 (convenção da cabine E/R/B aplicada; a correção converteu 33 O->E e 18 I->R na primeira passada e ficou keyed no valor errado, então repetir dá 0).
- `message_tag_definitions`: 21.547.
- Reparo dos 5 pares de `final_links` cruzados por NUMCTRLSPB duplicado da primeira carga (re-pareamento determinístico por DTHRINC; segunda rodada = 0).
- `legacy_ab_spb.final_links`: 24.692 (spb_operations 10.591 + bacen_messages 14.101).

## 7. Prova de idempotência (delta zero)

Protocolo: snapshot de contagem das 22 tabelas destino (16 PIX + 6 SPB) antes e depois da segunda execução completa de `project` (que inclui `fix-spb`).

- Diff dos snapshots (antes x depois da rodada 2): VAZIO. As 22 contagens idênticas, incluindo `final_links` (PIX 36.153, SPB 24.692).
- `verify` capturado em três momentos (baseline, pós-rodada 1, pós-rodada 2): os três arquivos são idênticos byte a byte (97 itens de contagem).
- `projection_audit` das duas rodadas finais: PIX 30 linhas por rodada e SPB 28 linhas por rodada, com TODOS os inserts/updates = 0. As únicas linhas com valor diferente de 0 são os contadores informativos de exceção, estáveis nas duas rodadas: `transactions excecoes_nao_projetadas = 54` e `infraction_reports excecoes_nao_projetadas = 1`.
- Somente as tabelas `legacy_*.projection_audit` cresceram entre rodadas (registro da rodada, por design): PIX com 288 linhas acumuladas e SPB com 278 ao fim da validação.

Mecanismos que garantem o delta zero: inserts com `NOT EXISTS`/`ON CONFLICT DO NOTHING` sobre chave natural determinística (com dedup in-batch por `DISTINCT ON` nas mesmas chaves); updates do `fix-spb` convergentes (gravam o valor canônico derivado do staging e só tocam linha divergente, via `IS DISTINCT FROM`).

## 8. Exceções não projetadas (nunca inventar identidade financeira)

PIX, ordens de pagamento: 54 exceções (audit `cecresa_spi.transactions excecoes_nao_projetadas = 54`), decompostas por query no staging:

| Motivo | Qtde | Observação |
|---|---:|---|
| EFETIVADA sem registro em `BLOQUEIO_ORDEM_PAGAMENTO` | 49 | sem valor/contraparte no legado; valores comprovados no extrato via E2E (R$ 3.580.073,14) e fechando a conciliação 1 ao centavo |
| RECUSADA sem bloqueio | 3 | sem identidade financeira |
| AGENDADA sem bloqueio | 1 | ordem nunca executada |
| RECUSADA com bloqueio mas sem identidade completa de contraparte | 1 | não satisfez os filtros NOT NULL de contraparte |

Os 109 registros de `STATUS_ORDEM_PAGAMENTO` dessas 54 ordens explicam exatamente a diferença 13.262 (staging) - 13.153 (projetadas) do histórico de status (comprovado por query: as 54 ordens têm 109 linhas de status).

PIX, infrações: 1 exceção (audit = 1). O staging tem 391 relatos (CLOSED 383, CANCELLED 8); 390 projetados (CLOSED 382, CANCELLED 8). 1 relato CLOSED não satisfez os filtros de E2E/ISPB/valor e virou exceção contada.

SPB: 130 operações de `TRANS_SISTEMAS` permanecem com `message_type = 'LEGACY'` (sem XML para extração; acervo auditável, sem derivação financeira, previsto no design). Contadores de valor: 4.038 mensagens sem `value_tag` no catálogo e 135 com tag ausente no XML ficam com valor 0, contadas no audit.

Demais projeções: 0 exceções (credit_notifications, balance_blocks, transaction_returns, refund_requests).

## 9. Correções de review aplicadas nesta rodada

Antes da execução final, o script recebeu as correções do code review (único arquivo tocado: `etl/legacy_pix_spb/load_legacy_pix_spb.py`; `py_compile` OK, reconferido nesta validação):

1. Achado 3: `DISTINCT ON (END_TO_END)` em `amount_ac` e `amount_bl` (candidatos de valor de `infraction_reports`), com `ORDER BY source_pk` para determinismo. Resultado inalterado: 390 projetadas + 1 exceção.
2. Achado 4: dedup in-batch por `DISTINCT ON` nas chaves dos `NOT EXISTS` de `tx_src` (e2e), `bloq` (ID_ORDEM_PAGAMENTO), `cn_src` (notification_id), `bb_src` (ID_ORDEM_PAGAMENTO) e `med_src` (refund_id), com ordenação determinística. Verificado antes: 0 duplicatas em todas as chaves (8 checagens no staging); contagens inalteradas.
3. Achado 9: `sanitize_output()` aplicado em `run()`, no raise de COPY e no raise do sqlcmd (remove linhas CONTEXT/DETAIL do psql, que ecoam a linha CSV com JSONB cru, e trunca em 1.500 caracteres). Testado empiricamente: PII sintética não vaza; erro real de psql vira RuntimeError curto.
4. Achado 6 (cosmético): janela do `verify` de `cecresa_spi_msg.xml_messages` ampliada para 900000000000..1099999999999. Banda 1,01e12..1,0999e12 confirmada vazia nesta validação (0 linhas); contagem permanece 30.569; maior id vivo 1.000.000.008.761.
5. Achados 1, 2, 5, 7, 8, 10, 11 e 12: verificados e confirmados como não-defeito ou informativos, sem mudança de código (a semântica dos contadores 54 e 1 foi reconfirmada nas duas rodadas; `balances` não rodou, flag desligada).

## 10. Divergências e observações (nenhuma omitida)

1. `spb_operations` com `message_type = 'LEGACY'` = 130, não zero: são as 130 linhas de `TRANS_SISTEMAS` sem XML, exceção declarada no design (seção 4.7). No nível de `bacen_messages` o LEGACY restante é 0, como esperado.
2. `transactions` settled = 4.255 e não 4.304: as 49 ordens EFETIVADA sem bloqueio não têm identidade financeira completa e, por design, viraram exceção contada; seus valores foram comprovados no extrato (R$ 3.580.073,14) e fecham a conciliação 1 ao centavo.
3. `infraction_reports` = 390 + 1 exceção: o design citava CLOSED 383; obtido CLOSED 382 projetados (o staging tem 383 CLOSED; 1 não satisfez os filtros e está contado no audit).
4. `cecresa_spi.balances` contém 1 linha legada (source `legacy_ab_pix:BALANCO_SALDO_SPI:1382`, inserida em 2026-07-01 14:43 UTC), proveniente da carga anterior PRÉ-gate. As duas rodadas desta execução pularam `balances` (audit = 0). A linha não foi removida por ser dado pré-existente fora do escopo de escrita desta execução. Houve ainda um teste de fase 3 às 22:40 UTC com a flag ativa (audit = 1, upsert convergente da mesma linha única), que comprova o gate nos dois sentidos.
5. Baseline de staging PIX no início desta execução já era 2.091.046 linhas / 65 fontes (maior que os 2.083.978 / 55 da carga v1): a fase 3 já havia stageado tabelas extras e rodado as projeções (audits de 22:39 a 23:19 UTC). Por isso a rodada 1 de `project` pós-stage já inseriu 0 em tudo, o que não refuta nada e reforça a idempotência.
6. Split de direção inbound 7.134 / outbound 6.967 vale para `bacen_messages` (14.101). Em `spb_operations` (10.591) o split é inbound 6.844 / outbound 3.747, porque há menos operações que mensagens (respostas R1/R2 compartilham operação). Consistente com o design.
7. Contagens da tabela 4.7 do design eram estimativas de fase 1 e diferem levemente nos buckets não-terminais: obtido 3/vazio = 102 (design 105), 1-2/vazio = 1 (design 17), vazio/vazio = 3.491 (design 3.495), 5/04+5/05 = 20 (design 9+11 = 20, exato). Os totais de estado canônico conferem com as operações vivas (created 103, processing 5, cancelled 23). O 17 do design corresponde na verdade às linhas com código de erro (`error_code` preenchido = 17, exato).
8. Idem para o tipo STR0008: o design estimou 5.425 na extração de CodMsg; o obtido em `bacen_messages` é 5.398 (2.699 + 2.699 conferidos no staging por regex idêntica à do script).
9. Processo permaneceu 100% local: nenhum comando `aws`, nenhum acesso a Aurora/HML. Nenhuma edição de arquivo do repositório foi necessária durante a execução final (o script já continha as extensões da fase 3; a modificação de `etl/legacy_pix_spb/load_legacy_pix_spb.py` segue não commitada na working tree, decisão de commit é do dono).

## 11. Pendências para promoção a HML (seção 7 do design; exige aprovação do dono)

1. Retarget dos schemas `cecresa_*` para `monetarie_*` e conexão Aurora (reescrita revisada; o script atual é incapaz de atingir HML por construção: docker exec local e schemas locais hardcoded).
2. Gate de `balances` mantido; definir janela e snapshot de rollback ANTES de qualquer carga em HML (o upsert é destrutivo por ISPB).
3. Mudanças de código da cabine SPB para exibição do acervo: KPIs/dashboards filtrando por proveniência (`source <> 'legacy_ab_spb'`), tela/aba de acervo read-only, `humanize_state` sem label cru.
4. Decidir exibição das linhas `legacy_erro` do extrato PIX (tela vs auditoria); hoje são 826 linhas audit-only que jamais sensibilizam saldo.
5. Reconciliação pós-carga em HML contra os totais deste relatório (seções 5 e 6).
6. Mapa oficial de status legado agora está comprovado com dados (seção 4); pendências declaradas do design continuam válidas para cargas futuras: STATUSSTR 03/07, TIPO_M R3, domínio completo de STATUSSPB e TIPO_E 'N' não ocorrem neste backup; se surgirem, mapear para `processing` + relatório.

## 12. Evidências

- Banco local (fonte primária desta validação): `legacy_ab_pix.*` e projeções em `cc_pix`; `legacy_ab_spb.*` e projeções em `cc_spb`, container `monetarie-postgres-1`.
- Audits: `legacy_ab_pix.load_audit` / `projection_audit` (288 linhas) e `legacy_ab_spb.load_audit` / `projection_audit` (278 linhas), com as duas rodadas finais integralmente zeradas.
- Logs da execução (scratchpad da sessão): `etl_stage_all.log` (265 tabelas, 0 erros), `etl_project_run1.log`, `etl_verify_run1.log` (42 itens PIX + 55 SPB), `verify_baseline.txt` = `verify_round1.txt` = `verify_round2.txt` (idênticos), `counts_before_run2.txt` = `counts_after_run2.txt` (22 tabelas, diff vazio), `before_pix/after_pix` e `before_spb/after_spb` (diffs vazios).
- Relatórios anteriores da carga v1: `docs/reports/2026-07-01-pix-spb-etl-handoff-claude.md`, `2026-07-01-pix-spb-cabine-etl-manifest.md`, `2026-07-01-pix-spb-etl-load-result.md`, `2026-07-01-sqlserver-backups-etl-map.md`.
