Integrar uma plataforma de recorrência é tão complicado quanto fazer sozinho — às vezes
mais. Aviso de pagamento, conciliação, estado de assinatura, os casos-limite das stores:
nada disso sai da sua mesa. E ainda vai uma mensalidade e uma porcentagem
por cima, todo mês, para sempre.
Pior: o que mais dói num aplicativo essas plataformas nem cobrem — assinatura dentro da App
Store e da Google Play, oferta dirigida a uma pessoa, conflito de conta, o balcão de
suporte.
O Bullgate é o contrário. Não é mais uma API para você colar: é o fluxo inteiro
pronto — SDK nativo, backend, painel e as jornadas que levaram meses para acertar —
open source, rodando no seu servidor. Os serviços são AGPL e os SDKs,
Apache-2.0: no self-hosted, não há cobrança de licença agora nem quando seu aplicativo
crescer. Você continua pagando apenas quem processa o pagamento e as taxas das stores —
custos que já existiam. Pedágio de plataforma, não.
ou role: o placar do que já roda com dinheiro real está logo abaixo
plataforma open source · mobile-first · self-hosted grátis
Bullgate
Acesso, assinatura, oferta e operação — a fundação que todo aplicativo com receita
refaz, e que aqui foi construída, quebrada e corrigida primeiro num produto real,
com assinante pagando. Quatro partes, cada uma apresentada pelo problema:
a dor que você reconhece, como ela morde, e o que já existe de verdade para resolvê-la.
No ar construído e rodando em produção no laboratório
Prova pendente construído inteiro, falta validação em aparelho/store
Plataforma já reexpresso como Bullgate, validado no 1º consumidor
Decidido contrato registrado, não construído
de onde vem
O laboratório
Nada aqui é slide de captação. Tudo que este documento chama de no ar roda
num produto real — publicado na Google Play e na App Store, com cinco planos de assinatura
mensal e assinante pagando. Renovação, troca de plano, cancelamento,
reembolso, aviso em tempo real e oferta dirigida operam lá desde agosto de 2026.
O Bullgate é a plataforma que empacota essa fundação para qualquer app — sem
conhecer o domínio de ninguém: onde o laboratório entrega o benefício dele, o seu
produto entrega o seu — plano Pro, minutos, telas, armazenamento. O primeiro serviço da
plataforma, o Bullgate Access, já é código próprio, com servidor e banco
separados, e foi validado em aparelho real com o laboratório como primeiro consumidor.
Cada afirmação daqui foi conferida no código, não no folheto das stores. Os blocos «história
real de produção» contam o incidente que originou cada regra — sem jargão; o detalhe
técnico fino terá seções próprias, em edições futuras.
parte 1 · acesso
A porta — e o dia em que ela emperra
Cadastro e login todo app tem. O que separa um produto amador de um profissional é
o dia em que a porta emperra — e ele sempre chega. Você reconhece estas
cenas:
«Criei outra conta sem querer»
Perdeu o acesso, cadastrou de novo — e agora o histórico está na conta velha e o uso na nova. Duas contas, uma pessoa.
«Troquei de número»
O código de confirmação vai para um chip que não existe mais — e ninguém no suporte sabe dizer o que fazer.
«Aquele e-mail não existe mais»
A conta foi criada com o e-mail do trabalho antigo. A pessoa é a mesma; o jeito de provar isso é que sumiu.
O Bullgate Access cuida da porta — cadastro, login, sessão — e, principalmente, desses
dias: cada cena vira um caminho claro dentro do seu app, com prova e regra
definida, em vez de virar um ticket de suporte decidido no achismo.
E tudo acontece nas suas telas: nada de abrir navegador, nada de página de
login de terceiro. O código chega por SMS e se preenche sozinho no Android; o iPhone sugere
o código em cima do teclado. Seu app entrega o visual; o Bullgate entrega o caminho.
Plataforma
Cadastro, login e sessão
Serviço próprio, com banco próprio, validado em aparelho real com o primeiro consumidor.
Plataforma
Jornadas de vários passos sem gambiarra
O servidor decide a próxima etapa; o app só desenha. Toque duplo e queda de rede não bagunçam o fluxo.
No ar
Login social, vínculo silencioso, funil completo
Provado no laboratório há meses; entra na plataforma pelos mesmos contratos.
Decidido
CPF como login e como prova de titularidade
Entrar com CPF, e — com fonte confiável — provar que a pessoa é a dona de verdade da conta.
acesso · o funil
Cadastro que não espanta
Fricção é o que você cobra de alguém antes de essa pessoa ter qualquer motivo para confiar
em você. Cada passo do cadastro é uma escolha entre pedir e não pedir — e a conta do excesso
não chega como erro no painel: chega como gente que fechou o aplicativo e não voltou.
Deixe entrar sem conta nenhuma. Modo visitante com dados de demonstração: quem decide criar conta já sabe o que está comprando.
A porta de menos atrito primeiro — é a tela abaixo: Google e Apple na frente (o provedor prova o e-mail); o formulário fica atrás de um toque.
Se o provedor já provou, não pergunte. E-mail repetido vindo de token verificado vincula em silêncio em vez de criar a segunda conta. A melhor tela de conflito é a que ninguém vê.
Não verifique e-mail para deixar entrar. A conta nasce sem essa prova — o custo é adiado para o dia da recuperação, e é por isso que a parte de recuperação existe.
O que não é essencial sai do formulário. Telefone vira passo próprio, depois da conta, com «Agora não» de verdade — e a etapa inteira liga e desliga por configuração de servidor, sem publicar versão.
A porta de menos atrito primeiroQuem entra pelo social termina sem escolher senha nem confirmar e-mail. E dá para ver o produto antes de qualquer cadastro.
O único ponto em que o sistema não decide sozinho é o telefone que já
pertence a outra conta — e ele ganhou uma seção inteira mais abaixo, porque é onde quase
todo produto erra para um dos dois lados.
acesso · códigos e links
«O código não chega» — e outros mitos
A parte mais odiada de qualquer cadastro é o código de confirmação. E quase tudo que se
fala dele é mito:
dizem que
«SMS não chega — e ninguém aguenta digitar código de seis números.»
na prática
O código chega e se digita sozinho: no Android o app identifica a mensagem e preenche o campo; no iPhone o código aparece em cima do teclado antes mesmo de a pessoa abrir o SMS. Ela não decora, não copia, não digita.
dizem que
«Link de redefinir senha por e-mail não funciona — cai no spam.»
na prática
Cai mesmo — e é exatamente por isso que o SMS é tão importante: entrega imediata, preenchimento automático, e ninguém caçando pasta de spam. O e-mail continua existindo como canal; o erro é deixá-lo como porta única.
dizem que
«WhatsApp não manda link.»
na prática
Manda — e, devidamente integrado, vai além: a pessoa toca na mensagem, o app abre direto no lugar certo e a leitura já libera o acesso, sem digitar nada.
dizem que
«Para entrar, sempre vai ter senha ou código para digitar.»
na prática
O magic link por e-mail abre o app e libera o acesso sem nenhum código digitado — o mesmo desenho da liberação pelo WhatsApp, por outro canal.
O código se digita sozinhoNo Android o app lê o SMS e preenche na hora; no iPhone ele aparece em cima do teclado. Ninguém decora, copia nem digita.
Placar honesto deste bloco: o código por SMS com preenchimento automático está no ar,
em produção; o magic link por e-mail e a liberação pelo WhatsApp estão no desenho da
plataforma — decididos, ainda não construídos.
acesso · duplicidade
O telefone já é de outra conta
A pessoa acabou de digitar o código certo — provou que o número é dela. E o número já está
confirmado em outra conta, quase sempre a conta antiga dela mesma, criada
de novo porque ela perdeu o acesso. Posse do aparelho não diz de quem é a conta.
«Telefone já cadastrado»
O erro genérico joga fora a prova que ela acabou de dar e manda o caso ao suporte — justamente quem não sabe quem é o dono.
Duas contas para sempre
Sem caminho de volta, a duplicidade vira permanente: histórico numa conta, uso na outra.
Ou pior: entrega sem prova
O atalho oposto — «deve ser a mesma pessoa, move tudo» — entrega uma conta com anos de histórico a quem só provou ter um chip.
o que o bullgate empacota
O número não vira cadastro antes da prova. Ele mora no desafio, com vencimento e contador — quem desiste no meio não deixa telefone pendurado na conta.
No código certo, procurar outro dono ANTES de gravar. É a consulta que quase todo produto pula. Sem dono: grava verificado. A própria conta: termina em paz. Um dono anterior: nasce o caso de conflito. Mais de um: anomalia em quarentena — sem dono claro, não se escolhe um.
Conflito é escolha, não erro — é a tela logo abaixo: o identificador da conta antiga mascarado (para reconhecer, não para descobrir) e três saídas claras.
Mover move só a chave, nunca o histórico. Ter o telefone + saber o e-mail antigo por inteiro autoriza transferir o número. A conta antiga fica sem ele; nada mais atravessa.
Limites no servidor, não na tela. Código de 6 dígitos, 10 minutos, poucas tentativas, teto por hora — e nada disso segura só na interface, porque contador de tela não para quem chama a API direto.
Escolha, não erroO e-mail aparece mascarado — dá para reconhecer a conta, não para descobri-la. E cada saída diz o que acontece.
história real de produção
A autorização do conflito é de uso único e morre sozinha. Vence em minutos,
pedir outra invalida a anterior, e errar o e-mail antigo repetidas vezes queima a
autorização — o caso encerra em vez de virar jogo de adivinhação.
E a guarda que não aparece na tela: a saída que recupera a conta antiga
apaga a conta recém-criada — e só a sessão que acabou de criá-la carrega essa permissão.
Provar um telefone não autoriza descartar uma conta com anos de histórico.
No ar
Fluxo completo no laboratório
Desafio, deteção de dono, três saídas e a guarda da conta estabelecida — em produção.
Plataforma
Reexpresso como política declarada
«Tem o telefone E sabe o e-mail anterior → pode mover só o número» — desafio, prova, caso e transferência já implementados na jornada da plataforma.
Decidido
Recuperar e consolidar a conta anterior
A saída que devolve a conta antiga inteira, com a provisória absorvida — entra quando estiver indivisível de ponta a ponta.
acesso · o dia ruim
Sessão e bloqueio — desenhados para o incidente
Sessão só é assunto interessante no dia em que uma conta é invadida ou o serviço cai. É
para esse dia que o desenho existe.
A sessão não carrega nada dentro. O que o app guarda é um bilhete aleatório, sem e-mail, sem permissão, sem nada interpretável — e o servidor guarda só a impressão digital dele. Roubar o bilhete não conta nenhum segredo.
Encerrar tudo é virar uma chave. Uma troca de senha, um bloqueio, um «desconecta tudo» — e nenhuma sessão antiga revive, nem por fuso horário, nem por repetição de chamada.
Bloquear é um ato só. Barra a entrada e derruba quem já está dentro, juntos — porque um sem o outro não resolve invasão. E desbloquear devolve o acesso, nunca a sessão antiga: senão o cookie do invasor voltaria junto com o da dona.
Queda do serviço não desloga ninguém. Se o serviço de identidade cair por minutos, o acesso fecha durante a falha e reabre sozinho — indisponibilidade curta não vira logout da base inteira.
Bloqueio vale na requisição seguinte. Sem cache escondido: cortar o acesso de alguém corta agora, não «em até 15 minutos».
história real de produção
A lacuna que o laboratório pagou e a plataforma fecha: o bloqueio original
gravava «bloqueada» e «derruba as sessões» em dois passos separados. Se o segundo falhasse,
a conta ficava bloqueada sem o corte — e, ao desbloquear, uma sessão antiga voltava a
valer. No Bullgate, bloquear-e-derrubar é uma operação indivisível, e repetir o comando não
bagunça o registro do incidente.
acesso · identity resolution
Recuperação por prova, não por opinião
Quando alguém perde o acesso, quase todo produto cai num dos dois erros: o suporte que
decide «no feeling» (e entrega a conta a quem contou uma boa história), ou o beco sem saída
(«não temos como te ajudar»). O Bullgate substitui os dois por política declarada.
Provas, não histórias: saber algo (o CPF, o e-mail antigo), ter algo (o código chegou no telefone ou no e-mail), já ser alguém (uma senha ou um login social que ainda funcionam) ou uma atestação externa de titularidade. Tentativa errada nunca vira prova.
A regra é declarada, nunca pontuação oculta:sabe o CPF E (tem o telefone OU tem o e-mail). E mudar a regra não muda o jogo no meio da jornada de ninguém.
Provou → destrava exatamente o que a regra diz. Trocar credenciais, derrubar sessões, absorver a conta duplicada — uma autorização de uso único, que morre ao ser usada. Sem as provas, nenhum operador libera; com as provas, opinião subjetiva não bloqueia.
Revisão manual não é válvula de escape. Ela só existe quando a regra nomeia a evidência extra que um operador pode validar. Falha técnica vira nova tentativa, nunca decisão sobre quem é o dono.
CPF comprovado vence e-mail e senha. Quando uma fonte confiável atesta que a pessoa é a titular, ela recupera a conta que tem o CPF — e-mail, senha e telefone cadastrados por terceiro não têm poder de veto. Depois, ela mesma consulta a trilha do que aconteceu, sem depender do suporte.
Plataforma
Caso, prova, regra e autorização no núcleo
Tudo registrado e indivisível: satisfazer a regra e destravar o caso acontecem juntos, ou não acontecem.
Decidido
Fontes de titularidade plugáveis
Certificado digital, biometria de fonte oficial e afins. Sem fonte ativa, a capacidade fica indisponível — a regra nunca é rebaixada para uma prova mais fraca.
parte 2 · billing
Assinatura no app: problemas e mitos
Quem nunca vendeu assinatura dentro de app ouve muita lenda — e quase toda lenda existe
porque alguém tentou, tropeçou numa regra pouco óbvia da store e desistiu. Vamos por
partes:
dizem que
«Assinatura na Apple e na Play Store não dá para gerenciar — o app fica refém da store.»
na prática
Dá para fazer quase tudo de dentro do seu produto: trocar de plano, desistir da troca, adiar uma cobrança para compensar alguém, cancelar, reembolsar, dar desconto para uma pessoa específica. E o pouco que a store reserva para ela mesma, o painel diz com todas as letras — em vez de fingir que o botão não existe.
dizem que
«É difícil sincronizar o usuário com a store — nunca se sabe quem pagou, quem cancelou, quem voltou.»
na prática
As duas stores avisam o servidor em segundos quando algo muda. O difícil nunca foi receber o aviso — é conhecer as regras do jogo: conferir antes de agir, não entregar duas vezes, não confundir estados. Essas regras já vêm prontas.
dizem que
«Não renovou é a mesma coisa que cancelou.»
na prática
Boa parte dos «cancelamentos» é cartão recusado em retentativa — a pessoa nem sabe. Tratar como cancelado derruba um cliente que ia voltar a pagar. Distinguir os dois é exatamente o tipo de detalhe que vem pronto.
dizem que
«Quem assina no iPhone vira outro cliente no Android.»
na prática
O plano é da pessoa, não do aparelho. Ela troca de celular e o plano vai junto — e a tela impede a segunda cobrança na store errada, que é reembolso, ticket e nota ruim.
dizem que
«Não dá para fazer promoção dentro das stores.»
na prática
Dá — e melhor que cupom: oferta para uma pessoa específica, sem código e sem link que se repassa, validada de ponta a ponta nas duas stores. A parte «Oferta via admin», mais abaixo, mostra o caminho inteiro.
E o que o Bullgate deliberadamente não faz: não processa pagamento, não
guarda cartão, não faz custódia de dinheiro. Quem cobra é a store ou o provedor; o Bullgate
cuida de todo o resto — e o benefício, cada app define (plano Pro, minutos, créditos,
armazenamento).
No ar
Assinatura nas 2 stores, ponta a ponta
Assinar, renovar, trocar, desistir da troca, cancelar, reembolsar, restaurar — com assinante real desde agosto/2026.
No ar
Compra avulsa nas 2 stores
Validada no servidor, entregue uma vez só, e liberada para recomprar o mesmo pacote.
Decidido
Como serviço da plataforma
O mesmo motor, genérico, para qualquer app — e cobrança web (PIX e cartão via provedor) na sequência.
billing · sincronizar
Cancelou pela store. O app ainda não sabe.
Assinatura é uma coisa que vive fora do app. A pessoa cancela pela Play Store, reativa pela
App Store, tem o cartão recusado, pede reembolso — e o app segue mostrando outra coisa até
alguém descobrir. A pergunta que decide a qualidade do serviço é quanto tempo você
leva para saber. E o erro mais caro nem é a demora:
Corta acesso de quem paga
Cartão em retentativa não é cancelamento — a store segue tratando a pessoa como assinante por dias. Quem não escuta isso derruba um cliente que ia voltar a pagar.
Mantém acesso de quem saiu
Sem o aviso, o cancelamento só aparece quando alguém abre o app — ou nunca.
Beneficia sem cobrança
Pausa, carência e espera de cartão não cobram — e não podem liberar período novo.
Estorna duas vezes
Reembolso processado pelo painel e pelo aviso da store, sem trava comum, devolve o benefício em dobro.
o que o bullgate empacota
O aviso em tempo real das duas stores, autenticado e verificado. Mudança feita na store aparece no app em segundos, sem ninguém atualizar nada.
Aviso é gatilho, nunca verdade. Antes de mexer no acesso de alguém, o sistema volta e pergunta à store qual é a situação de fato.
Um vocabulário só para as duas stores. Ativa, em carência, aguardando cartão, pausada, cancelada, expirada, reembolsada — e «cancelou» vira ativa que não renova: a pessoa fica com o que pagou até o fim.
Redes por baixo do aviso: uma varredura periódica, a confirmação defensiva que evita o reembolso automático da Play, e a recuperação de compra ao abrir a tela. Aviso perdido não pode virar acesso perdido.
história real de produção
O aviso da store chega antes de o app terminar a compra. Num aparelho que
trocou de dono, o aviso ressuscitava a assinatura encerrada na conta antiga — e o benefício
da compra nova ia para a pessoa errada. A regra que ficou: só a conclusão feita dentro do
app, com a conta logada, pode dizer de quem é a assinatura nova. O aviso espera por ela.
Reembolso estorna uma vez, e nunca deixa saldo negativo. A devolução fica
registrada mesmo quando não há o que devolver — é esse registro que impede o aviso da store
de estornar de novo o que o painel já processou.
a pessoa cancela na store, longe do appaviso da store→reconsulta oficial→estado aplicado→o app diz «não renova mais, válida até dia 30» — e não corta o que foi pago
O app sabe em segundosCancelou pela store, longe do app — e o app já diz o estado certo: não renova, continua válida, nada confiscado.
billing · troca de plano
Quem quer pagar menos, cancela
Se mudar de plano é difícil ou dá medo, a pessoa escolhe o caminho que ela entende:
cancelar. Você perde o cliente inteiro quando ele só queria pagar menos.
A régua inteira, sempre. Todos os planos visíveis com o atual marcado, mesmo para quem já assina. Esconder os outros planos é o que empurra para o cancelamento.
Timing assimétrico de propósito: subir vale agora (cobra e entrega na hora); descer vale na próxima renovação (nada cobrado no meio, nada confiscado) — é o aviso da tela abaixo, dito antes de abrir a store.
Nunca uma segunda assinatura em paralelo. Trocar é substituição — as duas stores fazem, mas só se o app pedir do jeito certo. E quem assinou numa store vê o plano em qualquer aparelho, sem receber ali o botão de assinar de novo.
Desistir da descida sem pagar de novo. A Play recusa «trocar» para o plano atual — a volta passa por um plano gêmeo invisível (mesmo preço, benefício e nome), sempre agendada, nunca cobrada. Só o Android precisa; a Apple resolve pela reescolha no grupo.
A régua inteira, sempreTodos os planos visíveis com o atual marcado — e o timing dito antes de abrir a store. Nenhum caminho passa por cancelamento.
história real de produção
A armadilha do downgrade agendado: a store chega a devolver o plano novo
antes de ele ser pago. Entregar o benefício nesse momento seria dar o plano de
graça. A regra que ficou: benefício só quando existe cobrança do plano novo
— e a troca agendada aparece na tela com a data em que passa a valer.
billing · a trava
A regra do dinheiro
Errar aqui não dá erro de compilação — dá benefício entregue de graça, ou cliente que pagou
e não recebeu. Três travas sustentam tudo:
Um período pago, um período de benefício. Cada cobrança da store tem um número próprio, e é ele que libera o benefício — uma vez. Consequência elegante: carência, pausa e cartão em retentativa não cobram → não liberam nada, sem regra especial para cada caso.
Repetir nunca duplica. Reabrir o app, reenviar a compra, receber o mesmo aviso duas vezes ou fora de ordem — tudo cai na mesma trava e volta «já entregue».
Excluir a conta não zera a trava. Um recibo anônimo — sem dono, sem nome, sem valor — sobrevive à exclusão e impede que o mesmo pagamento vire benefício de novo numa conta nova. E é justamente por não ter dono que ele pode ficar: não é dado pessoal.
história real de produção
A confiança viaja embarcada no produto, nunca herdada do ambiente. O
comprovante de compra da Apple é verificado contra o certificado oficial que acompanha o
próprio serviço — então a validação não depende de como o servidor foi montado e não se
perde quando ele é reinstalado.
E o recibo anônimo tem um detalhe deliberado: a compra avulsa repetida é
recusada; a assinatura repetida é registrada sem liberar aquele ciclo — porque ela
é real e continua cobrando, e recusá-la deixaria a pessoa pagando sem receber nada. A
renovação seguinte libera normal.
parte 3 · admin centralizado
Uma operação, um lugar
Antes do painel, a operação do laboratório vivia em três lugares que não são tela: um CLI
de manutenção na máquina do dev, a UI do agendador de jobs e SQL na mão —
o roteiro de conferência de compras era literalmente uma lista de SELECTs. Todo produto
pequeno opera assim, até o dia em que um cliente real liga.
O admin centralizado junta isso em duas superfícies complementares sobre os
mesmos contratos: a mesa (web) para trabalho de cadastro — catálogos de
ofertas, jobs, desenho do que vem — e o bolso (app interno de operação)
para atendimento por pessoa: busca, ficha, ações e conversa. No celular, o atendente nunca
está «no módulo de usuários»: ele está atendendo alguém — a pessoa é o eixo, não o
módulo.
Nas telas desenhadas deste documento, o formato diz de quem é a tela: celular
é o app do seu usuário; janela de desktop com o selo OPERAÇÃO é o painel de
quem opera.
dizem que
«Operação de app pequeno é planilha, SQL e achismo — painel de verdade é coisa de empresa grande.»
na prática
Busca, ficha completa da pessoa e toda ação com confirmação e registro — do celular do operador. Quem atende não precisa saber banco de dados, e «quem mandou isso?» tem resposta seis meses depois.
dizem que
«Suporte do app e WhatsApp são dois mundos que não se misturam.»
na prática
É uma fila só: a conversa que chegou pelo WhatsApp aparece ao lado da conversa do app, com a ficha da pessoa a um toque — e a resposta sai dali mesmo, chegando no WhatsApp dela.
dizem que
«Reembolso e cancelamento são caixa-preta — só a store resolve, e o suporte fica de mãos atadas.»
na prática
O operador reembolsa (integral ou proporcional), cancela a renovação, adia uma cobrança para compensar alguém e restaura a assinatura — da ficha, com confirmação e trilha. E o pouco que só a store pode fazer, a tela diz com todas as letras.
No ar
As duas superfícies em produção
Mesa com acesso restrito e login próprio; bolso validado no aparelho do operador, ação por ação.
Decidido
Como produto Bullgate Admin
Superfícies operando sobre contratos de Access e Billing — nunca escrevendo direto no banco de ninguém.
admin · leitura
A ficha da pessoa
Uma chamada, tudo que o atendimento precisa: identidade, plano vigente com nome
operacional, contas, benefício, compras e ciclos pagos, ofertas enviadas com o resultado
por canal, conversas, gravações de sessão e erros. Organizada por assunto — Acesso, Contas,
Benefícios, Assinatura, Atendimento — porque é assim que uma ligação de suporte anda.
A disponibilidade de cada ação vem do servidor, com o motivo escrito. «Apple não permite» e «sem assinatura ativa» são fatos do estado — e são textos diferentes de «não suportado», que se leria como ainda não fizemos. Recalcular isso no cliente divergiria no primeiro ajuste.
Valor sai cru, como está armazenado. O número viaja exato até a tela, sem nenhuma camada arredondar no caminho — arredondar esconderia justamente a divergência que se veio conferir.
Data em UTC, marcada como UTC, com o relativo ao lado e nunca no lugar — o absoluto confere contra banco e log, o relativo lê sem contar dia de cabeça.
«Sem registro» onde ninguém mediu — nunca travessão. Travessão se lê como «nunca aconteceu», que é afirmar um fato não medido.
Pendência não se sinaliza no app de operação. Nada de «em breve» nem botão morto: uma tela só entra quando faz o que promete. O que aparece é indisponibilidade daquela pessoa, com motivo.
A ficha da pessoa, no painelTudo que o atendimento precisa numa tela — e, quando uma ação não está disponível, o motivo escrito, nunca um botão morto.
admin · escrita
Ações que deixam trilha
Toda ação operacional — do reset de senha ao reembolso — passa pelo mesmo envelope de
auditoria: quem fez (da sessão de quem operou, nunca declarado à mão), o quê, em quem,
quando e com que desfecho. E repetir não repete: toque duplo ou queda de
rede devolvem o mesmo resultado, não executam duas vezes.
acesso
Conta comprometida
Enviar link de redefinição · encerrar sessões · bloquear · desbloquear · desconectar provedores. Bloquear barra as portas e derruba sessões num ato; desbloquear nunca devolve a sessão antiga.
assinatura
Dinheiro com guarda
Adiar cobrança (compensar sem devolver dinheiro) · cancelar renovação · reembolsar (integral ou proporcional, sem default) · restaurar. As guardas de store e estado vêm do domínio, não da tela.
comunicação
Alcançar a pessoa
Push avulso com destino fechado, e as duas ações de oferta — assinatura e pacote avulso — que ganharam a parte seguinte inteira.
Dinheiro com guardaO modo é escolha explícita — sem padrão silencioso —, o efeito está escrito antes do clique, e a trilha fica.
história real de produção
O destino do link de redefinição não é escolha do operador. Ele sai sempre
para o e-mail atual da conta, decidido no servidor — um campo de destino transformaria a
ação em «mande o link para onde eu quiser», que é entregar a conta. E cada erro diz ao
operador o que fazer: «não existe», «o estado não permite — não adianta insistir», «store
fora do ar — a ação ficou registrada».
A cota anual de extensões da Apple não é copiada localmente, de propósito.
Quem sabe quantas aquele cliente já teve é a store — inclusive as feitas fora do painel. Um
contador local bloquearia tendo cota, ou liberaria sem ter. A chamada é feita; a recusa da
store vira uma mensagem clara na tela.
admin · atendimento
Suporte no mesmo balcão
O inbox unifica as conversas do app (logado ou visitante) e as que chegam
pelo WhatsApp — rotuladas com o número, na mesma fila, com push nativo
avisando o atendente. E a conversa está costurada à ficha: o cabeçalho da thread já diz
plano, bloqueio, contas e último acesso, com a ficha a um toque.
Responder é persistir → transmitir → avisar → entregar, nessa ordem: só se transmite o que já está gravado, e falha de push não desfaz a resposta.
A falha do WhatsApp volta para a tela do operador com a causa distinguida: janela de 24h fechada (a pessoa precisa escrever primeiro) não é a mesma coisa que token vencido (troca de configuração) — e nenhuma das duas é «tentar de novo às cegas».
Visitante e WhatsApp não têm pessoa — e a tela diz isso. Casar conversa de WhatsApp com um cadastro só quando o telefone for verificado; antes disso o palpite viria de um campo que qualquer um edita.
Uma fila sóApp, visitante e WhatsApp lado a lado — a resposta sai daqui e chega no WhatsApp da pessoa, com a ficha a um toque quando existe cadastro.
parte 4 · oferta via admin
Sem cupom, com alvo
Cupom vaza. Código circula em grupo, link é repassado, e o desconto que era para reter uma
pessoa vira preço novo da base inteira. No outro extremo, o suporte «dá um desconto» direto
no banco — e a cobrança da store continua cheia, porque a store é a dona do
preço. A saída é a oferta dirigida: feita para uma pessoa específica,
que só ela vê, com validade, enviada pela ficha do admin e aceita na tela
da própria store. O preço da base inteira não muda, e cada passo deixa trilha.
introdução
«Comece com 25%»
Para quem nunca assinou. 25% por 2 meses no Android — a Play recusou desconto recorrente de 1 período só; regra de store absorvida pelo catálogo.
elegível se: sem assinatura atual E sem histórico
retenção
«Ficar»
50% por 3 meses para quem deu sinal de saída: cancelou a renovação ou agendou descida. Continua no plano que já tem, pagando metade por um tempo.
elegível se: assinatura atual na mesma store E mesmo plano visível
upgrade
«Subir de plano»
30% por 2 meses para quem usa muito e caberia no plano de cima. O desconto tira o medo do degrau.
elegível se: assinatura atual na mesma store E nível maior que o atual
win-back
«Voltar»
50% por 3 meses para quem já assinou e saiu. A conversa mais difícil — e a única em que o canal importa tanto quanto o preço.
elegível se: sem assinatura atual E histórico na mesma store
As regras acima não são etiqueta de marketing: o sistema confere o estado real da assinatura
antes de deixar enviar. «Voltar» não se oferece a quem está ativo; «subir» não se oferece a
quem já está no topo. Há um quinto momento, a cortesia, para gesto de
atendimento.
dizem que
«Reter quem vai cancelar e trazer de volta quem saiu? Dentro da store não dá.»
na prática
Dá — e é o uso mais valioso de tudo isto. Quem cancelou a renovação recebe «Ficar»: metade do preço por alguns meses, no plano que ela já tem. Quem saiu há meses recebe «Voltar». A oferta chega por push; a pessoa toca e já assina — o desconto aparece na própria tela da store, sem código, sem formulário.
a pessoa cancelou a renovaçãoo operador envia «Ficar» pela ficha→push no celular dela→toca e vê o preço com desconto, direto da store→assina na hora→sem cupom, sem suporte, sem sair do app
Do push à assinatura, sem códigoA pessoa toca no aviso, vê o valor real com desconto — buscado da store — e assina na hora.
oferta · trabalho de mesa
O catálogo: uma campanha, um cadastro por store
Para a operação, «Ficar — Tubarão» é uma campanha. Para a Apple e o Google
são registros distintos, com identificadores próprios que pertencem à store. O catálogo — a
tela de mesa do admin — guarda uma linha por store e agrupa as duas como canais do mesmo
cartão. Isso não é burocracia:
Ativar uma store e não a outra — caso real no ar: a mesma campanha com Apple inativa e Google ativa.
Absorver as divergências que a store impõe — as boas-vindas têm duração diferente por store porque a Play recusou o formato de 1 mês; a diferença fica registrada, não é forçada uma simetria que a store não aceita.
Oferta não se apaga, se desativa. O identificador é imutável na store e o histórico de quem recebeu aponta para ela. Desligar preserva a trilha; apagar a quebraria.
O cadastro valida na entrada o que o envio recusaria depois — inclusive a regra de store mais traiçoeira: o tipo de oferta que a Apple aceita para quem já assinou não serve para quem nunca assinou, e o catálogo recusa essa combinação na hora do cadastro em vez de deixá-la falhar na frente do operador.
história real de produção
A pergunta «o que posso ofertar para ela?» chegou a ter duas respostas —
a regra oficial e uma cópia dela numa tela, que divergiram: a tela oferecia uma combinação
que o envio recusava depois. A correção virou princípio de plataforma: a elegibilidade mora
num lugar só, e todo mundo — tela, envio, app — pergunta a ele.
oferta · pela ficha
O envio parte de uma pessoa, não de uma lista
O envio acontece na ficha da pessoa, dentro do admin — onde já se vê o
plano, o histórico de cobrança e os aparelhos. E o formulário é travado pelo estado,
não pelo bom senso: o operador não consegue mandar «volte» para quem está ativo,
porque a opção nem aparece.
como o envio funciona
Só o que a pessoa pode receber: das campanhas do catálogo inteiro, o formulário lista as elegíveis pelo estado real — na captura do laboratório, um perfil com assinatura encerrada via exatamente duas ofertas de «voltar». O resto nem aparece.
Quatro canais que não competem: pop-up e bolha vivem dentro do app — é a tela abaixo; e-mail alcança quem foi embora; push é o atalho. E-mail e push só ficam marcáveis quando existem de verdade: «sem aparelho registrado» trava a caixa e diz por quê.
A copy é a do catálogo. Ver antes de mandar é diferente de reescrever no celular: campo de texto que ninguém revisa convida a copy pior que a cadastrada.
Validade fechada (1/3/7/15 dias, padrão 15), resolvida em data concreta no servidor — «vale por 15 dias» não pode virar prazo que se move sozinho. Vencido, o convite some das telas; o histórico permanece.
Todo envio deixa registro: quem enviou, para quem, qual oferta, motivo interno, resultado por canal. Ação que mexe com dinheiro de cliente sem trilha vira «quem mandou isso?» seis meses depois.
A oferta mora dentro do appO pop-up garante a primeira vista (sai só no X); a bolha fica à mão enquanto o convite valer — e some sozinha quando vence. Push e e-mail são atalhos, não o único caminho.
história real de produção
Envio é UM fato; canal é técnica. Antes dessa regra, um e-mail que voltava
desfazia o envio inteiro — e a oferta sumia do app, embora existisse, válida, no
card. Hoje cada canal carrega o próprio resultado, e a oferta vive dentro do app enquanto
valer. E e-mail sem botão não sai: se não dá para montar o link que leva à
oferta, o canal é recusado — meio aviso é pior que nenhum.
oferta · o resgate
O aceite acontece onde a pessoa já paga
Do lado de quem recebe não existe resgate, código nem formulário. A oferta é um cartão na
tela; o toque abre uma tela dedicada que mostra o valor real vindo da store
(R$ 19,95 num plano de R$ 39,90) com condição, benefício e store declaradas — o app nunca
calcula preço; se a store não devolver a oferta, a tela não inventa o número. O botão abre a
folha de compra da própria store, com o desconto e o preço cheio lado a lado.
o ciclo de vida de cada convite, auditável ponta a ponta:
criada ──▶ enviada ──▶ aberta ──▶ resgatada
└──▶ expirada · cancelada · inelegível · recusada pela store
«resgatada» é quando a store confirma a cobrança COM a condição —
tocar no botão não resgata; abrir a folha da store não resgata.
O desconto não mexe no benefício. Quem aceita 50% recebe o benefício cheio do plano. Desconto que corta benefício é rebaixamento disfarçado, e a pessoa percebe na primeira renovação.
Aceitar usa a mecânica de sempre. Ficar com desconto compra o próprio plano; subir com desconto é a troca normal. Nunca nasce uma segunda assinatura em paralelo.
O mesmo desenho vale para compra avulsa: pacote único com desconto, apontando sempre para um produto real da store, e o benefício continuando a nascer só da compra confirmada.
história real de produção
No iPhone, a oferta só compra com uma autorização assinada pelo servidor —
ninguém injeta desconto por fora do sistema. E no resgate, o comprovante da store precisa
trazer exatamente a condição enviada àquela pessoa. Divergência não pune a
pessoa: a compra vale; a trilha registra que o desconto não foi aplicado, para a
operação ver.
No ar
Catálogo com 4 campanhas reais nas 2 stores
Ativação independente por store, cadastro validado na entrada.
No ar
Envio pela ficha, superfícies, push e e-mail com CTA obrigatório
Elegibilidade pelo estado, canais travados pelo que existe, trilha completa.
No ar
Aceite Android de ponta a ponta
Do card no app até a cobrança com desconto confirmada pela store — validado em aparelho real.
No ar
Aceite iOS de ponta a ponta
Validado em aparelho real, com a autorização assinada pelo servidor — para assinatura e pacote, como no Android.
Decidido
Como serviço da plataforma
Catálogo, convite e benefício genéricos — o app define o que o benefício significa.
parte 5 · documentação técnica · access
Comece pela fronteira, não pelos endpoints
O Bullgate Access é autoridade sobre identity, identificadores, senha, credenciais
sociais, sessões, recovery, provas e AccessFlow. Seu produto continua autoridade
sobre perfil, permissões de negócio, dados do domínio, layout, copy e navegação.
A integração pública da fase 1 usa uma regra sem exceção: o aplicativo chama o
backend do produto; o backend chama o Access. A credencial de integração nunca
entra no JavaScript, no bundle móvel ou numa variável pública.
Fase 1
Implementada no código; distribuição externa ainda pendente
Os contratos abaixo descrevem o que já existe. Os pacotes ainda não têm registry/release pública e o destino remoto para empresas externas ainda precisa ser provisionado.
BackendASP.NET Core · .NET 10
AplicativoReact Native · Expo · Web
Prefixo BFF/bullgate/access/v1
Seu aplicativoUsa SDK headless e chama somente o seu BFF.
Seu backend + BFFGuarda cookies HttpOnly e a credencial server-to-server.
Bullgate AccessResolve identity, sessão, provas e jornadas.
PostgreSQL próprioBanco isolado do domínio do seu produto.
Bullgate
Identidade e continuidade
identityId, e-mail principal, telefone verificado, senha, Google/Apple, sessões, recovery e estado do flow.
Identifiers podem mudar. Seu produto não deve associar perfil local por e-mail ou telefone.
Seu produto
Perfil e negócio
Nome de exibição, papéis, permissões, onboarding, dados do domínio e tudo que acontece depois da autenticação.
A associação estável é identityId → profileId, com provisionamento idempotente.
integração técnica · backend
ASP.NET Core: adapter, BFF e sessão composta
Para .NET, use Bullgate.Access.AspNetCore. O adapter registra o
client do Access, publica as rotas BFF e converte a sessão Bullgate no principal local do
produto. Em outra stack, reproduza a mesma fronteira server-to-server; o guia raw completo
ainda será publicado.
ContaSenha, troca direta de e-mail e vínculo/desvínculo de Google e Apple.
JornadasPOST /flows · GET /flows/{flowId} · POST /flows/{flowId}/actions
Exclusão é coordenada pelo produto. O BFF genérico não publica DELETE /account. Seu backend apaga o domínio conforme sua política e chama DeleteAccountAsync; não existe transação distribuída automática entre os dois bancos.
integração técnica · frontend
React Native: o SDK controla o protocolo; seu app controla a experiência
O pacote @bullgate/react-native é headless. Ele controla sessão,
concorrência, providers, revisão do flow, countdown, reset token e os estados técnicos. Seu
aplicativo mantém componentes, acessibilidade, copy, navegação, analytics e efeitos de negócio.
O baseUrl aponta para a API do seu produto, nunca para o Access.
O transport chama /bullgate/access/v1 com cookies; a integration credential
bgic_… não existe na configuração móvel.
Sessão, cadastro, login, Google/Apple, e-mail, senha, logout e exclusão coordenada.
Hook
useBullgateRegistration()
Continua o cadastro por AccessFlow sem expor intent ou capability às telas.
Hook
useBullgatePhoneManagement()
Adiciona ou troca telefone durante uma sessão Product.
Hook
useBullgatePasswordRecoveryByPhone()
Conduz telefone, OTP e nova senha mantendo o reset token privado.
regra de composição
Render pronto ou UI própria. A empresa pode usar journeys prontas, substituir slots ou renderizar cada step com hooks semânticos. Em todos os modos, a tela executa apenas ações oferecidas pela revisão atual do flow.
contrato vigente · fase 1
O que existe — e o que não deve ser inferido
Implementado no código
Cadastro e login por e-mail e senha.
Google e Apple quando habilitados no ambiente.
Sessões de cadastro e de produto.
Recovery por e-mail e telefone.
Telefone verificado e fluxos de conflito.
Troca direta de e-mail e exclusão da identity.
Fora da fase 1
E-mails alternativos ou consolidação de e-mails.
Merge automático de identities.
Verificação de e-mail por challenge ou link.
Login sem senha por magic link ou código de uso único.
Billing e entitlements dentro do Access.
Portal administrativo Bullgate.
Bullgate Cloud gerenciado.
Troca de e-mail substitui; não acumula. Na fase 1, o novo endereço substitui imediatamente o identifier principal. O antigo deixa de ser login por senha e o novo não vira endereço alternativo.
Recuperar a identity anterior não faz login silencioso. O caminho solicita reset no e-mail antigo, encerra o flow, revoga a sessão provisória e descarta o e-mail novo. Depois do reset e de um novo login, a identity original volta a resolver o perfil e o histórico existentes.
visão de produto · não implementado
Futuros do Access: autenticação primeiro, prova civil sob demanda
A ordem recomendada começa pelo que beneficia qualquer integração: verificação de
e-mail, login sem senha, passkeys, 2FA, step-up, controle de sessões e recovery forte.
Data de nascimento, CPF, documento, OCR e face entram apenas quando o produto precisa provar
identidade civil — como adapters substituíveis, nunca como obrigação do cadastro comum.
Verificação de e-mail
Recomendado a seguir
Comprovar a posse do e-mail no cadastro e antes de mudanças sensíveis, por código ou link de uso único.
Expiração, limite de tentativas, cooldown e reenvio seguem policy explícita.
Trocar o e-mail exige prova recente e revoga challenges anteriores.
A verificação confirma o endereço; não cria e-mail alternativo nem vincula identities automaticamente.
Fronteira: o provider entrega a mensagem; o Bullgate controla challenge, prova, expiração e decisão.
Login sem senha
Recomendado a seguir
Entrar por magic link ou código de uso único enviado a um e-mail já verificado, sem armazenar nem reutilizar senha.
O link abre o app ou a web no contexto correto e só pode ser consumido uma vez.
Pedido de login não revela se o endereço está cadastrado.
Dispositivo, expiração, tentativas e replay entram na trilha de segurança.
Fronteira: passwordless é um autenticador; verificação de e-mail é uma prova de posse. Um não deve ser documentado como sinônimo do outro.
Passkeys com WebAuthn
Recomendado a seguir
Entrada mais simples e resistente a phishing, sem senha reutilizável guardada pelo Bullgate.
Cadastrar, nomear, listar e revogar várias passkeys por identity.
Suportar passkeys sincronizadas e vinculadas a dispositivo.
Exigir autenticação recente para adicionar ou remover autenticador.
Fronteira: o Bullgate guarda chave pública e metadados mínimos. Biometria e PIN permanecem no dispositivo.
2FA e step-up por ação
Recomendado a seguir
TOTP e códigos de recuperação como fallback; política por realm para exigir prova adicional somente quando a ação justificar.
Step-up para e-mail, senha, telefone, recovery, exclusão e administração.
SMS e WhatsApp como fallback de menor garantia, nunca o fator mais forte.
Fronteira: a política decide o nível; o AccessFlow descreve a próxima prova sem entregar a decisão à tela.
Sessões visíveis e recovery por múltiplas provas
Recomendado a seguir
Listar e revogar sessões, notificar mudanças críticas e impedir que a recuperação seja mais fraca que o login.
Combinar autenticador disponível, código de recuperação, canal confirmado ou nova prova.
Modelar caso, evidências, política versionada, grant de uso único e execução idempotente.
Endereço de recuperação é canal de prova; não vira login alternativo.
Data de nascimento e garantia de idade
Adapter
Digitar uma data é declaração, não verificação. O adapter valida em fonte autorizada e, quando basta, devolve apenas uma conclusão como isOver18.
Fronteira: guardar o mínimo necessário; política, jurisdição e idade exigida pertencem ao realm.
Documento: captura, OCR e autenticidade
Adapter
OCR extrai campos, mas não prova autenticidade. A validação precisa observar formato, adulteração, elementos de segurança, MRZ/código de barras, captura ao vivo e mídia injetada.
Fronteira: fornecedor especializado e substituível; o núcleo recebe evidência normalizada, método, proveniência e validade.
Selfie, vivacidade e comparação facial
Adapter
Selfie isolada não prova identidade. Quando o risco exigir, combinar captura ao vivo, defesa contra apresentação/injeção e comparação com documento validado ou fonte emissora.
Fronteira: biometria é dado sensível. Preferir guardar resultado e trilha, não a amostra; prever retenção curta, base legal, região e revisão de falso negativo.
CPF como atributo e prova de titularidade
Adapter
CPF pode identificar; conhecer o número não prova titularidade. A política combina fonte autorizada ou credencial assinada com outra evidência adequada ao caso.
Fronteira: adapters como GOV.BR, Datavalid e ICP-Brasil sem acoplamento ao modelo central.
Federação e ciclo de vida enterprise
Depois do núcleo
OIDC primeiro; SAML, organizações, domínios verificados, SCIM e Shared Signals quando houver demanda empresarial e ecossistema reais.
Limites deliberados: não criar e-mail alternativo ou merge por efeito colateral; não chamar OCR de autenticidade; não tratar selfie como prova; não guardar data completa quando uma conclusão de idade basta; não deixar score oculto ou decisão manual sem evidências determinar titularidade.
Capturas reais do app de operação: ficha, ações e confirmações no celular do operador.
Em escrita
Cobrar direto, fora da comissão
PIX e cartão via provedor web (Mercado Pago) — o desenho já fala em «onde a pessoa paga» de forma genérica.
Em escrita
Self-hosted em uma tarde
Instalação guiada e repetível, cada serviço com seu banco, e o que a versão gratuita inclui (spoiler: tudo).
Em escrita
Figuras e capturas próprias
Hoje o material visual real é do laboratório; as telas entram com as próximas edições.
Próxima edição
Guias para outras stacks
Publicar o contrato raw server-to-server e exemplos de BFF fora do ASP.NET Core, sem levar a credencial de integração para o cliente.
para quem chegou até aqui
O que falta
Lista do que o projeto precisa para andar mais rápido — da ajuda que mais acelera para a
mais simples.
01Uso como laboratórioRodar seu app sobre a plataforma, com usuário e cobrança reais, e reportar o que
quebrar. Bug de produção vale mais que roteiro de teste.
02Trabalhar como desenvolvedorPôr a mão no código: .NET, PostgreSQL e React Native — continuidade de
conta, billing nas duas stores, oferta dirigida.
03Ideias e sugestõesApontar o que está errado, o que falta, o que ninguém pensou. Não precisa
programar para melhorar o produto.
04InfraestruturaServidor, máquina de build, banco, ambiente de teste, aparelho para validar compra
nas stores. Emprestado serve.
05Créditos de IACrédito de API que sobra no mês, licença ociosa.
06Contas para integrarAdquirente e meio de pagamento, conta bancária, WhatsApp Business, redes sociais.
Sandbox ou produção — sem conta real, integração não se testa.
07Custos fixosConta de desenvolvedor nas stores, certificado, envio de SMS.