# Handoff 14/07 (tarde): P1-P6 em produção, P7-P9 mapeados

`origin/main` nesta sessão: 6b36946c (P1+P2 core), 0c32c57e (mapa dashboard),
35262284 (P5), 10bcd99c (P6), 61e9e08e (P3+P4 pix), 2f4e2736 (P4 core).

## Produção (cluster monetarie-greenfield-prod)

| serviço | rev PROD | rollback | conteúdo |
|---|---|---|---|
| core-api | :35 | :34 | P1 unidade Subcent, P2 bacen_reference, P4 responder validate_debit |
| core-admin-ui | :13 | :12 | tela Liquidação (Subcent, Identificador BACEN filtrável) |
| pix-api | :36 | :35 | P3 PayerIdentity (DICT 503), P4 gate conta-corrente no envio manual |
| pix-admin-ui | :17 | :16 | consulta manda payer_document; erros legíveis no submit |
| spb-api | :24 | :23 | P5 alias ISPBIF*/CNPJCli* no Construtor, P6 payer/beneficiary na lista |
| spb-admin-ui | :8 | :7 | colunas e cards Pagador/Recebedor |

HML: core-api:130, core-admin-ui:23, pix-api:154, pix-admin-ui:40,
spb-api:52, spb-admin-ui:16. Migration 20260714150000 aplicada em HML
(ecto.migrate) e PROD (DDL idempotente via rpc + schema_migrations).

## Provas vivas em produção (read-only)

- P1/P2: GET /treasury/transactions devolve a TED do incidente com
  amountSubcent=12834700 (R$ 1.283,47) e bacenId=STR20260714033393350
  (num_ctrl_str) por fallback de leitura; filtro bacenIdType só devolve o
  trilho pedido; neutros não filtram.
- P3: Keys.lookup_entry("01264764030") com PayerIdentity institucional
  resolveu no DICT REAL: MURILO DE MELLO BAYER (mesma chave que dava 503 em
  ~10ms sem sair para o BACEN — logs de 14:23Z).
- P4: [PixDebitValidator] Subscribed em HML e PROD; gate fail-closed provado
  por teste (7/7 pix, 7/7 core). Em produção sem teste (regra do dono) — o
  primeiro envio manual real valida a ponta.
- P5/P6: spb-api:24 subiu com catálogo 992 XSDs; spb_operations em PROD já
  mostra payer_name/beneficiary_name reais (MUNICIPIO DE RIO DE JANEIRO na
  TED de R$ 1.283,47).

## Suítes vs baselines (mesma seed 42)

- core: 7282/68 -> 7298/66; diff por NOME = só 2 flaky de cripto e-Financeira.
- pix: 3770/23 -> 3781/23; conjuntos de falha IDÊNTICOS.
- spb: 17608/76 (handoff anterior: 77); 31 arquivos com falha dão 75 COM e
  SEM as mudanças (prova por stash).
- Frontend admin core: 319/319. Build spb-frontend ok.

## Decisão canônica (P2)

TED no BACEN: NumCtrlSTR é o análogo do E2E (XSD oficial STR0008.XSD v5.12:
atribuído pelo STR, único identificador presente em R1 E R2; já era a chave
de idempotência do TED-in nas duas pontas). NUOp é controle do envelope
BCMSG por perna (prefixo = ISPB do emissor da mensagem) e NÃO identifica a
operação. TED ENVIADA ainda fica sem referência (a cabine não repassa o
NumCtrlSTR do R1 no notify_status_change — follow-up).

## Pendências (ordem do dono: depois desta subida)

- P7: relatório diário movimento/saldos SPB — evidência completa em
  docs/reports/2026-07-14-paridade-relatorios-diarios-legadospb.md. Backend
  ~80% pronto (/exports/movement CSV, /reports/reserve-statement,
  balance_positions history); a tela Relatórios do OPERADOR é STUB.
- P8: relatório fixo de recebimentos PIX/TED/boleto com pagador/recebedor e
  nome validado. Extração imediata ENTREGUE: TEDs recebidas desde 09/07
  (108 ops, R$ 1.411.230,43, CSV no desktop do dono via chat).
- P9: dashboard SPB com reserva confirmada BACEN (consulta de saldo) +
  saldo auto-atualizado em envio/recebimento (base: balance_positions +
  Liquidante.BalanceManager).
- Mapa de melhorias do dashboard pix-admin (referência AutBank Gestão Conta
  PI): docs/reports/2026-07-14-mapeamento-dashboard-conta-pi-autbank.md.
- P4 follow-up: envio manual ainda NÃO debita a conta do cliente no Core (o
  gate impede envio sem lastro; o débito automático é a próxima etapa).
- Alerta observado em PROD: DLQ money-path acima do teto
  (monetarie.dlq.pix.failed=5, spb.failed=3, poison.outbound-sender=2) —
  investigar e reprocessar manualmente.

## Gotchas novos

- Teste verde-falso: alimentar teste com a TAG CRUA do catálogo esconde o
  descasamento com a chave snake que a tela realmente posta (P5).
- run-task de migration em PROD/EC2: reserva de MEMÓRIA é da task-def
  (override de container não ajuda); saída = DDL idempotente via rpc na
  task viva + INSERT em schema_migrations.
- Contrato de tela: unidade monetária no NOME do campo (*Subcent) — o
  `amount` sem unidade foi a raiz do 10.000x.

## Adendo (fim do dia): P7, P8, P9 e fluxo do P3 TAMBÉM em produção

Onda 2 em PROD (tag prod-3c1963cf-20260714, mesmo digest de HML):
core-api:36, core-admin-ui:14, pix-admin-ui:18, spb-api:25, spb-admin-ui:9
(rollbacks :35/:13/:17/:24/:8).

- P7: Relatórios do operador SPB reais (Movimento diário com preview + CSV de
  /exports/movement; Extrato de Reserva com D/C, sumário e saldo de
  abertura/fechamento do dia; Saldos diários por data com export). Validado
  vivo em HML (login + 200 nos dois endpoints).
- P8: GET /treasury/receipts (JSON + CSV) + tela Relatório de Recebimentos no
  coreadmin. PROVA EM PRODUÇÃO: rail=ted de 09 a 15/07 devolve 108 TEDs,
  total R$ 1.411.230,43 — AO CENTAVO igual à extração entregue ao dono
  (XLSX no Desktop), com pagador do fio (nome/CNPJ), titular do cadastro e
  NumCtrlSTR por linha.
- P9: dashboard SPB com card "Reserva confirmada BACEN" (fonte STR0013R1
  SldRB_CL / STR0014R1, com hora e chip de origem; Liquidante dormente não
  foi usado) e card "Saldo em movimento" com polling de 10s no novo
  GET /balances/live (TDD 3/3).
- P3 (fluxo): Nova Transação começa pelo pagador; o CPF/CNPJ digitado vira o
  PI-PayerId (consulta bloqueada sem ele) e o E2E devolvido pela consulta é
  persistido e enviado na criação — a pacs.008 sai com o MESMO E2E da
  consulta, sem depender do TTL do cache.

Suítes da onda 2: core 7303/67 (diff = flaky conhecido), vitest 325/325,
spb 3 falhas novas PROVADAS pré-existentes por stash (3=3, mesma seed).
Pendência de qualidade: validar os números dos relatórios novos contra o
acervo AutBank ao centavo antes de liberar ao cliente final.

## Adendo 2 (P10): trava de conta-corrente nos DOIS trilhos + menu unificado

PROD: core-api:37 (rollback :36), spb-api:26 (:25), spb-admin-ui:10 (:9).
HML: core-api:131, spb-api:54, spb-admin-ui:18.

- P10: STR0008 e qualquer financeira do Construtor com ag/conta debitada de
  cliente NOSSO só sai após o Core validar existência + saldo
  (core.validate_debit.request, subject neutro do MESMO responder do PIX;
  fail-closed). PROVA EM PRODUÇÃO: round trip SPB->NATS->Core respondeu
  account_not_found para conta inexistente e o gate travou o STR0008 com
  422. dry_run e débito em outra IF não passam pelo gate; fluxo do IB não
  entra por esse controller (Core reserva antes).
- Menu do spb-admin: o bloco operacional era v-else e ESCONDIA do admin os
  relatórios operacionais/saldos/contabilidade/exportações (raiz da
  reclamação do dono às 13h18). Admin agora vê TUDO (seção "Operacional").
  As telas novas ficam em /operator/reports e /operator/balances, acessíveis
  pelo menu do admin.
- RBAC real: roleCanAccess("operator") aceita QUALQUER usuário logado — a
  divisão admin/operador não é fronteira de segurança hoje. Aperto vai junto
  com o P11.
- Incidente de deploy evitado: o retag PROD falhou por word-split do zsh
  (gotcha conhecido) DEPOIS das task-defs registradas; retag refeito antes
  dos pulls esgotarem, rollouts completaram normais.

PRÓXIMO (P11): débito AUTOMÁTICO no conta-corrente para envios manuais dos
dois trilhos (registrar + hold no Core na criação; liquidar no R1/pacs.002;
estornar hold na rejeição — reusando OutboundRequests/SpbHandler/PixHandler,
a máquina provada do IB). Exige deploy coordenado e prova E2E em HML.

## Adendo 3 (14/07 madrugada) — PIX-out pacs.008, suítes zeradas, P18, Últimas Movimentações

- **Incidente PIX-out RESOLVIDO** (relato completo em
  `docs/reports/2026-07-14-pix-out-rejeicoes-pacs008-agencia.md`): 3 rejeições
  reais (AC03 BB 2x, AB09 Bradesco) causadas pela NOSSA pacs.008 sem a agência
  do recebedor (`Issr`), que o DICT entregava e todos os caminhos descartavam.
  Fix nos 3 caminhos (builder normaliza valor p/ 2 casas; controller manual
  completa recebedor da consulta DICT cacheada; CoreEventProcessor com
  creditor_params/2; tela com campos Agência e DICT forçado em envio por
  chave). As 3 reservas presas foram finalizadas (uma via pipeline real de
  evento rejected; a kot2yx exigiu camt.060 consulta de operação porque a
  pacs.002 se perdeu — o SPI respondeu camt.054 INFO + AC03).
- **P17 CONCLUÍDO — suítes ZERADAS**: PIX 3.817/0, Core 7.315/0, SPB 17.644/0.
  No Core, 3 defeitos REAIS de produção corrigidos: 16 cron workers ausentes do
  bloco :prod do runtime.exs; GET /accounts/:id/balance devolvia 200 com saldo
  0 para conta inexistente (agora 404); migrations não reproduziam o schema
  vivo de webhooks (migration idempotente `20260714200000`, aplicada em HML e
  PROD — atenção: o nome do arquivo não pode conter "secret" por causa do
  padrão `*_secret*` do .gitignore).
- **P18 em PROD**: motivo de rejeição COM código ISO (RejectCodes = fonte
  única; catálogo deriva dela) na timeline/histórico + GET
  /transactions/:id/xml com as mensagens BACEN cruas + chip de rejeição e
  seção XML no detalhe da transação.
- **Últimas Movimentações REAL**: GET /api/balances/movements (ledger
  balance_movements + contexto spb_operations) + tela Saldos do operador
  ligada (110 movimentos vivos em PROD no momento do deploy).
- **Deploys finais**: PROD core-api:40, core-admin-ui:15 (PR16 + telas),
  pix-api:39, pix-admin-ui:20, spb-api:29 (sidecar MQ preservado),
  spb-admin-ui:12. Rollbacks: :39/:14/:38/:19/:28/:11. HML: core-api:135,
  pix-api:158, pix-admin-ui:44, spb-api:58, spb-admin-ui:20, core-admin-ui:25.
- `origin/main = 91be6801`.

## Adendo 4 (14/07 noite) — envio manual DESTRAVADO, fim do "Aguardando retorno", relatórios SPB reais

- **Cliente travado no envio (RESOLVIDO, 2 defeitos)**: (1) CPF com máscara
  estourava a check constraint no insert do Payment (500 cru) — documento
  normalizado na borda + constraint no changeset (422 legível) + tela envia
  sem máscara; (2) a retentativa ficava fail-closed PARA SEMPRE: o
  `collapse_transfer_results` come o `:exists` do batch LINKED reenviado e a
  cura `all_exists?` nunca via a evidência — agora, só `linked_event_failed`
  = verificação NO LEDGER (lookup dos ids determinísticos) e convergência
  idempotente. Reserva órfã do incidente (R$1, e2e ...ryxvl2u4w6g) desfeita
  pelo caminho real (`void_and_fail`, nada enviado ao BACEN — provado).
- **Fim do "Aguardando retorno" eterno (ordem do dono)**:
  `PaymentStatusReconciler` (tick 30s) dispara camt.060 consulta de operação
  para pacs.008 OUTBOUND pendente há >90s (lote 10, backoff 5min por E2E via
  `camt060_requests` action `op_status:<e2e>`); o InboundProcessor resolve a
  transação pela camt.054 (INFO+código = rejected; BOOK+DBIT = settled)
  publicando o MESMO evento da pacs.002. Universo em PROD no deploy: 0
  presas. Follow-up: transação que NUNCA foi ao BACEN (admi.002 not_found)
  volta à fila após o backoff — inofensivo com lote 10, mas merece um estado
  terminal local.
- **Monitor fala a verdade**: cada fluxo carrega `transaction_status`
  (messages.status_id → ISO, query em lote) com prioridade sobre a derivação
  por pernas. Validado vivo em PROD: kot2yx/lokwg5/su36au = RJCT.
- **Movimento diário SPB (3 defeitos reais)**: entidade = contraparte REAL
  (ISPBIFCredtd/Debtd do XML + institutions; "STR"/"Banco Central" errados
  eliminados), finalidade/CPFs extraídos das tags REAIS do XSD v5.12
  (Finld/CNPJ_CPFDebtd não existem no fio), sinal por crédito/débito via a
  R2 do fio (o flag do código-pai assinava recebimento como débito).
  Validado vivo em PROD: "Banco do Brasil S.A." / "Banco Bradesco S.A.",
  valores de recebimento positivos, finalidade e documentos preenchidos.
- **Últimas Movimentações**: UMA operação = UMA linha (DISTINCT ON preferindo
  confirmada; caso SME0001 do dono validado vivo colapsando para 1 linha).
- **Deploys PROD**: core-api:41, pix-api:40, pix-admin-ui:21, spb-api:30
  (sidecar preservado), spb-admin-ui:13. Rollbacks: :40/:39/:20/:29/:12.
  Suítes: PIX 3.835/0, SPB 17.664/0. `origin/main = d1a91611`.

## Adendo 5 (14/07 madrugada) — devolução recebida CORRIGIDA pela verdade do BACEN, extrato completo, índices

- **Devolução recebida (pacs.004): o dono estava certo DUAS vezes.** (1) O
  replay planejado creditaria R$0,50 de operação INEXISTENTE: a consulta de
  operação (camt.060 EvtId=RtrId) provou que a devolução do Bradesco EXPIROU
  POR TIMEOUT (Sts INFO + AB03, "Pagamento expirado por timeout") — o SPI só
  liquida a devolução após o ACEITE pacs.002 do PSP do pagador original, e
  nós nunca respondemos (o erro no Bradesco fomos nós). (2) A versão da
  própria noite (nascer liquidada + creditar no recebimento) estava ERRADA e
  foi corrigida ANTES de ir a produção. Fluxo em PROD agora: pacs.004
  recebida nasce PENDENTE → aceite pacs.002 ACSP (OrgnlInstrId=RtrId,
  formato provado no LegadoPIX) → crédito SÓ na liquidação confirmada
  (camt.054 BOOK do RtrId → returned com valor PARCIAL e teto acumulado;
  INFO+código → RJCT sem crédito). O reconciliador também varre devoluções
  recebidas pendentes. A devolução real (tx 13498, return_id nulo no acervo)
  fica INTOCADA — reapresentação é comando do dono.
- **Extrato COMPLETO (ordem do dono)**: Máquina A grava account_entries no
  settle (ZERO linhas no acervo antes — o PIX de R$1 do Gabriel era invisível
  e o saldo divergia do ledger); evento da cabine carrega as PARTES (payments
  → nome/documento/conta); listagem + PDF + CSV do extrato com colunas
  Pagador/Recebedor derivadas do metadata real. Backfill do R$1 executado em
  PROD: conta 2031 com 4 linhas e saldo R$59,00 = ledger.
- **Índices em PROD nas 3 bases** (HML idem): pix 8 índices (GIN trigram no
  acervo + resource_id + original_e2e), core (account_entries recuperou
  índice secundário + trigram de busca), spb 9 índices — correlação por
  ILIKE caiu de full scan (255MB) para 11ms/9ms COM índice (provado por
  EXPLAIN). GOTCHA operacional NOVO: `statement_timeout=30s` no pool de PROD
  do pix MATA qualquer DDL longo (deixa índice INVALID); o runner correto é
  conexão Postgrex dedicada com `SET statement_timeout=0` via rpc.
- **Data Liquidação**: gravada no settle (D0, fuso de Brasília) + derivação
  para o acervo; tela de detalhe com mount paralelo e XML lazy.
- **Higiene de teste**: SpiService.Repo (pool próprio do espelho PI) agora é
  sandboxed no teste de liquidação de devolução — o crédito BOOK commitava
  de verdade no banco de teste e o resíduo (2,50) quebrava o saldo projetado.
- **Deploys PROD**: pix-api:41, pix-admin-ui:22, core-api:42,
  core-admin-ui:16, spb-api:31 (rollbacks :40/:21/:41/:15/:30).
  `origin/main = 1b91f46f`. Suítes: PIX 3.865/0*, Core 7.335/0, SPB 17.671/0
  (*última rodada completa antes do fix de sandbox: 795/0 no spi isolado).
