# Configuration

STA Connector uses Elixir configuration files with environment variable support for secure credential management in Phoenix applications.

## Configuration Files

Configuration is organized across multiple files in the `config/` directory:

| File | Purpose |
|------|---------|
| `config/config.exs` | Base configuration, shared across all environments |
| `config/dev.exs` | Development environment settings |
| `config/test.exs` | Test environment settings |
| `config/prod.exs` | Production compile-time settings |
| `config/runtime.exs` | Runtime configuration (environment variables) |

### Loading Order

Configuration is loaded in the following order:

1. **config/config.exs** - Base defaults, always loaded first
2. **config/{env}.exs** - Environment-specific overrides (dev, test, prod)
3. **config/runtime.exs** - Runtime configuration from environment variables

## Complete Configuration Reference

### Base Configuration (config/config.exs)

```elixir
# config/config.exs
import Config

# STA WebService connection
config :sta_connector, :sta,
  environment: :homologation,
  timeout_ms: 30_000,
  max_retries: 3,
  institution_code: nil

# Inbound poller (BCB -> Monetarie STA)
config :sta_connector, :poller,
  enabled: true,
  interval_ms: 30_000,
  systems: [:ccs, :cir, :cmp, :str, :spi, :cam, :ldl, :dict],
  batch_size: 10

# Outbound API (Monetarie STA -> BCB)
config :sta_connector, StaConnectorWeb.OutboundEndpoint,
  url: [host: "localhost"],
  http: [port: 4000]

# Admin API (management & monitoring)
config :sta_connector, StaConnectorWeb.AdminEndpoint,
  url: [host: "localhost"],
  http: [port: 4001]

# File routing (system code -> Monetarie STA endpoint)
config :sta_connector, :routes,
  spi: [
    url: "https://staapi-planner.monetarie.com.br/api/v1/spi",
    method: :post,
    timeout_ms: 30_000,
    retry_attempts: 3,
    enabled: true
  ],
  dict: [
    url: "https://staapi-planner.monetarie.com.br/api/v1/dict",
    method: :post,
    timeout_ms: 30_000,
    retry_attempts: 3,
    enabled: true
  ]

# Database configuration
config :sta_connector, StaConnector.Repo,
  database: "sta_connector_dev",
  pool_size: 10

# Logger configuration
config :logger, :console,
  format: "$time $metadata[$level] $message\n",
  metadata: [:request_id, :system, :file_id]

# Phoenix defaults
config :phoenix, :json_library, Jason
```

### Runtime Configuration (config/runtime.exs)

```elixir
# config/runtime.exs
import Config

if config_env() == :prod do
  # Database
  database_url =
    System.get_env("DATABASE_URL") ||
      raise """
      environment variable DATABASE_URL is missing.
      For example: ecto://USER:PASS@HOST/DATABASE
      """

  config :sta_connector, StaConnector.Repo,
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
    ssl: true

  # Phoenix secret key
  secret_key_base =
    System.get_env("SECRET_KEY_BASE") ||
      raise """
      environment variable SECRET_KEY_BASE is missing.
      You can generate one by calling: mix phx.gen.secret
      """

  # Outbound API endpoint
  config :sta_connector, StaConnectorWeb.OutboundEndpoint,
    url: [host: System.get_env("PHX_HOST") || "localhost", port: 443, scheme: "https"],
    http: [
      ip: {0, 0, 0, 0},
      port: String.to_integer(System.get_env("OUTBOUND_PORT") || "4000")
    ],
    secret_key_base: secret_key_base

  # Admin API endpoint
  config :sta_connector, StaConnectorWeb.AdminEndpoint,
    url: [host: System.get_env("PHX_HOST") || "localhost", port: 443, scheme: "https"],
    http: [
      ip: {0, 0, 0, 0},
      port: String.to_integer(System.get_env("ADMIN_PORT") || "4001")
    ],
    secret_key_base: secret_key_base

  # STA WebService credentials
  config :sta_connector, :sta,
    environment: String.to_atom(System.get_env("STA_ENVIRONMENT") || "homologation"),
    username: System.get_env("STA_USERNAME") || raise("STA_USERNAME is required"),
    password: System.get_env("STA_PASSWORD") || raise("STA_PASSWORD is required"),
    institution_code: System.get_env("STA_INSTITUTION_CODE") || raise("STA_INSTITUTION_CODE is required"),
    timeout_ms: String.to_integer(System.get_env("STA_TIMEOUT_MS") || "30000"),
    max_retries: String.to_integer(System.get_env("STA_MAX_RETRIES") || "3")

  # Poller configuration
  config :sta_connector, :poller,
    enabled: System.get_env("POLLER_ENABLED", "true") == "true",
    interval_ms: String.to_integer(System.get_env("POLLER_INTERVAL_MS") || "30000"),
    batch_size: String.to_integer(System.get_env("POLLER_BATCH_SIZE") || "10")

  # Admin API authentication
  config :sta_connector, :admin_auth,
    username: System.get_env("ADMIN_USERNAME") || "admin",
    password: System.get_env("ADMIN_PASSWORD") || raise("ADMIN_PASSWORD is required")

  # Outbound API authentication
  config :sta_connector, :outbound_auth,
    api_key: System.get_env("OUTBOUND_API_KEY") || raise("OUTBOUND_API_KEY is required")

  # Monetarie STA integration
  config :sta_connector, :monetarie,
    base_url: System.get_env("MONETARIE_STA_BASE_URL") || raise("MONETARIE_STA_BASE_URL is required"),
    token: System.get_env("MONETARIE_STA_TOKEN") || raise("MONETARIE_STA_TOKEN is required")
end
```

## Section Details

### STA Settings

BCB STA WebService connection configuration:

```elixir
config :sta_connector, :sta,
  environment: :homologation,
  username: System.get_env("STA_USERNAME"),
  password: System.get_env("STA_PASSWORD"),
  institution_code: "12345",
  timeout_ms: 30_000,
  max_retries: 3
```

| Setting | Default | Description |
|---------|---------|-------------|
| `environment` | `:sandbox` | BCB environment: `:homologation`, `:production`, `:sandbox` |
| `username` | required | Sisbacen username |
| `password` | required | Sisbacen password |
| `institution_code` | required | Institution code in Sisbacen |
| `timeout_ms` | `30_000` | HTTP request timeout in milliseconds |
| `max_retries` | `3` | Retry attempts on transient failures |

#### Environment URLs

| Environment | URL |
|-------------|-----|
| `:homologation` | `https://sta-h.bcb.gov.br/staws` |
| `:production` | `https://sta.bcb.gov.br/staws` |
| `:sandbox` | `https://sta-h.bcb.gov.br/staws` |

### Poller Settings

Configure inbound polling from BCB:

```elixir
config :sta_connector, :poller,
  enabled: true,
  interval_ms: 30_000,
  systems: [:ccs, :spi, :dict],
  batch_size: 10
```

| Setting | Default | Description |
|---------|---------|-------------|
| `enabled` | `false` | Enable/disable inbound polling |
| `interval_ms` | `60_000` | Milliseconds between poll cycles |
| `systems` | all | BCB systems to poll (list of atoms) |
| `batch_size` | `100` | Maximum files per poll cycle |

#### Supported Systems

| System | Atom | Description |
|--------|------|-------------|
| CCS | `:ccs` | Customer Consultation System |
| CIR | `:cir` | Credit Information Registry |
| CMP | `:cmp` | Means of Payment Control |
| STR | `:str` | Reserve Transfer System |
| SPI | `:spi` | Instant Payment System (PIX) |
| CAM | `:cam` | Foreign Exchange System |
| LDL | `:ldl` | Deferred Settlement |
| DICT | `:dict` | PIX Directory |

### Phoenix Endpoint Settings

#### Outbound API

```elixir
config :sta_connector, StaConnectorWeb.OutboundEndpoint,
  url: [host: "localhost"],
  http: [ip: {0, 0, 0, 0}, port: 4000],
  secret_key_base: "your-secret-key-base"
```

#### Admin API

```elixir
config :sta_connector, StaConnectorWeb.AdminEndpoint,
  url: [host: "localhost"],
  http: [ip: {127, 0, 0, 1}, port: 4001],
  secret_key_base: "your-secret-key-base"
```

### Routes Configuration

Define how inbound files are delivered to Monetarie STA:

```elixir
config :sta_connector, :routes,
  spi: [
    url: "https://staapi-planner.monetarie.com.br/api/v1/spi",
    method: :post,
    headers: [
      {"authorization", "Bearer #{System.get_env("MONETARIE_STA_TOKEN")}"},
      {"content-type", "application/json"}
    ],
    timeout_ms: 30_000,
    retry_attempts: 3,
    enabled: true
  ]
```

| Setting | Default | Description |
|---------|---------|-------------|
| `url` | required | Destination URL for files |
| `method` | `:post` | HTTP method atom |
| `headers` | `[]` | Custom headers as keyword list |
| `timeout_ms` | `30_000` | Request timeout in milliseconds |
| `retry_attempts` | `3` | Retry count on failure |
| `enabled` | `true` | Enable/disable this route |

### Database Configuration

#### PostgreSQL (Production)

```elixir
config :sta_connector, StaConnector.Repo,
  url: System.get_env("DATABASE_URL"),
  pool_size: 10,
  ssl: true,
  ssl_opts: [verify: :verify_peer]
```

#### SQLite (Development)

```elixir
config :sta_connector, StaConnector.Repo,
  database: Path.expand("../sta_connector_dev.db", Path.dirname(__ENV__.file)),
  pool_size: 5,
  stacktrace: true,
  show_sensitive_data_on_connection_error: true
```

## Environment Variables

### Required Variables (Production)

```bash
# Phoenix
export SECRET_KEY_BASE="generate-with-mix-phx-gen-secret"
export PHX_HOST="sta-connector.example.com"

# Database
export DATABASE_URL="ecto://user:password@host/sta_connector_prod"
export POOL_SIZE="10"

# STA WebService
export STA_ENVIRONMENT="production"
export STA_USERNAME="sisbacen_user"
export STA_PASSWORD="sisbacen_password"
export STA_INSTITUTION_CODE="12345"

# API Authentication
export ADMIN_PASSWORD="secure_admin_password"
export OUTBOUND_API_KEY="your_api_key"

# Monetarie STA Integration
export MONETARIE_STA_BASE_URL="https://staapi-planner.monetarie.com.br"
export MONETARIE_STA_TOKEN="your_token"
```

### Optional Variables

```bash
# Ports (defaults: 4000, 4001)
export OUTBOUND_PORT="4000"
export ADMIN_PORT="4001"

# STA settings (with defaults)
export STA_TIMEOUT_MS="30000"
export STA_MAX_RETRIES="3"

# Poller settings (with defaults)
export POLLER_ENABLED="true"
export POLLER_INTERVAL_MS="30000"
export POLLER_BATCH_SIZE="10"
```

## Hot Reload

Configuration changes can be applied at runtime through multiple mechanisms.

### Phoenix LiveReload (Development)

In development, Phoenix LiveReload automatically recompiles and reloads code changes:

```elixir
# config/dev.exs
config :sta_connector, StaConnectorWeb.Endpoint,
  live_reload: [
    patterns: [
      ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
      ~r"lib/sta_connector_web/(live|views)/.*(ex)$",
      ~r"lib/sta_connector_web/templates/.*(eex)$"
    ]
  ]
```

### Admin API Runtime Updates

The Admin API supports runtime configuration updates without restart:

```bash
# Get current configuration
curl -u admin:password http://localhost:4001/api/admin/config

# Update poller settings
curl -u admin:password -X PATCH http://localhost:4001/api/admin/config \
  -H "Content-Type: application/json" \
  -d '{
    "poller": {
      "interval_ms": 60000,
      "enabled": true
    }
  }'

# Update route settings
curl -u admin:password -X PATCH http://localhost:4001/api/admin/config \
  -H "Content-Type: application/json" \
  -d '{
    "routes": {
      "spi": {
        "enabled": false
      }
    }
  }'
```

### Application.put_env/3

For programmatic updates within the application:

```elixir
# Update poller interval at runtime
Application.put_env(:sta_connector, :poller,
  Keyword.merge(
    Application.get_env(:sta_connector, :poller),
    [interval_ms: 60_000]
  )
)

# Notify the poller GenServer of the change
StaConnector.Poller.reload_config()
```

### Supported Hot-Reload Settings

| Setting | Hot-Reloadable |
|---------|----------------|
| Logger level | Yes |
| `poller.enabled` | Yes |
| `poller.interval_ms` | Yes |
| `poller.batch_size` | Yes |
| `routes.*.enabled` | Yes |
| `routes.*.url` | Yes |
| `routes.*.timeout_ms` | Yes |
| `sta.timeout_ms` | Yes |
| `sta.max_retries` | Yes |

Settings like ports, hosts, and database connections require a restart.

### Via Admin Portal

1. Navigate to the Configuration page
2. Edit settings in the form
3. Click "Apply Changes"
4. Changes take effect immediately

## Configuration Validation

The connector validates configuration on startup using Elixir's config providers:

```elixir
# lib/sta_connector/config.ex
defmodule StaConnector.Config do
  def validate! do
    sta_config = Application.get_env(:sta_connector, :sta)

    unless sta_config[:username] do
      raise "STA username is required"
    end

    unless sta_config[:password] do
      raise "STA password is required"
    end

    unless sta_config[:environment] in [:homologation, :production, :sandbox] do
      raise "STA environment must be :homologation, :production, or :sandbox"
    end

    :ok
  end
end
```

### Validation Rules

- `sta.username` and `sta.password` must not be nil
- `sta.environment` must be `:homologation`, `:production`, or `:sandbox`
- `poller.interval_ms` must be positive when enabled
- `poller.batch_size` must be positive when enabled
- Phoenix endpoints must have valid port numbers (1-65535)
- `routes.*.url` must be a valid URL

## Example Configurations

### Development (config/dev.exs)

```elixir
import Config

config :sta_connector, :sta,
  environment: :sandbox,
  username: System.get_env("STA_USERNAME"),
  password: System.get_env("STA_PASSWORD"),
  institution_code: "99999",
  timeout_ms: 10_000

config :sta_connector, :poller,
  enabled: true,
  interval_ms: 10_000,
  systems: [:spi],
  batch_size: 5

config :sta_connector, StaConnectorWeb.OutboundEndpoint,
  http: [ip: {127, 0, 0, 1}, port: 4000],
  check_origin: false,
  code_reloader: true,
  debug_errors: true,
  secret_key_base: "dev-secret-key-base-min-64-chars-long-for-development-only",
  watchers: []

config :sta_connector, StaConnectorWeb.AdminEndpoint,
  http: [ip: {127, 0, 0, 1}, port: 4001],
  check_origin: false,
  code_reloader: true,
  debug_errors: true,
  secret_key_base: "dev-secret-key-base-min-64-chars-long-for-development-only"

config :sta_connector, :admin_auth,
  username: "admin",
  password: "admin"

config :sta_connector, :outbound_auth,
  api_key: "dev-api-key"

config :sta_connector, StaConnector.Repo,
  database: Path.expand("../sta_connector_dev.db", Path.dirname(__ENV__.file)),
  pool_size: 5,
  stacktrace: true,
  show_sensitive_data_on_connection_error: true

config :logger, :console, format: "[$level] $message\n"
```

### Production (config/prod.exs + config/runtime.exs)

```elixir
# config/prod.exs
import Config

config :sta_connector, :sta,
  environment: :production,
  timeout_ms: 60_000,
  max_retries: 5

config :sta_connector, :poller,
  enabled: true,
  interval_ms: 30_000,
  systems: [:ccs, :cir, :cmp, :str, :spi, :cam, :ldl, :dict],
  batch_size: 50

config :sta_connector, StaConnectorWeb.OutboundEndpoint,
  cache_static_manifest: "priv/static/cache_manifest.json"

config :sta_connector, StaConnectorWeb.AdminEndpoint,
  cache_static_manifest: "priv/static/cache_manifest.json"

config :logger, level: :info
```

## BCB Rate Limits

BCB enforces strict rate limits on the STA WebService:

| Limit | Value | Description |
|-------|-------|-------------|
| Max Concurrent Connections | 10 | Per institution |
| Max Queries per Minute | 120 | Per institution |

The connector automatically enforces these limits. Configure conservatively to avoid hitting limits:

```elixir
config :sta_connector, :poller,
  batch_size: 10,        # Don't exceed 10 concurrent downloads
  interval_ms: 30_000    # Avoid rapid polling

config :sta_connector, :rate_limiter,
  max_concurrent: 10,
  max_per_minute: 120
```

## Next Steps

- [Inbound Pipeline](/guide/inbound) - Configure file polling
- [Outbound Pipeline](/guide/outbound) - Configure file uploads
- [Admin API](/api/admin) - Configuration API reference
