Go-live do operador — checklist de produção¶
Você só recebe key_live_ depois de cumprir esta lista na sua operação de sandbox. Cada item tem uma
prova: algo que você mostra (saída de teste, print de painel, log, dashboard), não uma promessa.
Um item sem prova conta como não feito.
Copie a lista para o seu tracker, preencha a coluna de prova e anexe ao registro de go-live (onboarding, passo 9 — README.md).
1. Conformidade¶
- [ ] Suíte de conformidade verde contra a sua operação de sandbox, rodada com a URL de webhook real do
seu conector (sandbox.md). Prova: saída do
go test … -vcom todos os casosPASSe a data. - [ ] Seus clientes reproduzem os vetores de assinatura byte a byte (as três chamadas, os dois webhooks válidos e a recusa do negativo) no seu CI. Prova: teste no seu repositório, como os de exemplos/.
- [ ]
GET /v1/pingcom a credencial de sandbox devolveenvironment: "sandbox"e ooperation_idesperado.
2. Chamadas¶
- [ ] Nonce por CSPRNG, 32 hex minúsculos, novo a cada requisição (inclusive em retry).
- [ ] Timestamp em segundos; host com NTP e alerta de desvio > 5 s comparando com
server_timedoGET /v1/ping. - [ ] Timeout de cliente de 10 s.
- [ ] Todo
POSTcomIdempotency-Key; em depósito/saque,Idempotency-Key = external_id, gravados no seu banco antes da chamada (outbox). - [ ] Regra de ouro implementada: 4xx não repete; 5xx/429/rede repete com a mesma chave;
codedesconhecido tratado pela classe HTTP (erros-e-idempotencia.md). Prova: caso de teste comPOST /sandbox/outage {"down": true}→ 503 → retomada com a mesma chave sem duplicar. - [ ]
trace_id/Dracma-Trace-Idregistrado em todo log de chamada ao Dracma.
3. Webhooks¶
- [ ] Verificação de assinatura sobre o corpo cru, janela de 300 s,
Dracma-Timestamp=t=, aceita qualquerv1com qualquer segredo ativo (lista para rotação), comparação em tempo constante. - [ ]
Dracma-Event-Id=iddo corpo, senão 400. - [ ] Dedup por
Dracma-Event-Idcom índice único, retenção ≥ 7 dias; duplicata → 200 sem efeito. Prova:POST /sandbox/webhooks/redelivercom um evento já processado → 200, saldo inalterado. - [ ] Fetch-back obrigatório antes de mover dinheiro: o crédito sai do
GET /deposits/{id}, nunca do corpo do webhook. Prova: um webhookdeposit.paidforjado com assinatura válida para um depósito que estápendingna API não credita. - [ ] No fetch-back, confere
external_id(é seu),amount/currency(idênticos ao registrado) eplayer_ref(idêntico). Divergência → não credita, marca para revisão, alerta. - [ ] Crédito/débito idempotente por
external_id(um depósito credita uma vez, mesmo com dois eventos diferentes para o mesmo objeto). - [ ] Ordem não garantida:
version≤ já aplicado é ignorado (com 200). - [ ] Leitor tolerante: tipo de evento,
status,methodou campo desconhecido → 200, grava, não move dinheiro, confere depois. - [ ] Responde em ≤ 10 s; trabalho pesado vai para fila local.
- [ ] Rota de webhook sem autenticação de usuário, mas com a allowlist de IP de saída do Dracma aplicada no proxy como defesa extra (não substitui a assinatura).
4. Depósitos¶
- [ ] Só
paidcredita, pelo valor registrado na criação (depositos.md). - [ ]
under_review,pending,createde qualquer estado desconhecido não creditam. - [ ]
refunded/chargebackdepois depaid: política definida e escrita (recomendação: não mover automaticamente;needs_decision+ alerta + fila para uma pessoa decidir). - [ ] Pagamento após expirar: não credita; revisão.
- [ ]
player.external_refopaco e imutável (nunca e-mail/telefone); documento do jogador consistente entre depósito e saque. - [ ] Exigências por operação lidas de
GET /v1/currencies(method_details[].deposit_requirements) no boot e periodicamente; os campos exigidos (ex.:player.nameeplayer.emailcom Mercado Pago) vão preenchidos a partir do cadastro do jogador. Prova: depósito sem o campo exigido →400comreason: required_by_operationtratado como recusa (sem retry,external_idnovo depois da correção). - [ ] Fora de produção, e-mails de jogador só de domínio reservado (
.test/.invalid/.example); o sandbox recusa outros comreserved_domain_required. - [ ] Mostra ao jogador
instructions.pix.expires_atdevolvido (o PSP pode ajustar o prazo).
5. Saques¶
- [ ] Reserva (débito) do saldo do jogador ANTES de
POST /withdrawals, na mesma transação que grava oexternal_id(saques.md). - [ ] Devolve a reserva só em
rejected,failed,cancelled(confirmados por fetch-back) ou em 4xx conclusivo na criação. Nunca em timeout/5xx sem resposta conclusiva. - [ ]
paidfinaliza e guardapsp_reference(E2E id do PIX). - [ ]
player.ip= IP do jogador em todo saque (sem ele o saque nunca é automático:OWNERSHIP_UNVERIFIED). Prova: no sandbox, saque automático dentro de X× complayer.ip→approved. - [ ]
returneddepois depaid: política definida (recomendação: não mover;needs_decision+ alerta). - [ ]
review_requested: truequando a sua pré-checagem desconfiar (você só pode tornar a decisão mais restritiva). - [ ]
decision.reasonsexibido para o seu time de suporte/risco; nada de motivo de bloqueio exibido ao jogador. - [ ] Prova: no sandbox, um saque acima de X× vai para
under_reviewcomAUTO_MULTIPLIER_EXCEEDED, ereject/faildevolvem a reserva exatamente uma vez.
6. Recuperação e reconciliação¶
- [ ] Job de
GET /events?after=<último evt>a cada 5 min, com cursor persistido, passando pelo mesmo dedup + fetch-back do webhook (webhooks.md). - [ ] Reconciliação diária por moeda (
GET /reconciliation) com verificação do digest e da assinatura (reconciliacao.md). - [ ] Alerta de divergência: todo
paiddo Dracma tem crédito/débito seu e vice-versa; qualquer diferença abre incidente. Prova: reconciliação de um dia de sandbox comparada nos dois lados, com zero divergência (onboarding, passo 7). - [ ] Alerta para: webhook com assinatura inválida (pode ser ataque),
401/403na sua saída (credencial ou IP errados), filaneeds_decisionparada > 4 h, job de/eventsatrasado, desvio de relógio.
7. Segredos e rede¶
- [ ] Segredo de chamada, segredo de webhook e chave privada do mTLS no cofre; entregues ao host pela
sua ferramenta de deploy; arquivo
0400do usuário do serviço; nunca em repositório, imagem, log, variável de front (NEXT_PUBLIC_*,VITE_*) ou ticket. - [ ] O Dracma é chamado só do servidor. Nenhum app/navegador de jogador fala com ele.
- [ ] Logs não registram segredos, headers
Dracma-Signaturecompletos, documento completo do jogador nem chave PIX em claro. - [ ] Allowlist de IP de produção cadastrada com todos os IPs de saída (cluster, NAT redundante, DR) antes do corte. Lista vazia = sem acesso.
- [ ] Certificado mTLS de produção instalado; renovação agendada aos 60 dias (validade ≤ 90).
- [ ] Rotação de chave (≤ 90 dias) e de segredo de webhook ensaiada no sandbox sem downtime, com o verificador aceitando dois segredos ao mesmo tempo.
- [ ] Procedimento de revogação de emergência escrito: quem clica "Revogar agora", como a chave nova chega ao conector, quanto tempo leva.
8. Ambientes¶
- [ ] Homologação aponta para o sandbox com
key_test_; produção para produção comkey_live_. Prova: chamar produção com a chave de sandbox dá401 unknown_key. - [ ] Fixtures, seeds e testes usam só domínios reservados (
.test,.invalid,.example) e documentos de teste; nenhum dado de jogador real fora de produção.
9. Dia do corte¶
- [ ] Limites conservadores configurados na operação de produção.
- [ ] Primeira transação real de valor mínimo (depósito e saque) acompanhada pelos dois lados, do
POSTao crédito/débito e à linha da reconciliação. - [ ] Caixa inicial conferido em
GET /balances. - [ ] Plano de volta: como desligar o método no seu front sem derrubar o resto do seu sistema se o Dracma ficar indisponível (o seu serviço sobe e funciona sem o Dracma; pagamentos ficam em fila/indisponíveis).
- [ ] Registro de go-live assinado pelos responsáveis dos dois lados.