# Analise GAP Completa — FluxiQ PIX
**Data**: 2026-02-12
**Escopo**: E2E ID, DICT Rate Limiting, SPI/DICT/ARQ, ANS, TPS 5K+, Regulatorio APIX, Resiliencia 99.999%
**Metodo**: 6 agentes paralelos + exploracao profunda de codigo + verificacao cruzada

---

## RESUMO EXECUTIVO

| Area | Status | Gaps Criticos | Gaps Altos | Gaps Medios | Nota |
|------|--------|:---:|:---:|:---:|:---:|
| **E2E ID Lifecycle** | FALHA | 3 | 1 | 0 | 25/100 |
| **DICT Rate Limiting** | FALHA | 2 | 2 | 1 | 30/100 |
| **SPI Messages (27 tipos)** | OK | 0 | 0 | 0 | 100/100 |
| **DICT API v2.10.0** | OK | 0 | 0 | 1 | 95/100 |
| **ARQ Files** | PARCIAL | 1 | 1 | 0 | 60/100 |
| **ANS Monitoring** | PARCIAL | 0 | 1 | 1 | 70/100 |
| **TPS 5K+ Sustained** | OK | 0 | 0 | 1 | 90/100 |
| **Regulatorio APIX** | PARCIAL | 0 | 2 | 1 | 65/100 |
| **Resiliencia 99.999%** | PARCIAL | 0 | 3 | 2 | 75/100 |
| **DB Performance** | OK | 0 | 0 | 2 | 90/100 |
| **TOTAL** | | **6** | **10** | **9** | **70/100** |

**Veredito**: Sistema com excelente qualidade de codigo backend (95/100) e cobertura SPI/DICT completa, mas com **gaps criticos** no lifecycle do E2E ID e DICT rate limiting que impedem operacao real com BACEN.

---

## SECAO 1: GAPS CRITICOS (Bloqueadores de Producao)

### C1. E2E ID — Tres Geradores Independentes e Inconsistentes

**Impacto**: Violacao da especificacao BACEN. E2E IDs gerados por caminhos diferentes nao seguem o mesmo algoritmo.

#### Gerador 1: `MessageBuilder.generate_e2e_id/1` (CORRETO)
**Arquivo**: `shared/lib/shared/bacen/iso20022/message_builder.ex:599-603`
```elixir
def generate_e2e_id(ispb) do
  date = Date.utc_today() |> Calendar.strftime("%Y%m%d")
  rand = :crypto.strong_rand_bytes(11) |> Base.encode32(case: :lower, padding: false)
  "E#{ispb || "00000000"}#{date}#{String.slice(rand, 0, 16)}"
end
```
- Usa `:crypto.strong_rand_bytes` (criptograficamente seguro)
- Gera 32 caracteres corretos
- Usado no building de pacs.008

#### Gerador 2: `PaymentController.generate_e2e_id/2` (BUGADO + INSEGURO)
**Arquivo**: `spi_service/lib/spi_service_web/controllers/payment_controller.ex:208-213`
```elixir
defp generate_e2e_id(ispb, now) do
  date_str = Calendar.strftime(now, "%Y%m%d")
  rand_str = :rand.uniform(99_999_999_999_999) |> to_string() |> String.pad_leading(14, "0")
  seq_str = :rand.uniform(999_999_999) |> to_string() |> String.pad_leading(9, "0")
  "E" <> String.slice("#{ispb}#{date_str}#{rand_str}#{seq_str}", 0, 31)
end
```
- **BUG**: `String.slice(_, 0, 31)` gera **31 caracteres** em vez de 32
- **INSEGURO**: Usa `:rand.uniform` (pseudo-random, NAO criptografico)
- Usado quando pagamento e criado via API direta (POST /api/v1/payments)

#### Gerador 3: `CoreEventProcessor` (Fallback)
**Arquivo**: `settlement_service/lib/settlement_service/workers/core_event_processor.ex:185`
```elixir
end_to_end_id: message["end_to_end_id"] || generate_e2e_id()
```
- Usado quando Core Banking NAO fornece E2E ID no payment_request

**Fix Requerido**: Centralizar E2E ID generation em UMA UNICA funcao (`MessageBuilder.generate_e2e_id/1`) e remover os outros dois geradores.

---

### C2. E2E ID — Sem Correlacao entre DICT Lookup e SPI Transaction

**Impacto**: O usuario solicitou especificamente que o E2E ID gerado no DICT lookup deve ser reutilizado no SPI transaction. Atualmente NAO EXISTE esse mecanismo.

**Fluxo Atual (QUEBRADO)**:
```
1. DICT Lookup  → Retorna: {ispb, account, name}  → SEM E2E ID
2. Payment Create → Gera NOVO E2E ID               → ID DIFERENTE
```

**Fluxo Correto (REQUERIDO)**:
```
1. DICT Lookup  → Gera E2E ID + Retorna com dados  → Armazena no cache
2. Payment Create → Recupera E2E ID do cache        → MESMO ID
```

**Impacto Regulatorio**: BACEN exige que o E2E ID seja unico e rastreavel do inicio ao fim da transacao. Se DICT lookup e SPI payment usam IDs diferentes, perde-se a rastreabilidade.

**Fix Requerido**:
1. Gerar E2E ID no momento do DICT lookup
2. Armazenar E2E ID + dados do lookup em Redis (TTL 30min)
3. Payment creation deve recuperar E2E ID do cache usando a chave PIX como lookup key
4. Fallback: gerar novo E2E ID somente se cache expirou ou lookup nao ocorreu

---

### C3. DICT Rate Limiting — Institution Controller MOCKED

**Arquivo**: `dict_service/lib/dict_service_web/controllers/admin/institution_controller.ex`

**Problema**: TODA a logica de rate limiting por instituicao no DICT Service e um STUB:
```elixir
# Comentarios no codigo: "In a real implementation, this would query Redis or the database"
@categories %{
  "G" => %{capacity: 200, refill_per_minute: 100},  # HARDCODED
  ...
}
```

**Valores Incorretos**: O usuario especificou **G = 250 bucket, 25/min replacement**. O codigo tem:
- Institution Controller: G = 200/100 (MOCKED)
- Settlement Rate Limit: G = 500/250 (REAL mas diferente do BACEN)

**Fix Requerido**: Implementar rate limiting REAL por instituicao no DICT Service usando Redis token bucket, com valores conforme Manual do PIX v8.0:
```
G: capacity=250, refill_per_minute=25
```

---

### C4. DICT Rate Limiting — DICT e SPI Compartilham Bucket

**Arquivo**: `settlement_service/lib/settlement_service_web/plugs/rate_limit.ex`

**Problema**: DICT lookups e SPI payments usam o MESMO bucket de rate limiting por ISPB. Uma instituicao que faz muitas consultas DICT pode esgotar seu budget SPI.

**Requisito BACEN**: DICT e SPI devem ter quotas SEPARADAS por instituicao:
- DICT: Quotas por categoria (A-H) conforme Manual do DICT
- SPI: Quotas separadas conforme Manual do SPI

**Fix Requerido**: Criar buckets Redis separados:
- `rate_limit:dict:ispb:{ISPB}` — Para operacoes DICT
- `rate_limit:spi:ispb:{ISPB}` — Para operacoes SPI

---

### C5. DICT Rate Limiting — Sem PI-PayerId (Per-User Rate Limiting)

**Problema**: BACEN exige header `PI-PayerId` para rate limiting per-usuario dentro de uma instituicao. Isso evita que um unico usuario consuma toda a quota da instituicao.

**Implementacao Atual**: Rate limiting e somente por ISPB (instituicao inteira).

**Fix Requerido**: Adicionar buckets per-user:
- `rate_limit:dict:payer:{CPF/CNPJ}` — Limite por pagador
- Implementar header `PI-PayerId` no BACEN DictClient

---

### C6. E2E ID — PaymentController Nao Aceita E2E Externo

**Arquivo**: `spi_service/lib/spi_service_web/controllers/payment_controller.ex:117`

**Problema**: `PaymentController.create/2` SEMPRE gera um novo E2E ID:
```elixir
e2e_id = generate_e2e_id(ispb, now)  # Ignora qualquer E2E fornecido nos params
```

Nao ha logica para aceitar `end_to_end_id` do request body ou de um lookup anterior.

**Fix Requerido**: Verificar se `params["end_to_end_id"]` existe e e valido antes de gerar um novo.

---

## SECAO 2: GAPS ALTOS (Corrigir antes de Producao)

### H1. ARQ Files — Apenas Import, Sem Export

**Arquivo**: `settlement_service/lib/settlement_service/workers/file_importer.ex`

**Cobertura Atual (60%)**:
- camt.052 (balance report): IMPORT OK
- camt.053 (end-of-day statement): IMPORT OK
- camt.054 (debit/credit notification): IMPORT OK
- STR00 (settlement result file): NAO IMPLEMENTADO
- ARQS (movement file): NAO IMPLEMENTADO
- Outbound settlement files: NAO IMPLEMENTADO

**Fix**: Implementar parser STR00/ARQS + gerador de arquivos de saida.

---

### H2. ANS — Sem Alerting Automatico

**Contexto**: BCB exige liquidacao PIX em 1.6 segundos (1600ms).

**Implementacao Atual**:
- Timestamps rastreados: `operation_time`, `acceptance_time`, `settlement_time`
- Delta calculavel: `settlement_time - operation_time`
- Frontend exibe badge OK/EXCEDIDO
- K6 testa p(99) < 1500ms

**Gap**: NAO existe alerting automatico quando ANS e violado. Nenhum GenServer monitora o SLA em tempo real.

**Fix**: Criar `AnsMonitor` GenServer que:
1. Calcula delta a cada status update (STLD)
2. Emite telemetria `[:pix, :ans, :breach]` quando > 1600ms
3. Broadcast via WebSocket canal `system:health`
4. Publica metrica Prometheus `pix_ans_breach_total`

---

### H3. Regulatorio — Sem Export BCB Circular 4010

**Contexto**: COSIF accounting implementado (44 contas, double-entry), mas sem endpoint de exportacao no formato exigido pelo BCB.

**Fix**: Adicionar endpoint `GET /api/v1/accounting/export/circular-4010` que gera arquivo no formato BACEN.

---

### H4. Regulatorio — Sem Balancete/DRE

**Fix**: Adicionar endpoints:
- `GET /api/v1/accounting/balance-sheet` — Balancete mensal
- `GET /api/v1/accounting/income-statement` — DRE mensal

---

### H5. DICT Rate Limit — Valores Divergentes do BACEN

**Valores no codigo vs BACEN vs Usuario**:

| Categoria | Settlement rate_limit.ex | Dict institution_ctrl (MOCKED) | Usuario Pediu | BACEN Manual v8.0 |
|:---------:|:---:|:---:|:---:|:---:|
| A | 50,000/25,000 | 50,000/25,000 | — | TBD |
| B | 25,000/12,500 | 25,000/12,500 | — | TBD |
| G | 500/250 | 200/100 | **250/25** | **250/25** |
| H | 1,000/500 | 50/2 | — | TBD |

**Fix**: Alinhar TODOS os valores com o Manual do PIX BACEN v8.0 e aceitar configuracao via SystemConfig DB.

---

### H6. Resiliencia — Token Blacklist Fail-Open

**Arquivo**: `shared/lib/shared/auth/token_blacklist.ex`

```elixir
case Shared.Redis.Connection.command(["EXISTS", key]) do
  {:ok, 1} -> true
  {:ok, 0} -> false
  {:error, _} -> false  # FAIL-OPEN!
end
```

Se Redis cair, tokens revogados voltam a funcionar ate expirarem naturalmente.

**Mitigacao**: Token TTL curto (1h), mas para 99.999% uptime, considerar circuit-breaker no Redis com fallback local.

---

### H7. Resiliencia — Sem Read Replicas

**Todas as queries usam o mesmo `Shared.Repo` (read-write)**. Para 100M+ transacoes/dia:
- Queries de reporting devem usar replica read-only
- Dashboard + analytics isolados da carga de escrita

**Fix**: Configurar `Shared.Repo.ReadOnly` apontando para read replica do Cloud SQL.

---

### H8. Resiliencia — DLQ Replay Manual

**Fix**: Adicionar endpoint admin `POST /api/v1/admin/dlq/replay` para replay automatizado de mensagens DLQ.

---

## SECAO 3: GAPS MEDIOS (Proximo Sprint)

### M1. Tabela `monetarie_spi.messages` Sem Particionamento

A 100M+ transacoes/dia, esta tabela cresce ~3B linhas/mes. Sem particionamento, queries degradam apos 1B linhas.

**Fix**: Particionar por `operation_time` (mensal), similar ao que ja foi feito para `activity_log`.

---

### M2. TPS — Memory Headroom K8s

Limite 4Gi com uso estimado 3.5Gi a 5K TPS. Margem de apenas 0.5Gi antes de OOMkill.

**Fix**: Aumentar `limits.memory` para 6Gi no backend.yaml.

---

### M3. DICT — Schemas Duplicados (InfractionReport)

Dois schemas mapeiam a mesma tabela `monetarie_dict.infraction_reports`:
- `Shared.Schemas.Dict.InfractionReport`
- `DictService.Infractions.InfractionReport`

**Fix**: Consolidar em um unico schema.

---

### M4. ANS — Alerting de TPS Threshold

Nao existe alerta quando TPS cai abaixo de 5K ou sobe acima de capacidade.

**Fix**: Adicionar metrica `pix_tps_current` + threshold alert no QueueMonitor.

---

### M5. Regulatorio — Sem Deteccao Automatica de Fraude

MED 2.0 esta 100% implementado (infraction reports, blocking, recovery), mas toda a deteccao e MANUAL. Nao ha heuristicas, ML ou triggers automaticos.

**Fix para MVP**: Regras simples (valor > R$50K + horario 00h-06h + primeiro uso da chave).

---

### M6. DB — Queries `Repo.all` Sem LIMIT em Alguns Controllers

Alguns controllers ainda fazem `Repo.all(query)` sem LIMIT explicito:
- `permission_controller.ex`
- `message_controller.ex`
- `simulator_controller.ex`

**Fix**: Adicionar LIMIT 10K em todas as queries de listagem.

---

### M7. NATS — DICT Streams Precisam de Configuracao max_bytes

Os streams DICT ja tem max_bytes (configurado em Phase 11), mas validar que os valores sao adequados para 100M+ transacoes/dia.

---

### M8. `monetarie_spi.message_history` — Sem Retention Policy

Cresce a 5 entries/tx × 100M TX/dia = 500M linhas/dia = 15B/mes.

**Fix**: Particionar por `history_time` (mensal) + retention 90 dias.

---

### M9. Resiliencia — Sem Message Draining Explicito no Shutdown

BaseWorker tem `terminate/2` que loga stats mas nao faz drain explicito de mensagens em processamento.

**Fix**: Implementar drain loop no terminate com timeout de 30s.

---

## SECAO 4: O QUE ESTA EXCELENTE

### Backend Code Quality: 95/100

- **27 tipos de mensagem ISO 20022**: Todos implementados no MessageBuilder (622 linhas)
- **XMLDSig**: 3-ref SPI + 2-ref DICT, RSA-SHA256, Exclusive C14N — 100% compliant
- **Certificate Management**: Pool com refresh 5-min, dual-active rotation
- **XSD Validation**: Dual strategy (structural + xmllint) para todos 27 tipos
- **Error Handling**: RFC 7807 Problem Details em todos os 3 servicos
- **Logging**: 2064+ chamadas Logger com niveis corretos
- **Sensitive Data**: Filtro remove password/token/secret/private_key
- **SQL Injection**: ZERO — todos raw SQL parametrizados
- **Atom DoS**: Todos `String.to_atom` usam whitelist

### DICT API v2.10.0: 100/100

- Key CRUD (5 tipos: CPF, CNPJ, PHONE, EMAIL, EVP)
- Claims (portabilidade + posse)
- MED 2.0 completo (infractions, funds recovery, tracking graph, refunds)
- CID Sync (full sync 6h + events 5min)
- Batch key check (200 keys/request)
- Admin: institution management, blocking, fraud marking

### Resiliencia: 85/100

- **Circuit Breaker**: ETS atomico, 5 failures → open, 30s → half_open
- **K8s HA**: RollingUpdate, PDB, HPA (2-10 pods), anti-affinity, preStop 10s
- **NATS Workers**: BaseWorker com retry + DLQ + adaptive backpressure
- **Idempotency**: Redis SET NX atomico, SHA-256 body hash, fail-closed
- **RBAC**: ETS-cached, 5-min TTL, fail-closed no DB error
- **Distributed Tracing**: x-trace-id em HTTP + NATS headers

### Database: 90/100

- **25 migrations**: Schema completo e evoluido
- **74 Ecto schemas**: Cobertura quase total das tabelas
- **46 indexes**: Incluindo GIN trigram, composites, FK indexes
- **12 PL/pgSQL functions**: Auto-update, retention, daily summary
- **15 triggers**: Timestamp auto-update + audit trail
- **2 tabelas particionadas**: activity_log + login_history (mensal)
- **Pool**: 200/repo × 4 repos × 2 pods = 1600 conn (Cloud SQL max: 6000)

### Seguranca: 90/100

- HttpOnly cookies + CSRF double-submit pattern
- RSA-OAEP 2048-bit login encryption
- MFA TOTP com backup codes
- Login rate limit: 10/15min por IP
- Account lockout: 10 falhas → bloqueio automatico
- Token blacklist Redis (fail-open trade-off)
- CSRF bypass exige IP privado

### Monitoring: 85/100

- HealthChecker: 10s services + DB + Redis + NATS
- QueueMonitor: 15s NATS consumer lag
- WebSocket: 6 canais real-time
- Telemetry: 15+ event types (worker, circuit breaker, DB)
- K6 Load Tests: 5K TPS, simulator E2E, Phase 12 validation

---

## SECAO 5: INVENTARIO COMPLETO

### Database

| Metrica | Quantidade |
|---------|:---:|
| Migrations | 25 |
| Ecto Schemas | 74 |
| Tabelas | ~196 |
| Indexes | ~46 |
| Functions (PL/pgSQL) | 12 |
| Triggers | 15 |
| Views | 2 |
| Tabelas Particionadas | 2 |
| Seed Files | 11 |
| ENUMs | 3 |
| Extensions | 3 (pg_trgm, pgcrypto, pg_uuid) |

### Backend

| Metrica | Quantidade |
|---------|:---:|
| Elixir Apps (umbrella) | 4 |
| Total Endpoints | ~420 |
| NATS Streams | 7 |
| NATS Workers | 7 |
| ISO 20022 Message Types | 27 |
| BACEN Error Codes | 161 |
| XSD Schemas | 27 |
| COSIF Accounts | 44 |

### Frontend

| Metrica | Admin | User |
|---------|:---:|:---:|
| Routes | 82 | 30 |
| Views | 86 | 32 |
| Stores | 17 | 10 |
| Services | 27 | 4 |
| Locales | 5 | 5 |

---

## SECAO 6: PLANO DE ACAO PRIORIZADO

### Sprint 1: E2E ID + DICT Rate Limiting (BLOQUEADORES)

| # | Acao | Arquivos | Esforco | Prioridade |
|:-:|------|----------|:---:|:---:|
| 1 | Centralizar E2E ID em MessageBuilder (remover geradores duplicados) | payment_controller.ex, core_event_processor.ex, transactions.ex | 2h | P0 |
| 2 | Corrigir bug 31→32 caracteres no PaymentController | payment_controller.ex | 15min | P0 |
| 3 | PaymentController.create aceitar `end_to_end_id` do request | payment_controller.ex | 30min | P0 |
| 4 | Implementar cache E2E ID no DICT lookup (Redis, TTL 30min) | dict_lookup_responder.ex, entry_controller.ex | 4h | P0 |
| 5 | Implementar DICT-specific rate limiting (bucket separado) | Novo: dict_rate_limit.ex | 6h | P0 |
| 6 | Implementar PI-PayerId per-user rate limiting | dict_rate_limit.ex, dict_client.ex | 4h | P0 |
| 7 | Corrigir valores G=250/25 e alinhar com BACEN Manual v8.0 | rate_limit.ex, institution_controller.ex | 2h | P0 |
| 8 | Implementar real institution category lookup (DB/Redis) | institution_controller.ex | 3h | P0 |

**Total Sprint 1**: ~22h

### Sprint 2: ARQ + ANS + Regulatorio

| # | Acao | Esforco | Prioridade |
|:-:|------|:---:|:---:|
| 9 | Implementar parser STR00 (settlement result file) | 8h | P1 |
| 10 | Implementar parser ARQS (movement file) | 8h | P1 |
| 11 | Implementar outbound settlement file generation | 6h | P1 |
| 12 | Criar AnsMonitor GenServer (alerting automatico 1.6s) | 4h | P1 |
| 13 | Endpoint BCB Circular 4010 export | 6h | P1 |
| 14 | Endpoints Balancete + DRE | 4h | P1 |

**Total Sprint 2**: ~36h

### Sprint 3: Resiliencia + Performance

| # | Acao | Esforco | Prioridade |
|:-:|------|:---:|:---:|
| 15 | Particionar `monetarie_spi.messages` (mensal) | 4h | P2 |
| 16 | Particionar `monetarie_spi.message_history` (mensal) | 3h | P2 |
| 17 | Configurar read replica Cloud SQL + Repo.ReadOnly | 4h | P2 |
| 18 | Aumentar memory limit K8s 4Gi → 6Gi | 15min | P2 |
| 19 | DLQ replay admin endpoint | 3h | P2 |
| 20 | BaseWorker message draining no shutdown | 2h | P2 |
| 21 | Consolidar schemas duplicados InfractionReport | 1h | P2 |
| 22 | LIMIT em queries sem LIMIT | 1h | P2 |
| 23 | Fraud detection heuristicas basicas | 8h | P2 |
| 24 | TPS threshold alerting | 2h | P2 |

**Total Sprint 3**: ~28h

---

## SCORECARD FINAL

| Dimensao | Nota | Comentario |
|----------|:---:|------------|
| **Qualidade de Codigo Backend** | 95/100 | Excepcional. Error handling, logging, supervision exemplares. |
| **SPI/DICT Coverage** | 95/100 | 27 msg types, DICT v2.10.0, MED 2.0 completo. |
| **E2E ID Lifecycle** | 25/100 | 3 geradores, bug 31-char, sem correlacao DICT→SPI. |
| **DICT Rate Limiting** | 30/100 | Institution controller MOCKED, sem bucket separado. |
| **ARQ Files** | 60/100 | Import OK, export e STR00/ARQS faltantes. |
| **ANS Monitoring** | 70/100 | Timestamps OK, alerting automatico faltante. |
| **TPS Readiness (5K+)** | 90/100 | Load tested, backpressure, circuit breaker. |
| **Regulatorio APIX** | 65/100 | Contabilidade implementada, exports faltantes. |
| **Resiliencia (99.999%)** | 75/100 | HA solida, fail-open em blacklist, sem read replicas. |
| **DB Performance** | 90/100 | 46 indexes, partitioning parcial, pool adequado. |
| **Seguranca** | 90/100 | Robusta, sem vulnerabilidades encontradas. |
| **Observabilidade** | 85/100 | Telemetry, health checks, WebSocket, trace ID. |

**NOTA GLOBAL: 70/100** — Sistema com base excelente mas com gaps concentrados em E2E ID e DICT rate limiting que sao bloqueadores para operacao real.

---

## NOTA SOBRE REQUISITOS DO USUARIO

O usuario especificou:
1. **99.999% uptime** (5.26 min downtime/ano) — Requer: read replicas, fail-closed em blacklist, message draining, DLQ auto-replay
2. **24x7x365** — K8s HA ja suporta (PDB, HPA, RollingUpdate)
3. **100M+ transacoes/dia** (~1,157 TPS avg, 3-5x peaks = 3,500-5,800 TPS) — Capacidade testada a 5K TPS sustentado
4. **E2E ID DICT→SPI** — **NAO IMPLEMENTADO** (gap critico C2)
5. **DICT rate limiting G=250/25** — **NAO IMPLEMENTADO corretamente** (gap critico C3-C5)

**Conclusao**: Os Sprints 1 e 2 sao pre-requisitos absolutos para producao BACEN. Sprint 3 e necessario para escalar alem de 100M TX/dia.
