# Runbook W1-F5 — lote de pacs.008 (empacotamento ate 10) — G3 em HML + janela dedicada de PRD

Escrito na task B11 da frente F5 (Wave 1). EXECUCAO: SOMENTE o orquestrador.
Mandato do dono (17/07): deploy PRD desta frente APENAS em janela dedicada
com acompanhamento de logs; ligar QUALQUER flag = decisao explicita do dono.

## 0. O que este deploy carrega (tudo dormente por default)

- Leitura multi-tx (B1-B3): JA em PRD (pix:62, deploy do P0 em 18/07).
- Builder `:transactions` (B4): so e exercitado pelo lote/simulador.
- Lote no OutboundSender (B5): `PIX_OUTBOUND_BATCH_ENABLED=false` (mestre;
  OFF = drain de mailbox nem acontece — comportamento byte-identico).
- Simulador multi-tx + cenario `:partial_reject` (B6): so simulador.
- Fan-out terminal de admi.002 de lote (B7): so age sobre claims com
  `batch_message_id` (inexistentes com a flag OFF).
- Token bucket ICOM (B8): `PIX_ICOM_BUDGET_MODE=observe` (NUNCA bloqueia;
  so telemetria/warning). ATENCAO: B8 tambem REVIVEU o desfecho terminal de
  4xx sincrono do POST (antes todo 4xx caia em retry ate DLQ) e o 429 passa
  a respeitar Retry-After DE FATO (delay do NAK = max(backoff exponencial,
  Retry-After)) — MUDANCA VIVA mesmo com flags OFF (correta: antes era loop
  de re-POST; vigiar na janela). **EXCECAO (H1 da revisao adversarial): a
  pacs.004 (devolucao, obrigacao regulatoria) NAO entra no 4xx-terminal —
  mantem retry ate esgotamento; incluir a pacs.004 no
  terminal e decisao FUTURA do dono.**
  Atualizacao B6+fix (19/07): a excecao H1 virou configuravel pela flag `PIX_RETURN_4XX_TERMINAL_ENABLED`. Comportamento REAL dos dois modos: OFF (default) = a pacs.004 4xx faz retry ate o esgotamento e ai o BaseWorker ACKa e manda a DLQ SEM passar por handle_failure (ramo `{:retry}`), ou seja, SEM alerta e com a linha PDNG eterna (DLQ SILENCIOSA; a deteccao fica com StuckOutbound/reconciliacao). ON = terminaliza ja na 1a recusa 4xx pelo trilho barulhento do return_not_sent (log ERRO + linha RJCT + alerta critico return_failed + aviso `return.rejected` ao Core quando a devolucao e origin=client), com ACK imediato (sem NAK: cada redelivery re-assinava e re-POSTava a MESMA pacs.004, e um re-POST aceito apos o RJCT abriria devolucao DUPLA com o reenvio manual do operador); alem disso o gate de status da pacs.004 barra re-POST em QUALQUER redelivery de linha nao-PDNG. O flip em PRD e decisao operacional do dono.
  FLIP EXECUTADO 19/07 tarde: `PIX_RETURN_4XX_TERMINAL_ENABLED=true` nas task-defs pix-api de HML (:192) e PRD (:66), provado no BEAM vivo dos 2. NOTA DE EXPOSICAO (follow-up do handoff 19/07): com a flag ON, 4xx AMBIGUOS tambem terminalizam (ex.: 404 de janela de propagacao, 409) — mesma exposicao ja aceita para a pacs.008 desde o B8/F5; o alerta critico `return_failed` cobre o caso e o reenvio manual do operador e o caminho de cura.
- Quarentena de lote AMBIGUO (C1 da revisao adversarial): erro de
  transporte ambiguo (`:timeout` etc.) num POST de lote MANTEM os claims de
  membros+envelope ("em duvida, NAO reenviar" — reenvio unitario teria
  BizMsgIdr novo com os MESMOS E2Es). As linhas ficam PDNG com claim: caem
  na deteccao do StuckOutbound/reconciliacao. Vigia da janela: telemetria
  `[:pix, :outbound, :batch_quarantine]` + log "claims MANTIDOS". Release
  imediato SO em erro comprovadamente pre-conexao (econnrefused, nxdomain,
  pool_timeout) e no 429. 4xx sincrono no ENVELOPE = fallback unitario (M1:
  manual garante 4xx = nada gravado; cada membro ganha o SEU veredito).
- PERF por sub-fase (B9): linhas `[ICOM] SEND_OK/SEND_FAIL` novas (info) —
  vivas com flag OFF (batch=1).

## 1. Migration

- `pix/backend/apps/shared/priv/repo/migrations/20260718130000_add_batch_message_id_to_outbound_send_claims.exs`
  (aditiva, idempotente: ADD COLUMN IF NOT EXISTS + CREATE INDEX IF NOT
  EXISTS em `monetarie_spi.outbound_send_claims`).
- Aplicar via rpc no container novo, HML ANTES de PRD:
  `bin/monetarie_pix rpc "Shared.Release.migrate()"`.
- Janela pre-migrate e segura: o codigo so escreve `batch_message_id` com a
  flag ON (OFF = INSERT nas colunas antigas).

## 2. HML — G3 da frente (validacao viva roteirizada)

1. Deploy pix-api em HML com TODAS as flags OFF. Conferir ICOM CPM+CSM
   reassumidos pos-swap (lider + sessoes; zero janela surda).
2. Caminho unitario intacto: 1 PIX real do parceiro (OAuth via tunel SSM
   18080), conferir pacs.002 e extrato; nos logs, linha nova
   `[ICOM] SEND_OK rid=... batch=1 gate_ms=.. sign_ms=.. xsd_ms=.. post_ms=..`.
3. Ligar SO em HML: `PIX_OUTBOUND_BATCH_ENABLED=true` (manter
   `PIX_BATCH_MAX_TXS=10`, `PIX_BATCH_WINDOW_MS=0`).
4. Injetar rajada de 12 PIX reais/validos (parceiro OAuth, valores minimos,
   contas conhecidas). Provar VIVO:
   - 2 POSTs nos logs: `SEND_OK ... batch=10 batch_key=HIGH|PAGPRI|CPM
     merge_ms=..` e `SEND_OK ... batch=2 ...`;
   - 12 desfechos individuais (pacs.002 por E2E; B3 aplica multi-status se
     o SPI consolidar);
   - claims: `SELECT message_id, result, batch_message_id FROM
     monetarie_spi.outbound_send_claims WHERE batch_message_id IS NOT NULL`
     = 12 membros "sent" em 2 batch_message_id distintos + 2 claims de
     envelope "sent"; ZERO membro orfao;
   - webhooks/extrato por transacao no Core;
   - ICOM CPM/CSM saudaveis; `[:pix, :outbound, :batch]` size 10 e 2;
   - budget observe: `[:pix, :icom, :budget]` SEM evento de overdraft.
5. Cenarios de falha em HML (opcional, recomendado): derrubar o sidecar
   mTLS durante uma rajada — esperar release total dos claims + redelivery
   UNITARIA (attempt>1 nunca re-loteia).
6. Evidencia colada no fecho da frente (logs + selects + extrato).

## 3. PRD — janela dedicada (mandato)

1. Janela combinada com o dono, NUNCA durante operacao ao vivo do
   money-path; freeze durante as sequencias do cliente (21/07).
2. Deploy com flags OFF (comportamento identico ao atual, exceto o fix
   4xx/429 do B8 — item 0). Ordem: nenhuma dependencia de core-api nesta
   frente; pix-api sozinho. Migration via rpc ANTES de considerar a janela
   fechada.
3. Pos-swap: ICOM CPM+CSM reassumidos (lider + sessoes), health 200, DLQ
   estavel. Vigiar por >= 30min: `[ICOM] SEND_OK` (batch=1), `SEND_FAIL`,
   `[:pix, :icom, :budget]` (overdraft = vazao acima da tabela do manual),
   429 nos logs do Client, DLQ depth.
4. Rollback = revisao anterior do task-def (anotar ANTES do swap). A
   migration e aditiva — rollback de codigo nao exige rollback de DDL.
5. **Ligar o lote em PRD = decisao explicita do dono em janela propria**,
   com vigia de `SEND_OK batch=`, claims por batch_message_id, DLQ e budget
   em observe. Comecar com rajadas controladas nossas antes de trafego de
   cliente. Em producao nao existe teste: prova definitiva = trafego real
   acompanhado 100%.

## 4. Knobs (fonte: config/runtime.exs)

| Env | Default | Teto hard | Efeito |
|---|---|---|---|
| `PIX_OUTBOUND_BATCH_ENABLED` | false | - | mestre do lote (OFF = zero drain) |
| `PIX_BATCH_MAX_TXS` | 10 | 2..10 (raise no boot) | tx por envelope |
| `PIX_BATCH_WINDOW_MS` | 0 | 0..50 (raise no boot) | espera adicional de coleta (debita ANS de TODAS as tx) |
| `PIX_ICOM_BUDGET_MODE` | observe | observe/enforce/off | bucket cliente do manual §2.2.1.5 |
| `PIX_ICOM_CPM_BUCKET` / `PIX_ICOM_CPM_RECHARGE` | 3750 / 750 | - | parametros do bucket CPM |

## 5. Regras duras herdadas

- Nunca deployar/reiniciar pix durante operacao ao vivo (ICOM perde
  mensagem na troca de lideranca); deploy combinado com o dono.
- Flags nascem OFF; ligar = decisao do dono, por ambiente.
- Migrations sempre aditivas/idempotentes, via rpc, no MESMO commit do
  codigo (classe netting).
- Em producao nao existe teste — validacao definitiva e trafego real
  acompanhado, perna a perna.
