Segurança
Sujeito a alterações conforme a evolução do MVP. Em caso de divergência entre versões, a publicada nesta página prevalece. Dúvidas: suporte.
Aqui a gente abre o capô. Se você é creator e vai depositar dinheiro para pagar streamers, ou streamer e vai esperar receber pelo cumprimento do desafio, é justo conhecer as garantias estruturais do sistema. Nada do que está abaixo depende de promessa nossa — está implementado em código aberto que você pode auditar.
1. O dinheiro fica em escrow no banco de dados, não em planilha
Quando o creator cria um desafio com valor máximo de R$ 50, esse valor é imediatamente travado na carteira dele dentro da mesma transação SQL que cria o desafio. Não existe um momento em que o desafio existe sem o dinheiro travado. Se algo falhar (rede, energia, bug), a transação inteira é desfeita e nada acontece.
Esse modelo se chama escrow e é o mesmo padrão que casas de aposta sérias usam: o valor sai do bolso de quem desafia antes de qualquer entrega, vai pra um cofre, e só sai dali pra duas direções possíveis: pago ao streamer (quando a entrega é aprovada) ou devolvido ao creator (quando o desafio expira ou é rejeitado).
2. O ledger é append-only — nem nós conseguimos editar histórico
Toda movimentação financeira (depósito, escrow, pagamento, reembolso) é gravada como um lançamento permanente em uma tabela do banco onde os comandos UPDATE e DELETE foram explicitamente revogados. Isso significa que:
- Nem o app, nem um administrador, nem mesmo um atacante que comprometesse nosso código consegue editar o histórico de transações.
- O saldo da sua carteira não é um campo guardado em algum lugar — é derivado matematicamente da soma dos lançamentos. Saldo nunca pode divergir do extrato porque o extrato é a única fonte.
- Cada operação gera dois lançamentos espelhados (sai de um bucket, entra em outro) que somam zero. Auditoria automática checa essa propriedade depois de cada operação.
3. Aprovar o próprio pagamento é estruturalmente impossível
Streamers não conseguem aprovar a própria submissão — a função do banco que libera pagamento checa quem está chamando e rejeita se for a mesma conta que enviou a prova. Isso vale também pra creators que tentam se autodesafiar: se creator e streamer forem o mesmo usuário, o pagamento é bloqueado com erro self-dealing detected.
Antes de qualquer pagamento sair, ainda checamos:
- O streamer foi verificado (KYC concluído).
- Existe uma conta de payout cadastrada (chave PIX).
- Se a integração com o gateway começou, o streamer está com onboarding aprovado.
Falhar qualquer um desses checks aborta a aprovação inteira — o dinheiro fica travado até a situação ser regularizada.
4. Concorrência: corridas reais resolvidas no banco
No modo Race (qualquer streamer pode tentar), dois streamers podem clicar em “aceitar” ao mesmo tempo. Em vez de confiar na ordem da rede, usamos travas de linha do Postgres (FOR UPDATE). Quem chega primeiro ganha; o outro recebe um erro claro de “challenge not pending”. Não há janela em que dois aceites coexistem.
Aprovação em race obedece ordem FIFO: se há submissões anteriores ainda pendentes, o creator não consegue pular pra mais recente. Quando uma submissão vence, todas as outras são marcadas como race_lost automaticamente em uma única transação. O escrow nunca paga duas vezes.
5. Antifraude estrutural, não só “de aplicativo”
Submissões de prova passam por filtros que vivem no banco — não dá pra burlar mexendo no front-end:
- Cooldown de 60s entre submissões do mesmo streamer (qualquer desafio).
- Cooldown de 2 minutos por desafio individual.
- Limite de 20 submissões por hora.
- URL duplicada é rejeitada estruturalmente — não é uma checagem do app, é uma restrição de unicidade da tabela. A mesma URL não consegue entrar duas vezes mesmo que alguém tente fraudar.
- Submissão antes da criação do desafio (time-travel) é bloqueada.
Streamers com 3 ou mais rejeições, ou que tentaram URL duplicada, são marcados como suspeitos. A partir desse ponto, nenhuma submissão deles é auto-aprovada por timeout — passa obrigatoriamente pela revisão manual do creator.
6. Top-up só acontece quando o gateway confirma o pagamento
Saldo só entra na sua carteira quando o gateway de pagamento (Asaas, via PIX) confirma o evento PAYMENT_RECEIVED por webhook autenticado. A função do banco que credita saldo (record_deposit) é impossível de ser chamada por um usuário comum — só roda com a chave de serviço (que vive no servidor, nunca no navegador). Tentativas via sessão de usuário falham com forbidden.
Cada evento do gateway é registrado uma única vez (idempotência garantida por unicidade do event_id no banco, namespacado como asaas:evt_*). Isso evita crédito duplicado caso o gateway reentregue o webhook.
7. Histórico completo do desafio é preservado
Toda mudança de estado (criado, aceito, submetido, aprovado, rejeitado, expirado) gera um evento numa tabela de auditoria que também é append-only. Nem admin consegue editar esses eventos. Em caso de disputa, a linha do tempo do desafio é reconstrutível com carimbo de data/hora preciso.
8. Webhooks externos são autenticados antes de qualquer ação
Todos os eventos vindos do gateway (Asaas, tanto pra top-up via PIX PAYMENT_RECEIVED quanto pra payout TRANSFER_DONE/FAILED) só são aceitos se a assinatura criptográfica do webhook for válida. Tentativa de forjar uma transferência batendo direto no endpoint é descartada antes de chegar perto do banco — o secret é obrigatório em produção e nenhuma rota webhook aceita requisição sem assinatura conferida.
9. O que ainda estamos melhorando
Não somos perfeitos e não vamos pintar quadro de marketing. Em obras:
- Hardening adicional de segredos sensíveis: estamos migrando tokens de integração para uma camada extra de proteção (Vault/KMS) em cima do que já é coberto pela encriptação de disco do banco.
- Reconciliação automática entre nosso ledger interno e os saldos do gateway (hoje confiamos no gateway como verdade pós-aprovação).
- Rate limit em buscas de streamer pra mitigar enumeração de lista.
10. Quer auditar?
Cada propriedade acima tem origem em código versionado. Se você é dev ou está fazendo due diligence, peça acesso a nosso suporte — mantemos um documento técnico interno que mapeia cada garantia para o arquivo e linha exatos onde está implementada, disponível sob solicitação.
E se você acha que encontrou uma falha, mande pra suporte com o assunto [segurança]. Resposta em até 24h úteis e disclosure responsável é sempre bem-vindo.