Bugs de aplicação de faturamento: corrija verificações de plano e lacunas em webhooks
Bugs na aplicação de faturamento podem vazar receita silenciosamente. Aprenda a corrigir checagens de plano, casos-limite de webhooks e condições de corrida em upgrades no seu SaaS.

Como aparecem na prática os bugs de aplicação de faturamento
Bugs de aplicação de faturamento acontecem quando sua página de preços diz uma coisa, mas o produto se comporta de forma diferente. Um usuário no plano free clica num botão e, de repente, consegue exportar, convidar colegas ou gastar créditos AI premium sem pagar.
O primeiro sinal é inconsistência. Um cliente é bloqueado, outro com o mesmo plano não é. O acesso muda após um refresh, logout ou tentativa de upgrade. Tickets de suporte começam a soar como: “Funcionou ontem”, “Meu colega consegue mas eu não”, ou “Eu fiz upgrade e ainda aparece bloqueado.”
Protótipos são especialmente vulneráveis porque frequentemente pulam as salvaguardas chatas. A primeira versão pode confiar num botão escondido, numa checagem no front-end ou numa única flag plan numa tabela de usuário. Isso pode funcionar em demos, mas quebra quando chegam retries de cobrança, webhooks e usuários reais.
Aplicar a política é responder quatro perguntas cada vez que uma ação valiosa é solicitada:
- Quem é o usuário, e a que conta/workspace ele pertence?
- Que plano e add‑ons estão ativos agora?
- Qual ação exata ele está tentando executar?
- O servidor deve permitir isso (não apenas a UI)?
Quando essas respostas estão confusas, ou espalhadas por muitos lugares, bugs aparecem. Um exemplo clássico: alguém adiciona um endpoint “só Pro”, mas esquece de adicionar a mesma checagem a um job em background que o chama. A UI ainda esconde o recurso, mas o endpoint fica acessível direta ou indiretamente.
Se você herdou um protótipo SaaS gerado por AI (Lovable, Bolt, v0, Cursor, Replit), essas lacunas são comuns. A FixMyMess costuma encontrar verificações de plano faltando em um ou dois caminhos críticos, além de pelo menos um lugar onde o estado de cobrança é assumido em vez de verificado. Isso costuma ser o suficiente para recursos pagos virarem gratuitos silenciosamente.
Mapeie os lugares onde o acesso deve ser aplicado
A maioria dos bugs de aplicação de faturamento acontece porque o acesso é checado num lugar e pulado no seguinte. A maneira mais rápida de evitar acesso gratuito a recursos pagos é mapear cada “ação paga” que um usuário pode desencadear e garantir que cada caminho atinja a mesma regra.
Comece com ações pagas em linguagem de usuário: “exportar CSV”, “convidar um colega”, “rodar o relatório”, “remover marca d’água”. Depois traduza cada uma para os caminhos reais de execução: o endpoint da API, qualquer job em background que ele enfileira, e qualquer caminho da UI (incluindo botões escondidos) que ainda possa chamar a API.
Coloque checagens no servidor primeiro. A UI pode esconder botões, mas não é de confiança. Se um endpoint pode ser chamado, ele deve validar os direitos sempre.
Sistemas para incluir no seu mapa
Anote todo sistema que mexe com entitlements, mesmo que o código seja bagunçado:
- Banco de dados da app (usuário, org/workspace, tabelas de subscription ou entitlement)
- Camada de autenticação (sessions, claims JWT, roles)
- Provedor de billing (plans, subscriptions, invoices)
- Webhooks e processamento de eventos (incluindo retries e delays)
- Caches/filas (qualquer coisa que possa servir acesso obsoleto)
Quando você ver o panorama completo, escolha uma fonte da verdade para entitlements e mantenha‑se nela. Para a maioria das apps SaaS, isso é um registro de entitlement no seu próprio banco que representa “o que este workspace pode fazer agora”, atualizado por webhooks e verificado em ações-chave.
Um erro comum em protótipos: checagens de plano espalhadas pelo frontend, algumas rotas de API e um handler de webhook. O resultado é acesso inconsistente e vazamentos difíceis de reproduzir. Um único modelo de entitlement mais um guarda compartilhado no servidor fecha a maioria das lacunas rapidamente.
Passo a passo: corrija checagens de plano para manter recursos pagos bloqueados
A aplicação do faturamento quebra quando as regras estão espalhadas. Um endpoint checa o plano, outro confia numa flag da UI, e um terceiro esquece de checar qualquer coisa. A correção é simples: centralize a decisão e reutilize‑a em todos os lugares.
1) Ache todo lugar que pode disparar uma ação paga
Faça um inventário de rotas do servidor e jobs em background que fazem algo valioso: exportar dados, convidar colegas, remover limites, gerar relatórios, usar chamadas AI premium e ações de admin. Se altera dados ou te custa dinheiro, precisa de um gate.
Depois adicione um guarda em um lugar só que todas as rotas pagas usem. Não reescreva checagens dentro de cada handler.
2) Mova todas as decisões de acesso para o servidor
Trate qualquer coisa vindo do cliente como uma pista, não como fonte da verdade. Flags de UI como isPro, valores em local storage e botões escondidos são fáceis de falsificar. O servidor deve decidir com base nos seus entitlements armazenados.
Um padrão prático é computar “o que é permitido” a partir de uma função única, usando um registro de entitlement. Free pode ver dashboards mas não exportar. Pro pode exportar. O crucial é que todo endpoint use a mesma decisão.
Um pequeno checklist para o guarda:
- Carregar o usuário e seu registro de entitlement atual do banco.
- Calcular
allowedFeaturesem uma função (sem checagens ad‑hoc espalhadas pelos arquivos). - Bloquear por padrão quando os dados estiverem faltando ou incertos.
- Retornar um erro claro: o que foi bloqueado e por quê.
- Logar a decisão com ID do usuário e versão do entitlement.
Erros claros ajudam o suporte (“Exportar requer Pro. Seu plano é Free.”). Também tornam os logs pesquisáveis quando alguém diz: “Paguei mas ainda aparece bloqueado.”
3) Adicione alguns testes que detectem vazamentos cedo
Mantenha simples. Você quer três testes: um usuário free é bloqueado, um usuário pago é permitido, e um usuário com dados de entitlement faltando é bloqueado. Só esses já pegam muitos vazamentos antes de chegarem à produção.
Se você herdou um protótipo gerado por AI, times como a FixMyMess frequentemente começam centralizando esses guards porque isso para vazamentos sem forçar uma grande reescrita.
Webhooks: trate eventos faltantes, duplicados e atrasados
Webhooks não são garantidos. Podem chegar atrasados, duas vezes, fora de ordem ou nunca chegar. Se sua app assume “recebemos o webhook, então o acesso está correto”, você continuará vendo bugs de aplicação de faturamento.
Trate webhooks como notificações sobre uma mudança, não a mudança em si. Sua app deve responder, agora, “o que este cliente pode fazer?” mesmo que o último evento esteja atrasado.
Torne o processamento de webhook seguro e confiável
Comece verificando que o evento é real. Cheque a assinatura do provedor, rejeite payloads não confiáveis e não desbloqueie recursos apenas porque um campo do webhook diz isso. Contraste com o estado atual do cliente.
Depois torne os handlers idempotentes. Se o mesmo evento for processado duas vezes, o resultado deve ser idêntico.
Um checklist curto que previne a maioria dos vazamentos de receita:
- Verifique assinaturas e rejeite requisições que falhem na validação.
- Armazene um event ID e ignore duplicatas já processadas.
- Aplique mudanças apenas se o evento for mais novo que o que você tem gravado.
- Recheque subscription/entitlements atuais antes de conceder acesso.
- Logue falhas com detalhe suficiente para permitir replay seguro depois.
Lide com eventos fora de ordem e eventos faltantes
Eventos fora de ordem são comuns em upgrades, reembolsos e cancelamentos. Use timestamps (ou números de sequência, se fornecidos) e compare com seu estado gravado. Se um evento mais antigo chegar depois de um mais novo, não sobrescreva o estado recente.
Para eventos faltantes, construa um caminho de retry seguro. Enfileire o webhook, tente processar de novo e alerte quando os retries continuarem falhando. Em protótipos que pulam essas salvaguardas, um evento perdido pode deixar recursos pagos desbloqueados por dias.
Uma boa regra: webhooks atualizam seus registros, mas seu produto deve liberar recursos com base nos entitlements atuais que você tem, não no último webhook que você recebeu por acaso.
Condições de corrida em upgrades e downgrades
Condições de corrida são uma forma fácil dos bugs de aplicação de faturamento entrarem. Ocorrem quando duas partes da sua app atualizam ou leem o plano de um cliente ao mesmo tempo, e uma delas vê dados obsoletos. O resultado geralmente é acesso gratuito (ou bloqueios aleatórios) justamente quando alguém muda de plano.
Um padrão comum: o usuário clica em Upgrade, a UI vira “Pro” imediatamente, mas a checagem do servidor ainda lê o plano antigo do banco (ou do cache). Se sua API confia no estado da UI, o usuário recebe recursos pagos antes de qualquer confirmação. Se sua API confia em estado antigo, o usuário paga mas ainda vê “bloqueado”, depois atualiza a página e de repente funciona.
Uma correção é forçar toda mudança de plano a passar por um único caminho no backend. Não deixe a UI, o handler de webhook e um cron noturno escreverem nos mesmos campos de entitlement de formas diferentes. Escolha um dono para os entitlements e faça todo mundo passar por ele.
Também ajuda separar estados para que a app possa ser honesta sobre o que está acontecendo:
- Payment started (checkout criado)
- Payment confirmed (provedor diz pago)
- Entitlement granted (seu sistema atualizou acesso)
- Entitlement revoked (downgrade efetivo)
Para evitar escritas duplas, adicione um lock de curta duração ou uma checagem de versão no registro do cliente durante mudanças de plano. Por exemplo, armazene um número entitlements_version. Ao aplicar um upgrade, escreva somente se a versão for a que você leu por último, então incremente. Se mudou, tente de novo com dados frescos.
Exemplo concreto: um usuário faz upgrade, e ao mesmo momento seu cron “conserta” subscriptions sincronizando o plano de ontem. Sem lock ou checagem de versão, a escrita do cron pode chegar por último e desfazer o upgrade. A UI pode mostrar Pro enquanto a API os bloqueia como Free, ou o contrário.
Se você herdou um protótipo gerado por AI, isso é um achado comum na auditoria: múltiplas escritas de plano, sem fonte única da verdade, e checagens de acesso que dependem de quem ganhou a corrida.
Faça dos entitlements um modelo de dados limpo e consistente
A maioria dos bugs de aplicação de faturamento começa com a verdade espalhada. Uma parte da app checa uma string de plano no registro do usuário. Outra checa uma flag do provedor de billing. Uma terceira checa se existe uma subscription. Quando discordam, pessoas ou obtêm recursos pagos de graça ou clientes pagantes ficam bloqueados.
Corrija criando um único registro de entitlement que sua app trate como fonte da verdade. Armazene‑o em uma tabela (ou documento) e atualize‑o via webhooks e resultados de checkout verificados. Inclua timestamps para que você possa raciocinar sobre o que mudou e quando.
Um registro de entitlements prático costuma incluir:
- Plano atual (free, pro, team)
- Status da subscription (active, trialing, past_due, canceled)
- Period start e period end (data de renovação)
- Entitlement version e
updated_at(para debugging e replay) - Política de grace e
grace_until(se você permite grace)
Defina períodos de tolerância (grace) em linguagem clara e os codifique no modelo. Por exemplo: permitir acesso somente de leitura por 3 dias após um pagamento falhar, mas bloquear exportações e chamadas de API pagas imediatamente. A ideia é fazer “o que é permitido” ser uma regra ligada a status e tempo, não um monte de condicionais pontuais.
Também decida o que acontece em pagamentos falhos. Bloqueio imediato é o mais simples. Acesso limitado pode reduzir churn, mas só se aplicado consistentemente em todo o produto.
Por fim, trate overrides de admin como dados de primeira classe. Eles frequentemente viram a causa oculta de bugs porque ninguém sabe por que um usuário está desbloqueado. Registre quem mudou o override, quando e por quê. Adicione um tempo de expiração para desbloqueios temporários. Torne o estado de override visível na sua UI de admin. Faça logging das decisões de entitlement (pelo menos em modo debug) para que você consiga explicar allow/deny sem adivinhar.
Se você está herdando um protótipo gerado por AI, é comum encontrar 3–5 fontes concorrentes de entitlement. Consolidá‑las costuma ser o caminho mais rápido para parar vazamentos sem reescrever tudo.
Casos-limite que comumente vazam receita
Bugs de aplicação de faturamento raramente vivem no caminho feliz. Surgem quando usuários mudam de ideia, compartilham contas ou batem em problemas de timing que seu protótipo nunca viu.
Regras de trial vs paid podem colidir de maneiras surpreendentes. Um erro comum é checar isTrialActive primeiro e retornar cedo, mesmo depois que o usuário fez upgrade. Isso pode aplicar limites de trial a usuários pagos ou, pior, aplicar regras de trial mais permissivas que as de paid. Faça “paid vence trial” uma regra explícita.
Downgrades são outro vazamento silencioso. Se você só trava recursos no login, usuários podem manter uma aba aberta e continuar usando recursos pagos após um downgrade. O mesmo acontece quando você cacheia entitlements por muito tempo. Se o plano muda, sua app precisa de um modo rápido de rechecagem de acesso (ou invalidar cache) antes de ações sensíveis.
Reembolsos e chargebacks precisam de uma política clara para acesso e dados. Se você não fizer nada, pode conceder acesso indefinidamente depois que o pagamento for revertido.
Alguns casos confusos que valem testes:
- Duas subscriptions ativas (usuário assinou duas vezes, ou trocou de plano sem cancelar)
- Descompasso entre billing de workspace e usuário (um membro herda o plano do dono por acidente)
- Bypass por role (admins têm acesso total mesmo no plano free)
- Flags antigas “grandfathered” sobrescrevendo checagens atuais
- Fatura manual marcada como paga sem atualizar entitlements
Um cenário comum: um dono de time faz upgrade, depois faz downgrade imediatamente, e um webhook chega atrasado. Se sua app desbloqueia no upgrade mas nunca relocka no downgrade, os recursos ficam abertos.
Erros comuns e armadilhas a evitar
Bugs de aplicação de faturamento geralmente acontecem porque as regras vivem em muitos lugares, e nem todos concordam. Um protótipo pode parecer OK na UI, enquanto o backend ainda permite endpoints pagos.
A maneira mais rápida de vazar receita é tratar controle de acesso como um problema de front-end. Botões e telas são fáceis de contornar com chamadas diretas à API, requisições salvas ou um script simples.
Erros comuns para vigiar:
- Gating só na UI: esconder um recurso na app, mas nunca checar o plano no servidor.
- Checagens de plano espalhadas: arquivos diferentes usam regras diferentes (nome do plano aqui, price ID ali, lógica de trial em outro lugar).
- Confiança cega em campos de payload de webhook: aceitar status do plano vindo de um evento sem verificar com seus próprios registros.
- Sem segurança de webhook: ignorar retries, duplicatas ou eventos fora de ordem e reabilitar acesso por acidente.
- Ambientes misturados: chaves de dev em produção (ou o inverso), então você “conserta” os dados errados e o bug volta.
Outro clássico: um usuário faz upgrade, a UI mostra Pro, mas o backend lê um plano antigo em cache por 10 minutos. Essa janela é suficiente para gerar exports ou outras ações pagas.
Se você herdou código gerado por AI, essas questões frequentemente vêm como checks copiados e colados. Consolidar a lógica em uma checagem de entitlement única no servidor e endurecer o tratamento de webhooks reduz a chance do bug reaparecer após o próximo refactor.
Antes de lançar, faça dois testes de sanidade:
-
Chame o endpoint pago diretamente enquanto está em um plano free.
-
Reproduza o mesmo webhook de upgrade duas vezes, depois envie um evento de downgrade atrasado, e confirme que o acesso termina no estado correto.
Checagens rápidas antes do lançamento ou relançamento
Antes de relançar um protótipo, rode algumas checagens rápidas que pegam a maioria dos bugs de aplicação de faturamento. Você está respondendo duas perguntas: alguém pode obter valor pago sem pagar, e clientes legítimos podem ser bloqueados?
Uma revisão rápida que você consegue fazer em menos de uma hora com um usuário de teste e seus logs:
- Tente ações pagas a partir de uma conta free chamando a API diretamente (não pela UI). Se qualquer endpoint pago retornar sucesso, você tem um vazamento.
- Faça upgrade de uma conta de teste e atualize a partir de outro dispositivo ou janela anônima. O acesso deve destravar rapidamente, e deve continuar destravado 10 minutos depois.
- Faça downgrade ou force um pagamento falho, então tente as mesmas ações pagas. Elas devem parar de forma confiável, mesmo que a UI ainda mostre botões antigos.
- Reproduza webhooks de billing. Handlers devem ser seguros para rodar mais de uma vez, e o resultado deve ser claro nos logs.
- Abra uma tela interna que mostre os entitlements atuais do usuário, sua origem (plano, add-on, trial) e quando foi atualizado pela última vez.
Um teste realista: faça upgrade de um usuário e imediatamente inicie um job pago pesado (export, execução AI, ação em massa). Se esse job começar antes de os entitlements serem atualizados, você achou uma corrida. Correções normalmente incluem checar entitlements no servidor no momento da ação e fazer o fluxo de upgrade esperar até o novo estado ser confirmado.
Também verifique seu logging. Quando algo dá errado, você deve conseguir responder “por que essa requisição foi permitida/negada?” sem adivinhação:
- Requisição permitida/negada porque entitlement X era true/false.
- ID do evento de webhook, status (processed/skipped) e motivo.
- Estado antigo vs novo do entitlement, com timestamps.
Exemplo: o upgrade que desbloqueia recursos de graça
Um vazamento comum parece inofensivo: um usuário clica em Upgrade, vê “Pro” na UI e imediatamente começa a usar recursos pagos. Mais tarde, você percebe que ele nunca pagou de fato, ou o pagamento falhou, e mesmo assim manteve o acesso.
Imagine um momento ocupado (um lançamento, um e‑mail promocional ou uma demo). Um usuário faz upgrade enquanto sua app está com carga, o provedor de billing está lento, e sua app trata “checkout iniciado” como “agora é Pro”.
Onde o bug se esconde
A UI vira Pro baseada numa flag local (ou num registro em cache). Mas o backend ainda vê o usuário como Free porque o entitlement real só é atualizado quando um webhook chega.
Se sua checagem de recurso depende do estado do cliente, de uma sessão em cache ou de uma leitura de banco lenta, o usuário passa pela porta. Se depende de estado antigo, o usuário paga mas continua vendo “bloqueado” até um refresh.
Como reproduzir (de forma confiável)
Geralmente você consegue reproduzir sem ferramentas sofisticadas:
- Abra duas abas logadas.
- Na Aba A, clique em Upgrade e complete o checkout.
- Na Aba B, atualize e rapidamente acione um recurso pago (ou pressione o botão várias vezes).
- Adicione um delay no processamento de webhooks (ou teste em ambiente lento) e observe o comportamento.
Se a ação paga tiver sucesso antes de o webhook atualizar os entitlements, você tem uma lacuna.
Uma solução prática que fecha a lacuna
Trate upgrades como uma máquina de estados no servidor, não como um toggle na UI:
- Guarda server-side: toda ação paga checa entitlements no servidor, não o label do plano no cliente.
- Estado pendente: quando checkout inicia, defina um status como
pending_upgradee mantenha recursos pagos bloqueados (ou permita apenas um preview limitado). - Tratamento idempotente de webhooks: processe o mesmo evento duas vezes sem efeitos colaterais e ignore eventos fora de ordem usando event ID e timestamps.
Para confirmar que foi corrigido, repita o teste de duas abas e verifique nos logs que ações pagas são negadas até o entitlement estar realmente ativo, então permitidas somente depois que o webhook (ou pagamento verificado) atualizar o estado no servidor.
Se você herdou um protótipo gerado por AI (Lovable, Bolt, v0, Cursor, Replit), esse bug aparece com frequência porque o plano é rastreado em múltiplos lugares. A FixMyMess costuma resolver traçando cada checagem de plano, migrando para uma fonte única no servidor e reforçando a lógica de webhooks para que “Pro” signifique apenas pago.
Próximos passos: trave os vazamentos de receita sem reescrever tudo
Comece escrevendo as ações exatas que devem ser pagas em linguagem clara: “exportar relatório”, “convidar colega”, “remover marca d’água”, “usar modelo premium”. Essa lista vira sua checklist.
Escolha um lugar no servidor para ser o gatekeeper e faça todo mundo passar por ele. Se sua app checa planos em cinco arquivos diferentes (ou só na UI), você vai perder pelo menos um.
Uma ordem prática que funciona para a maioria dos times:
- Liste ações pagas e adicione um guarda server-side usado por todos os endpoints pagos.
- Endureça o tratamento de webhooks: verifique assinaturas, armazene eventos e torne o processamento idempotente.
- Adicione retries para processamento de webhooks falhos e trate eventos atrasados sem quebrar o acesso.
- Stress‑teste upgrades: simule redes lentas, cliques duplos e dois dispositivos fazendo upgrade ao mesmo tempo.
- Revalide downgrades e reembolsos para que o acesso mude corretamente, no momento certo.
Antes de mudar a lógica, decida em qual “verdade” você vai confiar durante a janela de upgrade. Você pode conceder acesso só depois de gravar um pagamento confirmado, ou conceder acesso temporário por um curto período e revogar automaticamente se o pagamento não ocorrer. Qualquer abordagem pode funcionar, desde que seja consistente.
Se você está trabalhando com um protótipo gerado por AI, problemas de billing costumam vir junto com outras falhas como auth confusa, segredos expostos ou arquitetura confusa. Se quiser uma segunda opinião, a FixMyMess (fixmymess.ai) foca em diagnosticar e reparar codebases geradas por AI, incluindo lógica de entitlements, tratamento de webhooks, hardening de segurança e preparação para deployment.
A FixMyMess também oferece uma auditoria de código gratuita para apontar onde o acesso está vazando, e então repara checagens de plano e casos limite de webhook com verificação humana, frequentemente em 48–72 horas.
Perguntas Frequentes
Qual a forma mais rápida de impedir que usuários Free usem recursos pagos?
Comece assumindo que qualquer verificação no cliente é contornável. A correção mais rápida é adicionar um único guarda no servidor que rode em todos os endpoints de API pagos e em qualquer job em background que faça trabalho pago, e fazê-lo ter negar como comportamento padrão quando os dados de direito (entitlement) estiverem faltando ou incertos.
Por que esconder botões no frontend não é suficiente?
Porque a UI não é uma fronteira de segurança. Usuários podem chamar sua API diretamente, reutilizar requisições antigas ou acionar jobs em background indiretamente. Se o servidor não verificar direitos a cada ação valiosa, recursos pagos vão vazar mais cedo ou mais tarde.
Como mapear todos os lugares onde uma ação paga pode ser acionada?
Um bom mapa conecta a ação visível ao usuário com cada caminho de execução que pode realizá‑la. Por exemplo, “exportar CSV” geralmente envolve uma rota de API, um job enfileirado e um endpoint de download. Se qualquer um desses caminhos pular a mesma checagem de direito, o acesso fica inconsistente.
Qual deve ser a fonte da verdade para plano e add-ons?
Armazene os direitos atuais no seu próprio banco de dados como fonte da verdade, e atualize esse registro por resultados de checkout verificados e pelo processamento de webhooks. O servidor deve ler esse registro de entitlement no momento da requisição (ou com cache de TTL muito curto) para decidir permitir/negá.
Como evitar que glitches em webhooks desbloqueiem recursos?
Trate webhooks como sinais pouco confiáveis: podem chegar atrasados, duplicados, fora de ordem ou nunca chegar. Verifique assinaturas, torne o processamento idempotente e só atualize o estado de entitlement se o evento for mais novo do que o que você já tem gravado.
Como corrigir o vazamento “usuário fez upgrade mas não pagou de fato”?
Separe o fluxo de upgrade em estados claros e não conceda acesso só porque o checkout foi iniciado. Só liberre recursos pagos depois que seu sistema registrar o pagamento confirmado e atualizar o entitlement. Faça com que as checagens da API dependam desse estado no servidor, não de uma flag no cliente.
O que causa condições de corrida durante upgrades e downgrades?
Ocorrem quando diferentes partes do sistema leem ou escrevem o estado do plano ao mesmo tempo e uma delas vê dados obsoletos. Use um caminho único no backend para atualizar entitlements, adicione checagens de versão ou locks curtos durante mudanças de plano e sempre revalide direitos no momento da ação paga.
Devo fazer cache dos entitlements ou sempre consultar o banco?
Faça cache só se puder invalidá‑lo rapidamente quando os direitos mudarem, e evite TTLs longos para qualquer coisa que gateie ações pagas. Se usar cache, inclua uma versão de entitlement ou um timestamp de updated_at e recuse valores obsoletos quando o usuário estiver fazendo algo custoso ou pago.
Quais são os testes mínimos para detectar vazamentos de aplicação de faturamento?
Três testes já pegam muita coisa: um usuário free deve ser bloqueado, um usuário pago deve ser permitido, e um usuário com dados de entitlement ausentes deve ser bloqueado. Acrescente um teste adicional para sua maior ação monetizável (ex.: export ou chamadas AI premium) para checar jobs em background também.
E se meu protótipo SaaS foi gerado por ferramentas como Lovable, Bolt, v0, Cursor ou Replit?
Se você herdou um protótipo gerado por AI, comece com uma auditoria focada em ações pagas, rotas do servidor, jobs e handlers de webhook para achar checagens faltantes e fontes de verdade conflitantes. Se quiser ajuda, a FixMyMess pode fazer uma auditoria de código gratuita e depois reparar verificações de plano, casos-limite de webhook e brechas de segurança com verificação humana, frequentemente em 48–72 horas.