Do contrato assinado à cobrança recebida, num sistema só.
Construí e mantenho o sistema interno de um escritório de advocacia: Node.js, PostgreSQL e oito integrações externas, em produção e uso diário por cinco perfis. Trabalho na fronteira entre sistemas — onde a documentação diz uma coisa e a API devolve outra.
Panorama
arquitetura, código
e operação Falha silenciosa 2 meses sem
evento de assinatura
Do contrato ao pós-venda, num sistema só
A operação vivia em planilha e WhatsApp: contrato redigido à mão, assinatura perseguida por mensagem, cobrança lembrada de cabeça, pós-venda sem dono. Construí a aplicação que fecha esse ciclo — geração do contrato e da procuração em PDF, assinatura eletrônica, cobrança, comissões e acompanhamento pós-venda — com controle de acesso por papel para cinco perfis.
- Regra de negócio como função pura. Os motores — cobrança, comissão, etapa de pós-venda, follow-up — não sabem o que é banco nem HTTP. Recebem estado, devolvem decisão. É o que torna possível testar a régua dia a dia, isolada, e mudar regra sem derrubar o que roda.
- Integração nunca bloqueia o caminho crítico. Drive, Discord e CRM entram como efeito lateral isolado. Se o Drive cair, o contrato ainda é assinado.
- Estado derivado, nunca digitado. Onde o dado pode ser calculado do que já existe, ele é calculado. Campo que depende de alguém lembrar de preencher apodrece — e painel com dado podre é pior que painel nenhum.
Depois de migrar de servidor, o webhook de assinatura continuou apontando para o endereço antigo — eu esqueci de trocar. Por cerca de dois meses nenhum evento de assinatura chegou, e nada pareceu quebrado: o sistema se corrige ao consultar o provedor, mas só quando alguém abre a tela daquele contrato. Arquivamento, cadastro no CRM e as tarefas da equipe ficaram todos esperando um clique que ninguém sabia ser necessário.
Recadastrar o webhook levava trinta segundos. Em vez disso escrevi uma varredura horária que confere as assinaturas pendentes direto na fonte, à prova de execução simultânea entre réplicas — porque automação não pode depender de alguém lembrar de abrir uma tela. Código correto não é o mesmo que código chegando: verifique a entrega, não só a implementação.
A interface é a real, renderizada com uma resposta de API fabricada — nenhum dado do escritório aparece aqui. Cada cartão fecha numa ação: número que não vira decisão não entra na tela.
Stack Node.js · Express · PostgreSQL (pg, sem ORM)
· JWT · bcrypt · TOTP/2FA · helmet · rate limiting
· PWA · Docker Swarm + Traefik em VPS
não documentados Maior lacuna 377 de 447
registros
A resposta vinha 200, bem formada, e incompleta
O acompanhamento das famílias dependia de uma pergunta simples: quais processos tiveram andamento no tribunal? A resposta se mostrou não confiável de cinco maneiras diferentes — nenhuma delas anunciada por um erro. Passei a medir cada uma contra a API real, em vez de deduzir da documentação.
Quatro são comportamentos que a documentação não descreve. Nenhuma dá para deduzir lendo:
- A listagem entrega menos do que ela mesma declara. 377 clientes num corpo
que anuncia 447; 157 tarefas anunciando 169. O
totalCountdenuncia a própria resposta, e paginar por offset não alcança o resto. - Tarefa concluída sai da lista de criadas e passa a existir só na de concluídas. Lendo uma só, metade do histórico some sem aviso — e o que some é justamente o trabalho que foi terminado.
- O filtro por origem é aceito e ignorado. Um andamento escrito pelo próprio sistema volta como se fosse do tribunal. O que separa é outro campo.
- E a chamada barata perde justamente esse campo. A versão em lote devolve nulo onde estaria a origem — então a consulta eficiente é a que não permite decidir.
Por que isso importa Aqui a consequência de acreditar na resposta seria avisar a família de um cliente preso sobre um boleto achando que era notícia do processo.
Cheguei a reportar que um processo não tinha andamento nenhum. Tinha 23. Eu havia
chamado um caminho que não existe — e essa API responde 200 com
lista vazia, não 404. O caminho certo estava na
documentação; eu tinha consultado um resumo interno.
Duas regras saíram daí: resumo não é fonte, e um
200 vazio não distingue “não tem” de
“perguntei errado”.
A tela que nasceu do achado acima. Quando não há número de processo, ela diz “normal nesta etapa” em vez de “sem novidade” — porque não saber e não haver são estados diferentes.
Virou código
advbox-client
— biblioteca aberta que trata essas armadilhas: nenhuma listagem devolve array, todas
devolvem { itens, total, completa }. Sem dependências, 28 testes, MIT.
sem I/O
Uma régua de cobrança que não pode pular etapa
Cobrar o primeiro pagamento é uma escada: boas-vindas, relacionamento, aviso antes do vencimento, cobrança em atraso, triagem, decisão. O erro fácil é fazer a escada andar pelo calendário — aí um dia perdido pula um degrau e o cliente recebe a cobrança sem nunca ter recebido as boas-vindas.
- O avanço lê a conclusão real, não a data. Um degrau só nasce quando o anterior foi efetivamente concluído no sistema da equipe. Dia perdido atrasa; nunca pula.
- Só existe uma tarefa aberta por vez. Invariante do motor, não convenção de quem usa.
- Reconciliação em vez de fila. O motor recebe o estado atual e devolve uma decisão. Rodar duas vezes no mesmo dia não duplica nada.
Consequência prática Como o motor não faz I/O, a régua inteira é testável dia a dia em memória — inclusive os casos que na vida real levariam semanas para acontecer.
conhecidos 2 marcados
como ativos
Cruzar o diário oficial com a carteira de processos
O Diário de Justiça Eletrônico Nacional tem API pública do CNJ, sem autenticação. Levantei o que ela entrega de verdade — volume, cobertura por tribunal, quanto do texto permite extrair prazo — e cruzei as publicações de 30 dias contra a carteira cadastrada no sistema jurídico.
29 processos receberam publicação em 30 dias. 27 existiam no cadastro — mas apenas 2 constavam como ativos. A lista de “processos em andamento” que a equipe consultava não descrevia a realidade, e ninguém tinha como saber: a fase é digitada à mão e envelhece em silêncio, enquanto o tribunal continua andando.
Também medi o que não dá para prometer: só 39% dos textos trazem prazo extraível, e parte das publicações é sigilosa e não traz teor nenhum. Uma ferramenta que calcule prazo automático em cima disso precisa dizer quando não sabe, em vez de calar.
Estágio Levantamento e prova de conceito concluídos; a integração contínua está desenhada, ainda não em produção.
Ponto de método Medir a cobertura da fonte antes de desenhar a tela. O custo de descobrir depois é uma interface que mente com confiança.
Obra Integrada — controle de acesso de ponta a ponta
Sistema acadêmico de gestão de obras, sete pessoas, fluxo com branches e pull requests. Segundo maior contribuidor do repositório. Se o sistema do escritório prova que eu construo sozinho, este prova que eu construo acompanhado — revisando e integrando o trabalho dos outros.
- Projetei e implementei o RBAC inteiro: matriz de perfis × permissões como fonte única, guarda nas rotas do backend e nos componentes do frontend.
- Modelagem de dados com Prisma sobre PostgreSQL — 33 entidades entre obras, etapas, materiais, estoque, requisições, financeiro, RH e auditoria.
- Integração do trabalho do time: revisão e merge de PRs, resolução de conflitos de dependência, padronização dos scripts de banco e dos
.env.example.
Stack React 19 · Vite · Tailwind · Node/Express · Prisma ORM · PostgreSQL
todos entregues
íbis
App para guardar frases que marcam. PWA com share target: instalado no celular, aparece na folha de compartilhamento do sistema — guardar uma frase vira dois toques. React 19, Express serverless, Prisma.
Koyo Creative
Painel de gestão de estúdio criativo. Next.js, shadcn/ui, deploy na Vercel. 48 commits. Kanban com progresso derivado do estado real, nunca digitado.
Relatório de tráfego pago
Cruza a Graph API do Meta Ads com o funil do CRM e gera tendência semanal — custo por conversa, CTR, alcance × leads qualificados. Python, só stdlib, sem persistir dado pessoal.
Chatbot de qualificação
Fluxo em n8n integrado ao CRM, em produção, qualificando lead antes de chegar em pessoa.
Observabilidade em Discord
33 canais e 22 webhooks alimentados por três fontes, mais uma ferramenta read-only que inventaria a topologia e marca cada afirmação como confirmada em código, inferida ou a verificar.
consigo explicar
Backend
Segurança
Frontend
Infra
Integrações em produção Asaas (pagamentos) · ZapSign (assinatura eletrônica) · Google Drive · Kommo e ADVBOX (CRMs) · Meta Ads · OpenAI · Discord
Explorado, fora de produção DJEN/CNJ (Diário de Justiça Eletrônico Nacional)
Procuro vaga de backend ou full stack, remota
Bacharelado em Sistemas de Informação no UniFOA, previsão de conclusão em 2028.1. Português nativo, inglês com leitura técnica fluente.