Certificação de provedores

Para: Dev · Adm — Conferido em 2026-10-31.

Nenhum provedor entra em hml ou produção sem passar pelo kit de conformidade (dracma_spp_conformance). Esta página mostra o que ele prova, como montar o fake do parceiro, como rodar e o que precisa estar marcado no checklist antes de pedir o enable.

O que é

A suíte fala o protocolo SPP v1 pelo loopback, como se fosse o executor (assina HMAC v2, envia a credencial no corpo), contra o seu adaptador, que por sua vez conversa com um parceiro falso (fake-PSP) controlado pela suíte. Ela prova comportamento, não implementação: serve para qualquer linguagem.

Regras fixas:

  • Sem pular teste. Não existe skip. Se a capacidade é false no descriptor, o caso vira "a rota responde 501 unsupported".
  • Sem efeito externo real. O adaptador roda em modo sandbox, apontando só para o fake. Nada sai para o parceiro de verdade.
  • Mesma semântica de hoje. Cada caso preserva uma regra que o executor já consome (breaker, failover, reconciliador). Um adaptador que passa na suíte pode substituir os atuais sem mudar comportamento.

Quando usar

  • Ao terminar um adaptador novo (antes do primeiro register em hml).
  • A cada mudança do descriptor ou de comportamento do adaptador (recertificação).
  • No CI do repositório do provedor, a cada PR.

Como funciona

flowchart LR R[runner da suíte] -->|SPP: HMAC v2 + credential| A[seu adaptador] A -->|API do parceiro| F[fake-PSP] R -->|controle de cenário| F R --> L[relatorio.json]
Componente Quem escreve O que faz
runner kit Lê o descriptor, escolhe os casos aplicáveis pelas capacidades, executa, grava o relatório com o descriptor_sha256.
Cliente SPP kit Age como o executor: assina, gera Spp-Idempotency-Key, Spp-Timeout-Ms e traceparent; relógio e nonce injetáveis.
Fake-PSP você Servidor HTTP que fala o formato REAL do parceiro, dirigido por cenário. Registra tudo que recebe.
Perfil (profile.yaml) você Diz, por operação SPP, qual requisição o parceiro deve receber e qual resposta devolver em cada cenário.

Cenários canônicos do fake

O perfil precisa mapear estes cenários para respostas reais do parceiro (os que não se aplicam ao parceiro são declarados n/a com justificativa, nunca omitidos):

Cenário Significado
ok, ok_replay Sucesso; repetição com o mesmo identificador (o parceiro deduplica).
slow, drop_after_send Responde depois do orçamento; fecha a conexão depois de receber o corpo.
http_500, http_502, http_503 Falha de servidor do parceiro.
http_400, http_401, http_403, http_404, http_409, http_429 Recusa de negócio do parceiro.
garbage_2xx, empty_2xx, huge_body 200 com corpo irreconhecível, vazio ou gigante.
unknown_status Status de cobrança ou saque que o adaptador não conhece.
redirect_other_host 302 para um host fora do egress_hosts.

Exemplo de perfil

provider: exemplo
operations:
  create_charge:
    upstream: { method: POST, path: /v1/pix/charges, must_contain: [identifier, amount] }
    scenarios:
      ok:        { status: 201, body: { id: "ch_1", brcode: "000201...", expires_at: "2026-11-01T12:00:00Z" } }
      http_400:  { status: 400, body: { error: "invalid_amount" } }
      http_503:  { status: 503, body: "" }
      garbage_2xx: { status: 200, body: "<html>ok</html>" }
  get_payout:
    upstream: { method: GET, path: /v1/pix/transfers, query: [clientIdentifier] }
    scenarios:
      ok:        { status: 200, body: { status: "PAID", id: "tr_1", e2e: "E2E123", amount: "10.50" } }
      http_404:  { status: 404, body: { error: "not_found" } }

Rodar

spp-conformance run \
  --url http://127.0.0.1:7101/spp/v1 \
  --hmac-secret-env INTERNAL_HMAC_EXEMPLO_EXECUTOR \
  --fake-profile conformance/profile.yaml \
  --out relatorio.json

Código de saída diferente de zero se qualquer caso obrigatório falhar. O relatório traz descriptor_sha256, versão da suíte, casos com evidência e o resumo passed/total. Depois, o ops grava a certificação no registro:

dracma_ops provider certify exemplo --report relatorio.json

O que a suíte cobre

Família Casos Obrigatória quando
Descriptor e metadados C-DESC-01 a C-DESC-12 sempre
Autenticação e transporte C-AUTH-01 a C-AUTH-15 (inclui a matriz de acesso: uma linha por rota servida) sempre
Cobrança C-CHG-01 a C-CHG-17 cash_in
Consulta de cobrança C-GET-01 a C-GET-08 charge_lookup
Resolução de referência C-REF-01 a C-REF-04 charge_ref_resolution
Saque C-PAY-01 a C-PAY-15 cash_out
Consulta de saque C-PGET-01 a C-PGET-10 cash_out
Callbacks C-CB-01 a C-CB-16 callbacks
DICT, saldo, credencial C-KEY-*, C-BAL-*, C-CRED-* key_lookup, balance, credential_check
Saúde C-HEALTH-01 a C-HEALTH-05 sempre
Guarda de ambiente C-ENV-01 a C-ENV-07 sempre
Mapeamento de erros matriz por operação (abaixo) sempre, nas operações declaradas
Observabilidade C-OBS-01 a C-OBS-04 sempre (C-OBS-04 é recomendado)
Segurança do processo C-SEC-01 a C-SEC-07 sempre
Cripto C-CRY-01 a C-CRY-09 método crypto
Caos C-CHAOS-01 a C-CHAOS-13 sempre (C-CHAOS-13 só cripto)

Matriz de erros (a mais importante)

Para toda operação de rede declarada, a suíte injeta cada cenário e confere a resposta exata. É esta tabela que garante que o breaker e o failover do executor continuam corretos:

Cenário do fake HTTP SPP code effect Vira no executor Retry interno?
slow, drop_after_send 504 upstream_timeout unknown Timeout não
http_500/502/503 502 ou 503 upstream_unavailable unknown Unavailable(status) não
http_400/401/403/404/409/429 422 upstream_rejected none Rejected(status) não
garbage_2xx, empty_2xx, huge_body 502 unrecognized_response unknown Unrecognized não
redirect_other_host 502 ou 422 upstream_unavailable ou misconfigured unknown ou none — não segue

Em consultas, o 404 do recurso segue a regra da operação: saque desconhecido é resposta not_found (não erro), cobrança sem registro volta pending ou unrecognized, referência de outro sistema volta deposit_id: null, chave DICT inexistente é key_not_found.

Caos

Injeção O que a suíte exige
Rajada de timeouts Todas as respostas dentro do orçamento, memória estável, health vivo.
5xx intermitente Cada resposta reflete exatamente o que o fake devolveu; replay continua válido.
Parceiro some durante um saque unknown; ao voltar, a consulta pela mesma chave devolve o estado real; nenhum segundo envio.
Callbacks malformados (fuzz de 1000 corpos) Nunca 5xx nem queda; sempre callback_unauthenticated ou invalid_request; p99 de 200 ms.
Replay de callback e de chamada SPP Idempotente / replayed_nonce; sem crescimento de memória.
Corpo gigante ou lento Corta por tempo e tamanho sem travar chamadas legítimas.
Reinício com kill -9 em carga Volta em 10 s sem dupla execução.
Credencial rotacionada no meio da rajada Cada chamada usa a credencial do próprio corpo.

Suíte do executor

Além da suíte do autor, o executor roda X-01 a X-10 em hml com o provedor registrado: breaker por provedor, failover de depósito, saque que nunca troca de provedor, drenagem, unplug com trabalho em voo, callbacks (401 uniforme e mesma latência para conexão desconhecida), guarda de ambiente, teste diferencial contra o adaptador em-processo, mudança de descriptor e a prova de que o núcleo não tem lista de provedores.

Checklist de certificação

Marque tudo antes de pedir enable em hml ou prd.

Contrato

  • [ ] GET /descriptor válido; name imutável; egress_hosts completo e mínimo.
  • [ ] Toda capacidade true implementada; toda false responde 501 unsupported.
  • [ ] Segredos do credential_schema com x-secret; rótulos e ajuda em português.
  • [ ] Rotas servidas iguais ao OpenAPI do SPP (diff vazio).

Comportamento

  • [ ] Suíte 100% nos casos obrigatórios, relatório anexado, nenhum skip.
  • [ ] Caos 100%: sem queda, vazamento nem dupla execução.
  • [ ] Idempotência provada para cobrança e saque.
  • [ ] Matriz de erros inteira verde; nenhum erro ambíguo virou definitivo.
  • [ ] Callback sobre os bytes crus, comparação em tempo constante, isca, fuzz.

Segurança e operação

  • [ ] Usuário Linux próprio, unit hardened, container não-root somente leitura, egress só do descriptor, bind em loopback.
  • [ ] Nenhum segredo de longa duração; logs sem credencial nem dado pessoal.
  • [ ] SBOM e scan sem vulnerabilidade crítica ou alta aberta.
  • [ ] Matriz de acesso no CI do provedor e pentest de entrada limpo.
  • [ ] Guarda de ambiente provada; nenhum efeito externo real fora de produção.

Observabilidade e documentação

  • [ ] Logs JSON com trace_id; métricas e traces propagados; dashboard e alertas como código.
  • [ ] README do provedor com parceiro, credenciais, limites, particularidades e runbook de falha do parceiro.

Integração

  • [ ] Suíte do executor (X-01 a X-10) verde em hml.
  • [ ] Certificação gravada para o descriptor_sha256 atual.
  • [ ] Revisão de segurança por quem não escreveu o adaptador.

Aprovação, validade e recertificação

  • Passa com 100% dos casos obrigatórios aplicáveis, zero skip. Casos recomendados aparecem no relatório e não bloqueiam.
  • Reprova com qualquer falha. A suíte nunca é editada para passar: corrige-se o adaptador. Se o contrato é que está errado, abre-se emenda ao protocolo.
  • Caso intermitente reprova e abre defeito; "repetir até passar" não vale.
  • A certificação vale para o descriptor_sha256 e a versão da suíte certificados. Mudou qualquer campo do descriptor, ou o comportamento do adaptador: recertifica.
  • Suíte nova de versão menor: provedores já habilitados têm 30 dias para recertificar e não são desabilitados.
  • Se o parceiro mudou a API (sinal: unrecognized_response em 1% ou mais das chamadas), recertifica depois do ajuste.
  • A certificação não substitui o monitoramento: breaker e alertas continuam valendo em produção.

Erros comuns

Sintoma Causa provável
C-CHG-02 falha O adaptador cria uma segunda cobrança no parceiro: repasse a chave como identificador do parceiro ou grave a chave localmente.
C-PAY-04 falha com 2 chamadas no fake O adaptador reenvia o saque sozinho depois de timeout. Remova o retry: o executor decide.
C-CB-07 falha O adaptador reserializa o JSON antes de conferir a assinatura. Use os bytes de body_base64.
C-BAL-03 falha Saldo desconhecido virou zero. Responda unrecognized_response.
C-SEC-01 falha A credencial foi parar em log, cache em disco ou resposta de erro.
C-AUTH-11 falha Há rota servida que não está no OpenAPI, ou rota sem checagem de chamador.

Próximos passos