# Monetarie Ecosystem Compliance Audit

## Date: 2026-02-13

---

## Executive Summary

The Monetarie platform is a comprehensive Brazilian financial infrastructure comprising 8 active repositories (Core, NPC, STA, PIX, SPB, CLST, Backoffice, Infra) deployed across 7+ Kubernetes namespaces on GCP (project `fluxiqbr`, region `southamerica-east1`). The audit reveals a platform in **advanced development stage** with strong architectural consistency across services. All repos share the same Elixir 1.17/OTP 27/Phoenix stack (except STA which has a legacy Go module alongside the production Elixir backend), use Bandit as the HTTP server, and communicate via NATS JetStream on a dedicated VM cluster.

**Overall Health: GOOD with notable gaps.** The PIX subsystem is the most mature, having passed 13 hardening phases with production-grade resilience (circuit breakers, DLQ, RBAC, idempotency, table partitioning, BACEN rate limiting). Core Banking is feature-complete with all 4 regulatory waves + BaaS deployed. NPC, STA, SPB, and CLST have functional backends and deployments but lack the deep hardening applied to PIX. Critical findings include: (1) NPC has no DLQ or circuit breaker; (2) CLST has only 1 migration and zero seed files; (3) NPC/STA K8s configmaps reference Cloud SQL Proxy while PIX uses direct private IP — inconsistency; (4) No automated onboarding runbook exists for new institutional clients; (5) NPC, STA, and Backoffice repos lack `cloudbuild.yaml` files.

**24-hour client onboarding: NOT YET ACHIEVABLE** without manual intervention. Core has a tenant management API (BaaS Wave) and PIX has institution management, but there is no end-to-end automated provisioning flow spanning all subsystems. A new client requires manual ISPB configuration in PIX, NPC, SPB, and CLST, plus certificate provisioning for BACEN mTLS. Realistic estimate: 1-3 days (excluding certificate provisioning).

---

## 1. Code vs Deployment Alignment

### 1.1 Summary Table

| Service | Dockerfile | CloudBuild | K8s Manifest | Health Endpoint | Port Match |
|---------|-----------|------------|-------------|-----------------|------------|
| **Core Backend** | `/monetarie/core/backend/Dockerfile` (Debian) | `/monetarie/core/infrastructure/cloudbuild-api.yaml` | `/monetarie/infra/kubernetes/core/backend-deployment.yaml` | GET /health, GET /readiness | 4000 consistent |
| **NPC Backend** | `/monetarie/npc/backend/Dockerfile` (Alpine) | **MISSING in repo** | `/monetarie/infra/kubernetes/npc/backend-deployment.yaml` | GET /api/health | 4000 consistent |
| **STA Backend** | `/monetarie/sta/backend/Dockerfile` (Alpine) | **MISSING in repo** | `/monetarie/infra/kubernetes/sta/backend-deployment.yaml` | GET /health, GET /ready | 4000 consistent |
| **PIX Backend** | `/monetarie/pix/backend/Dockerfile` (Debian) | `/monetarie/pix/backend/cloudbuild.yaml` | `/monetarie/pix/deploy/backend.yaml` | GET /health on :4003 | 4001/4002/4003 consistent |
| **SPB API Gateway** | `/monetarie/spb/services/api_gateway/Dockerfile` | `/monetarie/spb/services/api_gateway/cloudbuild.yaml` | `/monetarie/spb/k8s/production/05-api-gateway.yaml` | GET /api/health | 4000 consistent |
| **SPB BACEN GW** | `/monetarie/spb/services/bacen_gateway/Dockerfile` | `/monetarie/spb/services/bacen_gateway/cloudbuild.yaml` | `/monetarie/spb/k8s/production/04-bacen-gateway.yaml` | GET /health | 4000 consistent |
| **CLST Backend** | `/monetarie/clst/Dockerfile` (Alpine) | `/monetarie/clst/cloudbuild.yaml` | `/monetarie/infra/kubernetes/clst/backend-deployment.yaml` | GET /health, GET /readiness | 4004 consistent |
| **Backoffice** | `/monetarie/backoffice/Dockerfile` | **MISSING in repo** | `/monetarie/infra/kubernetes/backoffice/deployment.yaml` | GET /health (nginx 200) | 8080 consistent |

### 1.2 Key Findings

- **F1.1 (CRITICAL):** NPC repo has NO `cloudbuild.yaml`. Builds require manual `gcloud builds submit --tag=...`.
- **F1.2 (CRITICAL):** STA repo has NO `cloudbuild.yaml`. Same issue.
- **F1.3 (CRITICAL):** Backoffice repo has NO `cloudbuild.yaml`.
- **F1.4 (HIGH):** Root CLAUDE.md documents Core health as `POST /api/v1/auth/login`. Actual health endpoint is `GET /health`.
- **F1.5 (HIGH):** NPC/STA K8s configmaps reference `DATABASE_HOST: "127.0.0.1"` (Cloud SQL Proxy sidecar) while PIX uses direct private IP `10.140.241.2`. Inconsistent patterns.
- **F1.6 (HIGH):** STA has a legacy Go module (`/monetarie/sta/go.mod` with go 1.22) alongside the production Elixir backend.
- **F1.7 (MEDIUM):** PIX Dockerfile lacks HEALTHCHECK directive (unlike Core, NPC, STA, CLST). K8s probes compensate but images are inconsistent.
- **F1.8 (MEDIUM):** Mixed base images: Core and PIX use Debian bookworm-slim; NPC, STA, SPB, CLST use Alpine 3.21.0.

---

## 2. Database Completeness

### 2.1 Migration Summary

| Service | Migration Count | Seed Files | Notes |
|---------|----------------|------------|-------|
| **Core** | 49 | 1 (seeds.exs) | Covers Oban, regulatory (CCS, SISBAJUD, E-Financeira, DIMP, PGV, SCR), compliance, accounts, treasury, payables, CNAB, open finance, BaaS |
| **NPC** | 11 + .formatter | 1 (seeds.exs) | Boletos, settlements, users, configs, audit, Oban, webhooks, events |
| **STA** | 4 | 1 (seeds.exs) | Processed protocols, outbound files, retry queue, config overrides |
| **PIX** | 27 | 13 files (SQL + Elixir) | Most comprehensive: 8+ DB schemas, 15K+ seeded records |
| **SPB** | 42+ (across 8 services) | 7 seed files (BACEN GW) | Split across microservices |
| **CLST** | **1** | **0** | Single migration, no seeds |

### 2.2 Key Findings

- **F2.1 (CRITICAL):** CLST has only 1 migration and ZERO seed files. Fresh deployment = empty, non-functional database.
- **F2.2 (HIGH):** SPB migrations are split across 8+ services with separate Ecto repos. No single migration runner exists.
- **F2.3 (MEDIUM):** STA has only 4 migrations, which seems minimal for a file transfer service.
- **F2.4 (MEDIUM):** Core has 49 migrations with no migration verification tests. Rollback scenarios are untested.

---

## 3. API Documentation Accuracy

### 3.1 Endpoint Counts (Actual vs Documented)

| Service | Actual Routes (Router) | Documented | Delta |
|---------|----------------------|------------|-------|
| **Core** | ~178 | Listed by category in CLAUDE.md | Generally aligned |
| **NPC** | ~27 | ~27 | Aligned |
| **STA** | ~48 | ~48 | Aligned |
| **PIX Settlement** | ~210 | ~207 | +3 undocumented (Phase 13 accounting exports) |
| **PIX Dict** | ~95 | ~92 | +3 undocumented (admin/blocking/fraud endpoints) |
| **PIX SPI** | ~96 | ~95 | +1 undocumented |
| **SPB API Gateway** | ~25 | ~25 | Aligned |
| **SPB BACEN Gateway** | ~50+ | Not explicitly counted | **Major documentation gap** |
| **CLST** | 22 | 22 | Aligned |
| **TOTAL** | **~775+** | | |

### 3.2 Key Findings

- **F3.1 (HIGH):** SPB BACEN Gateway has ~50+ endpoints with no comprehensive listing in CLAUDE.md.
- **F3.2 (HIGH):** PIX CLAUDE.md Phase 5 section lists accounting endpoint path as `/api/v1/accounting/circular-4010-export` but actual router may use different path.
- **F3.3 (HIGH):** Root CLAUDE.md lists Core health endpoint as `POST /api/v1/auth/login` — that is the auth endpoint, not health.
- **F3.4 (MEDIUM):** PIX Dict admin endpoints under `/api/v2/admin/` not fully documented in phase tables.

---

## 4. Integration Map

### 4.1 NATS Message Bus (25+ Subject Patterns)

| Subject | Publisher | Consumer | Documented? |
|---------|-----------|----------|-------------|
| `monetarie.core.pix.payment_request` | Core (PixController, Payables, OpenFinance) | PIX CoreEventProcessor | Yes |
| `monetarie.core.pix.return_request` | Core (PixController) | PIX CoreEventProcessor | Yes |
| `monetarie.core.pix.key_create` | Core (PixController) | PIX CoreEventProcessor | Yes |
| `monetarie.core.pix.key_delete` | Core (PixController) | PIX CoreEventProcessor | Yes |
| `monetarie.core.spb.transfer_request` | Core (TedController, Payables) | SPB CoreEventConsumer | Yes |
| `monetarie.spi.transaction.*` | PIX SPI Workers | Core PixConsumer, CLST | Yes |
| `monetarie.spi.payment.*` | PIX SPI Workers | Core PixConsumer | Yes |
| `monetarie.spi.return.*` | PIX SPI Workers | Core PixConsumer | Yes |
| `monetarie.settlement.session.*` | PIX Settlement | Core PixConsumer | Partially |
| `monetarie.spb.transactions.*` | SPB BACEN GW CoreNotifier | Core SpbConsumer | Yes |
| `monetarie.spb.messages.*` | SPB BACEN GW | Core SpbConsumer | Yes |
| `monetarie.npc.boleto.*` | NPC Publisher | Core NpcConsumer | Yes |
| `monetarie.npc.cycle.*` | NPC Publisher | Core NpcConsumer | Yes |
| `monetarie.npc.protocol.processed` | NPC Publisher | Core NpcConsumer | Yes |
| `monetarie.sta.sisbajud.order` | STA | Core JudicialNatsHandler | Yes |
| `monetarie.sta.sisbajud.response` | Core JudicialNatsHandler | STA | Yes |
| `monetarie.sta.accs.generated` | Core Publisher | STA | Partially |
| `monetarie.clst.settlement.*` | CLST Publisher | Core | Yes |
| `monetarie.clst.clearing.*` | CLST Publisher | Core | Yes |
| `monetarie.clst.liquidity.*` | CLST Publisher | Core | Yes |
| `monetarie.clst.reconciliation.*` | CLST Publisher | Core | Yes |
| `monetarie.audit.>` | PIX Workers | PIX Audit | Yes |
| `monetarie.dlq.>` | PIX BaseWorker | PIX DlqController | Yes |

### 4.2 Shared Resources

| Resource | Services | Config |
|----------|----------|--------|
| **PostgreSQL (Cloud SQL)** | All 6 backends (separate DBs) | Private IP `10.140.241.2` (PIX) or sidecar proxy (NPC, STA) |
| **Redis (Memorystore)** | Core, PIX, NPC, STA, SPB | `10.140.240.4:6379` |
| **NATS JetStream** | All 6 backends | VMs `10.10.40.{4,5,7}:4222` |
| **TigerBeetle** | Core only | VMs `10.10.40.{2,3,6}:3001` |
| **Guardian JWT Secret** | Core = CLST = PIX | Shared `SECRET_KEY_BASE`/`GUARDIAN_SECRET_KEY`/`JWT_SECRET` |

### 4.3 External Integrations

| Integration | Service | Protocol | Status |
|------------|---------|----------|--------|
| BACEN DICT v2.10.0 | PIX Dict | HTTPS + mTLS + XMLDSig | Homologation |
| BACEN SPI | PIX SPI | HTTPS + mTLS + XMLDSig | Homologation |
| BACEN SPB (STR, MES) | SPB BACEN GW | IBM MQ + HTTPS | Homologation |
| Nuclea NPC | NPC Backend | HTTPS | Production-ready |
| BACEN STA WebService | STA Backend | HTTPS | Configured |

---

## 5. 24-Hour Client Onboarding Assessment

### What EXISTS

- Core tenant CRUD API (`/api/v1/tenants`) with tomadoras, API keys, white-label, billing
- PIX institution management (`/api/v2/admin/institutions`) with category-based rate limits
- PIX user creation and RBAC management
- BACEN simulator for testing
- SSO code exchange (Core `/api/v1/sso`)
- Webhook management

### What is MISSING

| Gap | Impact | Effort |
|-----|--------|--------|
| No cross-service auto-provisioning | Tenant in Core does not create institution in PIX/NPC/SPB/CLST | 3-5 days |
| No ISPB auto-propagation | Manual DB insert per subsystem | 2-3 days |
| No certificate provisioning workflow | ICP-Brasil certs require manual config | Depends on CA |
| No self-service onboarding portal | No UI for institutions | 10+ days |
| No onboarding runbook | No operator documentation | 1-2 days |
| NPC/STA/SPB lack institution admin APIs | Unlike PIX, no admin endpoints | 3-5 days each |

**Estimated onboarding time (current state): 1-3 days** (excluding certificate provisioning). NOT 24 hours.

---

## 6. Resilience Assessment

| Capability | Core | NPC | STA | PIX | SPB | CLST |
|-----------|------|-----|-----|-----|-----|------|
| Circuit Breaker | NO | NO | YES | YES (atomic ETS) | NO | NO |
| DLQ | YES (DB) | **NO** | NO | YES (NATS + admin UI) | YES (DB) | **NO** |
| Retry w/ Backoff | YES (Oban) | YES (Oban) | YES | YES (BaseWorker) | YES | NO |
| Health Check | /health + /readiness | /api/health | /health + /ready | /health + /ready (x3) | /health + /ready (all) | /health + /readiness |
| Graceful Shutdown | NO | NO | NO | YES (30s drain) | NO | NO |
| Rate Limiting | YES (5/min auth) | **NO** | YES | YES (Redis + BACEN) | NO | NO |
| Idempotency Keys | YES (journal) | **NO** | NO | YES (Redis 24h) | NO | NO |
| Token Blacklist | NO | NO | NO | YES (Redis) | NO | NO |
| Distributed Tracing | NO | NO | NO | YES (x-trace-id) | NO | NO |
| Table Partitioning | YES | NO | NO | YES | NO | NO |
| Prometheus /metrics | YES | YES | YES | YES | YES | **NO** |

---

## 7. Critical Findings (Priority Order)

### P0 — Must Fix Before Production

1. **F6.1** NPC needs circuit breaker + DLQ for Nuclea API integration.
2. **F6.2** CLST needs retry logic + DLQ. Current `Task.start` with try/rescue is insufficient for a clearing/settlement aggregator.
3. **F2.1** CLST has no seed data. Fresh deployment = empty, non-functional database.
4. **F6.3** Core needs circuit breaker for TigerBeetle. Outage cascades to all wallet/balance/transfer operations.

### P1 — High Priority

5. **F1.1/F1.2/F1.3** NPC, STA, Backoffice need `cloudbuild.yaml` for CI/CD.
6. **F6.4** All services except PIX need graceful shutdown handling for NATS workers.
7. **F1.5** Standardize database connectivity (direct IP vs Cloud SQL Proxy).
8. **F3.1** SPB BACEN Gateway needs comprehensive API documentation.
9. **F6.7** CLST needs `/metrics` endpoint for Prometheus observability.

### P2 — Medium Priority

10. **F1.6** Remove or deprecate STA legacy Go module.
11. **F1.7** Add HEALTHCHECK to PIX Dockerfile.
12. **F3.2** Update PIX CLAUDE.md accounting endpoint paths.
13. **F5.1** Cross-service institution provisioning via NATS events.
14. **F5.2** Write operator onboarding runbook.

---

## 8. Recommendations

### Immediate (1-2 weeks)

1. **Add circuit breakers to NPC and CLST** — copy PIX's `SettlementService.CircuitBreaker` pattern (ETS-based, atomic counters, 5 failures/30s cooldown). ~2 days per service.
2. **Add DLQ to NPC and CLST** — NPC can use Oban's dead job mechanism; CLST needs NATS DLQ stream. ~2-3 days per service.
3. **Create CLST seed data** — settlement window configs, participants, reference data. ~1 day.
4. **Add cloudbuild.yaml to NPC, STA, Backoffice**. ~1 day.
5. **Write onboarding runbook**. ~1 day.

### Short-Term (2-4 weeks)

6. **Standardize on direct Cloud SQL IP** for all services (remove proxy sidecar).
7. **Add graceful shutdown** to Core, NPC, STA, CLST workers following PIX BaseWorker pattern.
8. **Implement cross-service institution provisioning** via `monetarie.core.institution.created` NATS event.
9. **Add distributed tracing** to all services using x-trace-id header propagation.
10. **Document SPB API comprehensively** in CLAUDE.md.

### Medium-Term (1-2 months)

11. **Build self-service onboarding portal** in Backoffice.
12. **Automated cross-service integration tests** (Core → PIX → Core → CLST flow).
13. **Table partitioning** for NPC boletos, SPB bacen_messages, CLST clearing batches.
14. **Chaos testing suite** using K6 + Litmus for failure scenarios.

### Architecture Improvements

15. **Consider consolidating SPB microservices** into umbrella app (10+ services creates operational overhead).
16. **Platform-wide event schema registry** (Protobuf/JSON Schema for NATS payloads).
17. **Certificate rotation automation** for ICP-Brasil mTLS certificates.

---

## Appendix: Platform Totals

| Metric | Value |
|--------|-------|
| Active repositories | 8 |
| K8s namespaces | 10 (pix, spb, npc, sta, core, backoffice, clst, rsfn-edge, monitoring, infra) |
| Total API endpoints | ~775+ |
| Total migrations | ~134+ (49 Core + 11 NPC + 4 STA + 27 PIX + 42 SPB + 1 CLST) |
| Total seed files | ~24 (1 Core + 1 NPC + 1 STA + 13 PIX + 7 SPB + 0 CLST) |
| NATS subject patterns | 25+ |
| Dockerfiles | 25+ |
| VitePress doc pages | 136+ (12 Core + 44 NPC + 68 STA + 13 PIX + 12 SPB) |
| Elixir services | 18+ (1 Core + 1 NPC + 1 STA + 4 PIX + 10 SPB + 1 CLST) |

---

This report was produced by reading actual source code across all 8 repositories. No files were modified during the audit. All file paths, endpoint counts, and findings are based on code inspection as of 2026-02-13.
