# Dossiê técnico — degradação do HSM RTM (EcosCryptoServer) com 504 "HttpClient.Timeout of 3 seconds"

Data: 2026-07-23 (noite). Ambientes: Monetarie SCD (ISPB 46026562), vHSM 60042.
Endpoints: HML `https://monetarie-hsm-hml.priv.rtmcloud.net.br`, PRD
`https://monetarie-hsm-prd.priv.rtmcloud.net.br`.

## Sumário executivo

O gateway HTTP do HSM RTM (EcosCryptoServer) está **cancelando as requisições ao
vHSM backend com HTTP 504 após 3 segundos**, em ambos os ambientes, para uma
fração grande das chamadas (HML ~50-67%, PRD ~50-67% no momento da medição). O
corpo da resposta 504 é explícito e idêntico nos dois ambientes:

```
{"returnValue":"The request was canceled due to the configured HttpClient.Timeout of 3 seconds elapsing."}
```

Essa mensagem é do próprio gateway (padrão de `HttpClient.Timeout` do .NET): o
gateway EcosCryptoServer tem um timeout INTERNO de 3 segundos entre ele e o vHSM,
e o vHSM está demorando mais que 3s para responder. **O timeout de 3s é
configuração do lado da RTM** — o timeout do cliente da Monetarie é 8 segundos,
ou seja, nós esperaríamos; quem corta em 3s é o gateway deles.

Impacto na Monetarie: falha intermitente de assinatura (mensagens de saída ao
BACEN) e de decifra (mensagens de entrada do BACEN), causando, entre outros, o
encerramento indevido de um GEN0001 por `StaleOperationSweeper` (a resposta
GEN0001R1 chegou pelo MQ mas a decifra falhou por 504 do HSM).

## Evidência empírica (medição controlada 2026-07-23)

Probe de caracterização por endpoint, chamadas SEQUENCIAIS espaçadas 700ms
(não concorrentes), timeout do cliente = 8000ms, medindo status HTTP + latência
+ corpo.

### HML (6 amostras por endpoint)

| Endpoint | OK | Erro | Latências OK (ms) | Latências erro (ms) | Status erro |
|---|---|---|---|---|---|
| `GET /v1/health` | 6/6 | 0 | 37, 3043, 3045, 3044, 22, 22 | — | — |
| `POST get-session-credential` | 3/6 | 3 | 240, 251, 239 | 3007, 3010, 3021 | 504 |
| `POST sign-rsa` | 2/6 | 4 | 64, 27 | 3007, 3018, 3026, 3019 | 504 |

### PRD (3 amostras por endpoint)

| Endpoint | OK | Erro | Latências OK (ms) | Latências erro (ms) | Status erro |
|---|---|---|---|---|---|
| `GET /v1/health` | 3/3 | 0 | 3182, 3057, 3060 | — | — |
| `POST get-session-credential` | 2/3 | 1 | 745, 652 | 3005 | 504 |
| `POST sign-rsa` | 1/3 | 2 | 33 | 3004, 3024 | 504 |

Corpo do 504 (idêntico HML e PRD, todas as ocorrências):
`{"returnValue":"The request was canceled due to the configured HttpClient.Timeout of 3 seconds elapsing."}`

### Leitura da evidência

1. **O corte é do gateway deles, em 3s.** Todas as falhas ocorrem em ~3000ms
   (3004-3026ms) e o corpo cita "the configured HttpClient.Timeout of 3 seconds".
   O timeout do cliente Monetarie é 8000ms — não é o nosso cliente que desiste.
2. **Não é carga que a Monetarie gera.** O `GET /v1/health` — o endpoint mais
   barato, SEM sessão KMIP, SEM operação criptográfica, SEM vHSM — respondeu 200
   mas levou ~3s em várias amostras (HML 3 de 6; PRD 3 de 3). Um health lento
   indica lentidão do gateway/backend deles independente do nosso volume cripto.
3. **A degradação está no caminho gateway->vHSM.** As operações que dependem do
   vHSM (get-session, sign, decrypt) falham com o 504 de 3s; o padrão bimodal
   (respostas em dezenas de ms OU corte em 3s) é típico de backend saturado/lento
   atrás de um proxy com timeout fixo.

## Volume de requests da Monetarie ao HSM (para descartar abuso do nosso lado)

Inventário completo dos requests que a aplicação Monetarie emite ao HSM:

| Origem | Endpoint | Cadência | Observação |
|---|---|---|---|
| SPB `MessagePacker.pack` | `sign-rsa` (via sessão) | 1 por mensagem BACEN de SAÍDA | dirigido por tráfego; não periódico |
| SPB `MessagePacker.unpack` | `decrypt-rsa` (via sessão) | 1 por mensagem BACEN de ENTRADA | dirigido por tráfego; não periódico |
| SPB `OurCertStore.verify_hsm` | `sign-rsa` | manual (tela admin) | NÃO periódico |
| PIX `XmlSigner` (pacs.008 etc.) | `sign-rsa` (via sessão) | 1 por mensagem de saída | dirigido por tráfego |
| PIX `HsmKeepWarm` | `GET /v1/health` | 1 a cada 20s | mantém o TLS vivo; SEM sessão/cripto/vHSM |
| Ambos `RtmHsm.with_session` | `get-session-credential` | ~1 a cada 5 min (cache ETS de sessão) | reusa a sessão; não por operação |

Não há nenhum worker que faça `sign`/`decrypt`/`get-session` em laço. A única
chamada periódica é o `GET /v1/health` do PIX a cada 20s (3/min), que é o
endpoint mais leve e não toca o vHSM. A sessão KMIP é cacheada por 5 minutos, de
modo que N operações consomem 1 `get-session`, não N. Em repouso (sem tráfego
BACEN) o SPB não emite NENHUMA chamada ao vHSM.

## Impacto operacional comprovado

- 2026-07-23 23:23:31Z: GEN0001 enviado (operação `6f6f0a47`).
- 2026-07-23 23:24:52Z: `StaleOperationSweeper` (threshold 60s) marcou a operação
  como *error* — a GEN0001R1 chegou pelo MQ mas o `MessagePacker.unpack`
  (decrypt-rsa no HSM) recebeu 500/504 e não processou a tempo.
- 2026-07-23 23:30:44Z: `MessagePacker.unpack: {:http_status, 500}` +
  `[MQBridge] Failed SPB01 message (3285ms)`; a reentrega da MQ processou o
  GEN0001R1 às 23:30:46 (98ms) — depois do sweeper já ter marcado error.

## Pedido à RTM

1. Elevar (ou tornar configurável para a Monetarie) o `HttpClient.Timeout` de 3s
   do gateway EcosCryptoServer entre o gateway e o vHSM 60042, OU sanar a
   lentidão do vHSM backend que faz as respostas ultrapassarem 3s.
2. Investigar por que até o `GET /v1/health` leva ~3s (gateway saturado?).
3. Informar limites de concorrência/rate suportados pelo vHSM 60042 para
   dimensionarmos o pool do lado da Monetarie sem induzir o timeout.

## Mitigação do lado da Monetarie (em curso, não substitui o item acima)

Retry resiliente com backoff curto + jitter no cliente HSM (`RtmHsm.sign` /
`decrypt_private`) para status transitórios (500/502/503/504/timeout),
preservando idempotência (sign/decrypt são determinísticos). Reduz o impacto do
504 de 3s, mas NÃO resolve a causa raiz: com o vHSM cortando em 3s a 50-67% das
chamadas, mesmo o retry paga latência acumulada — incompatível com o ANS de
liquidação < 500ms.
