Indo para produção
A demo omite várias coisas que uma integração de produção precisa. Esta página lista a distância entre ela e algo por onde você passaria dinheiro.
O que a demo pula
| Faltando | Por que importa |
|---|---|
| Contas e sessões de jogador | A demo pega um playerRef de uma caixa de texto |
| Carteira, saldo, débito de entrada | Ninguém paga para entrar, e ninguém recebe |
| Sessões reais de provedor | demoSessionUrl() retorna uma URL falsa |
| Persistência | Liquidações vivem num Map e morrem no restart |
| Uma fila atrás do webhook | Ela liquida inline; uma real enfileira e retorna |
| Autenticação | Toda página é pública |
| KYC, jogo responsável, jurisdição | Quais jogadores podem jogar |
Tudo isso fica do seu lado da fronteira, e o SlotBattle não vai desenvolver isso. Veja O que o SlotBattle não faz.
Faça isto antes de aceitar dinheiro
Debite a entrada antes de abrir a batalha, e torne isso reversível. Batalhas podem terminar
failed ou cancelled. Decida a sua política de estorno antes de precisar de uma, e faça um
webhook battle.failed disparar isso automaticamente, e não por ticket de suporte.
Liquide dentro de uma transação, com chave de idempotência. A entrega é ao menos uma vez, então uma duplicata vai chegar em algum momento e não pode pagar duas vezes.
Nunca liquide pelo socket. Ele é melhor esforço e não tem replay.
Cheque ok por assento. Uma batalha completed pode conter um assento que falhou.
Emita sessões de provedor por jogador, no servidor. game_url é uma sessão de dinheiro ao
vivo. Ela não aparece em nenhuma resposta, log, evento ou webhook do SlotBattle; mantenha a
mesma linha nos seus logs.
Verifique que a fronteira se mantém
npm run build
grep -r "sbk_" dist/ && echo "LEAK" || echo "clean"
Rode isso na CI. Uma chave num bundle de cliente não é algo que revisão de código pegue de forma confiável; é algo que você pega dando grep no artefato construído.
Confirme também que lib/slotbattle.ts nunca é alcançável de um componente de cliente. O guard
em runtime pega isso em desenvolvimento; o grep pega o que o guard não pega.
Realidade operacional
503 unavailable é normal sob carga. A instância limita batalhas em voo. Retente com
backoff exponencial e jitter; esse é o único erro rotineiramente retentável.
Tokens de viewer expiram em 15 minutos. Emita de novo na reconexão, e quando uma página ficar aberta mais tempo que isso.
Rotações de chave de assinatura deveriam ser invisíveis. O operador nomeia uma chave nova e
deixa a antiga verificando até se aposentar, então tokens já nos browsers continuam
funcionando. Espectadores tomando 401 no socket de repente significa que a rotação foi feita
sem janela. Reemitir é a sua mitigação, e a rotação deve ser reportada.
Deploys podem falhar batalhas em voo. Uma batalha no meio da gravação depende de gravadores
que já estão rodando. Trate battle.failed como desfecho rotineiro, não como exceção.
Assista a uma gravação real de ponta a ponta. Um gravador sem aceleração de GPU cai para cerca de 2 fps: a gravação termina com sucesso e fica impossível de assistir. Nenhuma checagem automática pega isso, então uma pessoa precisa olhar.
Checklist final
- Nenhum
sbk_em bundle de cliente, checado na CI - A verificação de assinatura de webhook recusa um corpo adulterado, testado e não presumido
- A liquidação é idempotente sob entrega duplicada
- Assentos com
ok: falsesão excluídos dos pagamentos -
battle.failedebattle.cancelleddisparam estorno automaticamente -
503é retentado com backoff;400/409não - Um espectador que chega tarde renderiza um lobby correto
- Tokens de viewer são reemitidos na reconexão
-
game_urlnão aparece em nenhum log que você controla - Uma gravação completa foi assistida por uma pessoa
Por onde seguir
- Referência da API: toda rota, com Try It
- Erros: todo código e o que fazer com ele
- Chaves e credenciais: toda credencial e como ela rotaciona
- O que o host controla: de que lado está um problema