# Handoff — Fronts admin (SPB/STA/NPC), login coreadmin, monitor PIX timeline e CAMT.060 inbound

Data: 2026-06-24. Sessão: 92f11cf0. HEAD ao escrever: `607a8e50` (main, pushed).

Este handoff fecha uma sessão longa e prepara uma **nova sessão focada** para
entregar a **CAMT.060 completa 100% validada** (envio + retorno + correlação +
exibição). Tudo abaixo foi validado **empiricamente** (screenshot/log/SQL vivo);
onde não foi, está marcado como PENDENTE/HIPÓTESE.

## REGRA do dono (reforço)
Sem atalhos, sem inferência, sem invenção, sem overclaim. Toda tela/fluxo só é
"validado" com prova real (screenshot + ausência de erro + dado vivo). pt-BR com
acentuação correta, sem travessão de IA. Segredos só no Secrets Manager. Não
atropelar a sessão PIX ativa (ver constraint abaixo).

## CONSTRAINT crítico (por que não terminei a CAMT.060 aqui)
A **sessão PIX ativa está deployando a `pix-api` AGORA** — os logs da `pix-api`
mostram `SIGTERM` + restart às **22:03:12** e certs remateralizados às 22:04.
A árvore tem trabalho **não-commitado** dela em `pix/backend` (`dict_lookup_responder.ex`,
`dict_client.ex`). **Buildar/deployar a `pix-api` empacotaria a obra inacabada dela.**
Logo: o front PIX (`pix-admin-ui`, imagem separada) pode ser deployado sozinho;
a `pix-api` (backend) **NÃO** pode ser deployada sem coordenar com a sessão ativa.
A CAMT.060 completa depende da pix-api → tem de ser feita em coordenação.

## ENTREGUE e VALIDADO nesta sessão (com prova)
Causa-raiz comum dos 3 fronts admin: as cabines SPB/STA/NPC subiram no ECS mas
os bancos **nunca foram migrados/seedados** (Core e PIX estavam ok).

1. **SPB admin (#27)** — `mon_spb` sem schema → login 500 → "senha inválida".
   Fix: `BacenGateway.Release.migrate()` + `seed()` (one-off ECS task). Login
   `admin@monetarie.com.br` / `Monetarie#Adm2026!` → dashboard. Validado (screenshot).
2. **NPC admin (#29)** — `mon_npc` vazio → 502. Fix: `MonetarieNpc.Release.migrate()`
   + `seed()`. Login idem. Validado.
3. **STA admin (#28)** — (a) `sta/frontend/nginx.conf` (contexto real do `sta-admin-ui`)
   usava `resolver 127.0.0.11` + upstream `sta-api:4000` (Docker Swarm, inválido no
   Fargate) → 502; corrigido p/ `169.254.169.253` + `staapi-h.monetarie.internal:80`.
   (b) `mon_sta` sem schema → `StaConnector.Release.migrate()`. (c) env divergente: o
   AuthController lê `STA_ADMIN_PASSWORD` mas o `ecs.tf` injetava
   `MONETARIE_STA_INITIAL_PASSWORD` → 500; corrigido no `ecs.tf` e aplicado via
   **revisão de task def CLI `sta-api:8`** (NÃO terraform apply — ver gotcha TB).
   Login `admin` / `Monetarie#Adm2026!` → dashboard. Validado.
4. **WebSocket "Desconectado/Erro" (#34)** — `check_origin` default `true` do Phoenix
   rejeitava a origem `http://*admin-h` → 403. Fix: `check_origin` via env
   `WS_CHECK_ORIGIN` (default false p/ admin interno) em `runtime.exs` de npc-api e
   sta-api. (1ª tentativa quebrou no boot por `case` inline em keyword list — corrigido
   com variável antes do `config`; circuit breaker do ECS manteve a task antiga, sem
   outage.) Validado: STA e NPC = "Conectado" (handshake STA = 101; NPC conecta com token).
5. **Branding/login coreadmin (#35)** — STA/NPC usavam só o ícone, depois card central
   simples. O dono exigiu o **layout do coreadmin**. Reescrito o `LoginView` de STA e NPC
   no split-panel do coreadmin: painel verde `linear-gradient(160deg,#00573F,#003D2B 60%,#002920)`
   + **wordmark dourado** (`logo-monetarie-gold.png`, copiado do coreadmin) + tagline +
   3 bullets com check dourado + "Monetarie"; card branco "Bem-vindo de volta" / "Acesse
   sua conta de administrador STA|NPC" + botão **`#B48F5E`** (valor exato extraído do
   coreadmin vivo via getComputedStyle). Acentuação pt-BR corrigida. Validado: layout
   idêntico ao coreadmin + login funcional (entra no dashboard).
6. **Monitor PIX — aba "Linha do tempo" (#33, parcial/frontend)** — o detalhe da operação
   mostrava 1 mensagem isolada. Adicionada aba que correlaciona por E2E
   (`end_to_end_id`/`pi_resource_id`/`tx_id`) via o próprio endpoint de listagem
   (`?search=`, que cobre esses campos no `monitor_controller.ex:265-270`), **frontend-only**
   (`pix-admin-ui`). Renderiza cascata ida↔retorno ordenada por `created_at`. Deployado e
   no ar. **LIMITAÇÃO honesta:** não há fluxo PIX completo na homolog (categoria PIX=0) e a
   camt.060 não tem E2E → a aba mostra o estado correto "sem E2E"/"sem retorno". Vira útil
   quando houver fluxo real (depende da CAMT.060/inbound abaixo).

Commits (todos na main, pushed): `5ba142fc` (STA nginx+ecs.tf) · `fdfa3c8d` (branding
wordmark v1) · `3b895869` (WS check_origin) · `0a312665` (login coreadmin) · `607a8e50`
(monitor timeline). TigerBeetle intacto o tempo todo (recusei o terraform apply que o
replaceava — ver gotcha).

## CAMT.060 completa — DIAGNÓSTICO EMPÍRICO (estado real, sem inferência)
Objetivo da próxima sessão: **enviar uma CAMT.060 e validar o retorno camt.052/camt.053
ponta a ponta**, com correlação e exibição.

Fatos vivos (via `pix-api` rpc + logs + SQL no `XmlAuditLog`):
- **9 camt.060 ENVIADAS** (dir=SENT, ex.: id `64d0c4b3-2b9e-443a-8b98-9129e780d8dd`,
  `correlation_id=monetarie-d6fb1ab179c9af67`, MsgId/BizMsgIdr `M46026562482c45a657c209038b73f63`,
  ispb `46026562→00038166`), todas 201. **0 camt.052/camt.053** no audit
  (`Enum.frequencies` de `message_type like 'camt%'` = `%{"camt.060" => 9}`).
- `INBOUND_SOURCE=icom_http` JÁ está na task viva (task-def `monetarie-pix-api-homolog:34`);
  `SIMULATOR_ENABLED=false`, `BACEN_ENABLED=true`, `DICT_EXTERNAL_MODE=bacen`.
- Coordinators inbound **sobem**: `Icom.Cpm.Coordinator` e `Icom.Csm.Coordinator`
  "leader acquired ispb=46026562 spawning 4 workers" + "resuming 4 existing open sessions".
- Certs mTLS do inbound **existem** no container: `/tmp/pix/certs/client_cert.pem` (2641 b)
  + `client_key.pem` (1707 b, modo 600), materializados às 22:04 pelo
  `Shared.Crypto.CertMaterializer` (lê do Secrets Manager; dir via `PIX_CERT_DIR`,
  paths via `BACEN_CLIENT_KEY_PATH`).
- O `:enoent` de `client_key.pem` ocorreu **1 vez** (22:04:27.493), em **corrida de boot**
  (worker CSM tentou polar antes do cert gravar). **count de "transport error" na última
  1h = 1.** Depois disso, **sem erros** de transporte ICOM.
- `InboundProcessor` heartbeat `mode=push`, `processed=0` desde o restart de 22:04.

**CONTEXTO da sessão PIX ativa (memória `monetarie-pix-inbound-diagnosis` — LER PRIMEIRO):**
a sessão ativa JÁ corrigiu, ao longo de 06-24, a maior parte deste fluxo, em task-defs
sucessivos: (a) **429 do pool Finch** super-dimensionado (BACEN limita 6 conexões/canal/ISPB)
→ pools `count:1,size:6` + `ICOM_MAX_SLOTS` + eleição de líder por advisory-lock (`:25`);
(b) **verificação XMLDSig inbound** — faltava o cert de assinatura do BACEN (PIA-T517 serial
65477...) + bug `CertificatePool.load_public_key` (`:26`); (c) **XMLDSig outbound DICT**
(placeholder no digest + insert + whitespace) → CID file ACEITO pelo BACEN (`:30`);
(d) **camt.060 `<ReqdMsgNmId>` era `AVLB` (inválido) → virou `camt.053`** ("era a razão do
BACEN nunca devolver o relatório de saldo", `:26`). Task-def vivo agora é **`:34`** (além do
`:30` da memória). O pendente registrado lá é literalmente **"falta o dono reenviar a
camt.060/pacs.008 p/ ver a timeline fechar"**. **NÃO refazer esses fixes — eles já existem na
pix-api viva.** A nova sessão deve coordenar com a sessão PIX (ou após ela commitar) e
focar em **reenviar + observar o retorno**, não em re-diagnosticar o inbound.

**Conclusão (validada):** o caminho de envio funciona; o inbound está ligado, com cert e
sem erro atual (429=0, transport error=1 só na corrida de boot) — mas **nenhum retorno
chegou ainda** porque ninguém reenviou uma camt.060 depois dos fixes/restart. Para fechar 100% falta:
1. **Enviar uma camt.060 NOVA** com o inbound estável (rpc de envio já existe; ver
   `apps/spi_service/.../camt060.ex` + controller `camt060_controller.ex`).
2. **Confirmar que o BACEN homolog devolve** o camt.052/camt.053 e que o worker CSM
   (`icom-sec`/secundário, não-financeiro) **recebe** — observar `Icom.Csm.Worker`/
   `InboundProcessor processed` subir e uma linha `camt.05x` aparecer no `XmlAuditLog`.
   HIPÓTESE a confirmar (NÃO assumir): se o camt.053 vier pelo canal secundário (CSM,
   `icom-sec-h:17522`) e esse canal estiver em DROP pela RTM, o retorno não chega —
   testar reachability real de `icom-sec-h` a partir da pix-api antes de concluir.
3. **Correlação camt.060↔camt.053**: a camt.060 NÃO tem E2E; correlaciona por
   `correlation_id` e/ou MsgId/BizMsgIdr (`OrgnlMsgId` no retorno). O backend hoje **não
   liga** os dois (Explore confirmou: falta persistência/endpoint). Ver
   `apps/spi_service/lib/spi_service/camt060.ex` + `balances.ex`.
4. **Exibir inline**: a tela `pixadmin/camt060` (`Camt060ToolView.vue`) mostra
   "Aguardando retorno"/fallback `manual_homolog`; o monitor timeline correlaciona só por
   E2E. Após a correlação por correlation_id no backend, ligar a exibição.

## PENDENTE (lista para a nova sessão)
- **CAMT.060 completa (#31)** — enviar nova + validar retorno + correlação + exibição
  (precisa pix-api → coordenar com a sessão ativa).
- **DICT e2e no monitor** — o dono apontou (com razão): a GetEntry DICT manda
  `PI-EndToEndId` mas o monitor mostra E2E "—". O `XmlAuditLog` não captura o e2e do DICT
  (`end_to_end_id`/`pi_end_to_end_id` nil para DICT). Fix = capturar no logger de auditoria
  DICT (pix-api, `apps/shared/lib/shared/audit/` + o caminho DICT GetEntry) e redeploy.
  Atenção: mexe perto de `dict_lookup_responder.ex`/`dict_client.ex` que a sessão ativa
  está editando — coordenar.
- **Central de Mensagens** — o dono relatou que a construção de mensagens via "Central de
  Mensagens" não funciona. NÃO investigado ainda. Ponto de partida: rota `/messages` no
  `pix/frontend/admin` + os endpoints de envio no `spi_service`/`settlement_service`.
- **Monitor timeline (#33)** — frontend pronto; passa a mostrar cascata quando a CAMT.060/
  PIX inbound funcionar; estender p/ correlacionar também por `correlation_id` (não só E2E)
  para cobrir camt.060↔camt.053.
- **IB unidades (#30)** — mostra R$10mi no lugar de R$100k. **OVERLAP**: a sessão ativa está
  editando `core/apps/banking/src/lib/formatters.ts` + criando `useBalances.ts`/
  `useBankAccounts.ts` — provavelmente já no escopo dela. NÃO tocar sem coordenar.

## GOTCHAS importantes (não repetir erro)
- **terraform apply arrasta replace do TigerBeetle**: `aws_ecs_service.app` referencia
  `local.base_api_env` que inclui o IP do TB, e o state tem drift de `user_data` do TB →
  qualquer `terraform apply` (mesmo `-target`) dá replace em `aws_instance.tigerbeetle`
  (derruba o TB). Para mudar env/task def das cabines use **revisão de task def via CLI +
  force-new-deployment**, NUNCA terraform apply. Ver [[monetarie-admin-cabins-provisioning]].
- **Deploy**: `docker buildx --builder coreproviders-mk-builder --platform linux/arm64 -t
  <ECR>/monetarie/<svc>:homolog-latest --push <contexto>` + `ecs update-service
  --force-new-deployment`. OrbStack precisa estar UP (`open -a OrbStack`). Confere por DIGEST.
- **Build do front pix-admin** = `vite build` (sem vue-tsc); os outros admin idem.
- **Cache de navegador engana validação** de front: usar `?nocache=`/`?v=N` ou conferir o
  bundle servido (`curl .../assets/index-*.js | grep <asset>`).
- **rpc na pix-api**: `XmlAuditLog` NÃO tem `inserted_at` (usar `received_at`). Bin do
  release = `monetarie_pix`; Repo = `Shared.Repo`; schema audit = `Shared.Schemas.Audit.XmlAuditLog`.
- Senha padrão admin de todos os fronts (homolog): `Monetarie#Adm2026!` (secrets
  `monetarie/homolog/admin/{spb,npc,sta,pix}/initial_password` — todos já = padrão).

## Estado AWS / serviços (vivos, 2026-06-24)
Conta `990933657879`, sa-east-1, cluster `monetarie-greenfield-homolog`, profile
`vulcimonetarie`. Tasks vivas: pix-api `monetarie-pix-api-homolog:34`. Admin UIs por
DIGEST. TigerBeetle `i-039942152c33522c6` t4g.large, intacto.
