# Topologia de rede Monetarie: HML (10.45) e PROD (10.50)

Data: 2026-07-10
Método: leitura read-only do Terraform em `infra/aws/greenfield/` (um único módulo parametrizado por ambiente: HML usa os defaults de `variables.tf`; PROD usa `envs/prod.tfvars` com backend isolado `backend.prod.hcl`). Complementado por `docs/reports/2026-07-07-fase3-infra-prod-status.md` (validação viva da Fase 3) e `docs/architecture/2026-06-22-monetarie-hml-vpc-10-45-openvpn.md`. Nenhum comando de escrita foi executado; nenhum segredo consta neste documento (regra absoluta #10).

Conta AWS: `990933657879`, região `sa-east-1`, profile `vulcimonetarie` (`variables.tf:199-218`). Estados Terraform separados no mesmo bucket: `homolog/greenfield/terraform.tfstate` (`backend.tf:4-11`) e `prod/greenfield/terraform.tfstate` (`backend.prod.hcl`).

## 1. Comparativo HML x PROD (resumo)

| Dimensão | HML (homolog) | PROD |
|---|---|---|
| VPC (adotada via data source) | `vpc-03e25a932e9fd22a8` `monetarie-rtm-hml` 10.45.0.0/16 (`variables.tf:221-231`, `data.tf:6-8`) | `vpc-0da523dbdbac50b5d` `monbank-rtm-prod` 10.50.0.0/16 (`envs/prod.tfvars:12-13`) |
| Subnets de app | 10.45.1/2/3.0/24 (a/b/c) (`variables.tf:233-241`) | 10.50.1/2/3.0/24 (a/b/c) (`envs/prod.tfvars:14-18`) |
| Route table de app | `rtb-0b1f289a9d513cd03` (`variables.tf:243-247`) | `rtb-022392b605e241db7` (`envs/prod.tfvars:19`) |
| Egress de internet | IGW + rota default 0.0.0.0/0, tasks e EC2 com IP público (`vpc-endpoints.tf:21-42`, `variables.tf:97-101,175-179`) | NAT Gateway `nat-0f0cbaab083db3502` (EIP 18.228.20.148) em subnet pública dedicada 10.50.4.0/24 com IGW próprio; tasks e EC2 SEM IP público (`nat.tf:6-59`, `envs/prod.tfvars:39-41,143`) |
| `assign_public_ip` (Fargate) | `true` (`ecs.tf:584-594`) | `false` (`envs/prod.tfvars:41`) |
| Sufixo de hosts internos | `-h` (`variables.tf:7-11`) | vazio, hosts sem sufixo (`envs/prod.tfvars:23`) |
| Sufixo de nomes de recursos | `-45` (`variables.tf:13-17`) | `-50` (`envs/prod.tfvars:30`) |
| Cluster ECS | `monetarie-greenfield-homolog` (`ecs.tf:368-377`) | `monetarie-greenfield-prod` (mesmo recurso, env=prod) |
| Serviços ECS no Terraform | 15 services + task-defs geridos pelo estado (`ecs.tf:496-648`) | `create_ecs_services=false`: o estado cria cluster/roles/log groups; services e task-defs de aplicação são geridos FORA do Terraform, por digest (Fase 6) (`variables.tf:91-95`, `envs/prod.tfvars:77-79`) |
| Aurora | `monetarie-core-homolog-45`, PostgreSQL 16.6, Serverless v2 0,5 a 4 ACU, deletion_protection=false (`aurora.tf:26-59`, `variables.tf:434-447`) | `monetarie-core-prod-50`, PostgreSQL 17.9, 0,5 a 16 ACU, deletion_protection=true (`envs/prod.tfvars:64,111-117`) |
| Redis | `monetarie-gf-redis-node-homolog-45`, 7.1, cache.t4g.micro, 1 nó, sem TLS (`elasticache.tf:8-19`) | `monetarie-gf-redis-node-prod-50`, mesma configuração (deliberado para o go-live) (`envs/prod.tfvars:118`) |
| NATS | 1 nó `10.45.1.10`, t4g.micro, JetStream, streams replica=1 (`variables.tf:151-155,163-167,466-470`, `messaging.tf:10-15`) | 3 nós `10.50.{1,2,3}.10` (1 por AZ), t4g.small, cluster `monetarie-prod` porta 6222, streams replica=3 (`envs/prod.tfvars:122,140-142`) |
| TigerBeetle 0.17.3 (regra #8) | 1 nó `10.45.1.20`, t4g.large, modo `--development`, EBS gp3 30GB dedicado com prevent_destroy (`messaging.tf:137-254`) | 3 réplicas `10.50.{1,2,3}.20` (1 por AZ), t4g.large, SEM `--development`, EBS dedicado por nó (`envs/prod.tfvars:141`, `messaging.tf:17-31`) |
| OpenVPN | `10.45.1.30` (subnet a), EIP `54.94.247.111`, UDP 1194 (`variables.tf:490-499`, doc 2026-06-22) | `10.50.4.30` (subnet pública do NAT), EIP `15.229.92.89`, UDP 1194 (`envs/prod.tfvars:99-102`, relatório Fase 3 linha 46) |
| Zona `monetarie.internal` | CRIA a zona canônica `Z07255101LW0TK32G8LU2` e associa a VPC 10.45 (`dns.tf:10-32`) | ADOTA a mesma zona (`create_internal_zone=false`) e só associa a VPC 10.50 + registros sem sufixo (`envs/prod.tfvars:28-29`, `dns.tf:36-40`) |
| Resolver RSFN (outbound) | ENIs `10.45.1.53` / `10.45.2.53` (`variables.tf:312-324`) | ENIs `10.50.1.53` / `10.50.2.53` (`envs/prod.tfvars:93-96`) |
| Portas RSFN | dict 16522, dict-np 16532, icom 16522, icom-sec 17522, arq 1130 (`variables.tf:353-363`) | dict 16422, dict-np 16432, icom 16422, icom-sec 17422, arq 1130 (`envs/prod.tfvars:131-137`) |
| HSM RTM (HTTPS 443, nunca :6443) | `monetarie-hsm-hml.priv.rtmcloud.net.br` (10.151.11.140/141) (`variables.tf:103-107`, `locals.tf:17-19`) | `monetarie-hsm-prd.priv.rtmcloud.net.br` (10.151.11.138/139); `cloudhsm.priv.rtmcloud.net.br` (10.173.1.247) é só o console Ecos (`envs/prod.tfvars:81-87`) |
| IBM MQ RTM | `172.31.2.50`: SPB01 `QM.46026562.01:1514` (operante), MES01 `QM.46026562.02:12522` (DROP na RTM) (`variables.tf:115-131`) | `172.31.1.50`: SPB01 `:1414`, MES01 `:12422` (ambos CONNECT provado em 2026-07-07) (`envs/prod.tfvars:88-90`) |
| ALB interno recebe da VPC RTM 192.168/16 | sim (operação via bastion) (`security-groups.tf:124-131`) | não (`allow_rtm_vpc_ingress=false`; acesso só pela OpenVPN prod) (`envs/prod.tfvars:63`) |
| ECR / rotas TGW / KMS alias | HML é dono dos repos ECR e da rota estática DX no TGW; aliases KMS sem sufixo (`ecr.tf:6-20`, `tgw-routes.tf:5-10`, `kms-secrets.tf:14-18`) | adota ECR via data source, não gerencia a rota TGW compartilhada, aliases `-prod` (`envs/prod.tfvars:31-36`) |
| Endpoints SSM | criados pelo estado (interface endpoints próprios) (`vpc-endpoints.tf:76-87`) | ssm/ssmmessages/ec2messages são os `monbank-prod-*-TEMP` da RTM (skip no nosso estado) + regra 443 no SG default (`envs/prod.tfvars:69-72`) |

## 2. Diagrama: topologia HML

```mermaid
flowchart LR
  time["Time Monetarie"] -->|"UDP 1194"| eiph["EIP OpenVPN HML<br/>54.94.247.111"]
  eiph --> vpnh["OpenVPN HML<br/>10.45.1.30 (subnet a)<br/>BIND local + easy-rsa"]

  subgraph vpch["VPC monetarie-rtm-hml vpc-03e25a932e9fd22a8 (10.45.0.0/16)"]
    subgraph subh["Subnets 10.45.1/2/3.0-24, rtb-0b1f289a9d513cd03"]
      albh["ALB interno HTTP 80<br/>monetarie-internal-homolog-45<br/>roteia por Host header"]
      ecsh["ECS monetarie-greenfield-homolog<br/>14 servicos Fargate ARM64 (IP publico)<br/>+ core-api em EC2 (io_uring)"]
      natsh["NATS 2.10 JetStream<br/>10.45.1.10 (1 no, t4g.micro, IP publico)"]
      tbh["TigerBeetle 0.17.3<br/>10.45.1.20 (1 no, t4g.large, IP publico,<br/>EBS 30GB dedicado)"]
      resh["Route 53 Resolver outbound RSFN<br/>10.45.1.53 / 10.45.2.53"]
    end
    aurorah["Aurora PG 16.6 Serverless v2<br/>monetarie-core-homolog-45 (0,5-4 ACU)<br/>6 bancos mon_*"]
    redish["Redis 7.1 cache.t4g.micro<br/>monetarie-gf-redis-node-homolog-45"]
    vpceh["VPC endpoints<br/>S3 gateway + 12 interface<br/>(ecr, logs, secretsmanager, ssm, ecs, kms, sts)"]
    igwh["IGW + rota default 0.0.0.0/0"]
  end

  vpnh --> albh
  albh --> ecsh
  ecsh --> aurorah
  ecsh --> redish
  ecsh -->|"4222"| natsh
  ecsh -->|"3001"| tbh
  ecsh --> vpceh
  ecsh -->|"egress internet<br/>(bcb.gov.br etc.)"| igwh

  ecsh -->|"rotas especificas<br/>RTM/RSFN/HSM"| tgw["TGW tgw-051f1a3c159dfb25b<br/>(Direct Connect / RTM)"]
  resh -->|"rsfn.net.br"| irs["6 IRS RSFN<br/>200.218.64.6/.38/.70/.134/.166/.198"]
  tgw --> hsmh["HSM RTM HML<br/>monetarie-hsm-hml.priv.rtmcloud.net.br:443"]
  tgw --> mqh["IBM MQ RTM 172.31.2.50<br/>SPB01 1514 / MES01 12522 (DROP)"]
  tgw --> rsfnh["RSFN dict/icom/arq<br/>16522/16532/17522/1130"]

  zdns["Route 53 privado:<br/>monetarie.internal (*-h)<br/>priv.rtmcloud.net.br"] -.-> vpch
```

Notas HML:
- O ALB interno aceita HTTP 80 da VPC 10.45 e também da VPC RTM 192.168.0.0/16 (bastion) (`security-groups.tf:113-131`).
- O egress padrão é IGW com IP público nas tasks Fargate (necessário para o worker diário da lista de participantes PIX em www.bcb.gov.br; ingress segue bloqueado pelo SG) (`ecs.tf:586-593`).
- `core-api` roda em ECS EC2 (ASG `monetarie-core-ecs-homolog`, t4g.small, AMI ECS-optimized AL2023 arm64, io_uring habilitado) porque o cliente TigerBeetle usa io_uring, indisponível no Fargate (`ecs-ec2-core.tf:23-114`, `variables.tf:478-482`, `ecs.tf:611-648`).
- Registros estáticos RSFN de HML (dict-h/dict-np-h/icom-h/icom-sec-h/arq-h para o relay Cecresa 172.16.70.51-55) seguem declarados em `variables.tf:340-351`, mas o caminho vivo é o RSFN direto resolvido pelo Resolver.

## 3. Diagrama: topologia PROD

```mermaid
flowchart LR
  time["Time Monetarie"] -->|"UDP 1194"| eipp["EIP OpenVPN PROD<br/>15.229.92.89"]
  eipp --> vpnp["OpenVPN PROD<br/>10.50.4.30 (subnet publica do NAT)"]

  subgraph vpcp["VPC monbank-rtm-prod vpc-0da523dbdbac50b5d (10.50.0.0/16)"]
    subgraph pub["Subnet publica 10.50.4.0/24 (rt propria: IGW + rotas TGW)"]
      natgw["NAT Gateway nat-0f0cbaab083db3502<br/>EIP 18.228.20.148"]
      igwp["IGW proprio (monetarie-igw-prod)"]
    end
    subgraph subp["Subnets de app 10.50.1/2/3.0-24, rtb-022392b605e241db7<br/>rota default 0.0.0.0/0 -> NAT (sem IP publico)"]
      albp["ALB interno HTTP 80<br/>monetarie-internal-prod-50<br/>15 target groups mon-*-50"]
      ecsp["ECS monetarie-greenfield-prod<br/>services/task-defs por digest (fora do TF)<br/>core-api em EC2, demais Fargate"]
      natsp["NATS JetStream cluster (R=3)<br/>10.50.1.10 / 10.50.2.10 / 10.50.3.10<br/>t4g.small, 1 por AZ"]
      tbp["TigerBeetle 0.17.3 cluster 3 replicas<br/>10.50.1.20 / 10.50.2.20 / 10.50.3.20<br/>t4g.large, EBS dedicado por no"]
      resp["Route 53 Resolver outbound RSFN<br/>10.50.1.53 / 10.50.2.53"]
    end
    aurorap["Aurora PG 17.9 Serverless v2<br/>monetarie-core-prod-50 (0,5-16 ACU)<br/>deletion_protection=true"]
    redisp["Redis 7.1 cache.t4g.micro<br/>monetarie-gf-redis-node-prod-50"]
    vpcep["VPC endpoints proprios +<br/>ssm/ssmmessages/ec2messages TEMP da RTM"]
  end

  vpnp --> albp
  albp --> ecsp
  ecsp --> aurorap
  ecsp --> redisp
  ecsp -->|"4222"| natsp
  ecsp -->|"3001"| tbp
  ecsp -->|"egress internet"| natgw
  natgw --> igwp

  ecsp -->|"10.151.11.0/24 e demais<br/>rotas RTM/RSFN via TGW"| tgw["TGW tgw-051f1a3c159dfb25b<br/>(Direct Connect / RTM)"]
  vpnp -->|"rotas TGW na rt publica:<br/>HSM, MQ, RSFN"| tgw
  resp -->|"rsfn.net.br"| irs["6 IRS RSFN 200.218.64.x"]
  tgw --> hsmp["HSM RTM PROD<br/>monetarie-hsm-prd.priv.rtmcloud.net.br:443<br/>(10.151.11.138/139)"]
  tgw --> mqp["IBM MQ RTM 172.31.1.50<br/>SPB01 1414 / MES01 12422"]
  tgw --> rsfnp["RSFN dict/icom/arq<br/>16422/16432/17422/1130"]

  zdnsp["Route 53 privado:<br/>monetarie.internal (sem sufixo)<br/>priv.rtmcloud.net.br"] -.-> vpcp
```

Notas PROD:
- A subnet pública 10.50.4.0/24 tem route table própria com rota default para o IGW e rotas TGW espelhando os destinos RTM/RSFN (`10.0.17.2/32`, `10.0.33.2/32`, `10.151.11.0/24`, `10.173.1.247/32`, `172.31.1/2/3.0/24`, `200.160.160.0/22`, `200.218.64.0/18`); sem isso a VPN não alcançaria HSM/MQ/RSFN (`nat.tf:61-70`, `envs/prod.tfvars:46-56`).
- A route table de app ganha adicionalmente `10.151.11.0/24 -> TGW` para as tasks alcançarem o gateway KMIP REST do HSM prod (`nat.tf:72-80`, `envs/prod.tfvars:60`).
- O ALB interno de prod NÃO aceita a VPC RTM 192.168/16; o acesso operacional é exclusivamente pela OpenVPN prod (`envs/prod.tfvars:63`).
- Os services/task-defs de aplicação de prod vivem fora deste estado Terraform (promovidos por digest na Fase 6); o estado criou cluster, roles, log groups e a ASG `monetarie-core-ecs-prod` (1 EC2 para o core-api) (`envs/prod.tfvars:74-79`, relatório Fase 3 linha 42).

## 4. Diagrama: caminho RSFN/RTM (cabines para HSM, MQ e RSFN)

```mermaid
flowchart TB
  subgraph cab["Cabines na VPC de app (ECS)"]
    pix["pix-api (cabine PIX)<br/>assina no HSM, mTLS ICP-Brasil direto"]
    spb["spb-api (cabine SPB)"]
    sc["spb-mq-sidecar<br/>HTTP localhost:9080 -> JMS/MQ"]
    core["core-api (Core)<br/>NUNCA assina mensagem BACEN (regra #13);<br/>publica eventos via NATS"]
    spb --- sc
  end

  subgraph dns["Resolucao de nomes"]
    z2["priv.rtmcloud.net.br (zona privada da conta):<br/>monetarie-hsm-hml / monetarie-hsm-prd / cloudhsm"]
    rr["Resolver rule rsfn.net.br<br/>forward para os 6 IRS oficiais 200.218.64.x"]
  end

  pix -->|"HTTPS 443, POST /v1/kmip/60042/sign-rsa<br/>(RSAHASH PKCS1 v1.5 SHA-256)"| hsm["HSM RTM (Ecos vHSM 60042)<br/>HML: monetarie-hsm-hml (10.151.11.140/141)<br/>PROD: monetarie-hsm-prd (10.151.11.138/139)<br/>console: cloudhsm.priv.rtmcloud.net.br (10.173.1.247)<br/>PROIBIDO :6443"]
  spb -->|"HTTPS 443 (assinatura/decifragem SPB)"| hsm

  sc -->|"HML: 172.31.2.50:1514 (SPB01)<br/>:12522 (MES01, DROP na RTM)<br/>PROD: 172.31.1.50:1414 / :12422<br/>QM.46026562.01/.02, canal APP.SVRCONN,<br/>MCAUSER spb_server"| mq["IBM MQ RTM<br/>(mensageria SPB/STR com o BACEN)"]

  pix -->|"mTLS ICP-Brasil verify_peer, sem proxy:<br/>DICT HML 16522 / PROD 16422<br/>DICT-NP 16532/16432<br/>ICOM 16522/16422, ICOM-SEC 17522/17422<br/>ARQ 1130 (ambos)"| rsfn["RSFN (BACEN)<br/>dict(-h).pi.rsfn.net.br<br/>icom(-h).pi.rsfn.net.br<br/>arq(-h).pi.rsfn.net.br"]

  hsm -.->|"TGW tgw-051f1a3c159dfb25b<br/>+ Direct Connect (rotas RTM)"| rtm["Rede RTM / RSFN"]
  mq -.-> rtm
  rsfn -.-> rtm
  rr -.-> rsfn
  z2 -.-> hsm
```

Pontos canônicos desse caminho:
- Assinatura BACEN (XMLDSig PIX, cifra SPB) é responsabilidade exclusiva das cabines PIX e SPB; o Core nunca assina (regra #13 do `CLAUDE.md`).
- HSM sempre em HTTPS 443; o endpoint histórico `:6443` é diagnóstico antigo e é proibido como runtime.
- Em HML os nomes RSFN levam sufixo `-h` (`dict-h.pi.rsfn.net.br` etc.); em prod, sem sufixo (`locals.tf:78-86`).
- Errar a porta RSFN por ambiente gera falso diagnóstico de bloqueio (errata registrada no relatório da Fase 3): HML 165xx/175xx, PROD 164xx/174xx.

## 5. Tabelas de referência

### 5.1 Subnets e roteamento

| Ambiente | Subnet | CIDR | AZ | Papel | Rota default |
|---|---|---|---|---|---|
| HML | `subnet-01194da7817adf43a` (a) | 10.45.1.0/24 | sa-east-1a | app (ECS, NATS, TB, OpenVPN, resolver a) | 0.0.0.0/0 -> IGW (`vpc-endpoints.tf:32-37`) |
| HML | `subnet-06aac3d8df4e5f6d5` (b) | 10.45.2.0/24 | sa-east-1b | app (resolver b) | idem (rtb única `rtb-0b1f289a9d513cd03`) |
| HML | `subnet-012bfe64ab5455fdc` (c) | 10.45.3.0/24 | sa-east-1c | app | idem |
| PROD | `subnet-0be2197fa3490cffb` (a) | 10.50.1.0/24 | sa-east-1a | app (NATS 1, TB 0, resolver a) | 0.0.0.0/0 -> NAT GW (`nat.tf:54-59`) |
| PROD | `subnet-06977634d4344b353` (b) | 10.50.2.0/24 | sa-east-1b | app (NATS 2, TB 1, resolver b) | idem (rtb única `rtb-022392b605e241db7`) |
| PROD | `subnet-0bba584ac8c6caf94` (c) | 10.50.3.0/24 | sa-east-1c | app (NATS 3, TB 2) | idem |
| PROD | `monetarie-nat-public-prod` | 10.50.4.0/24 | sa-east-1a | pública (NAT GW + OpenVPN) | 0.0.0.0/0 -> IGW próprio + rotas TGW (`nat.tf:12-37,65-70`) |

Rotas RTM/RSFN nas route tables de app (mantidas pela RTM, mais específicas que a default): blocos `200.218.64.0/18`, `200.160.160.0/22`, `10.173.1.247/32`, `172.31.x.0/24` e, em prod, `10.151.11.0/24` (esta última criada pelo nosso estado, `nat.tf:75-80`) via `tgw-051f1a3c159dfb25b`. O estado HML é dono da rota estática DX `200.160.160.0/22` na route table do TGW compartilhado `tgw-rtb-00c87955e8b181f3f` (`tgw-routes.tf:5-10`); em prod `manage_tgw_routes=false` (regra #3: não escrever em recurso compartilhado).

### 5.2 Hosts internos `monetarie.internal` (zona única `Z07255101LW0TK32G8LU2`)

HML resolve com sufixo `-h`, PROD sem sufixo, na MESMA zona (`dns.tf:1-40`). Todos os hosts de serviço são alias A para o ALB interno do respectivo ambiente (`alb-internal.tf:210-222`). Porta de origem no ALB: sempre HTTP 80.

| Serviço | Porta do container | Hosts HML | Hosts PROD |
|---|---|---|---|
| core-api | 4000 | `core-api-h`, `coreapi-h` | `core-api`, `coreapi` |
| pix-api | 4003 (DICT 4001, SPI 4002 internos) | `pixapi-h`, `pix-api-h` | `pixapi`, `pix-api` |
| spb-api | 4010 | `spbapi-h`, `spb-api-h` | `spbapi`, `spb-api` |
| npc-api | 4020 | `npcapi-h`, `npc-api-h` | `npcapi`, `npc-api` |
| sta-api | 4000 | `staapi-h`, `sta-api-h` | `staapi`, `sta-api` |
| clst-api | 4004 | `clstapi-h`, `clst-api-h` | `clstapi`, `clst-api` |
| core-admin-ui | 8080 | `coreadmin-h` | `coreadmin` |
| core-banking-ui (IB) | 8080 | `ib-h`, `corebanking-h` | `ib`, `corebanking` |
| core-merchant-ui | 8080 | `merchant-h`, `coremerchant-h` | `merchant`, `coremerchant` |
| pix-admin-ui | 8080 | `pixadmin-h` | `pixadmin` |
| spb-admin-ui | 8080 | `spbadmin-h` | `spbadmin` |
| npc-admin-ui | 8080 | `npcadmin-h` | `npcadmin` |
| sta-admin-ui | 8080 | `staadmin-h` | `staadmin` |
| backoffice | 8080 | `backoffice-h` | `backoffice` |
| docs-portal | 8080 | `docs-h` | `docs` |
| NATS (registro A direto, não ALB) | 4222 | `nats-h` (1 IP) | `nats` (multi-A com os 3 nós) + `nats-1`, `nats-2`, `nats-3` (`messaging.tf:282-292`) |
| TigerBeetle (registro A direto) | 3001 | `tigerbeetle-h` | `tigerbeetle` (nó 0) + `tigerbeetle-0`, `tigerbeetle-1`, `tigerbeetle-2` (`messaging.tf:294-302`; clientes usam a lista ordenada `TIGERBEETLE_ADDRESSES`) |

Definição dos hosts/target groups em `alb-internal.tf:1-131`. Target groups: `mon-<svc>-h-45` em HML e `mon-<svc>-50` em prod (target_type `ip`, health check `/health`, matcher 200-399) (`alb-internal.tf:166-191`). ALB: `monetarie-internal-homolog-45` / `monetarie-internal-prod-50` (`alb-internal.tf:133-148`). Zona `priv.rtmcloud.net.br` (`Z01622251A8R9AC0HXS4K`, da nossa conta) associada às duas VPCs para resolver o HSM (`variables.tf:109-113`, `dns.tf:45-48`).

### 5.3 Portas

| Fluxo | Porta/protocolo | HML | PROD | Fonte |
|---|---|---|---|---|
| OpenVPN (time -> VPC) | UDP 1194 | EIP 54.94.247.111 | EIP 15.229.92.89 | `variables.tf:496-499`, `envs/prod.tfvars:99-102` |
| ALB interno | TCP 80 (HTTP-only) | sim | sim | `alb-internal.tf:150-164` |
| APIs (ALB -> tasks) | TCP 4000-4040 | sim | sim | `security-groups.tf:148-170` |
| UIs (ALB -> tasks) | TCP 8080 | sim | sim | `security-groups.tf:156-178` |
| Aurora (só do SG do ECS) | TCP 5432 | sim | sim | `security-groups.tf:181-187` |
| Redis (só do SG do ECS) | TCP 6379 | sim | sim | `security-groups.tf:189-195` |
| NATS client / monitor / cluster | TCP 4222 / 8222 / 6222 (self) | 4222/8222 | 4222/8222/6222 entre nós | `security-groups.tf:197-219` |
| TigerBeetle | TCP 3001 (do ECS e entre réplicas) | sim | sim | `security-groups.tf:221-235` |
| VPC endpoints | TCP 443 do CIDR da VPC | sim | sim | `security-groups.tf:238-244` |
| HSM RTM | TCP 443 (HTTPS) | monetarie-hsm-hml | monetarie-hsm-prd | `variables.tf:103-107`, `envs/prod.tfvars:87` |
| IBM MQ SPB01 | TCP | 172.31.2.50:1514 | 172.31.1.50:1414 | `variables.tf:121-125`, `envs/prod.tfvars:89` |
| IBM MQ MES01 | TCP | 172.31.2.50:12522 (DROP na RTM) | 172.31.1.50:12422 (CONNECT) | `variables.tf:127-131`, `envs/prod.tfvars:90` |
| RSFN DICT / DICT-NP | TCP | 16522 / 16532 | 16422 / 16432 | `variables.tf:353-363`, `envs/prod.tfvars:131-137` |
| RSFN ICOM / ICOM-SEC | TCP | 16522 / 17522 | 16422 / 17422 | idem |
| RSFN ARQ | TCP 1130 | sim | sim | idem |
| DNS RSFN (resolver -> IRS) | UDP/TCP 53 para os 6 IRS | sim | sim | `rsfn-resolver.tf:9-25` |

## 6. Caminhos externos (detalhe)

1. **RSFN direto (DICT/ICOM/ARQ)**: a cabine PIX fala mTLS ICP-Brasil (verify_peer, sem proxy/relay, decisão do dono) direto com os hosts `*.pi.rsfn.net.br`, resolvidos pela regra do Route 53 Resolver `rsfn.net.br -> 6 IRS oficiais 200.218.64.{6,38,70,134,166,198}` (`rsfn-resolver.tf:43-64`, `variables.tf:293-304`) e roteados pelo TGW/Direct Connect (rotas `200.218.64.0/18` e `200.160.160.0/22`). Em HML permanecem declarados os registros estáticos do relay Cecresa (172.16.70.51-55), histórico; em prod só `www.rsfn.net.br` estático (`envs/prod.tfvars:106-108`).
2. **HSM RTM (assinatura/decifragem)**: gateway KMIP REST em HTTPS 443, vHSM 60042; HML `monetarie-hsm-hml.priv.rtmcloud.net.br` (10.151.11.140/141), PROD `monetarie-hsm-prd.priv.rtmcloud.net.br` (10.151.11.138/139, rota `10.151.11.0/24 -> TGW` criada pelo nosso estado). `cloudhsm.priv.rtmcloud.net.br` (10.173.1.247) é o console de administração Ecos, não a API de assinatura. Credenciais e UIDs só em Secrets Manager `monetarie/{env}/hsm/*` (`kms-secrets.tf:47-51`, relatório Fase 3).
3. **IBM MQ RTM (SPB/STR)**: o `spb-api` não fala MQ direto; o sidecar `spb-mq-sidecar` (mesma task, HTTP `localhost:9080` -> JMS) conecta em `QM.46026562.01` (SPB01) e `QM.46026562.02` (MES01), canal `APP.SVRCONN`, usuário `spb_server` (`ecs.tf:467-491,147-204`). HML: 172.31.2.50, 1514 vivo e 12522 ainda DROP na RTM. PROD: 172.31.1.50, 1414 e 12422 com CONNECT provado em 2026-07-07 (auth de canal validada com o sidecar no deploy).
4. **OpenVPN (acesso do time)**: instância t4g.micro por ambiente, com BIND local encaminhando para o resolver da VPC (domínios `monetarie.internal`, `priv.rtmcloud.net.br` e `rsfn.net.br` empurrados aos clientes) e MASQUERADE dos clientes para os CIDRs gerenciados (VPC do app, `10.173.1.247/32`, `200.218.64.0/18`, `200.160.160.0/22`) (`locals.tf:31-45`, `scripts/openvpn-user-data.sh.tftpl:108-142`). Pool de clientes `10.250.0.0/22` (`variables.tf:513-522`).
5. **Egress internet**: HML sai pelo IGW com IP público por recurso; PROD sai pelo NAT Gateway (EIP 18.228.20.148) sem IP público nas tasks/EC2. Em ambos, as rotas RTM/RSFN/HSM são mais específicas e não passam pelo egress de internet.

## 7. Segurança

### 7.1 Security groups (padrão: datastores nunca aceitam CIDR, só o SG do ECS)

| SG | Ingress | Observação |
|---|---|---|
| `monetarie-alb-<env>` (público) | 80/443 de 0.0.0.0/0 | criado, mas a plataforma vive no ALB interno (`security-groups.tf:96-110`) |
| `monetarie-alb-internal-<env>` | 80 da VPC de app; em HML também da VPC RTM 192.168/16 | prod não aceita a RTM (`security-groups.tf:113-131`) |
| `monetarie-fargate-<env>` (ecs_tasks) | 4000-4040 e 8080 apenas dos dois ALBs | nenhum ingress de CIDR (`security-groups.tf:148-178`) |
| `monetarie-aurora-<env>` | 5432 só do SG ecs_tasks | `security-groups.tf:181-187` |
| `monetarie-redis-<env>` | 6379 só do SG ecs_tasks | `security-groups.tf:189-195` |
| `monetarie-nats-<env>` | 4222/8222 do ecs_tasks; 6222 self (cluster) | `security-groups.tf:197-219` |
| `monetarie-tigerbeetle-<env>` | 3001 do ecs_tasks e self (réplicas) | `security-groups.tf:221-235` |
| `monetarie-vpc-endpoints-<env>` | 443 do CIDR da VPC | `security-groups.tf:238-244` |
| `monetarie-openvpn-<env>` | UDP 1194 de 0.0.0.0/0 (default `openvpn_allowed_cidrs`) | pendência de hardening (`variables.tf:502-511`) |
| `monetarie-ecs-container-instance-<env>` | sem ingress declarado (egress all) | EC2 do core-api (`ecs-ec2-core.tf:10-21`) |
| `monetarie-rsfn-resolver-out-<env>` | n/a (egress 53 restrito aos 6 IRS) | `rsfn-resolver.tf:1-25` |
| SG default da VPC (só prod) | +443 do CIDR da VPC | para os endpoints SSM TEMP da RTM (`vpc-endpoints.tf:62-70`, `envs/prod.tfvars:72`) |

Todos os SGs têm egress liberado 0.0.0.0/0 (`security-groups.tf:88-93`), exceto o do resolver RSFN (egress 53 apenas para os IRS).

### 7.2 O que tem IP público e por quê

| Recurso | HML | PROD | Motivo |
|---|---|---|---|
| Tasks Fargate | IP público (`ecs_assign_public_ip=true`) | sem IP público | HML não tem NAT; a subnet roteia para o IGW e sem IP público não há saída (ex.: importar diretório de participantes do bcb.gov.br). Ingress permanece bloqueado pelo SG (`ecs.tf:584-594`) |
| core-api (EC2/awsvpc) | `assign_public_ip=false` no service | idem | tráfego via ENI da task; egress pela rota da subnet (`ecs.tf:628-632`) |
| NATS / TigerBeetle (EC2) | IP público (`runtime_ec2_public_ip=true`) | sem IP público | mesmo motivo de egress em HML; hardening pendente (`variables.tf:175-179`, `messaging.tf:80,146`) |
| OpenVPN | EIP (por design, é a porta de entrada) | EIP (por design) | `openvpn.tf:1-66` |
| NAT Gateway | não existe em HML | EIP 18.228.20.148 | egress de prod (`nat.tf:39-52`) |

### 7.3 Pendências de hardening conhecidas

1. **HML: tirar IP público de NATS e TigerBeetle** (e das tasks), o que exige criar NAT GW em HML (alternativa adiada por decisão registrada no `CLAUDE.md`).
2. **SG do OpenVPN aberto a 0.0.0.0/0 (UDP 1194) nos dois ambientes**: restringir a IPs administrativos quando definidos (`variables.tf:502-511`; pendência 6 do relatório da Fase 3).
3. **Redis sem encryption at-rest/in-transit** (aceito em homolog; em prod o t4g.micro sem TLS foi deliberado para o go-live, rever com tráfego real).
4. **ALB interno HTTP-only (porta 80, sem TLS interno)**, por design de custo (`dns.tf:1`); mitigado por ser alcançável apenas via VPN/VPC.
5. **MES01 12522 em HML segue DROP na RTM** (cobrar liberação; em prod 12422 conecta).
6. **Sidecar MQ de HML em tag mutável `homolog-latest`** (fixar por digest; prod já nasce por digest) (`variables.tf:145-149`).
7. **PROD: endpoints SSM `monbank-prod-*-TEMP` são da RTM**; se forem removidos, as EC2 perdem SSM (mitigação documentada: esvaziar `skip_interface_endpoints` e aplicar) (`envs/prod.tfvars:66-72`).
8. **UIDs de HSM injetados como env nas task-defs** (padrão herdado de HML): avaliar mover para secrets (pendência 5 do relatório da Fase 3).
9. **Drift conhecido no NATS de prod**: o Terraform declara root gp3 de 20GB (`messaging.tf:87-92`), mas os discos foram redimensionados ao vivo em 2026-07-09 (incidente de storage do JetStream; 100GB gp3 por nó, `max_storage` 75GB). Reconciliar no código antes de qualquer apply em prod.
10. **Drift conhecido em HML** (registrado no relatório da Fase 3): plan de HML acumula replace de nats/openvpn/tigerbeetle (AMI nova) e task-defs; NÃO aplicar em HML sem tratar.

## 8. Acessos operacionais

- **VPN**: cada ambiente tem seu OpenVPN (HML `54.94.247.111`, PROD `15.229.92.89`, ambos UDP 1194). Perfis `.ovpn` nominais (`Monetarie-HML-OpenVPN-<Nome>.ovpn` / `Monetarie-PROD-OpenVPN-<Nome>.ovpn`) ficam em `/opt/monetarie/openvpn/` na instância (`outputs.tf:103-110`); emissão de novos perfis é feita via SSM com o easy-rsa da própria instância, sem restart do serviço (procedimento registrado na memória operacional de 2026-07-09). Revogação exige `crl-verify`.
- **DNS via VPN**: o cliente recebe DNS do BIND da instância e os domínios `monetarie.internal`, `priv.rtmcloud.net.br` e `rsfn.net.br`; as rotas empurradas cobrem a VPC do app, o console do HSM (`10.173.1.247/32`) e os blocos RSFN/BCB (`200.218.64.0/18`, `200.160.160.0/22`).
- **Acesso às telas/APIs**: sempre pelos hosts `*.monetarie.internal` da tabela 5.2, HTTP 80 no ALB interno (HML com `-h`, prod sem sufixo). Regra #4/#5 do `CLAUDE.md`: homolog usa só hosts `-h`; não usar `.local`. Em HML também é possível chegar ao ALB a partir da VPC RTM (bastion); em prod, só pela VPN.
- **EC2 (NATS, TigerBeetle, OpenVPN, container instance do core)**: acesso por SSM Session Manager (role `AmazonSSMManagedInstanceCore` em `messaging.tf:61-64`); em prod os endpoints SSM em uso são os TEMP da RTM.
- **AWS CLI**: exclusivamente com o profile isolado (o `default` do Mac resolve OUTRA conta). Wrapper canônico:

```bash
awsmon() {
  env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
    AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 aws "$@"
}
```

- **Terraform**: HML é o estado default (`terraform init` com `backend.tf`); PROD exige `terraform init -reconfigure -backend-config=backend.prod.hcl` e `-var-file=envs/prod.tfvars`. Segredos nunca em tfvars: UIDs/senhas entram por `TF_VAR_*` no momento do apply e vivem no Secrets Manager `monetarie/{env}/*` com CMK por domínio (`kms-secrets.tf`).
- **Logs**: CloudWatch `/ecs/monetarie/homolog/<svc>` e `/ecs/monetarie/prod/<svc>` (`ecs.tf:355-360`).

## 9. Evidências principais (arquivo:linha)

| Tema | Evidência |
|---|---|
| Parametrização HML vs PROD | `infra/aws/greenfield/variables.tf:1-533`, `infra/aws/greenfield/envs/prod.tfvars:1-155` |
| VPCs adotadas por data source | `infra/aws/greenfield/data.tf:6-18`, `infra/aws/greenfield/vpc.tf:1-6` |
| ALB interno, TGs, hosts | `infra/aws/greenfield/alb-internal.tf:1-223` |
| ECS (Fargate + core-api EC2, sidecar MQ, assign_public_ip) | `infra/aws/greenfield/ecs.tf:467-648`, `infra/aws/greenfield/ecs-ec2-core.tf:23-114` |
| Aurora / Redis | `infra/aws/greenfield/aurora.tf:26-70`, `infra/aws/greenfield/elasticache.tf:8-19` |
| NATS / TigerBeetle (nós, IPs .10/.20, EBS, DNS) | `infra/aws/greenfield/messaging.tf:7-321` |
| NAT GW + subnet pública + rotas TGW de prod | `infra/aws/greenfield/nat.tf:6-80` |
| OpenVPN (instância, EIP, user-data) | `infra/aws/greenfield/openvpn.tf:1-67`, `infra/aws/greenfield/scripts/openvpn-user-data.sh.tftpl` |
| Zonas DNS privadas | `infra/aws/greenfield/dns.tf:1-54` |
| Resolver RSFN | `infra/aws/greenfield/rsfn-resolver.tf:1-65` |
| Security groups | `infra/aws/greenfield/security-groups.tf:1-245` |
| IGW/VPC endpoints/SG default prod | `infra/aws/greenfield/vpc-endpoints.tf:1-88` |
| Rota DX no TGW compartilhado (só HML) | `infra/aws/greenfield/tgw-routes.tf:1-16` |
| KMS/Secrets (contêineres, sem valores) | `infra/aws/greenfield/kms-secrets.tf:1-62` |
| ECR compartilhado (HML dono, prod adota) | `infra/aws/greenfield/ecr.tf:1-33` |
| Backends de estado | `infra/aws/greenfield/backend.tf:3-12`, `infra/aws/greenfield/backend.prod.hcl` |
| Validação viva de PROD (EIPs, matriz de acessos, portas RSFN) | `docs/reports/2026-07-07-fase3-infra-prod-status.md` |
