# Dicionário de Dados do SPB (banco `mon_spb`)

Data: 2026-07-10. Fonte: leitura direta das migrations Ecto (`spb/services/bacen_gateway/priv/repo/migrations/`, 52 arquivos), do dump base (`spb/services/bacen_gateway/priv/repo/sql/mon_spb_schema_clean.sql`) e dos módulos com DDL em runtime (`ensure_table`). Todos os caminhos abaixo são relativos a `/Users/luizpenha/monetarie/spb/services/bacen_gateway/` salvo indicação em contrário.

O schema é único (`public`), banco `mon_spb` (Aurora PostgreSQL). Não existe schema `stg.*` versionado no repositório: o staging `stg.*` usado na reconciliação do acervo AutBank vive só no banco (criado por scripts de ETL, ver `/Users/luizpenha/monetarie/etl/legacy_hml_import/21_project_spb.sql`).

Como ler: cada tabela traz o propósito em 1 linha, a origem (migration ou DDL em runtime, com arquivo:linha), colunas com tipo e os índices/constraints relevantes. PK padrão = `id uuid DEFAULT gen_random_uuid()` salvo indicação.

---

## 1. Núcleo transacional (operação e mensagem)

### 1.1 `spb_operations` (pai: 1 linha por operação financeira)

Propósito: espelho do legado `spb_tb_pil_operacoes`; a OPERAÇÃO agrupa as pernas de mensagem (envio, R1, R2, R3) de um mesmo negócio. Origem: `priv/repo/migrations/20260425200001_create_spb_operations.exs` + colunas adicionadas em `20260511160000`, `20260511173500`, `20260513223000`, `20260529083000`, `20260606200000`, `20260704150000`.

| Coluna | Tipo | Nota |
|---|---|---|
| `id` | uuid PK | |
| `nuop` | varchar(50) | Número Único da Operação |
| `state` | varchar(20) NOT NULL default `created` | máquina de estados (ver `lib/bacen_gateway/operations/spb_operation.ex:12-19`) |
| `message_type` | varchar(20) | ex. STR0008 |
| `message_category` | varchar(10) | grupo SFN (STR, GEN, LDL...) |
| `domain` | varchar(20) | domínio RSFN (SPB01, MES01...) |
| `sender_ispb` / `receiver_ispb` | varchar(8) NOT NULL | roteamento |
| `amount` | numeric(18,2) | valor em reais |
| `currency` | varchar(3) default BRL | |
| `settlement_date` | date | |
| `sent_at`, `r0_received_at`, `coa_received_at`, `cod_received_at`, `r1_received_at`, `r2_confirmed_at`, `r3_settled_at`, `cancelled_at`, `failed_at` | timestamptz(usec) | carimbos do ciclo R0/COA/COD/R1/R2/R3 |
| `error_code` varchar(20), `error_description` text, `retry_count` int, `priority` int | | rastreio de erro |
| `correlation_id` varchar(50), `control_number` varchar(50), `parent_operation_id` uuid (self-FK) | | correlação; `control_number` alargado p/ 50 em `20260526190000` |
| `payer_account`, `payer_cpf_cnpj`, `payer_name`, `beneficiary_account`, `beneficiary_cpf_cnpj`, `beneficiary_name`, `description`, `purpose_code` | | contrapartes |
| `mq_timestamp` timestamptz, `origin_system` varchar(100) | | auditoria/origem |
| `status_code` int NOT NULL default 0 | | status numérico legado (`20260511160000`) |
| `direction` | varchar(10) NOT NULL default `outbound` | `outbound`/`inbound` |
| `clearing_group` | varchar(10) | preenchida por trigger `sync_spb_operations_clearing_group` (`20260511173500`) |
| `control_number_clearing` | varchar(50) | NumCtrlSTR/NumCtrl da câmara |
| `xml_content` text, `xml_hash` varchar(64), `observation` text | | |
| `integration_level` varchar(2), `grid_type` varchar(1), `send_type` varchar(1) | | vestigial legado |
| `scheduled_at`, `confirmed_at` | timestamptz(usec) | |
| `response_code` varchar(10), `is_corrected`, `is_split`, `is_reprocessing` bool | | |
| `created_by_user_id` int, `institution_id` int | | |
| `locked_by` varchar(80), `locked_at` timestamp | | lock pessimista (`20260513223000`) |
| `original_operation_id` uuid, `reason_code` varchar(20), `notes` text, `created_by` text | | devolução/substituição (`20260529083000`) |
| `tp_oper_grid` | varchar(1) | F/C/A/N, segregação de grid (`20260606200000`) |
| `on_hold` bool NOT NULL default false, `hold_reason` text, `held_by` varchar(100), `held_at` timestamptz | | hold por operação (`20260704150000`) |
| `created_at` / `updated_at` | timestamptz(usec) | `timestamps(inserted_at: :created_at)` |

Índices: unique `nuop`; `state`; `(state, created_at DESC)`; `sender_ispb`; `receiver_ispb`; `correlation_id`; `parent_operation_id`; `settlement_date`; parciais de relatório `(clearing_group, created_at, state)`, `(settlement_date, message_category, state)`, `(created_at, message_category, state)`, `spb_operations_live_created_at_idx` (estados vivos), `(tp_oper_grid, created_at)`, `spb_operations_on_hold_idx (held_at DESC) WHERE on_hold`. **Idempotência do crédito TED-in**: unique parcial `(message_type, control_number_clearing) WHERE direction='inbound'` (`20260606100000_add_inbound_str_credit_unique_idx.exs`). CHECKs de CNPJ/ISPB alfanumérico (`20260612400000`).

### 1.2 `bacen_messages` (filha: N mensagens por operação)

Propósito: cada mensagem SFN individual (XML enviado/recebido), ligada à operação por `operation_id` (FK `ON DELETE SET NULL`). Origem: dump base `priv/repo/sql/mon_spb_schema_clean.sql:108-134` + `20260425200000_align_bacen_messages_v3.exs` (rename `status`→`state` + 18 colunas), `20260511171000` (`created_at`), `20260526070000` (payloads binários), `20260606200000` (`tp_oper_grid`).

| Coluna | Tipo | Nota |
|---|---|---|
| `id` | uuid PK | |
| `message_id` | varchar(50) NOT NULL unique | identificador interno |
| `message_type` | varchar(20) NOT NULL | ex. STR0008R2 |
| `message_category` | varchar(10) NOT NULL | grupo (validado contra 30 categorias em `lib/bacen_gateway/messages/bacen_message.ex:27`) |
| `state` | varchar(20) NOT NULL | ciclo completo (`bacen_message.ex:16-26`): pending, processing, sent, confirmed, failed, created, awaiting_approval, sent_to_mq, scheduled, coa_received, cod_received, r0_received, r1_confirmed, r1_error, r1_rejected, r2_confirmed, r2_rejected, r3_settled, cancelled, expired, dead_letter |
| `direction` | varchar(10) NOT NULL | inbound/outbound |
| `institution_id` | uuid NOT NULL | FK lógica a `institutions` |
| `content` | jsonb NOT NULL | parâmetros decodificados |
| `xml_content` text, `response_content` jsonb, `response_xml` text | | XML bruto e resposta (response_content normalizado em `20260527164500`) |
| `binary_payload`, `binary_response` | bytea | wire bytes cifrados (`20260526070000`) |
| `source` | varchar | origem (ex. `legacy_autbank` no acervo importado) |
| `signature_valid` bool, `error_code` varchar(20), `error_description` text | | |
| `sent_at`, `received_at`, `acknowledged_at`, `confirmed_at`, `failed_at` | timestamptz | |
| `retry_count` int, `priority` int, `parent_message_id` varchar(50), `settlement_date` date | | |
| `sender_ispb`/`receiver_ispb` varchar(8), `scheduled_at`, `control_number` varchar(50), `nuop` varchar(50), `domain` varchar(20), `operation_id` uuid, `response_code` varchar(20), `correlation_id` varchar(50) | | v3 (`20260425200000`) |
| `r0_received_at`, `coa_received_at`, `cod_received_at`, `r1_received_at`, `r2_confirmed_at`, `r3_settled_at` | timestamptz | ciclo |
| `message_sequence` int NOT NULL default 1, `control_number_clearing` varchar(50), `integration_level` varchar(2), `mq_timestamp` timestamptz, `origin_system` varchar(100), `amount` numeric(18,2) NOT NULL default 0 | | |
| `tp_oper_grid` | varchar(1) | F/C/A/N |
| `created_at` timestamptz (espelho de `inserted_at`, `20260511171000`), `inserted_at`, `updated_at` | | |

Índices: unique `message_id`; `direction`, `message_type`, `(message_type, status)`, `status` (nome herdado do dump), `state`, `(state, inserted_at DESC)`, `(state, created_at DESC)`, `created_at DESC`, parcial `pending`, `(operation_id, message_sequence)`, `sender_ispb`, `receiver_ispb`, `nuop`, `correlation_id`, `parent_message_id`, `settlement_date`, `institution_id`, `inserted_at`, `(tp_oper_grid, created_at)`, parcial `bacen_messages_close_signal_idx (message_type, direction, created_at DESC) WHERE state='confirmed'` (sinal de fechamento STR0016).

### 1.3 `operation_events`

Propósito: trilha append-only de eventos por operação (state_change, mq_send, mq_receive, r0_ack, coa_ack, cod_ack, r1_response, r2_response, r3_response, error, retry, cancelled). Origem: `20260425200002_create_operation_events.exs`.
Colunas: `id` uuid PK; `operation_id` uuid NOT NULL FK→`spb_operations` ON DELETE CASCADE; `event_type` varchar(50) NOT NULL; `previous_state`/`new_state` varchar(20); `actor` varchar(255); `event_data` jsonb default `{}`; `occurred_at` timestamptz NOT NULL default now(); `created_at`.
Índices: `(operation_id, occurred_at DESC)`, `event_type`, `(operation_id, event_type)`.

### 1.4 `message_state_history`

Propósito: histórico de transição de estado por mensagem (nível `bacen_messages`). Origem: dump base `mon_spb_schema_clean.sql:216-224`.
Colunas: `id` uuid PK; `bacen_message_id` uuid NOT NULL; `from_status`/`to_status` varchar(20); `changed_by` varchar(255); `reason` text; `inserted_at`. Índices: `bacen_message_id`, `inserted_at`.

### 1.5 `message_tracking` (sem DDL no repositório)

Propósito: carimbos de rastreamento por operação (integrated_at, sent_at, r1_response_at, error_response_at), escrita best-effort por `lib/bacen_gateway/lifecycle_engine.ex:138,183,568` e `lib/bacen_gateway/legacy_parity.ex:896`. A tabela existe no banco vivo (herança de ambiente), mas nenhuma migration/seed atual a cria; os INSERTs são tolerantes a falha.

### 1.6 `pending_publish_events` (outbox)

Propósito: outbox durável único de saída (envios MQ + publicações NATS), drenado por `BacenGateway.Outbox.Worker`. Origem: `20260425210000_create_pending_publish_events.exs`.
Colunas: `id` uuid PK; `event_type` varchar(64) NOT NULL (`mq_send`, `nats_publish`, `spb_inbound_credit`, `spb_return_status`); `destination` varchar(128) NOT NULL (fila ou subject); `payload` bytea NOT NULL; `metadata` jsonb NOT NULL; `status` varchar(32) default `pending`; `attempts` int, `max_attempts` int default 5, `last_error` text; `next_attempt_at` naive NOT NULL; `published_at`; timestamps.
Índices: `(status, next_attempt_at)`, `event_type`, `(status, inserted_at)`, parcial `pending_publish_events_pending_due_idx (next_attempt_at, inserted_at) WHERE status='pending'` (`20260511171000`).

### 1.7 `dlq_entries`

Propósito: dead-letter queue persistida de mensagens que esgotaram retries (schema Ecto em `lib/bacen_gateway/dead_letter_queue.ex:17`). Origem: dump base `:141-153`.
Colunas: `id` uuid PK; `message_id` varchar(50); `message_type` varchar(20); `payload` text; `error_message` text; `retry_count` int; `last_retry_at`; `resolved` bool default false; `resolved_at`; timestamps. Índices: `inserted_at`, `message_id`, `resolved`.

### 1.8 `message_hashes`

Propósito: dedupe de mensagens inbound por hash (DuplicateDetector). Origem: `20260513223000_create_runtime_readiness_schema.exs` (bloco `message_hashes`).
Colunas: `id` uuid PK; `message_hash` varchar(128) NOT NULL unique; `message_id` uuid; `message_type` varchar(20); `received_at` timestamp default now(); `inserted_at`. Índices: unique `message_hash`, `received_at`.

### 1.9 `mq_quarantine`

Propósito: quarentena de poison messages do sidecar IBM MQ (deliveryCount acima do teto → POST `/api/mq/webhook/:domain/quarantine`). Origem: `20260704120000_create_mq_quarantine.exs` (espelhada em `lib/bacen_gateway/mq/quarantine.ex:39`).
Colunas: `id` bigserial PK; `domain` varchar(10) NOT NULL; `queue_manager` varchar(60); `source_queue` varchar(80); `message_id` text; `correlation_id` text; `delivery_count` int; `reason` text; `payload` bytea; `payload_size` int; `headers` jsonb; `status` varchar(16) default `parked`; `resolved_by` text; `resolved_at`; `notes` text; `inserted_at`.
Índices: unique parcial `(domain, message_id) WHERE message_id IS NOT NULL`; `(status, inserted_at DESC)`.

### 1.10 `num_ctrl_if_seq` e `nuop_seq`

Propósito: contadores sequenciais crash-safe de NumCtrlIF (por ISPB+data) e NUOp (por ISPB+data+domínio), com advisory lock. DDL declarado em `lib/bacen_gateway/str/num_ctrl_if.ex:209-231` (`migration_sql/0`; aplicado direto no banco, sem migration versionada). Uso: upserts em `num_ctrl_if.ex:69` e `:118`.
`num_ctrl_if_seq`: `ispb` varchar(8) + `dt_movto` date (PK composta), `last_value` int, timestamps. `nuop_seq`: idem + `domain` varchar(10) na PK. Índices por `dt_movto`.

---

## 2. Referência do catálogo SFN e roteiro de mensagens

### 2.1 `bacen_validation_rules`

Propósito: regras de validação por campo (espelho de `spb_tb_leg_valida_msg_int`, ~20.639 linhas) que dirigem o Validator data-driven. Origem: `20260426100000_create_bacen_validation_rules.exs`.
Colunas: `cd_msg` varchar(50), `id_node` varchar(200), `seq_tag` int, `id_tag` varchar(100), `obrigatoria` bool, `tp_sql` varchar(20), `tp_dados` varchar(50), `tamanho`, `decimais`, `tam_min`, `tam_max`, `pos_ini`, `pos_fim`, `id_conversao` int, `fc_chk_espec` varchar(50). Sem PK própria.
Índices: `cd_msg`; unique `(cd_msg, id_node, seq_tag)`.

### 2.2 `message_type_config`

Propósito: driver por tipo de mensagem (1.448 linhas; espelho do `spb_tb_gen_msg_detalhe`): grupo, direção, flags financeiras, tags de valor/controle, grid. Origem: `20260513223000` + colunas `open_time`, `close_time`, `xsd_schema_path` em `20260513224500`.
Colunas: `message_type` varchar(20) PK; `clearing_id` int; `message_group` varchar(20); `direction_flag` varchar(1); `domain` varchar(20); `grid_type` varchar(20); `debit_credit_flag` varchar(1); `financial_flag` varchar(1); `default_status` int; `finalize_on_cod` bool; `allows_split` bool; `is_large_xml` bool; `mq_sequence` varchar(5); `is_return_alert` bool; `is_refund` bool; `value_tag` varchar(500); `confirmed_value_tag` varchar(500); `ctrl_number_tag` varchar(100); `settlement_date_tag` varchar(100); `open_time`/`close_time` time; `xsd_schema_path` text; timestamps.

### 2.3 `message_flow_types`

Propósito: classificação de fluxo por `cd_msg` (`id_tipo_msg`: O=originada, A=recebida, C=consulta, R=resposta, E=erro), 1.794 tipos, paridade `spb_tb_gen_msg_detalhe`. Origem: `20260605500000_create_message_flow_types.exs`.
Colunas: `message_type` varchar(20) PK; `id_tipo_msg` varchar(1) NOT NULL; timestamps.

### 2.4 `message_tag_definitions`

Propósito: definição de tags por tipo de mensagem (21.417 linhas do legado). Origem: `20260513223000`.
Colunas: `id` bigserial PK; `message_type` varchar(20); `tag_sequence` int; `tag_name` varchar(120); `min_occurs`/`max_occurs` varchar(10); `is_enabled` bool; `is_exclusive` bool; timestamps. Unique `(message_type, tag_sequence)`; índice `message_type`.

### 2.5 `message_groups`

Propósito: grupos de mensagens (STR, GEN, LDL...) com lista de tipos e prioridade; colunas duplicadas `code`/`group_code` sincronizadas por trigger `sync_message_groups_runtime_columns`. Origem: `20260513230000`.
Colunas: `id` uuid PK; `group_code`/`code` varchar(20) (uniques); `name`; `description`; `category` varchar(20); `clearing_code` varchar(20); `direction` varchar(20); `priority` int; `message_types` text[]; `message_count` int; `active` bool; `created_at`/`inserted_at`/`updated_at`.

### 2.6 `message_templates`

Propósito: templates XML por tipo de mensagem para o construtor. Origem: `20260513230000`; trigger `sync_message_templates_runtime_columns`.
Colunas: `id` uuid PK; `name`; `message_type` varchar(20) unique; `template_xml` text; `description`; `message_group` varchar(20); `direction` varchar(20) default both; `active` bool; `version` int; timestamps. Índices: `message_group`, unique `(name, version)`, parcial `active`.

### 2.7 `grade_message_map`

Propósito: liga `message_type` → `grade_code` (janela de grade horária aplicável, ex. STR0004→STR01); multi-grade por mensagem. Origem: `20260605200000` + `20260605210000` (PK trocada por unique `(message_type, grade_code)`).
Colunas: `message_type` varchar(20); `grade_code` varchar(10); timestamps. Índices: `grade_code`; unique `(message_type, grade_code)`.

### 2.8 `bacen_operating_schedule` e `bacen_operating_schedule_especial`

Propósito: grade horária padrão por grupo/grade (`message_group`, keyed por cd_grade) e a variante por data específica. Origem: `20260513223000`; unique `(message_group, clearing, day_type, start_time, end_time)` em `20260513224500`.
Colunas (padrão): `id` uuid PK; `message_group` varchar(20); `clearing` varchar(20) default ALL; `day_type` varchar(20) default business; `start_time`/`end_time` time; `active` bool; timestamps. A "especial" troca `day_type` por `schedule_date` date + `reason`.

### 2.9 `grade_schedule_overrides` e `grade_schedule_msg`

Propósito: overrides de grade por data (ingestão da grade real do BACEN via `PostIntegration.GradeScheduleIngestor`) e janelas por mensagem individual. Origem: `20260513223000`.
`grade_schedule_overrides`: `id` uuid PK; `message_group`; `clearing`; `override_date` date; `start_time`/`end_time`; `updated_at`. `grade_schedule_msg`: `id` uuid PK; `message_type`; `start_time`/`end_time`; `override_date`; `active`; timestamps.
Obs.: `special_schedules` (loja paralela morta) foi dropada em `20260605100000_drop_orphaned_special_schedules.exs`.

### 2.10 Mapas de status (pós-integração)

Origem: `20260513223000` (+ ajuste `20260513225500` para `fbs_status_map.fl_status_bc` virar varchar).
- `status_de_para`: por grupo: `(message_group, bacen_status_value, clearing_id)` → `internal_status` + flags `is_confirmed`/`is_tariffed`/`is_finalizer`. uuid PK.
- `status_de_para_special`: idem com `message_type` específico.
- `group_status_map`: paridade COMPLETA com `spb_tb_gen_status_de_para` (26 grupos / 495 regras; `status_code` é varchar pois há grupos alfabéticos). Origem: `20260605300000`. Colunas: `message_group` varchar(8), `status_code` varchar(20), `internal_status` int, `is_confirmed`, `is_tariffed`, `is_finalizer`; unique `(message_group, status_code)`.
- `mecir_status_map`: transições MECIR (`cd_msg`, `st_mcr_ant`→`st_mcr_atu`, fórmulas, flags).
- `pag_str_status_map`: de-para de tags/status entre PAG e STR.
- `special_status_map`: status especial por conteúdo de tag (`grp_mensagem`, `ds_conteudo_tag`, `st_operacao`, `cd_msg`, `tag_especial`).
- `fbs_status_map`: eventos FBS (`id_evento`, `nm_dominio`, `fl_status_bc` varchar(10)); índices `id_evento` e `(id_evento, nm_dominio)`.
- `legacy_status_mapping`: `legacy_code` int PK → descrição, representação, flags (`allows_cancellation`, `is_final`, `is_r1_type`), cor hex, `current_state`/`current_status_code` (58 códigos → ETS via `Engines.StatusMapper`).
- `operation_status_catalog`: `status_code` int PK, `name`, `hex_color` (catálogo de exibição).
- `operation_statuses`: `status_code` varchar(20) unique + colunas geradas `code`/`label` (compat frontend). Origem: `20260513230000`.
- `status_transitions`: `(from_status, to_status)` unique + `automatic` bool (matriz de transição exposta na UI).

### 2.11 `post_integration_config`

Propósito: configuração de pós-integração por `cd_msg` (espelho do legado): flags débito/crédito, financeiro, grupo de saldo, tags de valor/controle, procs legadas. Origem: `20260513223000`.
Colunas: `cd_msg` varchar(20) PK; `grp_mensagem`; `flag_db_cr`, `flag_financ`, `flag_sentido` varchar(1); `tp_sld_impactar` varchar(10); `grp_saldo` int; `id_tag_vlr`, `id_tag_vlr_confirmado`, `id_tag_vlr_rejeitado` varchar(500); `id_tag_numctrl`, `id_tag_carac`, `id_tag_sinal_operacao` varchar(100); `nm_proc_pos_int`, `nm_proc_saldo`, `nm_proc_retorno` varchar(120); `st_operacao_padrao` int; `dom_spb` varchar(20); timestamps.

### 2.12 `message_splits`, `split_rules`, `automation_rules`

Origem: `20260513223000`.
- `message_splits`: regra de derivação (source_msg + direction → target_msg com `field_mapping`/`conditions` jsonb, `target_action`, `priority`).
- `split_rules`: regras de lote (message_type, clearing, `max_batch_size`, `split_strategy`, `threshold_amount`, `split_count`).
- `automation_rules`: automação de resposta (trigger_message_type + condition jsonb → action_type/response_message_type).

### 2.13 `bacen_error_codes`

Propósito: catálogo de códigos de erro BACEN (5.314 códigos) com severidade e política de retry; usado por `Engines.ErrorCodeEngine` e `STR.RstrErrorMapper`. Origem: `20260427000000` + colunas `error_code`, `error_type`, `domain` em `20260513223000`.
Colunas: `id` uuid PK; `code` int unique; `description` text; `category`; `severity`; `suggested_action` text; `retryable` bool; `metadata` jsonb; `error_code` varchar(20); `error_type` varchar(40); `domain` varchar(20); timestamps. Índices: `category`, `severity`, `retryable`.

### 2.14 `bacen_domain_values` (DDL em runtime)

Propósito: valores de domínio BACEN por categoria/código (DDA/PCR e gerais) editáveis pela UI. DDL: `lib/bacen_gateway_web/controllers/domain_values_controller.ex:169`.
Colunas: `id` bigserial PK; `category` varchar(100); `code` varchar(100); `description` varchar(500); `active` bool; `metadata` jsonb; timestamps. Unique `(category, code)`.

### 2.15 `bacen_domains`

Propósito: catálogo de domínios/valores de tag (`domain_tag`, `code`, descrição, `system`, `domain_type` char(1)). Origem: `20260513224500`. Unique `(domain_tag, code)`.

---

## 3. Instituições, clearings e topologia MQ

### 3.1 `institutions`

Propósito: cadastro de instituições do SFN (435+ reais) com participação SPB/STR/PIX, filas MQ e FTP; trigger `sync_institutions_runtime_columns` mantém `active`/`is_active`, `cnpj`/`document_number` e datas coerentes. Origem: dump base `:185-209` + `20260513223000` (`institution_type`, `operational_status`, `liquidante_ispb`) + `20260513231000` (document_number, clearings jsonb, compe_code, ftp_*).
Colunas principais: `id` uuid PK; `ispb` varchar(8) unique; `cnpj` varchar(14) unique; `name`; `short_name`; `type` varchar(50); `institution_type` varchar(50); `operational_status` varchar(30) default active; `liquidante_ispb` varchar(8); `is_active`/`active` bool; `document_number` varchar(14); `clearings` jsonb; `compe_code` varchar(3); endereço/contato; `bacen_registered`, `spb_participant`, `str_participant`, `pix_participant` bool; `mq_queue_send`/`mq_queue_receive` varchar(100); `certificate_expiry`; `max_message_size` int; `ftp_host/port/user/password_encrypted/path/protocol`; timestamps + `created_at`.

### 3.2 `financial_institutions`

Propósito: diretório enxuto ISPB→nome/COMPE (fonte do upsert para `institutions` em `20260513231000`). Origem: `20260513230000`. Colunas: `id` uuid PK; `ispb` varchar(8) unique; `name`; `short_name`; `compe_code` varchar(4); `active`; timestamps.

### 3.3 `bacen_ispbs`

Propósito: diretório BACEN de ISPBs com habilitação de clearing e categoria. Origem: `20260513224500`. Colunas: `id` uuid PK; `ispb` unique; `name`; `short_name`; `compe_code`; `active`; `clearing_enabled`; `spb_direct`; `category` varchar(40); timestamps.

### 3.4 `clearings`

Propósito: câmaras/entidades externas (SELIC, STN, CIPs, B3...) com domínio de sistema e filas; trigger `sync_clearings_runtime_columns`. Origem: `20260513230000`; seed de 13 entidades reais em `20260601164000:59-88`.
Colunas: `id` uuid PK; `ispb` varchar(8) unique; `abbreviation`; `code`; `name`; `description`; `system_domain` varchar(20) default SPB; `mq_queue_send`/`mq_queue_receive`; `operating_hours` jsonb; `settlement_type`; `active`; timestamps.

### 3.5 `bacen_clearings_mqs`

Propósito: topologia MQ por (ISPB, domínio RSFN), espelho `spb_tb_gen_clearings_mqs`; `st_funcionamento` é o status aberto/fechado da clearing dirigido por mensagem (ClearingLifecycle). Origem: `20260426100001` + timestamps/índices em `20260601164000`/`20260604000000`.
Colunas: `ispb` varchar(8); `dom_spb` varchar(5); `seq_mqs` varchar(2); `str_compl_fila` varchar(10); `st_funcionamento` varchar(1); `bol_ativo` bool; `id_usr_ult_alt` int; `st_envio_mq` varchar(1); `server_name`, `channel_name` varchar(100); `port_number` int; `qm_name` varchar(100); timestamps. Unique `(ispb, dom_spb, seq_mqs)`; índices `(dom_spb, ispb)`, `(st_funcionamento, st_envio_mq)`.

### 3.6 `bacen_entity_status_audit`

Propósito: trilha de mudanças de status de clearing/MQ (abre/fecha). Origem: `20260601164000` (+ `20260604000000`, e DDL defensivo em `lib/bacen_gateway_web/controllers/entity_status_controller.ex:530`).
Colunas: `id` uuid PK; `ispb`; `dom_spb`; `seq_mqs`; `target` varchar(20); `previous_status`/`new_status` varchar(1); `reason` text; `changed_by` text; `changed_at`. Índice `(ispb, dom_spb, changed_at DESC)`.

### 3.7 `mq_domains` (DDL em runtime + migration)

Propósito: cadastro dos domínios MQ (SPB01, MES01...) com host/porta/canal/QM para a UI de administração. Origem: `20260529083000` e `lib/bacen_gateway_web/controllers/admin/domain_controller.ex:215`.
Colunas: `id` bigserial PK; `name` varchar(20) unique; `host`; `port` int default 1414; `channel`; `queue_manager`; `ssl_cipher`; `ssl_enabled`; `active`; `status` varchar(40) default unvalidated; `max_connections` int; `description`; `deleted_at`; timestamps.

### 3.8 `branches`

Propósito: agências/filiais por ISPB (UI admin). Origem: `20260529083000` e `lib/bacen_gateway_web/controllers/admin/branches_controller.ex:192`.
Colunas: `id` bigserial PK; `branch_code`; `name`; `ispb`; `city`; `state` varchar(2); `active`; `compe_code`; timestamps. Índices `ispb`, `active`.

---

## 4. Certificados e criptografia

### 4.1 `institution_certificates`

Propósito: certificado ativo de cada instituição do SFN por domínio (MES/SPB), das listas "Ativados" do BACEN + GEN0007; usado na verificação de assinatura inbound por serial. Origem: `20260604120000`.
Colunas: `id` uuid PK; `ispb`; `dom_spb` varchar(5); `serial` varchar(64); `subject_cn` text; `not_after`; `pem` text NOT NULL; `source` varchar(24) default bacen_ativados; `active`; timestamps. Unique `(ispb, dom_spb)`; índice `serial`.

### 4.2 `bacen_domain_certificates`

Propósito: certificados do BACEN por domínio RSFN (destino da cifragem C14 e verificação C15), self-service com histórico; 1 ativo por (ispb, domain). Origem: `20260630140000`. Schema Ecto: `lib/bacen_gateway/crypto/bacen_domain_certificate.ex:17`.
Colunas: `id` uuid PK; `ispb`; `domain` varchar(10); `serial_hex` varchar(64); `subject_cn`; `issuer_cn`; `ac_code` int; `not_before`/`not_after`; `fingerprint_sha256`; `pem` text; `active` bool default false; `imported_by`; `imported_at`; `replaced_serial`; timestamps. Unique parcial `(ispb, domain) WHERE active`; índices `serial_hex`, `(ispb, domain)`.

### 4.3 `our_signing_certificates`

Propósito: NOSSOS certificados de assinatura (ex. T010) com chave privada no HSM (somente UIDs aqui, nunca a chave); ciclo imported→verified→activating→active (ativação no BACEN via GEN0006). Origem: `20260630160000`. Schema Ecto: `lib/bacen_gateway/crypto/our_signing_certificate.ex:19`.
Colunas: `id` uuid PK; `ispb`; `label`; `serial_hex`; `subject_cn`; `issuer_cn`; `ac_code`; `not_before`/`not_after`; `fingerprint_sha256`; `pem`; `hsm_private_key_uid`; `hsm_public_key_uid`; `hsm_vhsm`; `status` varchar default imported; `activation_message_id` uuid; `activation_response` text; `activated_at`; `imported_by`; `imported_at`; `replaced_serial`; timestamps. Unique parcial `(ispb) WHERE status='active'`; índices `serial_hex`, `status`.

---

## 5. Money path: saldos, contabilidade, tarifas

### 5.1 `balance_positions`

Propósito: posição de saldo por grupo de liquidação e data (abertura, previsto/confirmado débito e crédito, fechamento). Origem: `20260513224500`.
Colunas: `id` bigserial PK; `group_id` varchar(10); `position_date` date; `opening_balance`, `debit_predicted/confirmed/rejected`, `credit_predicted/confirmed/rejected`, `closing_balance` numeric(20,2); `is_closed` bool; extras `prev_debit`, `prev_credit`, `conf_debit`, `conf_credit`, `balance_type` varchar(10) default combined, `transported`, `previous_balance`, `institution_id` int, `branch_id` int; timestamps. Unique `(group_id, position_date)`; índices `position_date`, `group_id`.

### 5.2 `balance_movements`

Propósito: ledger de movimentos aplicados a `balance_positions` (fase prevista/confirmada, direção débito/crédito); dedup por movimento. Origem: `20260609100000`.
Colunas: `id` bigserial PK; `operation_id` uuid; `phase` varchar(10); `direction` varchar(6); `group_id` varchar(10); `position_date` date; `amount` numeric(20,2); `inserted_at`. Unique parcial `(operation_id, phase, direction) WHERE operation_id IS NOT NULL`; índice `(group_id, position_date)`.

### 5.3 `balance_operation_volumes`

Propósito: volume por operação (GUID) por data/grupo com flags de confirmação (paridade legado). Origem: `20260513224500`.
Colunas: `id` bigserial PK; `operation_guid` varchar(36) unique; `balance_date` date; `group_id` int; `predicted`, `confirmed`, `transported`, `previous_balance` numeric(20,2); `is_confirmed`, `is_predicted_applied` bool; `processing_status` int; timestamps. Índices `(balance_date, group_id)`, parcial `processing_status=0`.

### 5.4 `cip_balance_zeroing_log`

Propósito: log de zeragem de saldo CIP por produto/data/grupo. Origem: `20260513224500`. Unique `(product, movement_date, group_id)`.

### 5.5 `accounting_entries`

Propósito: partida dobrada COSIF por operação (1 linha por perna D/C; estorno RD/RC via `reversal_of_id`), trilha canônica `Accounting.Posting`. Origem: `20260527153000` + correlação/idempotência em `20260705120000` e `20260705130000`.
Colunas: `id` uuid PK; `operation_id` uuid NOT NULL; `account_code` varchar(30); `debit`/`credit` numeric(18,2); `description`; `posting_date` date; `reversal_of_id` uuid; `cd_msg` varchar(20); `cd_evento` int; `leg` varchar(2) (D/C/RD/RC); `created_at`.
Índices: `operation_id`, `posting_date`; unique parcial `(operation_id, cd_evento, leg) WHERE reversal_of_id IS NULL`; unique parcial `(reversal_of_id) WHERE reversal_of_id IS NOT NULL AND leg IN ('RD','RC')`.

### 5.6 `accounting_scripts`

Propósito: scripts contábeis por tipo de mensagem (contas débito/crédito, percentual, impostos, split) da trilha antiga configurável. Origem: `20260527153000`. Índice `(message_type, is_active, sort_order)`.

### 5.7 `spb_cnt_contas`, `spb_cnt_roteiro`, `spb_cnt_roteiro_tags` (roteiro contábil COSIF)

Propósito: fonte de verdade do roteiro contábil (paridade EvolutionPro): plano de contas (714 contas COSIF), eventos por `cd_msg` (histórico + conta débito + crédito) e condições de tag que selecionam o evento. Origem: `20260605600000` + `tp_sql` em `20260605700000`. Consumidos por `lib/bacen_gateway/accounting/roteiro.ex`.
- `spb_cnt_contas`: `id_conta` int PK; `cd_conta` varchar(30); `ds_conta`; timestamps; índice `cd_conta`.
- `spb_cnt_roteiro`: `id` bigserial PK; `cd_msg`; `cd_evento` int; `cd_historico` int; `debito_conta`/`credito_conta` varchar(30); timestamps; unique `(cd_msg, cd_evento)`.
- `spb_cnt_roteiro_tags`: `id` bigserial PK; `cd_evento`; `cd_msg`; `id_tag` varchar(60); `vl_tag` varchar(255); `cnt_ordem` int; `tp_sql` varchar(20) default alfanumerico; timestamps; índice `cd_evento`.

### 5.8 `cosif_chart_of_accounts` e `cosif_posting_templates`

Propósito: plano de contas COSIF hierárquico e templates de lançamento por evento (trilha alternativa/legada ao roteiro). Origem: `20260513223000`. Uniques: `account_code`, `event_type`.

### 5.9 `bacen_tariffs` e `bacen_tariff_bands`

Propósito: `bacen_tariffs` = modelo simples (1 tarifa por tipo/data, superado); `bacen_tariff_bands` = faixas REAIS de tarifa BACEN (9.473 faixas: hora do dia HHMMSS que pode cruzar meia-noite, faixa de quantidade diária, vigência, D0, valor emissor × destinatário). Origem: `20260513224500` e `20260605400000`.
`bacen_tariff_bands`: `id` uuid PK; `message_type`; `hr_de`/`hr_ate` int; `qty_de`/`qty_ate` bigint; `effective_date` date; `fl_d0` bool; `vl_emissor`/`vl_destinatario` numeric(18,4); `flg_sitraf` bool; timestamps. Índice `(message_type, effective_date)`; unique composto de 7 colunas `bacen_tariff_bands_uniq`.

### 5.10 `tariff_movements`

Propósito: movimento de tarifa calculado por operação liquidada (INSERT best-effort do `LifecycleEngine.record_tariff_movement/7`). Origem: `20260606000000`.
Colunas: `id` bigserial PK; `operation_id` uuid (sem FK, deliberado); `clearing_code` varchar(50); `message_type` varchar(50); `amount`, `tariff_amount` numeric(18,2); `tariff_rule_id` varchar(255); `calculated_at`, `inserted_at` naive. Índices `operation_id`, `(message_type, calculated_at)`.

### 5.11 `redesconto_value_ledger`

Propósito: valor restante por operação de redesconto originária (`NumCtrlRDCOr`); R1/erro credita `VlrFinanc` de volta para permitir reenvio. Origem: `20260605000000`.
Colunas: `id` uuid PK; `operation_id` uuid; `num_ctrl_rdc_or` varchar(50) unique; `remaining_amount` numeric(18,2); `initial_amount`; timestamps.

### 5.12 `credit_limits`

Propósito: limite de crédito por grupo de clearing (total/usado/reservado), persistência dual ETS+DB do `Credit.CreditControl`. Origem: `20260513223000`. Unique `group_id`.

### 5.13 `received_credits`

Propósito: créditos recebidos aguardando decisão (aceitar/devolver). Origem: `20260513223000`.
Colunas: `id` uuid PK; `message_id` uuid; `sender_ispb`; `amount`; `received_at`; `status` varchar(40) default pending_decision; timestamps.

---

## 6. Dia operacional, feriados e bloqueios

### 6.1 `spb_operational_date`

Propósito: ponteiro da data de movimento por ISPB (`dt_sistema` do legado): avança no fechamento e retroage via GEN0021. Origem: `20260604100000`.
Colunas: `ispb` varchar(8) PK; `operational_date` date; `status` varchar(10) default open; `opened_at`; `closed_at`; timestamps.

### 6.2 `closing_audit_log` e `day_closing_status`

Propósito: trilha de abertura/fechamento/transição da data operacional e o registro de fechamento por dia (`Day.DayAutoClose`). Origem: `20260604110000` (DDL defensivo também em `admin_controller.ex:1863`).
- `closing_audit_log`: `id` uuid PK; `action` varchar(50); `business_date` date; `user_id`; `clearing_id`; `closing_id` uuid; `details` jsonb; `created_at`. Índices `(business_date, created_at DESC)`, `action`.
- `day_closing_status`: `id` uuid PK; `business_date` date unique; `status` varchar(20); `closed_at`; `closed_by`; `summary` text; `force_reason` text; `created_at`.

### 6.3 `bacen_holidays`

Propósito: feriados (829 do legado) com flags de impacto STR/SELIC/CIP/PIX, por instituição/agência. Origem: `20260513224500`. Unique `(holiday_date, institution, branch)`; índice `holiday_date`.

### 6.4 `message_blocks`

Propósito: bloqueio administrativo de envio por tipo de mensagem/direção/grupo com expiração. Origem: `20260513224500`.
Colunas: `id` bigserial PK; `message_type`; `direction`; `group_id`; `reason`; `blocked_by`; `blocked_at`; `expires_at`; `active`; timestamps. Índices `message_type`, parcial `active`.

---

## 7. Alertas, watch-list e sanções

### 7.1 `operational_alerts` e `alert_user_routes`

Propósito: alertas operacionais roteados (tipos: `devolucao_pendente`, `rdc_intradia`, `devolucao_recebida`, `contabil`, ver `lib/bacen_gateway/alerts/operational_alerts.ex:36`) com dedupe por alerta aberto e roteamento por usuário (UI/e-mail). Origem: `20260611100000` (DDL espelhado em `alerts/operational_alerts.ex:48-96`).
- `operational_alerts`: `id` uuid PK; `alert_type` varchar(40); `severity` varchar(12) default media; `title`; `message` text; `payload` jsonb; `dedupe_key` varchar(160); `status` varchar(12) default novo (novo→visto→resolvido); `user_id` uuid; `acked_by`/`acked_at`; `resolved_by`/`resolved_at`; `email_sent_at`; `email_error`; timestamps. Unique parcial `(alert_type, dedupe_key) WHERE status <> 'resolvido'`; índices `(status, inserted_at DESC)`, parcial e-mail pendente.
- `alert_user_routes`: `id` bigserial PK; `user_id` uuid; `alert_type`; `notify_ui`/`notify_email`/`is_active` bool; timestamps. Unique `(user_id, alert_type)`.

### 7.2 `message_watch_subscriptions` e `message_watch_hits`

Propósito: watch-list de rastreamento por usuário e tipo de mensagem (6 classes de evento: integração, envio, R1, erro, cancelamento, não-processada) + ocorrências deduplicadas. Origem: `20260611120000`.
- Subscrições: `id` bigserial PK; `user_id` varchar(100); `message_type` varchar(10); flags `watch_*` (6) e `notify_email`/`notify_popup`; `active`; timestamps. Unique `(user_id, message_type)`.
- Hits: `id` bigserial PK; `subscription_id` FK CASCADE; `bacen_message_id` uuid; `operation_id` uuid; `message_type`; `event_class` varchar(20); `matched_at`; `summary` jsonb; `acked_at`. Unique parcial `(subscription_id, bacen_message_id, event_class)`.

### 7.3 `sanctions_screening` e `sanction_resolutions`

Propósito: resultado do screening de sanções por operação (SanctionsEngine) e a resolução manual (release = falso positivo / reject = hit confirmado, com motivo obrigatório de 10+ caracteres). Origem: `20260611130000`.
- `sanctions_screening`: `id` uuid PK; `operation_id` uuid (sem FK, deliberado); `screening_status` varchar(20); `screening_reason` text; `screening_metadata` jsonb; `screened_at`; `reviewed_by`/`reviewed_at`; timestamps. Índices `operation_id`, `screening_status`.
- `sanction_resolutions`: `id` uuid PK; `operation_id` FK→spb_operations ON DELETE RESTRICT, unique; `decision` varchar(10) CHECK in (release, reject); `reason` text CHECK len>=10; `decided_by`; `decided_at`; timestamps. Índice `decision`.

---

## 8. Alçada, vistos e aprovação

### 8.1 `alcadas` (DDL em runtime)

Propósito: níveis de alçada por faixa de valor/clearing/tipos de mensagem (CRUD da UI). DDL: `lib/bacen_gateway_web/controllers/alcadas_controller.ex:26` (`@table "alcadas"` na linha 14).
Colunas: `id` uuid PK; `name` varchar(100); `level` int default 1; `min_value`/`max_value` numeric(18,2); `clearing` varchar(20); `message_types` text[]; `requires_dual_approval` bool; `active`; timestamps.

### 8.2 `alcada_tag_rules` e `alcada_counterparty_rules`

Propósito: regras de alçada por tag da mensagem (padrão de valor) e por contraparte (ISPB destinatário + faixa de valor + dupla aprovação). Origem: `20260513223000`. Consumidas pelo `Alcada.AlcadaEngine` (ETS).

### 8.3 `vistos`

Propósito: pedidos de visto/aprovação (4 olhos) por operação com nível de alçada. Origem: `20260529083000` (DDL defensivo em `vistos_controller.ex:20`).
Colunas: `id` uuid PK; `operation_id` varchar(50); `operation_table` varchar(50); `status` varchar(20) default pending; `requested_by`/`approved_by` text; `reason` text; `amount` numeric(18,2); `alcada_level` int; timestamps.

---

## 9. Segurança, usuários e RBAC

### 9.1 `users`

Propósito: usuários do console SPB (login por e-mail, Bcrypt). Origem: dump base `:381-394` + `must_change_password` em `20260708220000`.
Colunas: `id` uuid PK; `email` unique; `username`; `password_hash`; `role` varchar(50); `is_active`; `institution_id` uuid; `last_login_at`; `failed_login_attempts` int; `locked_until`; `must_change_password` bool default false; timestamps. Índices `email` (unique), `username`, `role`, `is_active`, `institution_id`.

### 9.2 RBAC: `modules`, `features`, `groups`, `group_features`, `user_groups`

Propósito: RBAC completo (módulo → features com rota/ícone; grupos com 7 capacidades por feature: view/create/edit/delete/approve/configure/export; vínculo usuário-grupo com `is_primary`). Origem: `20260309100000_create_rbac_tables.exs`.
Uniques: `modules.code`, `features.code`, `groups.code`, `(group_id, feature_id)`, `(user_id, group_id)`. FKs com ON DELETE CASCADE (delete_all).

### 9.3 `sessions`

Propósito: sessões JWT persistidas (hash do token, expiração, revogação). Origem: dump base `:300-310`. Unique `token_hash`; índices `user_id`, `expires_at`. Limpeza pelo `Security.SessionCleanup`.

### 9.4 `api_keys`

Propósito: chaves de API por instituição (hash, expiração, contagem de uso). Origem: dump base `:73-84`. Unique `key_hash`.

### 9.5 `audit_logs`

Propósito: trilha de auditoria administrativa (ação, recurso, mudanças jsonb, IP, user agent) com colunas estendidas `details`/`category`/`request_id`. Origem: dump base `:91-101` + `20260511171000`/`20260511173500`.
Índices: `action`, `(resource_type, resource_id)`, `user_id`, `inserted_at`, `created_at DESC`, `(action, created_at DESC)`, `(resource_type, resource_id, created_at DESC)`, parcial `request_id`.

---

## 10. Configuração e utilidades

### 10.1 `system_config`

Propósito: chave→valor global de runtime (ex.: `cnt_ativa`, `cosif_to_core_enabled`, política de fechamento de dia). Origem: dump base `:366-374` + coluna `section` em `20260513223000`; DDL mínimo defensivo em `admin_controller.ex:2899`. Uniques: `key`, `(section, key)`.

### 10.2 `system_settings`

Propósito: settings tipados por seção (UI de configurações). Origem: `20260513223000` (e DDL em `settings_controller.ex:19` e `config_controller.ex:813`). Uniques: `key`, `(section, key)`.

### 10.3 `system_notices` (DDL em runtime + migration)

Propósito: avisos do sistema exibidos no console (título, corpo, prioridade, vigência). Origem: `20260529083000` e `lib/bacen_gateway/admin/system_notices.ex:163`.

### 10.4 `scheduled_queries` e `scheduled_query_runs`

Propósito: consultas agendadas (GEN0001 etc.) por cron e o histórico de execuções/despachos. Origem: `20260513223000` + `20260529083000`; DDL canônico em runtime `lib/bacen_gateway/queries/scheduled_query_executor.ex:34` e `:81`.
- `scheduled_queries`: `id` uuid PK; `name`; `query_type`; `msg_code`; `schedule_cron`; `params` jsonb; `last_run`/`next_run`; `is_active`; timestamps. Índice parcial `next_run WHERE is_active`.
- `scheduled_query_runs`: `id` uuid PK; `scheduled_query_id` text; `query_type`; `msg_code`; `status` varchar(40); `dispatch_mode` default pubsub_only; `source` default manual; `requested_at`/`completed_at`; `detail`; `message_id`; `protocol`; `params` jsonb.

### 10.5 `file_transfers`

Propósito: pipeline de transferência de arquivos BACEN (GEN0014-18): direção, tipo, assinatura/cifragem/transferência com retries. Origem: `20260513223000`.
Colunas: `id` uuid PK; `direction`; `file_type`; `file_name`; `status` default pending; `institution_ispb`; `domain`; `encoding`; `file_size` bigint; `retry_count`/`max_retries`; `signed_at`/`encrypted_at`/`transferred_at`; `gen_message_id`; `error_message`; timestamps.

### 10.6 `webhook_configs`

Propósito: webhooks por instituição (URL, eventos jsonb, secret, contadores de falha). Origem: dump base `:401-413`.

### 10.7 `accounts`

Propósito: contas de clientes/instituições usadas nos fluxos de teste e projeções (não é o ledger do Core). Origem: dump base `:52-66`. Unique `(institution_id, account_number)`.

### 10.8 `payment_requests`

Propósito: ordens de pagamento (boleto/TED) com dados completos de pagador/beneficiário (modelo herdado da fase de microsserviços; hoje leitura legada). Origem: dump base `:231-264`. Unique `payment_id`.

### 10.9 `str_transfers`, `settlements`, `forex_operations`, `securities_operations`

Propósito: tabelas de operação da fase V1 (pré modelo duas-tabelas); permanecem no schema por compatibilidade de leitura, o fluxo vivo usa `spb_operations`. Origem: dump base `:341-359`, `:317-334`, `:160-178`, `:274-293`. Uniques: `transfer_id`, `settlement_id`, `operation_id` (2x). CHECKs de ISPB alfanumérico aplicados em `20260612400000`.

---

## 11. Tabelas criadas apenas por seeds (apoio/legado)

Os seeds (`priv/repo/seeds/*.exs`) criam tabelas auxiliares com `CREATE TABLE IF NOT EXISTS` para importar dados do legado; não fazem parte do modelo canônico, mas existem nos bancos onde os seeds rodaram:
- `020_security_seeds.exs`: `spb_users`, `spb_groups`, `spb_user_groups`, `spb_modules`, `spb_permissions`, `spb_group_permissions`, `spb_message_permissions` (RBAC legado paralelo).
- `022_alcadas_vistos_seeds.exs`: `spb_alcadas` (regras que o `AlcadaEngine` lê, `lib/bacen_gateway/alcada/alcada_engine.ex:697`), `spb_vistos` (aprovações do engine, `alcada_engine.ex:238`).
- `024_external_entities_seeds.exs`: `spb_external_entities`, `spb_entity_status_history`.
- `011_transaction_seeds.exs`: `lpi_operations`, `sme_operations`, `cir_operations`, `slb_operations` (acervos por grupo).
- `023_schedule_holidays_seeds.exs`: `spb_schedules`, `spb_holidays_extended`.
- `030/031/033_legacy_*.exs`: `legacy_error_codes`, `legacy_tariffs`, `legacy_clearings`, `legacy_message_groups`.
- `039_branch_registry.exs`: `bank_branches`; `040_municipalities.exs`, `041_assignors.exs`, `042_custodians.exs`: cadastros de municípios, cedentes e custodiantes (DDA/PCR).

## 12. Observações de integridade

- Idempotência de dinheiro: crédito TED-in tem unique parcial em `spb_operations` (§1.1); movimentos de saldo têm dedup em `balance_movements` (§5.2); partidas contábeis têm uniques parciais ativa e de estorno (§5.5); outbox com `Nats-Msg-Id` dedup no JetStream (`lib/bacen_gateway/nats/publisher.ex:223`).
- CHECK constraints de CNPJ/ISPB alfanumérico (IN RFB 2.229/2024 + DRN BACEN v1.02) em 31 colunas de 24 tabelas, staged `NOT VALID` e depois validadas (`20260612400000` + `20260612500000`).
- Triggers vivos: `sync_spb_operations_clearing_group`, `sync_clearings_runtime_columns`, `sync_message_groups_runtime_columns`, `sync_message_templates_runtime_columns`, `sync_institutions_runtime_columns`.
