Pular para o conteúdo
Voltar aos projetos

JuscIA · jul a out 2026 · manutenção ativa

JuscIA

Plataforma jurídica SaaS com inteligência artificial, resgatada de dois anos sem versão estável e reconstruída em Google Cloud.

1M+

requisições por semana, de forma estável

< R$ 700

de custo mensal de infraestrutura no GCP

~75%

de redução no custo de infraestrutura

Resumo do que fiz

  • Plataforma estabilizada em um mês, depois de dois anos sem versão estável com a equipe anterior.
  • Arquitetura reconstruída em Google Cloud: mais de 1 milhão de requisições por semana com infraestrutura abaixo de R$ 700 por mês, cerca de 75% mais barata.
  • 24 falhas graves de segurança corrigidas, de brechas de acesso entre escritórios a injeção de SQL.
  • Testes de 8 para 63 arquivos, 77 migrações versionadas e processos em produção de 6 para 1.
  • Painel de controle de 13 telas construído do zero e 282 endpoints sob um padrão único.

Tecnologias

Google Cloud (GCP)PostgreSQLCI/CDCDNIA/LLM
JuscIA · painel de operação

Req. / semana

1M+

Infra / mês

< R$700

Usuários

2.951

Requisições por semana

produção

Google Cloud · PostgreSQL · CDN · CI/CD

A virada

O que mudou no projeto

A Juscia me chamou depois de dois anos com uma equipe interna que nunca conseguiu estabilizar o produto. Entrei, auditei o que existia, reescrevi a base da aplicação e, em um mês, entreguei o que a equipe anterior dizia não ser possível. É o tipo de trabalho que faço: encontrar falhas, arquitetura ruim e código ruim, e corrigir. Os números abaixo foram apurados no próprio repositório do projeto.

1 mês

Para estabilizar o que 2 anos de equipe anterior não conseguiram.

< 1 semana

Para entregar dois recursos que a equipe anterior dizia serem impossíveis.

< 10%

Era a satisfação dos usuários antes de eu assumir o projeto.

24

Falhas graves de segurança corrigidas, da senha universal a brechas de acesso entre escritórios.

Arquitetura

A infraestrutura antes e depois

Cada linha da coluna da esquerda é o estado que encontrei. À direita, o que ficou no lugar.

Antes

Depois

Tudo numa única VM, sem separação de serviços
Infraestrutura na Google Cloud, com serviços dedicados
6 processos em produção: a API e mais 5 serviços auxiliares em Python
1 processo em produção, com as filas rodando dentro da própria API
Agendamento e follow-up disparados por chamada HTTP sem retentativa
Jobs persistentes em fila Redis, com 3 retentativas automáticas
Esquema do banco sincronizado automaticamente em produção
77 migrações versionadas no controle do banco
Uma senha universal com acesso a qualquer conta do sistema
Senha temporária de 30 min, sob demanda, guardada só como hash
CORS liberado para qualquer origem e sem cabeçalhos de segurança
CORS restrito às origens conhecidas e cabeçalhos de segurança aplicados
Nenhum painel de controle pra equipe
Painel de controle completo, com 13 telas
Infraestrutura sem nenhuma capacidade de escalar
Arquitetura pronta pra escalar horizontalmente

Problema e solução

Ponto a ponto, o que estava errado e o que fiz

Cada par mostra o problema encontrado e a correção aplicada.

O que encontrei

Tudo numa única VM

API e serviços auxiliares dividiam a mesma máquina virtual, sem separação, sem redundância e sem capacidade de escalar. Qualquer pico de uso ou falha atingia o sistema inteiro de uma vez.

O que fiz

Infraestrutura reconstruída na Google Cloud

Banco, cache e armazenamento passaram a rodar em serviços dedicados, cada um configurado e protegido por conta própria, no lugar de tudo dividindo a mesma máquina.

O que encontrei

Seis processos rodando em paralelo

Além da API, mais cinco serviços auxiliares escritos em Python ficavam no ar o tempo todo, na mesma máquina, cada um com a própria porta e o próprio ciclo de vida pra alguém acompanhar.

O que fiz

Os cinco serviços em Python saíram do ar

Foram substituídos por filas sobre Redis, rodando dentro da própria API. Cinco processos a menos pra manter no ar, monitorar e reiniciar.

O que encontrei

Follow-up e agendamento sumiam em silêncio

O disparo dependia de uma chamada HTTP direta pra esses serviços auxiliares. Se o processo estivesse fora do ar ou reiniciando, a falha era engolida: não havia retentativa, não havia alerta, e o follow-up simplesmente desaparecia sem ninguém ficar sabendo.

O que fiz

Agendamento e follow-up viraram jobs persistentes

Cada tarefa entra numa fila que sobrevive a reinício do servidor, com 3 retentativas automáticas e espera crescente entre elas. Se algo falha, a fila tenta de novo em vez de perder o trabalho.

O que encontrei

Treze falhas de acesso entre escritórios

Um usuário autenticado de um escritório conseguia ler, editar ou apagar dados de outro escritório apenas trocando um identificador numérico na requisição. Eram treze pontos diferentes do sistema, da transferência de conversa aos quadros de kanban.

O que fiz

Treze falhas de acesso fechadas

O escopo do cliente passou a ser aplicado em todas as consultas. Pedir o dado de outro escritório agora devolve 404 em vez de entregar o registro.

O que encontrei

Rotas sem autenticação e uma injeção de SQL

Cinco endpoints respondiam a qualquer um que os chamasse, sem exigir login, um deles devolvendo a lista completa de usuários com e-mail. Uma rota de contagem também tinha uma injeção de SQL, por montar a consulta concatenando texto.

O que fiz

Rotas abertas fechadas e injeção de SQL corrigida

As cinco rotas sem autenticação passaram a exigir login, e a consulta vulnerável foi reescrita com parâmetros.

O que encontrei

Webhooks abertos

Os webhooks aceitavam qualquer chamada, sem validar a origem. Na prática, dava pra forjar um evento de entrada e fazer o sistema reagir a algo que nunca aconteceu.

O que fiz

Webhooks passaram a validar origem

Cada chamada precisa apresentar o token da instância. O que não valida é descartado.

O que encontrei

Credenciais escritas no código

Chaves de serviços externos estavam fixas no código-fonte. Quem tivesse acesso ao repositório, ou ao histórico dele, tinha as credenciais junto.

O que fiz

Credenciais fora do código

Todas as chaves saíram do código-fonte e passaram a vir de variáveis de ambiente.

O que encontrei

CORS liberado e sem cabeçalhos de segurança

A API aceitava requisição de qualquer origem e não enviava nenhum dos cabeçalhos de segurança que o navegador usa pra proteger o usuário.

O que fiz

CORS restrito e cabeçalhos de segurança aplicados

A API passou a aceitar só as origens conhecidas e a enviar os cabeçalhos de segurança que o navegador usa pra proteger o usuário.

O que encontrei

Uma senha universal abria qualquer conta

Existia uma senha única que dava acesso a qualquer conta do sistema, prática que a equipe anterior considerava aceitável.

O que fiz

Senha universal removida

No lugar dela, senha temporária gerada sob demanda no painel de controle: válida por 30 minutos, restrita a uma única conta, revogável a qualquer momento, guardada apenas como hash e exibida uma única vez a quem a gerou. A senha do próprio cliente continua valendo e não muda.

O que encontrei

Token de autenticação no localStorage

O token ficava guardado no armazenamento local do navegador, de onde qualquer script rodando na página consegue lê-lo.

O que fiz

Autenticação reescrita com dois tokens

O token de acesso vive só em memória e dura 15 minutos. A renovação fica num cookie httpOnly, que o JavaScript da página não consegue ler. Nenhum token voltou a ser gravado no navegador.

O que encontrei

Dados pessoais nos rastros de telemetria

Telefone, nome e conteúdo de mensagem do WhatsApp eram gravados nos rastros de monitoramento da aplicação, sem nenhuma anonimização, fora de conformidade com a LGPD.

O que fiz

Dados pessoais fora da telemetria

Telefone, nome e conteúdo de mensagem deixaram de ser gravados nos rastros de monitoramento, em conformidade com a LGPD.

O que encontrei

Banco sincronizado automaticamente em produção

O ORM alterava o esquema do banco sozinho a cada subida, sem migração versionada. O que existia eram dez arquivos SQL soltos, sem controle de ordem e sem histórico confiável do que já tinha sido aplicado.

O que fiz

Banco sob controle de migrações

A sincronização automática de esquema foi desligada em produção. Hoje são 77 migrações versionadas, aplicadas em ordem e com histórico do que já rodou.

O que encontrei

IDs sequenciais e fáceis de adivinhar

As tabelas centrais do banco usavam identificador numérico sequencial, o tipo de chave que facilita adivinhar o próximo registro só somando um ao anterior, exatamente o que abria as falhas de acesso entre escritórios.

O que fiz

Chaves primárias migradas para UUID

As 12 tabelas centrais deixaram de usar inteiro sequencial. Além de facilitar integração, tira do caminho a adivinhação de identificador que abria as falhas de acesso.

O que encontrei

Oito arquivos de teste no projeto inteiro

O back-end inteiro tinha oito arquivos de teste automatizado. Na prática, quase toda mudança dependia de teste manual pra não quebrar alguma coisa.

O que fiz

Suíte de testes de 8 para 63 arquivos

Mais de 770 testes rodando na última execução registrada, cobrindo o caminho crítico do sistema.

O que encontrei

Serviços gigantes, difíceis de manter

Alguns serviços chegavam a mais de 1.800 linhas de código numa função só, o que tornava qualquer mudança arriscada e praticamente impossível de testar em partes.

O que fiz

Serviços gigantes decompostos

Entre eles, um de 1.800 linhas. A quebra foi feita sempre começando pelos testes, pra garantir que o comportamento não mudasse no caminho.

O que encontrei

Consultas N+1 nos relatórios

Relatórios, dashboard e kanban faziam uma consulta ao banco pra cada item da lista, em vez de uma consulta só trazendo tudo de uma vez. Quanto mais dado, mais lenta ficava a tela.

O que fiz

Três consultas em cascata eliminadas

Relatórios, dashboard e kanban faziam uma consulta por item retornado. Viraram uma consulta agregada só.

O que encontrei

Relatório de vendas somava o escritório inteiro

O número de vendas mostrado pra um atendente era, na prática, a soma do escritório inteiro, não o total individual dele.

O que fiz

Erro de escopo em relatório corrigido

Cada atendente estava vendo o total do escritório inteiro no lugar do próprio número.

O que encontrei

Uma falha derrubava o servidor inteiro

Um erro no envio de uma única mensagem não ficava contido: derrubava o processo e, com ele, o sistema todo.

O que fiz

Falha de envio isolada

Um erro ao enviar uma mensagem passou a ficar contido nela mesma, sem derrubar o restante do sistema.

O que encontrei

Deploy manual aos domingos, sem esteira de integração contínua

Publicar uma versão era procedimento manual, só feito na madrugada de domingo pra reduzir o risco de atrapalhar quem estava usando. Não havia verificação automática a cada mudança: as checagens de qualidade existiam apenas num gancho local de commit, que qualquer pessoa podia pular.

O que fiz

Esteira de deploy automatizada

Publicar deixou de ser procedimento manual de madrugada de domingo.

O que encontrei

Interface difícil até pro básico

A interface era pouco funcional a ponto de tarefa simples do dia a dia virar obstáculo.

O que fiz

Front-end migrado para Angular 18

Com design system próprio baseado em tokens: uma fonte única de verdade pra cor, espaçamento e tipografia, no lugar de valor solto espalhado pelas telas.

O que encontrei

Bot e CRM sem funcionar

O bot de atendimento respondia errado quando respondia, e o CRM estava praticamente fora de uso.

O que fiz

Tema claro e escuro completo

A paleta foi gerada a partir da marca da Juscia, com contraste verificado, e o tema acompanha a preferência do sistema operacional.

O que encontrei

Paleta de gráficos ilegível pra quem tem daltonismo

As cores usadas nos gráficos ficavam praticamente indistinguíveis pra quem tem os tipos mais comuns de daltonismo, sem nenhuma validação de contraste entre elas.

O que fiz

Paleta de gráficos validada para daltonismo

As séries continuam distinguíveis nos três tipos de deficiência de visão de cores, verificado por medição de distância de cor, não no olho.

O que encontrei

Cinquenta e seis erros de acessibilidade no front-end

O front-end tinha 56 problemas de acessibilidade identificados, do tipo que dificulta o uso por quem depende de leitor de tela ou navegação por teclado.

O que fiz

Cinquenta e seis erros de acessibilidade corrigidos

E a verificação passou a travar a entrega se algum voltar.

O que encontrei

Dois anos sem uma versão estável

O projeto rodava havia dois anos e nunca tinha chegado a uma versão que a própria equipe considerasse estável em produção.

O que fiz

Carregamento com esqueleto de conteúdo

No lugar de giradores, cada tela mostra um esqueleto com as mesmas medidas do conteúdo real, então a página não pula quando os dados chegam.

O que encontrei

Nenhum painel de controle

A equipe da Juscia não tinha nenhuma tela administrativa. Qualquer ação de gestão precisava ser feita direto no banco de dados.

O que fiz

Painel de controle construído do zero

Treze telas, onde antes não havia nenhuma.

O que encontrei

Satisfação abaixo de 10%

Menos de um em cada dez usuários se dizia satisfeito com a plataforma.

O que fiz

Planos modulares e acompanhamento de processos

Os dois recursos que a equipe anterior dizia serem impossíveis, entregues e funcionais em menos de uma semana.

O que encontrei

Infraestrutura cobrando pelo que ninguém usava

O custo não tinha relação com o tamanho da base de usuários. Havia revisões antigas do serviço esquecidas no ar, sendo cobradas todo mês sem atender ninguém.

O que fiz

Custo de infraestrutura reduzido em cerca de 75%

Revisões ociosas desligadas e recursos redimensionados pro uso real, sem tirar capacidade de quem usa.

O que encontrei

Código sem padrão nenhum entre as partes do sistema

Cada parte do sistema seguia uma convenção diferente de código e de arquitetura, sem nada documentado pra próxima pessoa seguir.

O que fiz

Padronização de código e arquitetura

Um padrão único em todo o back-end, com as decisões de arquitetura registradas e documentação escrita por módulo, pra próxima pessoa não precisar adivinhar o porquê.

Entrega

Os números apurados no repositório

Nenhum número aqui é estimativa: todos saíram do próprio repositório do projeto.

24

Falhas de segurança corrigidas, de brechas de acesso a credenciais expostas.

~75%

De redução no custo mensal de infraestrutura.

282

Endpoints que a API expõe hoje, sob um padrão único.

13

Telas no painel de controle que a Juscia não tinha antes.

Migrações de banco versionadas

arquivos de migração

Antes10
Depois77

No lugar da sincronização automática de esquema direto em produção.

Arquivos de teste no back-end

arquivos de teste

Antes8
Depois63

Mais de 770 testes rodando na última execução registrada.

Processos rodando em produção

processos

Antes6
Depois1

Os cinco serviços auxiliares em Python viraram filas dentro da própria API.

Cobertura de testes

42,6%

Linhas cobertas

Última medição registrada, partindo de 8 arquivos de teste no projeto inteiro.

Falhas de segurança corrigidas, por tipo

Acesso indevido a dados de outro escritório13
Rotas sem autenticação5
Credenciais escritas no código3
Webhooks sem validação de origem2
Injeção de SQL1

Frentes de trabalho

Tudo que foi feito, por área

A entrega dividida nas frentes que ela realmente teve.

Segurança e acesso

Da senha universal às brechas entre escritórios, o que protegia menos do que devia.

Senha universal removida

Substituída por senha temporária de 30 minutos, gerada sob demanda, restrita a uma conta e revogável.

Senha guardada só como hash

Exibida uma única vez a quem a gerou, nunca guardada em texto puro depois disso.

Treze brechas de acesso fechadas

Escopo do cliente aplicado em todas as consultas, entre escritórios diferentes.

Rotas abertas e injeção de SQL corrigidas

Cinco rotas sem autenticação passaram a exigir login, e a consulta vulnerável foi corrigida.

Tokens fora do navegador

Acesso em memória por 15 minutos, renovação num cookie httpOnly que o JavaScript não lê.

Cabeçalhos de segurança e CORS restrito

A API só aceita as origens conhecidas e envia os cabeçalhos que protegem o usuário.

Dados pessoais fora da telemetria

Telefone, nome e mensagem deixaram de ser gravados nos rastros de monitoramento, em conformidade com a LGPD.

Auditoria e bloqueio de IP

Tela de saúde do sistema, com bloqueio de IP manual ou automático.

Confiabilidade da operação

Onde a operação parava de responder, e como ela passou a se recuperar sozinha.

Cinco serviços em Python saíram do ar

Viraram filas rodando dentro da própria API.

Jobs persistentes

Agendamento, follow-up e resposta sobrevivem a reinício do servidor.

Três retentativas automáticas

Por job, com espera crescente entre uma tentativa e outra.

Falha de envio isolada

Um erro ao enviar uma mensagem não derruba mais o restante do sistema.

Três consultas em cascata eliminadas

Nos relatórios, no dashboard e no kanban.

Erro de escopo em relatório corrigido

Cada atendente via o total do escritório inteiro; agora vê só o próprio número.

Banco e arquitetura

Como os dados e o código passaram a ter controle de versão e um padrão único.

Sincronização automática desligada

O esquema do banco não muda mais sozinho em produção.

77 migrações versionadas

Assumiram o controle do banco, em ordem e com histórico do que já rodou.

Chaves primárias em UUID

Nas 12 tabelas centrais, no lugar do inteiro sequencial fácil de adivinhar.

Serviços gigantes decompostos

A quebra foi feita sempre começando pelos testes.

Tipos em modo estrito

Verificação ligada em todo o projeto, não só em partes novas.

Decisões de arquitetura registradas

Documentação escrita por módulo, pra próxima pessoa não precisar adivinhar o porquê.

Interface e experiência

Do framework à acessibilidade, o que mudou pra quem usa o sistema todo dia.

Front-end migrado para Angular 18

A base do front-end saiu de uma versão antiga direto pro Angular 18.

Design system baseado em tokens

Uma fonte única de verdade pra cor, espaçamento e tipografia.

Tema claro e escuro completo

Segue a preferência do sistema operacional automaticamente.

Paleta gerada a partir da marca

Contraste verificado, não só escolhido no olho.

Paleta de gráficos validada

Pros três tipos mais comuns de daltonismo.

56 erros de acessibilidade corrigidos

A verificação trava a entrega se algum erro voltar.

Esqueleto de conteúdo no carregamento

No lugar de giradores, espelhando o layout real da tela.

Avisos e erros unificados

Numa camada só, no lugar de vários padrões espalhados.

Painel de controle, que não existia

Treze telas que a equipe da Juscia não tinha antes, construídas do zero.

13 telas construídas do zero

Onde antes não havia nenhuma tela administrativa.

Visão geral da operação

Usuários, planos, pacotes e cupons, tudo numa tela só.

Agentes e custos

Custo de IA e custo de consulta processual.

Processos

Lista e o detalhe de cada um.

Auditoria e saúde do sistema

Acompanhamento do estado geral da operação.

IPs bloqueados

Bloqueio manual ou automático, com histórico de tentativas.

Senha temporária pelos gerentes

Emissão e revogação de senha temporária pra qualquer conta, direto do painel.

Confiabilidade

Como a operação passou a se comportar

Mensagem perdida
AntesAcontecia
DepoisNunca mais
Follow-up perdido
AntesAcontecia
DepoisNunca mais
Bot deixava de responder
AntesAcontecia
DepoisNunca mais
Agendamento perdido
AntesAcontecia
DepoisNunca mais
Uma falha derrubava o servidor
AntesAcontecia
DepoisNunca mais
Retentativa automática
AntesNão existia
Depois3 por job

Resultado

O que a virada entregou na prática

Sistema estável e no ar

Em um mês, depois de dois anos sem conseguir sair do lugar.

Nada mais se perde

Mensagem, follow-up ou agendamento: tudo virou job persistente com retentativa automática.

24 falhas de segurança corrigidas

Entre elas, treze brechas de acesso a dados de outro escritório.

Acesso administrativo sempre temporário

Gerado sob demanda, sem nenhuma senha universal.

Painel de controle com 13 telas

Usado todos os dias pelos gerentes da Juscia.

Banco sob controle de 77 migrações

No lugar da sincronização automática em produção.

Suíte de testes, de 8 para 63 arquivos

Mais de 770 testes rodando na última execução registrada.

Custo de infraestrutura, cerca de 75% menor

Redução no custo mensal de infraestrutura.

Custo de operação reduzido

A uma fração do que a equipe interna anterior consumia.

Recursos antes vistos como inviáveis, no ar

Hoje em produção e usados pelos clientes da Juscia.

Próximo projeto

Toca aê

Ver estudo de caso