# Core Banking

Configuracao da integracao entre o Monetarie PIX e o Core Banking via NATS JetStream e autenticacao JWT compartilhada.

## Pre-requisitos

- Monetarie Core Banking implantado e operacional
- Cluster NATS JetStream compartilhado entre Core e PIX
- Secret Kubernetes `monetarie-shared-jwt-secret` criado no namespace `pix`
- Variavel `NATS_ENABLED=true` no backend PIX
- Conhecimento dos subjects NATS do Core Banking

## Arquitetura de Integracao

```mermaid
flowchart LR
    subgraph Core["Core Banking"]
        PH["PixHandler<br/>(consumer)"]
        PUB["Publisher<br/>(Oban outbox)"]
    end

    subgraph NATS["NATS JetStream"]
        S1["monetarie.core.pix.*<br/>(Core -> PIX)"]
        S2["monetarie.spi.transaction.*<br/>(PIX -> Core)"]
        S3["monetarie.dict.keys.*<br/>(PIX -> Core)"]
        RR1["dict.lookup.request<br/>(req/reply)"]
        RR2["dict.api.request<br/>(req/reply)"]
    end

    subgraph PIX["Monetarie PIX"]
        CEP["CoreEventProcessor<br/>(consumer)"]
        IP["SPI Workers<br/>(publishers)"]
        DP["DICT Publisher<br/>(publisher)"]
    end

    PUB -->|payment_request<br/>return_request<br/>key_create<br/>key_delete<br/>dict_lookup<br/>balance_inquiry| S1
    S1 --> CEP
    IP --> S2
    DP --> S3
    S2 --> PH
    S3 --> PH
    Core <-->|request/reply| RR1
    Core <-->|request/reply| RR2
    PIX <-->|request/reply| RR1
    PIX <-->|request/reply| RR2
```

## Autenticacao JWT

### Cadeia de Fallback

O Monetarie PIX utiliza uma cadeia de fallback para resolver o segredo JWT compartilhado com o Core:

```mermaid
flowchart LR
    A["JWT_SECRET"] -->|Nao definido| B["GUARDIAN_SECRET_KEY"]
    B -->|Nao definido| C["SECRET_KEY_BASE"]
    C -->|Nao definido| D["ERRO: sem segredo"]

    style A fill:#4caf50,stroke:#333,color:#fff
    style B fill:#ff9800,stroke:#333,color:#fff
    style C fill:#f44336,stroke:#333,color:#fff
    style D fill:#9e9e9e,stroke:#333,color:#fff
```

A cadeia e aplicada em 5 modulos:

| Modulo | Funcao |
|--------|--------|
| `Shared.Auth.JwtAuth` | Autenticacao de tokens JWT no Settlement Service |
| `Shared.Auth.SsoAuth` | Autenticacao SSO (aceita `iss: "monetarie"` do Core) |
| `DictServiceWeb.Plugs.Authenticate` | Autenticacao no DICT Service |
| `DictServiceWeb.AuthController` | Emissao de tokens no DICT |
| `Shared.Auth.MFA` | Verificacao MFA |

### Issuers Aceitos

| Issuer (`iss`) | Origem | Validacao `target_system` |
|----------------|--------|--------------------------|
| `"monetarie"` | Core Banking (Guardian) | **Nao** (confiavel, mesmo ecossistema) |
| `"monetarie-sso"` | SSO Hub (Backoffice) | **Sim** (deve conter `target_system: "pix"`) |
| `"monetarie-pix"` | PIX (interno) | **Nao** (token local) |

### Configuracao do Secret

```yaml
# Secret compartilhado entre Core Banking e PIX
apiVersion: v1
kind: Secret
metadata:
  name: monetarie-shared-jwt-secret
  namespace: pix
type: Opaque
stringData:
  jwt-secret: "mesmo-valor-do-GUARDIAN_SECRET_KEY-do-Core"
```

```yaml
# Referencia no deploy/backend.yaml
env:
  - name: GUARDIAN_SECRET_KEY
    valueFrom:
      secretKeyRef:
        name: monetarie-shared-jwt-secret
        key: jwt-secret
```

::: tip DESENVOLVIMENTO LOCAL
Para testes locais de integracao com Core Banking, defina:
```bash
export JWT_SECRET="dev-only-secret-key-not-for-production"
```
Este e o segredo de desenvolvimento usado pelo Core.
:::

## Eventos Core -> PIX

O `CoreEventProcessor` consome 6 tipos de eventos do Core Banking:

| Subject | Handler | Descricao |
|---------|---------|-----------|
| `monetarie.core.pix.payment_request` | `handle_payment_request/1` | Criar pacs.008 (transferencia) |
| `monetarie.core.pix.return_request` | `handle_return_request/1` | Criar pacs.004 (devolucao) |
| `monetarie.core.pix.key_create` | `handle_key_create/1` | Proxy: POST /api/v2/entries |
| `monetarie.core.pix.key_delete` | `handle_key_delete/1` | Proxy: DELETE /api/v2/entries/:key |
| `monetarie.core.pix.dict_lookup` | `handle_dict_lookup/1` | Consulta DICT, resposta via NATS |
| `monetarie.core.pix.balance_inquiry` | `handle_balance_inquiry/1` | Consulta saldo SPI, resposta via NATS |

### Payload: payment_request

```json
{
  "event": "payment_request",
  "correlation_id": "uuid-v4",
  "data": {
    "end_to_end_id": "E1234567820260213143000000000001",
    "amount": 15000,
    "debtor": {
      "ispb": "12345678",
      "branch": "0001",
      "account": "123456",
      "account_type": "CACC",
      "name": "Joao Silva",
      "cpf_cnpj": "12345678901"
    },
    "creditor": {
      "ispb": "53822116",
      "branch": "0001",
      "account": "654321",
      "account_type": "CACC",
      "name": "Maria Santos",
      "cpf_cnpj": "98765432100"
    },
    "remittance_info": "Pagamento referente ao pedido #12345",
    "pix_key": "maria@email.com",
    "pix_key_type": "EMAIL"
  }
}
```

::: danger CAMPO "event" E OBRIGATORIO
O campo `"event"` no payload e a **chave de roteamento** do CoreEventProcessor. Se estiver ausente ou com erro de digitacao, a mensagem sera reconhecida (ACK) silenciosamente sem processamento.
:::

### Payload: dict_lookup

```json
{
  "event": "dict_lookup",
  "correlation_id": "uuid-v4",
  "reply_to": "dict.lookup.response.{correlation_id}",
  "data": {
    "key": "12345678901",
    "key_type": "CPF"
  }
}
```

### Payload: balance_inquiry

```json
{
  "event": "balance_inquiry",
  "correlation_id": "uuid-v4",
  "reply_to": "balance.response.{correlation_id}",
  "data": {
    "ispb": "12345678",
    "settlement_date": "2026-02-13"
  }
}
```

## Eventos PIX -> Core

Os workers SPI e DICT publicam eventos com campos compativeis com o Core:

### Formato do Evento

```json
{
  "type": "transaction.settled",
  "source": "pix",
  "published_at": "2026-02-13T14:30:00.000Z",
  "data": {
    "end_to_end_id": "E1234567820260213143000000000001",
    "status": "STLD",
    "amount": 15000,
    "settlement_time": "2026-02-13T14:30:00.500Z",
    "debtor_ispb": "12345678",
    "creditor_ispb": "53822116"
  }
}
```

| Campo | Tipo | Descricao |
|-------|------|-----------|
| `type` | String | Tipo do evento (ex: `transaction.settled`, `keys.created`) |
| `source` | String | Sempre `"pix"` |
| `published_at` | ISO 8601 | Timestamp de publicacao |
| `data` | Object | Payload especifico do evento |

### Subjects de Eventos PIX -> Core

| Subject | Evento | Descricao |
|---------|--------|-----------|
| `monetarie.spi.transaction.created` | `transaction.created` | Transacao PIX criada |
| `monetarie.spi.transaction.accepted` | `transaction.accepted` | Transacao aceita (ACSP) |
| `monetarie.spi.transaction.settled` | `transaction.settled` | Transacao liquidada (STLD) |
| `monetarie.spi.transaction.rejected` | `transaction.rejected` | Transacao rejeitada (RJCT) |
| `monetarie.spi.transaction.returned` | `transaction.returned` | Devolucao processada (RTRN) |
| `monetarie.spi.transaction.cancelled` | `transaction.cancelled` | Transacao cancelada (CANC) |
| `monetarie.dict.keys.created` | `keys.created` | Chave PIX criada |
| `monetarie.dict.keys.deleted` | `keys.deleted` | Chave PIX removida |

## CoreEventProcessor

### Configuracao

| Parametro | Valor | Descricao |
|-----------|-------|-----------|
| Stream | MONETARIE_CORE | Stream JetStream consumido |
| Consumer | `core-events` | Consumer duravel |
| Filter | `monetarie.core.pix.>` | Filtro de subjects |
| batch_size | 50 | Mensagens por batch |
| poll_interval | 500ms | Intervalo base de polling |
| max_concurrency | 5 | Processamento paralelo |
| max_retries | 5 | Retries antes de DLQ |

### Chamadas HTTP Internas

O CoreEventProcessor faz chamadas HTTP para o DICT e SPI Services:

```mermaid
flowchart LR
    CEP["CoreEventProcessor"] -->|key_create<br/>key_delete<br/>dict_lookup| DICT["DICT Service<br/>:4001"]
    CEP -->|payment_request<br/>return_request<br/>balance_inquiry| SPI["SPI Service<br/>:4002"]
```

| Parametro | Valor | Descricao |
|-----------|-------|-----------|
| `receive_timeout` | 10.000ms | Timeout por requisicao HTTP |
| Retry | 3 tentativas | Backoff exponencial: 1s, 2s, 4s |
| Finch pool (DICT) | 10 conn x 2 = 20 | Pool de conexoes HTTP para DICT |
| Finch pool (SPI) | 25 conn x 2 = 50 | Pool de conexoes HTTP para SPI |

### Tracing Distribuido

O CoreEventProcessor propaga o `trace_id` (W3C `x-trace-id`) em todas as operacoes:

1. Extrai `trace_id` do header NATS da mensagem
2. Define `Logger.metadata(trace_id: trace_id)`
3. Inclui `x-trace-id` nos headers HTTP para DICT/SPI
4. Inclui `trace_id` nos headers NATS de eventos publicados

## Request/Reply (Subjects Dedicados)

::: danger SUBJECTS FORA DO JETSTREAM
Subjects de request/reply **devem** estar fora do escopo de streams JetStream. O stream `MONETARIE_SPI` captura `monetarie.spi.>`, entao qualquer request/reply em `monetarie.spi.*` sera interceptado pelo JetStream.
:::

| Finalidade | Subject | Escopo JetStream |
|------------|---------|-----------------|
| Consulta DICT | `dict.lookup.request` / `dict.lookup.response.*` | **Fora** (correto) |
| Claims/MED/Infracoes | `dict.api.request` / `dict.api.response.*` | **Fora** (correto) |

## Teste de Integracao Local

### 1. Configurar Segredos

```bash
# Terminal 1: Core Banking
export GUARDIAN_SECRET_KEY="dev-only-secret-key-not-for-production"
cd /monetarie/core && mix phx.server

# Terminal 2: PIX
export JWT_SECRET="dev-only-secret-key-not-for-production"
export NATS_ENABLED="true"
cd /monetarie/pix/backend && mix phx.server
```

### 2. Publicar Evento de Teste

```bash
# Publicar payment_request via NATS CLI
nats pub monetarie.core.pix.payment_request '{
  "event": "payment_request",
  "correlation_id": "test-001",
  "data": {
    "end_to_end_id": "E1234567820260213150000000000001",
    "amount": 1000,
    "debtor": {
      "ispb": "12345678",
      "branch": "0001",
      "account": "123456",
      "account_type": "CACC",
      "name": "Test User",
      "cpf_cnpj": "12345678901"
    },
    "creditor": {
      "ispb": "53822116",
      "branch": "0001",
      "account": "654321",
      "account_type": "CACC",
      "name": "Test Creditor",
      "cpf_cnpj": "98765432100"
    },
    "remittance_info": "Teste de integracao"
  }
}'
```

### 3. Verificar Processamento

```bash
# Verificar logs do CoreEventProcessor
kubectl logs -n pix deployment/pix-backend | grep "CoreEventProcessor"

# Verificar transacao criada
# Via API:
curl -s https://pixapi-dev.fluxiq.com.br/api/v1/payments \
  -H "Cookie: pix_session=<token>" | jq '.data[0]'

# Verificar evento PIX -> Core publicado
nats sub "monetarie.spi.transaction.>" --count=1
```

## Dependencias do Core Team

Para a integracao funcionar completamente, o time Core precisa:

1. **Publicar** em subjects `monetarie.core.pix.*` (nao `ledger.transaction.pix*`)
2. **Criar** o Secret Kubernetes `monetarie-shared-jwt-secret` no namespace `pix`
3. **Validar** que o `PixHandler` funciona com os campos `type`, `source`, `published_at`
4. **Usar** o padrao Oban outbox (`Publisher.publish_async/2`) para publicacao NATS

## Resultado Esperado

Apos a configuracao da integracao Core Banking:

- O `CoreEventProcessor` consome eventos de `monetarie.core.pix.>` sem erros
- Tokens JWT emitidos pelo Core (`iss: "monetarie"`) sao aceitos pelo PIX
- Pagamentos solicitados pelo Core criam transacoes `pacs.008` no SPI
- Eventos de transacao PIX sao publicados com campos Core-compativeis
- O `trace_id` e propagado end-to-end entre Core e PIX
- Consultas DICT via request/reply retornam resultados em menos de 200ms
- Logs mostram `[CoreEventProcessor] Processing event: payment_request`
