# Design: certificados PIX (PIA/PIC) no AWS Secrets Manager

Decisão do dono (2026-06-23): a cabine PIX usa os certificados ICP-Brasil PIA (assinatura) e PIC (conexão/mTLS) guardados no AWS Secrets Manager, com o HSM da RTM em stand-by, para o cliente subir os certificados dele e acelerar a homologação contra o BACEN. Esta é a Opção B (Secrets Manager de verdade), escolhida pelo dono.

## Estado atual (provado em código)

- Upload existe e funciona: `POST /api/v1/admin/certificates` e `/upload-pfx` (aceita PIA/PIC/PFX), autenticado (RBAC SYSTEM:create).
- Armazenamento hoje: Postgres `mon_pix`, schema `monetarie_spi_msg`, tabelas `crypto_keys` + `crypto_private_keys`, chave privada cifrada AES-256-GCM (`Shared.Crypto.CertificateManager.import_certificate`).
- Consumo PIA (assinatura): completo via `CertificatePool.get_signing_key` -> `get_active_signing_cert` (CPIA). Fallback HSM-vs-local correto: com `RTM_HSM_ENABLED=false`, assina local com a chave da PIA. OK.
- Consumo PIC (mTLS): DESCONECTADO. `Shared.Bacen.TLS.build` lê cert/chave de arquivo (`BACEN_CLIENT_CERT_PATH`/`KEY_PATH`); a CPIC do banco (`get_active_connection_cert`) não tem consumidor.
- Não há SDK AWS no projeto. Deps disponíveis: `finch`, `jason` (shared); `req` (settlement). IAM: nem a task role nem a execution role têm `PutSecretValue`/`CreateSecret`.

## Objetivo

1. No upload, gravar PIA e PIC (cert + chave) no Secrets Manager, além do banco.
2. No boot e em refresh, carregar do Secrets Manager para o store em uso (DB/pool), de forma idempotente.
3. Conectar a PIC ao mTLS (consertar o gap) usando a CPIC ativa.
4. Manter o HSM em stand-by; assinatura local com a PIA.
5. Ajustar o IAM para permitir a escrita/leitura dos secrets de certificado.

## Convenção de nome do secret

`monetarie/homolog/pix/cert/{ispb}/{cert_type}` com `cert_type` em `{CPIA, CPIC, CERTQRC}`. Valor = JSON:

```json
{ "cert_pem": "...", "key_pem": "...", "kid": "...", "thumbprint": "...", "valid_until": "...", "uploaded_at": "..." }
```

A `key_pem` fica em texto dentro do secret; o Secrets Manager cifra em repouso com KMS. O secret é a fonte segura. (Opcional futuro: CMK por domínio em vez da chave gerenciada.)

## Módulos

1. **Novo `Shared.Aws.SecretsManager`** (apps/shared): cliente fino sobre `ExAws.SecretsManager` para `get_secret_value/1`, `put_secret_value/2` (upsert: tenta put; se não existe, create), `list_secrets/1` por prefixo. Credenciais resolvidas pela task role do ECS (provider de credenciais do container, automático no ExAws). Deps a adicionar em `apps/shared/mix.exs`: `{:ex_aws, "~> 2.5"}`, `{:ex_aws_secretsmanager, "~> 2.0"}`, `{:hackney, "~> 1.20"}`. Config `:ex_aws` região sa-east-1, provider de credenciais padrão (task role).
2. **Novo `Shared.Crypto.CertVault`**: `put(ispb, cert_type, cert_pem, key_pem, meta)` monta o JSON e grava no secret; `get(ispb, cert_type)` lê e devolve `{cert_pem, key_pem, meta}`; `list(ispb)`; com feature flag `CERT_VAULT_ENABLED` (default true em homolog) para permitir desligar em dev/local.
3. **Modificar `CertificateManager.import_certificate`**: após o insert no banco (ou dentro da mesma operação), chamar `CertVault.put/5`. Em caso de erro do Secrets Manager: logar e retornar erro (o dono quer no Secrets Manager). Idempotente em re-upload (put sobrescreve a versão).
4. **Novo `Shared.Crypto.CertVaultLoader`** (GenServer no supervisor de `Shared.Application`, ao lado do `CertificatePool`): no boot, lista `monetarie/homolog/pix/cert/{ispb_proprio}/*`, e para cada certificado chama `CertificateManager.import_certificate(..., activate: true)` se ainda não estiver no banco (idempotente). Assim a cabine recém-subida já tem PIA/PIC sem depender de re-upload.
5. **Consertar PIC -> mTLS**: em `Shared.Bacen.Client`/`Shared.Bacen.TLS`, quando houver CPIC ativa, montar `:transport_opts` com `:cert` (DER) + `:key` em memória a partir de `get_active_connection_cert` + `get_private_key`, em vez de `:certfile`/`:keyfile`. Manter o caminho por arquivo como fallback. A CA continua o bundle ICP-Brasil empacotado.

## IAM (Terraform infra/aws/greenfield)

- Adicionar à role de task do pix (`monetarie-ecs-task-homolog`): `secretsmanager:CreateSecret`, `PutSecretValue`, `GetSecretValue`, `DescribeSecret`, `ListSecrets`, `TagResource` no recurso `arn:aws:secretsmanager:sa-east-1:990933657879:secret:monetarie/homolog/pix/cert/*`. O upload roda no container (task role), então é a task role que precisa de escrita.
- KMS: certificados sob a chave gerenciada do Secrets Manager (ou CMK do domínio pix, se preferir; então adicionar `kms:GenerateDataKey`/`Decrypt` na CMK).
- Não é necessário injetar como env (`secrets:` da task def): o app lê via SDK, então a allow-list da execution role não precisa mudar.

## Testes (TDD)

- `Shared.Aws.SecretsManager`: teste com `ExAws` em modo stub/mock (config `:ex_aws, :http_client` apontando para um stub) validando o request (action, body, secret-id) e o parse da resposta.
- `Shared.Crypto.CertVault`: round-trip put/get (com o cliente stubado) e formação do nome do secret.
- `CertificateManager.import_certificate`: com `CertVault` stubado, confirmar que grava no banco E chama o vault; e o caminho de erro.
- mTLS: teste de `Shared.Bacen.TLS`/Client montando `:transport_opts` a partir de uma CPIC ativa no banco (in-memory `:cert`/`:key`).
- Rodar `mix test` no umbrella (apps/shared + settlement) antes do deploy.

## Deploy e validação

1. `mix deps.get` + `mix test` verde no umbrella.
2. Build `docker buildx arm64` do `pix-api` -> ECR `monetarie/pix-api:homolog-latest` -> `ecs update-service --force-new-deployment`. (Conferir por digest.)
3. Aplicar o Terraform do IAM (task role).
4. Validar ao vivo: subir um certificado de teste (PIA e PIC) pelo endpoint -> confirmar o secret em `monetarie/homolog/pix/cert/46026562/CPIA` e `/CPIC` -> confirmar que a cabine carrega (assinatura usa a PIA; mTLS monta a PIC). Capturar evidência.

## Fora de escopo / depois

- Ligar `BACEN_ENABLED=true` (sair do simulador) só quando o cliente subir os certificados reais e quisermos bater no BACEN de verdade.
- CMK por domínio (hoje a chave gerenciada do Secrets Manager basta para homolog).
