# Monetarie PIX - System Testing Guide

**Version:** 1.0
**Date:** 2026-02-07
**Classification:** Internal
**Audience:** QA team, Operations team, Technical Support

---

## Table of Contents

1. [Quick Start](#1-quick-start)
2. [Environment Setup](#2-environment-setup)
3. [BACEN Simulator — Enable / Disable / Configure](#3-bacen-simulator--enable--disable--configure)
4. [Test Credentials & Test Data](#4-test-credentials--test-data)
5. [Health Checks — Verifying System Status](#5-health-checks--verifying-system-status)
6. [Test Scenarios — Step-by-Step](#6-test-scenarios--step-by-step)
7. [Automated Scenario Runner](#7-automated-scenario-runner)
8. [Frontend Testing Guide](#8-frontend-testing-guide)
9. [Settlement & Netting Testing](#9-settlement--netting-testing)
10. [MED 2.0 Fraud Recovery Testing](#10-med-20-fraud-recovery-testing)
11. [Performance & Stress Testing](#11-performance--stress-testing)
12. [Monitoring & Observability](#12-monitoring--observability)
13. [Troubleshooting](#13-troubleshooting)
14. [Test Execution Checklist](#14-test-execution-checklist)

---

## 1. Quick Start

### Minimum Prerequisites

| Requirement | Version |
|------------|---------|
| Elixir | 1.17+ |
| Erlang/OTP | 27+ |
| Node.js | 18+ |
| PostgreSQL | 15+ |
| Docker & Docker Compose | Latest |
| curl or Postman | Latest |

### 30-Second Start

```bash
# 1. Start infrastructure
cd /Users/luizpenha/monetarie/pix/backend
docker compose up -d

# 2. Setup database + seeds
mix deps.get
mix ecto.setup

# 3. Run seed data (simulator data included)
mix run apps/shared/priv/repo/seeds.exs
mix run apps/shared/priv/repo/seeds/simulator_seed.exs

# 4. Start backend with simulator enabled
SIMULATOR_ENABLED=true mix phx.server

# 5. Start frontend (separate terminal)
cd /Users/luizpenha/monetarie/pix/frontend/admin
npm install && npm run dev
```

### GKE Environment (Development)

```
Backend:  https://pixadmin-dev.fluxiq.com.br (port 4003 gateway)
Frontend: https://pixadmin-dev.fluxiq.com.br
Login:    admin / Admin@2026!
```

---

## 2. Environment Setup

### 2.1 Local Development (docker-compose)

The `docker-compose.yml` starts three infrastructure services:

| Service | Port | Image | Healthcheck |
|---------|------|-------|-------------|
| PostgreSQL | 5432 | postgres:15-alpine | `pg_isready` every 10s |
| NATS JetStream | 4222 (client), 8222 (monitor) | nats:2.10-alpine | `nats-server --help` every 10s |
| Redis | 6379 | redis:7-alpine | `redis-cli ping` every 10s |

```bash
# Start infrastructure
docker compose up -d

# Verify all healthy
docker compose ps
# Should show: postgres (healthy), nats (healthy), redis (healthy)

# Check NATS monitoring
open http://localhost:8222
```

### 2.2 Database Setup

```bash
# Create database + run all 16 migrations + seed
mix ecto.setup

# Or step by step:
mix ecto.create              # Create monetarie_pix_dev database
mix ecto.migrate             # Run 16 migrations
mix run apps/shared/priv/repo/seeds.exs  # Base seed data

# Simulator-specific seeds
mix run apps/shared/priv/repo/seeds/simulator_seed.exs
```

**Migrations (16 total):**

| # | Migration | Tables/Changes |
|---|-----------|----------------|
| 1 | `20260201000001_create_complete_schema` | All core schemas + tables |
| 2 | `20260203000001_gap_resolution_tables` | 13 additional tables |
| 3 | `20260203000002_gap_resolution_seed_data` | Reference data (SQL) |
| 4 | `20260206200001_create_compliance_tables` | Crypto keys, validations, XSD, errors |
| 5 | `20260206200002_create_domain_values_table` | Domain values enhancement |
| 6 | `20260206200003_create_alcada_tables` | Alcada authorization tiers |

### 2.3 Seed Data Summary

| Seed File | Records | What |
|-----------|---------|------|
| seeds.exs | ~700 | Users, participants, base data |
| gap_resolution_seed.sql | ~650 | Banks (369), status codes, reason codes, message types |
| pix_keys_seed.sql | 277 | PIX keys for testing |
| dict_operations_seed.sql | 15,442 | Historical DICT operations |
| xsd_schemas_seed.exs | 27 | XSD validation schemas |
| bacen_error_codes_seed.exs | 161 | BACEN error code catalog |
| bacen_domain_values_seed.exs | 175+ | Domain value lookups |
| full_bank_directory_seed.exs | 98 | Additional banks (220+ total) |
| realistic_transactions_seed.exs | 1,000+ | 30 days of transaction history |
| simulator_seed.exs | ~200 | Simulator config, scenarios, PIX keys, balances |

### 2.4 Environment Variables

**Minimum for local testing:**
```bash
export DB_HOST=localhost
export DB_PORT=5432
export DB_USER=postgres
export DB_PASS=postgres
export DB_NAME=monetarie_pix_dev
export SIMULATOR_ENABLED=true
export BACEN_ENABLED=false      # Use simulator, not real BACEN
export NATS_ENABLED=false       # Disable NATS workers for simple testing
```

**Full testing with NATS workers:**
```bash
export NATS_ENABLED=true
export NATS_HOST=localhost
export NATS_PORT=4222
export REDIS_HOST=localhost
export REDIS_PORT=6379
export SIMULATOR_ENABLED=true
export BACEN_ENABLED=false
```

---

## 3. BACEN Simulator — Enable / Disable / Configure

### 3.1 What is the Simulator?

The BACEN Simulator replaces the real BACEN Central Bank network with a local GenServer that:

- Receives outbound ISO 20022 messages (pacs.008, pacs.004, camt.060, pibr.001, etc.)
- Returns realistic simulated responses (pacs.002 ACCC/RJCT, camt.052, pibr.002, etc.)
- Generates inbound messages (incoming payments, returns, notifications)
- Runs pre-defined test scenarios (happy path, rejection, stress test, etc.)
- Tracks statistics (processed, accepted, rejected counts)

### 3.2 Enabling the Simulator

**Method 1 — Environment Variable (Recommended):**
```bash
# Set before starting the backend
export SIMULATOR_ENABLED=true
export BACEN_ENABLED=false

# Start backend
mix phx.server
```

**Method 2 — GKE Deployment:**
```bash
# Update the deployment environment
kubectl set env deployment/pix-backend \
  SIMULATOR_ENABLED=true \
  BACEN_ENABLED=false \
  -n pix

# Verify
kubectl get pods -n pix -w
```

**Method 3 — Runtime (IEx Console):**
```elixir
# Connect to running system
iex --sname debug --remsh pix@hostname

# Check status
Shared.Bacen.Simulator.status()

# Enable dynamically
Shared.Bacen.Simulator.set_config("enabled", "true")
```

### 3.3 Disabling the Simulator

```bash
# Set SIMULATOR_ENABLED=false and BACEN_ENABLED=true for real BACEN
export SIMULATOR_ENABLED=false
export BACEN_ENABLED=true

# Restart backend
mix phx.server
```

On GKE:
```bash
kubectl set env deployment/pix-backend \
  SIMULATOR_ENABLED=false \
  BACEN_ENABLED=true \
  -n pix
```

### 3.4 Configuring the Simulator

**Accept Rate (default: 90%):**
```bash
# Via IEx console
Shared.Bacen.Simulator.set_config("accept_rate", "0.75")  # 75% acceptance

# Reset to default
Shared.Bacen.Simulator.set_config("accept_rate", "0.9")
```

**Response Delays:**
```bash
Shared.Bacen.Simulator.set_config("min_delay_ms", "100")  # Min 100ms
Shared.Bacen.Simulator.set_config("max_delay_ms", "2000") # Max 2 seconds
```

**All Configurable Parameters:**

| Key | Default | Type | Description |
|-----|---------|------|-------------|
| `accept_rate` | `0.9` | float | Probability of accepting pacs.008 (0.0 to 1.0) |
| `min_delay_ms` | `50` | integer | Minimum simulated response delay |
| `max_delay_ms` | `500` | integer | Maximum simulated response delay |
| `max_exchanges_per_hour` | `10000` | integer | Rate limit for the simulator |
| `default_ispb` | `12345678` | string | Monetarie ISPB |
| `bacen_ispb` | `00038166` | string | Simulated BACEN ISPB |
| `auto_settlement` | `true` | boolean | Auto-generate settlement messages |
| `echo_enabled` | `true` | boolean | Respond to echo (pibr.001/002) |
| `async_response_enabled` | `false` | boolean | Enable delayed async responses |
| `async_response_delay_s` | `5` | integer | Async response delay in seconds |

### 3.5 Checking Simulator Status

```bash
# Via curl (requires authentication)
curl -s https://pixadmin-dev.fluxiq.com.br/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"login":"admin","password":"Admin@2026!"}' | jq .token
```

```elixir
# Via IEx
Shared.Bacen.Simulator.status()
# Returns:
# %{
#   config: %{accept_rate: 0.9, min_delay_ms: 50, ...},
#   stats: %{total_processed: 150, total_accepted: 135, total_rejected: 15, ...},
#   scenarios: [:happy_path, :rejected_payment, :return_flow, ...]
# }
```

---

## 4. Test Credentials & Test Data

### 4.1 User Accounts

| Username | Password | Role | Permissions |
|----------|----------|------|-------------|
| `admin` | `Admin@2026!` | System Administrator | Full access |
| `operator` | `Operator@2026!` | Transaction Operator | Payments, returns, balance |
| `viewer` | `Viewer@2026!` | Read-only Viewer | Read-only all modules |
| `lso.approver` | `Lso@2026!` | LSO Approver | First-level alcada approval |
| `rso.approver` | `Rso@2026!` | RSO Approver | Second-level alcada approval |
| `bank.admin` | `BankAdmin@2026!` | Bank Admin | Bank-level administration |
| `integration` | `Monetarie@2026!` | Integration User | API access for partners |

### 4.2 Test PIX Keys

| PIX Key | Type | ISPB | Bank | Owner |
|---------|------|------|------|-------|
| `12345678901` | CPF | 12345678 | Monetarie | JOAO SILVA TESTE |
| `98765432100` | CPF | 12345678 | Monetarie | MARIA SANTOS TESTE |
| `+5511999990001` | PHONE | 12345678 | Monetarie | PEDRO OLIVEIRA |
| `teste@fluxiq.com.br` | EMAIL | 12345678 | Monetarie | ANA COSTA |
| `a1b2c3d4-e5f6-7890-abcd-ef1234567890` | EVP | 12345678 | Monetarie | CARLOS FERREIRA |
| `33344455566` | CPF | 17184037 | Itau | ROBERTO ALMEIDA |
| `+5521988880001` | PHONE | 17184037 | Itau | LUCIA PEREIRA |
| `user@nubank.com.br` | EMAIL | 02332886 | Nubank | FERNANDO SOUZA |
| `55667788990` | CPF | 02332886 | Nubank | JULIANA LIMA |
| `11223344556` | CPF | 00000000 | Banco do Brasil | ANTONIO RIBEIRO |

### 4.3 Test Participant Balances

| ISPB | Institution | Account Balance | Available |
|------|-------------|----------------|-----------|
| 12345678 | Monetarie | R$ 2,500,000.00 | R$ 2,400,000.00 |
| 17184037 | Itau | R$ 50,000,000.00 | R$ 48,000,000.00 |
| 02332886 | Nubank | R$ 30,000,000.00 | R$ 29,000,000.00 |
| 00000000 | Banco do Brasil | R$ 100,000,000.00 | R$ 98,000,000.00 |
| 00360305 | Caixa | R$ 80,000,000.00 | R$ 78,000,000.00 |
| 10573521 | Mercado Pago | R$ 15,000,000.00 | R$ 14,500,000.00 |

---

## 5. Health Checks — Verifying System Status

### 5.1 Individual Service Health

```bash
# Dict Service (port 4001)
curl -s http://localhost:4001/health | jq .
curl -s http://localhost:4001/ready | jq .

# SPI Service (port 4002)
curl -s http://localhost:4002/health | jq .
curl -s http://localhost:4002/ready | jq .

# Settlement Service / Gateway (port 4003)
curl -s http://localhost:4003/health | jq .
curl -s http://localhost:4003/ready | jq .
```

**Expected `/health` Response:**
```json
{
  "status": "healthy",
  "service": "settlement-service",
  "timestamp": "2026-02-07T10:00:00Z"
}
```

**Expected `/ready` Response:**
```json
{
  "status": "ready",
  "service": "settlement-service",
  "checks": {
    "database": "healthy",
    "nats": "healthy"
  },
  "timestamp": "2026-02-07T10:00:00Z"
}
```

### 5.2 Aggregate Health (All Services)

```bash
# Check all services from the gateway
curl -s http://localhost:4003/api/v1/health | jq .
```

**Expected Response:**
```json
{
  "status": "healthy",
  "services": {
    "settlement": {"status": "healthy", "checks": {"database": "healthy", "nats": "healthy"}},
    "dict": {"status": "healthy", "checks": {"database": "healthy", "nats": "healthy"}},
    "spi": {"status": "healthy", "checks": {"database": "healthy", "nats": "healthy"}}
  },
  "timestamp": "..."
}
```

### 5.3 Comprehensive System Health

```bash
curl -s http://localhost:4003/api/v1/system/health | jq .
```

This checks ALL components in parallel:
- 3 services (DICT, SPI, Settlement) with response time measurements
- PostgreSQL (with version and database name)
- Redis (PING test)
- NATS (connection status, host, port)

**Expected Response:**
```json
{
  "overall": "healthy",
  "services": [
    {"name": "dict-service", "status": "healthy", "responseTimeMs": 12},
    {"name": "spi-service", "status": "healthy", "responseTimeMs": 8},
    {"name": "settlement-service", "status": "healthy", "responseTimeMs": 3}
  ],
  "database": {"name": "postgres", "status": "healthy", "responseTimeMs": 5, "details": {"version": "PostgreSQL 15..."}},
  "redis": {"name": "redis", "status": "healthy", "responseTimeMs": 2},
  "nats": {"name": "nats", "status": "healthy", "responseTimeMs": 3, "details": {"connected": true}},
  "lastUpdatedAt": "..."
}
```

### 5.4 GKE Health Checks

```bash
# Check pod status
kubectl get pods -n pix

# Check pod logs
kubectl logs -n pix deployment/pix-backend --tail=50

# Port-forward for local testing
kubectl port-forward -n pix svc/pix-backend 4003:4003

# Then use local curl commands as above
```

---

## 6. Test Scenarios — Step-by-Step

### Prerequisites for All Scenarios

```bash
# 1. Get authentication token
TOKEN=$(curl -s http://localhost:4003/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"login":"admin","password":"Admin@2026!"}' | jq -r .token)

echo "Token: $TOKEN"
```

### 6.1 Scenario: Happy Path (Successful Payment)

**Goal:** Send a PIX payment and verify it's accepted.

```bash
# Step 1: Create payment
PAYMENT=$(curl -s -X POST http://localhost:4003/api/v1/payments \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction": {
      "amount": 15000,
      "debtor_ispb": "12345678",
      "creditor_ispb": "17184037",
      "debtor_document": "12345678901",
      "creditor_document": "33344455566",
      "debtor_account": "123456",
      "creditor_account": "654321",
      "local_instrument": "DICT",
      "description": "Test payment - happy path",
      "creditor_proxy": "33344455566"
    }
  }')

echo "$PAYMENT" | jq .
PAYMENT_ID=$(echo "$PAYMENT" | jq -r .id)

# Step 2: Check payment status
curl -s http://localhost:4003/api/v1/payments/$PAYMENT_ID \
  -H "Authorization: Bearer $TOKEN" | jq .

# Step 3: Check payment history
curl -s http://localhost:4003/api/v1/payments/$PAYMENT_ID/history \
  -H "Authorization: Bearer $TOKEN" | jq .
```

**Expected Result:**
- Payment created with status `processing`
- With simulator, status updates to `settled` (ACCC)

### 6.2 Scenario: Rejected Payment

**Goal:** Verify system handles rejected payments correctly.

```bash
# Create payment with high amount (likely to trigger rejection in simulator)
curl -s -X POST http://localhost:4003/api/v1/payments \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction": {
      "amount": 9999999,
      "debtor_ispb": "12345678",
      "creditor_ispb": "17184037",
      "debtor_document": "12345678901",
      "creditor_document": "33344455566",
      "debtor_account": "123456",
      "creditor_account": "654321",
      "local_instrument": "MANU",
      "description": "Test - expecting rejection"
    }
  }' | jq .
```

**Expected Result:** Status `rejected` with a BACEN error code (AB03, AC03, AM04, etc.)

### 6.3 Scenario: Return Flow

**Goal:** Send a payment, then return it.

```bash
# Step 1: Create and settle a payment (use happy path first)
PAYMENT_ID="<id-from-step-1>"

# Step 2: Create return
curl -s -X POST http://localhost:4003/api/v1/transactions/$PAYMENT_ID/return \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 15000,
    "reason_code": "MD06",
    "reason_description": "Customer requested return",
    "requester": "creditor"
  }' | jq .

# Step 3: List returns for this transaction
curl -s http://localhost:4003/api/v1/transactions/$PAYMENT_ID/returns \
  -H "Authorization: Bearer $TOKEN" | jq .
```

### 6.4 Scenario: PIX Key CRUD

**Goal:** Test full lifecycle of a PIX key.

```bash
# Step 1: Create a PIX key
curl -s -X POST http://localhost:4003/api/v2/entries \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "key_type": "EMAIL",
    "key_value": "test.user@example.com",
    "owner_type": "NATURAL_PERSON",
    "owner_cpf_cnpj": "99988877766",
    "owner_name": "TESTE USUARIO",
    "branch_code": "0001",
    "account_number": "999888",
    "account_type": "CACC"
  }' | jq .

# Step 2: Query the key
curl -s http://localhost:4003/api/v2/entries/test.user@example.com \
  -H "Authorization: Bearer $TOKEN" | jq .

# Step 3: Delete the key
curl -s -X DELETE http://localhost:4003/api/v2/entries/test.user@example.com \
  -H "Authorization: Bearer $TOKEN" | jq .
```

### 6.5 Scenario: Echo Test (Connectivity)

**Goal:** Verify BACEN SPI connectivity.

```bash
curl -s -X POST http://localhost:4003/api/v1/echo \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"echo_data": "PING_TEST_12345"}' | jq .
```

**Expected Result:**
```json
{
  "status": "ok",
  "echo_data": "PING_TEST_12345",
  "response_time_ms": 45
}
```

### 6.6 Scenario: Balance Inquiry

**Goal:** Check participant balance.

```bash
# Current balance
curl -s http://localhost:4003/api/v1/balance \
  -H "Authorization: Bearer $TOKEN" | jq .

# Balance by participant
curl -s http://localhost:4003/api/v1/balance/account/12345678 \
  -H "Authorization: Bearer $TOKEN" | jq .

# All positions
curl -s http://localhost:4003/api/v1/balance/positions \
  -H "Authorization: Bearer $TOKEN" | jq .

# Intraday movements
curl -s http://localhost:4003/api/v1/balance/intraday/12345678 \
  -H "Authorization: Bearer $TOKEN" | jq .
```

### 6.7 Scenario: QR Code Generation

**Goal:** Generate static and dynamic QR codes.

```bash
# Static QR Code
curl -s -X POST http://localhost:4003/api/v1/qr-codes/static \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pix_key": "12345678901",
    "merchant_name": "LOJA TESTE",
    "merchant_city": "SAO PAULO",
    "description": "PIX static test"
  }' | jq .

# Dynamic QR Code (with amount and expiry)
curl -s -X POST http://localhost:4003/api/v1/qr-codes/dynamic \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pix_key": "12345678901",
    "amount": 15000,
    "merchant_name": "LOJA TESTE",
    "merchant_city": "SAO PAULO",
    "txid": "PEDIDO12345",
    "expires_in": 3600
  }' | jq .
```

### 6.8 Scenario: Statement Generation

```bash
# Generate statement
curl -s -X POST http://localhost:4003/api/v1/statements/generate \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "from_date": "2026-02-01",
    "to_date": "2026-02-07",
    "format": "json"
  }' | jq .

# List statements
curl -s http://localhost:4003/api/v1/statements \
  -H "Authorization: Bearer $TOKEN" | jq .
```

---

## 7. Automated Scenario Runner

The built-in ScenarioRunner executes pre-defined test scenarios programmatically.

### 7.1 Available Scenarios

| Scenario | Steps | Description |
|----------|-------|-------------|
| `:happy_path` | 2 | pacs.008 → pacs.002 ACCC |
| `:rejected_payment` | 2 | pacs.008 → pacs.002 RJCT |
| `:return_flow` | 4 | pacs.008 → ACCC → pacs.004 → ACCC |
| `:incoming_payment` | 1 | Receive inbound pacs.008 from external PSP |
| `:echo_test` | 2 | pibr.001 → pibr.002 |
| `:balance_check` | 2 | camt.060 → camt.052 |
| `:full_cycle` | 5 | Payment + notification + balance check |
| `:stress_test` | 20 | 10 concurrent payments (configurable) |

### 7.2 Running Scenarios via IEx Console

```bash
# Connect to running system
cd /Users/luizpenha/monetarie/pix/backend
iex -S mix phx.server
```

```elixir
# Ensure simulator is started
{:ok, _pid} = Shared.Bacen.Simulator.start_link([])

# Run happy path
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:happy_path)
IO.inspect(result, label: "Happy Path")
# Expected: %{status: :passed, total: 2, passed: 2, failed: 0}

# Run rejected payment
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:rejected_payment)
IO.inspect(result, label: "Rejected Payment")
# Expected: %{status: :passed, total: 2, passed: 2, failed: 0}

# Run return flow
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:return_flow)
IO.inspect(result, label: "Return Flow")
# Expected: %{status: :passed, total: 4, passed: 4, failed: 0}

# Run incoming payment simulation
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:incoming_payment)
IO.inspect(result, label: "Incoming Payment")
# Expected: %{status: :passed, total: 1, passed: 1, failed: 0}

# Run echo test
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:echo_test)
IO.inspect(result, label: "Echo Test")
# Expected: %{status: :passed, total: 2, passed: 2, failed: 0}

# Run balance check
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:balance_check)
IO.inspect(result, label: "Balance Check")
# Expected: %{status: :passed, total: 2, passed: 2, failed: 0}

# Run full cycle (payment + notification + balance)
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:full_cycle)
IO.inspect(result, label: "Full Cycle")
# Expected: %{status: :passed, total: 5, passed: 5, failed: 0}

# Run stress test (default 10 concurrent payments)
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:stress_test)
IO.inspect(result, label: "Stress Test (10)")
# Expected: ~90% passed (based on accept_rate)

# Run stress test with custom count
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:stress_test, count: 50)
IO.inspect(result, label: "Stress Test (50)")
```

### 7.3 Running All Scenarios Sequentially

```elixir
# Run all scenarios and collect results
scenarios = [:happy_path, :rejected_payment, :return_flow, :incoming_payment,
             :echo_test, :balance_check, :full_cycle, :stress_test]

results = Enum.map(scenarios, fn scenario ->
  {status, result} = Shared.Bacen.Simulator.run_scenario(scenario)
  {scenario, status, result}
end)

# Print summary
Enum.each(results, fn {scenario, status, result} ->
  case status do
    :ok ->
      IO.puts("#{scenario}: #{result.status} (#{result.passed}/#{result.total} passed)")
    :error ->
      IO.puts("#{scenario}: ERROR - #{inspect(result)}")
  end
end)
```

### 7.4 Viewing Scenario Results in Database

```sql
-- Recent test runs
SELECT id, name, status, total_messages, successful_messages, failed_messages,
       started_at, completed_at
FROM bacen_simulator.test_runs
ORDER BY started_at DESC
LIMIT 20;

-- Detailed results for a specific run
SELECT step_order, message_type, status, execution_time_ms, error_message
FROM bacen_simulator.test_results
WHERE test_run_id = '<run_id>'
ORDER BY step_order;

-- Message exchanges
SELECT id, message_type, direction, status, response_time_ms, error_code
FROM bacen_simulator.message_exchanges
ORDER BY created_at DESC
LIMIT 50;
```

### 7.5 Generating Inbound Messages

```elixir
# Simulate receiving an incoming payment from Itau
{:ok, xml, meta} = Shared.Bacen.Simulator.generate_inbound(:incoming_payment, %{
  sender_ispb: "17184037",
  amount: 25000
})
IO.puts("Received inbound payment: #{String.length(xml)} bytes")

# Simulate receiving a return
{:ok, xml, meta} = Shared.Bacen.Simulator.generate_inbound(:return, %{
  sender_ispb: "02332886",
  amount: 10000
})

# Simulate a system notification
{:ok, xml, meta} = Shared.Bacen.Simulator.generate_inbound(:notification, %{
  direction: "CRDT",
  amount: 50000
})

# Simulate BACEN system event (maintenance, rate limit, etc.)
{:ok, xml, meta} = Shared.Bacen.Simulator.generate_inbound(:system_event, %{})

# Simulate end-of-day settlement report
{:ok, xml, meta} = Shared.Bacen.Simulator.generate_inbound(:settlement_report, %{})
```

---

## 8. Frontend Testing Guide

### 8.1 Accessing the Admin Portal

| Environment | URL | Credentials |
|------------|-----|-------------|
| Local Dev | http://localhost:5173 | admin / Admin@2026! |
| GKE Dev | https://pixadmin-dev.fluxiq.com.br | admin / Admin@2026! |

### 8.2 Module Testing Checklist

**Dashboard:**
- [ ] Login with admin credentials
- [ ] Verify dashboard statistics load (total transactions, active keys, balance)
- [ ] Check real-time transaction chart renders
- [ ] Verify recent transactions list populates

**PIX Keys (DICT):**
- [ ] Navigate to PIX Keys module
- [ ] List existing keys (should show 277+ from seeds)
- [ ] Create a new CPF key
- [ ] Create a new EMAIL key
- [ ] Create a new EVP key (random)
- [ ] Search by key value
- [ ] Delete a test key
- [ ] Block/unblock a key

**Transactions (SPI):**
- [ ] Navigate to Transactions module
- [ ] List transactions (should show 1,000+ from seeds)
- [ ] Filter by date range
- [ ] Filter by status (pending, settled, rejected)
- [ ] Filter by local instrument (DICT, MANU, QR)
- [ ] View transaction detail
- [ ] View transaction history
- [ ] Create new payment
- [ ] Create return for an existing transaction

**Balance:**
- [ ] View current balance summary
- [ ] View balance by participant
- [ ] Check intraday movements
- [ ] View all participant positions
- [ ] Check liquidity status

**QR Codes:**
- [ ] Generate static QR code
- [ ] Generate dynamic QR code with amount
- [ ] View QR code list
- [ ] View QR code detail
- [ ] Cancel a QR code

**Accounting:**
- [ ] View accounting dashboard
- [ ] Check netting positions
- [ ] View reconciliation status
- [ ] View settlement sessions
- [ ] Check fee calculations

**Alcada (Authorization Tiers):**
- [ ] View alcada parameters
- [ ] Create new alcada parameter
- [ ] View pending approvals
- [ ] Approve/reject a pending registration
- [ ] View approval history

**Simulator:**
- [ ] Navigate to Simulator module
- [ ] View simulator dashboard (status, stats)
- [ ] Run test scenario from UI
- [ ] View scenario results
- [ ] Check message exchange history

**Users & Audit:**
- [ ] List users
- [ ] Create new user
- [ ] Deactivate a user
- [ ] Reset user password
- [ ] View audit logs
- [ ] Filter audit logs by date/user/action

**Reports:**
- [ ] Generate an intraday report
- [ ] Generate a statement
- [ ] Download report in JSON format
- [ ] Download report in CSV format

### 8.3 Multi-Language Testing

The frontend supports 4 languages:

| Locale | Language | Test Path |
|--------|----------|-----------|
| `en-US` | English | Default |
| `pt-BR` | Portuguese (Brazil) | Settings → Language |
| `zh-CN` | Chinese (Simplified) | Settings → Language |
| `es-ES` | Spanish | Settings → Language |

- [ ] Switch to pt-BR and verify all labels translate
- [ ] Switch to zh-CN and verify all labels translate
- [ ] Switch to es-ES and verify all labels translate
- [ ] Switch back to en-US

### 8.4 Role-Based Access Testing

Test with each user role to verify proper access controls:

| Test | admin | operator | viewer |
|------|-------|----------|--------|
| View dashboard | Yes | Yes | Yes |
| List transactions | Yes | Yes | Yes |
| Create payment | Yes | Yes | No |
| Create return | Yes | Yes | No |
| Manage PIX keys | Yes | Yes | No |
| Manage users | Yes | No | No |
| View audit logs | Yes | Yes | Yes |
| Configure simulator | Yes | No | No |
| Manage alcada params | Yes | No | No |

---

## 9. Settlement & Netting Testing

### 9.1 Settlement Session Lifecycle

```bash
# 1. Create D+0 settlement session
SESSION=$(curl -s -X POST http://localhost:4003/api/v1/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "d0",
    "settlement_date": "2026-02-07"
  }')
echo "$SESSION" | jq .
SESSION_ID=$(echo "$SESSION" | jq -r .id)

# 2. Open session
curl -s -X POST http://localhost:4003/api/v1/sessions/$SESSION_ID/open \
  -H "Authorization: Bearer $TOKEN" | jq .

# 3. Process transactions (create payments while session is open)
# ... create payments as in section 6.1 ...

# 4. Close session (calculates statistics)
curl -s -X POST http://localhost:4003/api/v1/sessions/$SESSION_ID/close \
  -H "Authorization: Bearer $TOKEN" | jq .

# 5. View session statistics
curl -s http://localhost:4003/api/v1/sessions/$SESSION_ID/statistics \
  -H "Authorization: Bearer $TOKEN" | jq .

# 6. Finalize session
curl -s -X POST http://localhost:4003/api/v1/sessions/$SESSION_ID/finalize \
  -H "Authorization: Bearer $TOKEN" | jq .
```

### 9.2 Session Status Transitions

Test these transitions and verify proper error handling:

| Transition | Expected | HTTP Code |
|-----------|----------|-----------|
| SCHEDULED → OPEN | Success | 200 |
| OPEN → CLOSED | Success | 200 |
| CLOSED → FINALIZED | Success | 200 |
| OPEN → OPEN (duplicate) | Error: invalid_status_transition | 422 |
| FINALIZED → OPEN | Error: invalid_status_transition | 422 |
| SCHEDULED → CANCELLED (with reason) | Success | 200 |
| SCHEDULED → CANCELLED (no reason) | Error: reason required | 422 |

---

## 10. MED 2.0 Fraud Recovery Testing

### 10.1 Full MED Flow

```bash
# 1. Create infraction report
# 2. Acknowledge infraction
# 3. Analyse infraction
# 4. Create funds recovery
# 5. Start refund
# 6. Complete refund
# 7. Close infraction

# Step 1: List infraction reports
curl -s http://localhost:4003/api/v2/infraction-reports \
  -H "Authorization: Bearer $TOKEN" | jq .

# Step 2: Create funds recovery
curl -s -X POST http://localhost:4003/api/v2/funds-recoveries \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "original_transaction_id": "<transaction_id>",
    "amount": 15000,
    "reason": "FRAUD_SUSPICION",
    "details": "Customer reported unauthorized transaction"
  }' | jq .

# Step 3: Check tracking graph
RECOVERY_ID="<id-from-step-2>"
curl -s http://localhost:4003/api/v2/funds-recoveries/$RECOVERY_ID/tracking-graph \
  -H "Authorization: Bearer $TOKEN" | jq .
```

---

## 11. Performance & Stress Testing

### 11.1 Using the Built-in Stress Test

```elixir
# In IEx console:

# 10 concurrent payments (default)
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:stress_test)

# 50 concurrent payments
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:stress_test, count: 50)

# 100 concurrent payments
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:stress_test, count: 100)

# 500 concurrent payments
{:ok, result} = Shared.Bacen.Simulator.run_scenario(:stress_test, count: 500)
```

### 11.2 Using curl for Load Testing

```bash
# Simple parallel requests using xargs
seq 1 100 | xargs -P 10 -I {} curl -s -X POST http://localhost:4003/api/v1/payments \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction": {
      "amount": '$((RANDOM % 100000 + 100))',
      "debtor_ispb": "12345678",
      "creditor_ispb": "17184037",
      "debtor_document": "12345678901",
      "creditor_document": "33344455566",
      "debtor_account": "123456",
      "creditor_account": "654321",
      "local_instrument": "DICT",
      "creditor_proxy": "33344455566"
    }
  }' -o /dev/null -w "Request {}: %{http_code} in %{time_total}s\n"
```

### 11.3 Rate Limit Testing

```bash
# Send requests rapidly to trigger rate limiting
for i in $(seq 1 20); do
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
    http://localhost:4003/api/v1/payments \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Participant-ISPB: 12345678")
  echo "Request $i: HTTP $STATUS"
done
```

**Expected:** After hitting the rate limit, you should see HTTP 429 responses with `Retry-After` header.

### 11.4 Monitoring During Tests

```bash
# Watch NATS monitoring (if NATS enabled)
open http://localhost:8222

# Watch Phoenix LiveDashboard
open http://localhost:4003/dev/dashboard

# Watch database connections
psql -h localhost -U postgres -d monetarie_pix_dev \
  -c "SELECT count(*) as active_connections FROM pg_stat_activity WHERE datname = 'monetarie_pix_dev';"
```

---

## 12. Monitoring & Observability

### 12.1 LiveDashboard (Dev Only)

Available at each service's dev dashboard:

| Service | URL |
|---------|-----|
| DICT | http://localhost:4001/dev/dashboard |
| SPI | http://localhost:4002/dev/dashboard |
| Settlement | http://localhost:4003/dev/dashboard |

Features: processes, memory, ETS tables, socket connections, request metrics.

### 12.2 Prometheus Metrics

```bash
curl http://localhost:4003/metrics
```

### 12.3 NATS JetStream Monitoring

```bash
# Stream info
curl http://localhost:8222/jsz

# Connection info
curl http://localhost:8222/connz

# Subscription info
curl http://localhost:8222/subsz
```

### 12.4 Grafana (GKE)

```
URL: https://monitoring-dev.fluxiq.com.br
Login: admin / Monetarie#Adm@2026
```

### 12.5 GKE Pod Monitoring

```bash
# Resource usage
kubectl top pods -n pix

# Recent events
kubectl get events -n pix --sort-by='.lastTimestamp' | tail -20

# HPA status
kubectl get hpa -n pix

# Pod logs (follow)
kubectl logs -n pix deployment/pix-backend -f --tail=100
```

---

## 13. Troubleshooting

### 13.1 Common Issues

**"Cannot connect to database"**
```bash
# Check PostgreSQL is running
docker compose ps postgres
# Expected: postgres (healthy)

# Check database exists
psql -h localhost -U postgres -l | grep monetarie_pix_dev

# Recreate if needed
mix ecto.reset  # WARNING: destroys all data
```

**"NATS connection refused"**
```bash
# Check NATS is running
docker compose ps nats

# Check NATS logs
docker compose logs nats

# Restart NATS
docker compose restart nats

# Or disable NATS workers
export NATS_ENABLED=false
```

**"Redis connection refused"**
```bash
docker compose ps redis
docker compose restart redis
```

**"401 Unauthorized" on API calls**
```bash
# Token may have expired (24h). Re-login:
TOKEN=$(curl -s http://localhost:4003/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"login":"admin","password":"Admin@2026!"}' | jq -r .token)
```

**"Simulator not responding"**
```elixir
# Check if simulator process is running
Process.whereis(Shared.Bacen.Simulator)

# If nil, start it manually
Shared.Bacen.Simulator.start_link([])

# Check configuration
Shared.Bacen.Simulator.status()
```

**"Migrations failed"**
```bash
# Check current migration status
mix ecto.migrations

# Run pending migrations
mix ecto.migrate

# Full reset (destroys data)
mix ecto.reset
```

### 13.2 Log Analysis

```bash
# Backend logs (local)
# Logs output to stdout with format: $time $metadata[$level] $message

# GKE logs
kubectl logs -n pix deployment/pix-backend --tail=200
kubectl logs -n pix deployment/pix-frontend --tail=200

# Filter by level
kubectl logs -n pix deployment/pix-backend | grep -i error
kubectl logs -n pix deployment/pix-backend | grep -i warning
```

### 13.3 Database Queries for Debugging

```sql
-- Recent transactions
SELECT id, end_to_end_id, amount, status, created_at
FROM monetarie_spi.transactions
ORDER BY created_at DESC LIMIT 20;

-- PIX key count by type
SELECT key_type, status, count(*)
FROM monetarie_dict.entries
GROUP BY key_type, status
ORDER BY key_type;

-- Recent audit logs
SELECT id, user_id, action, resource_type, created_at
FROM monetarie_auth.audit_logs
ORDER BY created_at DESC LIMIT 20;

-- Settlement sessions
SELECT id, type, status, settlement_date, opened_at, closed_at
FROM monetarie_settlement.sessions
ORDER BY created_at DESC LIMIT 10;

-- Simulator test runs
SELECT id, name, status, total_messages, successful_messages, failed_messages
FROM bacen_simulator.test_runs
ORDER BY started_at DESC LIMIT 10;
```

---

## 14. Test Execution Checklist

### Pre-Release Validation Checklist

**Infrastructure:**
- [ ] All 3 health endpoints return `"healthy"`
- [ ] System health shows all components green
- [ ] Database migrations are up to date
- [ ] Seed data is loaded correctly

**Authentication:**
- [ ] Login with admin credentials works
- [ ] Login with operator credentials works
- [ ] Login with viewer credentials works
- [ ] Invalid credentials return 401
- [ ] Token refresh works before expiry
- [ ] Expired token returns 401

**DICT (PIX Keys):**
- [ ] Create PIX key (CPF, CNPJ, PHONE, EMAIL, EVP)
- [ ] Query PIX key by value
- [ ] Delete PIX key
- [ ] Block/unblock PIX key
- [ ] List keys with filters
- [ ] Search by account
- [ ] Create portability claim
- [ ] Confirm/cancel/complete claim

**SPI (Payments):**
- [ ] Create payment (DICT initiation)
- [ ] Create payment (MANU initiation)
- [ ] List payments with date filter
- [ ] List payments with status filter
- [ ] View payment detail
- [ ] View payment history
- [ ] Create return (MD06)
- [ ] Create return (FRAD)
- [ ] Echo test successful

**Balance:**
- [ ] View current balance
- [ ] View balance by participant
- [ ] View intraday movements
- [ ] View all positions
- [ ] View balance history

**QR Codes:**
- [ ] Generate static QR code
- [ ] Generate dynamic QR code
- [ ] Validate QR code payload
- [ ] Cancel QR code

**Settlement:**
- [ ] Create session (D+0)
- [ ] Open session
- [ ] Close session
- [ ] Finalize session
- [ ] Cancel session (with reason)
- [ ] View session statistics

**Statements & Reports:**
- [ ] Generate intraday report
- [ ] Generate statement
- [ ] Download statement
- [ ] List available formats

**MED 2.0:**
- [ ] Create funds recovery
- [ ] View tracking graph
- [ ] List infraction reports

**Simulator:**
- [ ] Run happy_path scenario ✓
- [ ] Run rejected_payment scenario ✓
- [ ] Run return_flow scenario ✓
- [ ] Run incoming_payment scenario ✓
- [ ] Run echo_test scenario ✓
- [ ] Run balance_check scenario ✓
- [ ] Run full_cycle scenario ✓
- [ ] Run stress_test (10 payments) ✓

**Error Handling:**
- [ ] 400 for invalid JSON
- [ ] 401 for missing token
- [ ] 404 for non-existent resource
- [ ] 409 for duplicate PIX key
- [ ] 429 for rate limit (verify Retry-After header)
- [ ] RFC 7807 format for all errors

**Frontend:**
- [ ] All modules render correctly
- [ ] Navigation works between all sections
- [ ] Data tables load with pagination
- [ ] Forms validate input correctly
- [ ] Error messages display properly
- [ ] Multi-language switching works (4 locales)
- [ ] Role-based access enforced (admin vs viewer)

---

*Document generated by Monetarie Engineering Team — 2026-02-07*
