# PENDENTE (validar em HML amanhã): req/reply validate_account dentro do stream JetStream

> **NÃO IMPLEMENTAR sem a sessão de análise em HML combinada para 2026-07-11.**
> Diagnóstico feito 100% com código e histórico git LOCAIS (nenhum acesso a HML/prod).
> Registrado a pedido do dono como insumo, não como ação.

## Sintoma (provado vivo no LOCAL)

O caminho realista pacs.008 → InboundProcessor da cabine → validação de conta no Core → crédito está quebrado no ambiente local: a mensagem envenena até a DLQ sem gerar pacs.002 nem crédito. (Por isso o E2E do estudo de hoje precisou injetar `transaction.created` direto no NATS, pulando a cabine.)

## Causa raiz

O req/reply `monetarie.core.pix.validate_account` (cabine → Core) casa com o escopo `monetarie.core.>` do stream JetStream **MONETARIE_CORE**. Quando o `Gnat.request` publica com reply-to, o servidor JetStream responde o **PubAck** (`{"stream":"MONETARIE_CORE","seq":N}`) no mesmo inbox ANTES da resposta real do Core. O caller pega o PubAck, não acha a chave `valid`/`reason`, cai em `:unexpected_response` → `{:retry}` → NAK ×max → poison DLQ.

Prova viva local (corrida): publish com inbox manual + reply_to → reply #1 (+233ms) = PubAck `{"stream":"MONETARIE_CORE","seq":7}`; reply #2 (+260ms) = a resposta real do Core.

## Pontas e streams

- **Caller**: `pix/backend/apps/spi_service/lib/spi_service/workers/inbound_processor.ex:114` (`@core_validate_subject`), timeout 200ms (:116).
- **Responder**: `core/backend/lib/monetarie/infra/nats/responders/pix_account_validator.ex:33` (`@subject`), reply via `Gnat.pub` no reply_to (:65-76).
- **Stream MONETARIE_CORE (`monetarie.core.>`)** criado por 3 serviços: `core/backend/.../nats/stream_setup.ex:105-106`; `pix/backend/apps/shared/lib/shared/nats/jetstream.ex:87-88`; `spb/services/.../nats/stream_manager.ex`.
- Precedente: gotcha #7 do `core/CLAUDE.md` — req/reply do DICT (`dict.lookup.request` etc.) vive FORA de qualquer stream por exatamente este motivo.

## Datação (git local)

O subject entrou no escopo do stream em **2026-06-24 (`3b3a15f1`)**, que renomeou `rpc.core.pix.*` → `monetarie.core.pix.*` movendo o CALLER para dentro do stream (em vez de mover o responder para fora). Isto é ANTERIOR ao incidente pacs.008 de R$ 4,54 (2026-07-09). **Verificar em HML amanhã**: se o caminho de ACEITE de pacs.008 orgânica está de fato quebrado hoje nas pontas vivas, e como o incidente de R$ 4,54 foi creditado (o E2E sintético de HML pulou este gate).

## Fix proposto (para aplicar SÓ após validar em HML)

Mover o req/reply para fora de qualquer stream, no padrão do gotcha #7, reusando o subject pré-`3b3a15f1` `rpc.core.pix.validate_account` (nenhum stream captura `rpc.>`).

1. **CORE (deploy PRIMEIRO)**: `pix_account_validator.ex:33` — dual-subscribe `["rpc.core.pix.validate_account", "monetarie.core.pix.validate_account"]` no `subscribe/0` (:84-100). Lógica de reply inalterada.
2. **CABINE PIX (deploy DEPOIS)**: `inbound_processor.ex:114` — `@core_validate_subject "rpc.core.pix.validate_account"`.
3. **Cleanup** (release seguinte do Core): remover o subject legado da lista.
4. **Docs**: novo subject no gotcha #7 e na tabela Request/Reply do `core/CLAUDE.md`.

**Ordem de deploy obrigatória**: Core primeiro (responder dual), cabine depois. Invertido, os requests ao subject novo dariam timeout → NAK → DLQ. Não há env override (module attributes compile-time), então as duas trocas são de código.

**Fonte**: workflow `wf_ea432cbd-0c7`, trilha 3; provas vivas locais no `journal.jsonl` do transcript.
