João Pedro

Command Palette

Search for a command to run...

Command Palette

Search for a command to run...

Cliax, Gestão para Clínicas

Detalhes do Projeto

Período:
09.2026 → hoje
  • Company Project
  • TypeScript
  • Next.js
  • React 19
  • PostgreSQL
  • Row-Level Security
  • SaaS Multi-tenant
  • Prisma
  • Better Auth
  • BullMQ
  • fast-check
  • Playwright
  • Docker
  • LGPD
Logo de Cliax, Gestão para Clínicas
Cliax, Gestão para Clínicas

Impacto em números

Tabelas com RLS
54

De 66 em produção, isoladas por clínica no banco

Testes de Integração
761

Contra Postgres real, com as suítes de isolamento

Do 1º Commit ao Ar
1 dia

21/09 → 22/09/2026

Códigos CID-10
14.233

Lista oficial do DATASUS, com busca sem acento

A transformação

Antes
Depois
Crediário próprio em planilha, caderno ou na memória da recepção
+Parcelas geradas sozinhas a partir de uma venda
Venda parcelada virando uma dúzia de lançamentos à mão
+Contas a receber por período e inadimplência com dias de atraso
Ninguém sabendo quanto entra nos próximos 15 dias
+Painel em que todo número abre a lista que o compõe
Agenda, prontuário e financeiro em lugares diferentes
+Agenda, prontuário, documentos e financeiro no mesmo sistema
Isolamento entre clientes dependendo de alguém lembrar do filtro
+Isolamento entre clínicas garantido pelo Postgres e cobrado por teste

Sobre o projeto

Clínica que parcela tratamento caro convive com três problemas de uma vez. Ninguém responde rápido quanto entra nos próximos quinze dias. Cada venda parcelada vira uma dúzia de lançamentos feitos à mão, e erro de digitação vira briga com paciente. E agenda, prontuário e financeiro moram em lugares diferentes, quando moram em algum.

O Cliax começa por essa conta. A venda de R$ 5.000 com R$ 1.000 de entrada e quatro parcelas todo dia 20 é lançada uma vez, e as parcelas se geram sozinhas. O painel do gerente segue uma regra só: todo número abre a lista que o compõe, e a soma da lista bate com o cartão.

A decisão que eu mais defendo no projeto é onde mora o isolamento entre clínicas. Filtrar por clinicId no código funciona até o dia em que alguém esquece um where. Aqui a aplicação conecta ao Postgres com um papel sem BYPASSRLS, e toda tabela com dado de clínica tem política de Row-Level Security. Se a política falhar, a consulta volta vazia, e não com o dado do vizinho.

Regra que ninguém cobra vira sugestão. As suítes rls-coverage e tenant-isolation quebram de propósito quando alguém cria uma tabela com clinicId e esquece a política ou a fábrica de teste. Desligar o RLS derruba 7 testes, e um teste de mutação confirmou que as suítes pegam a falha. Antes de adotar, medi o custo: cerca de 6 ms por transação, não por consulta. Isso virou regra de código, e cada tela agrupa as leituras numa transação só.

O prontuário vai pelo mesmo caminho. Recepção, financeiro e até o dono sem papel clínico recebem zero linhas, mesmo consultando o banco direto. Registro finalizado é travado por gatilho, correção entra como adendo com autor e hora, e cada registro leva um hash encadeado ao anterior do mesmo paciente. O PDF do prontuário confere a cadeia.

O resto é o que uma clínica espera encontrar, feito com o mesmo cuidado:

  • agenda com cinco visões, arrastar para remarcar e conflito de horário barrado no banco;
  • documentos com papel timbrado, variáveis e um QR que qualquer pessoa usa para conferir se o atestado é verdadeiro;
  • prescrição pela Memed com o paciente já preenchido, esperando a homologação deles para ligar;
  • link de reservas público, com limite por IP e por celular e o desafio anti-robô da Cloudflare pronto para ligar;
  • o financeiro completo, construído e testado na última semana de setembro: taxa de cartão com recebível, caixa da recepção, repasse de profissionais, conciliação bancária por OFX, fechamento de mês e o lote do Carnê-Leão no layout da Receita.

Dinheiro é sempre inteiro em centavos, e data de vencimento é DATE, para não escorregar no fuso. O monólito é modular e o ESLint cobra as fronteiras: módulo não importa Next, domain/ não importa banco e ninguém entra no miolo de outro módulo sem passar pelo index.ts.

O desafio

Velocidade sem trava é imprudência. O primeiro commit é de 21 de setembro, e o sistema estava no ar no dia 22. Isso só foi possível porque a trava chegou antes da pressa: TDD nas regras de domínio, teste de propriedade com fast-check nos invariantes financeiros, integração contra Postgres de verdade e uma revisão de segurança a cada marco. Numa delas apareceram um redirecionamento aberto na entrada do modo suporte e um esgotamento de conexões no backoffice. Os dois foram fechados antes de alguém usar.

O mais difícil foi dizer não. Convênio, nota fiscal e odontograma ficaram para depois de propósito, e o produto está em piloto para aprender com clínica de verdade antes de endurecer regra que ninguém usou.

Métricas de Crescimento

Testes de integração ao longo da semana

761testes
1148%
F0F225/09

Resultados

No ar desde 22/09/2026, em piloto. Em produção são 66 tabelas, 54 delas isoladas por RLS, e a suíte de integração passa 761 testes contra Postgres real. Em cinco dias ficaram prontos o financeiro, a agenda, o prontuário, os documentos clínicos, a integração com a Memed, o link de reservas e o backoffice de suporte, com segundo fator obrigatório para quem mexe com dado clínico.

Stack técnica

01

Next.js 16 e React 19

Monólito modular: rotas e server actions em src/app, regra de negócio em módulos que não conhecem o Next.

02

PostgreSQL 17 com Row-Level Security

A aplicação conecta como app_user, sem BYPASSRLS, e toda tabela com dado de clínica tem política.

03

Prisma 7

82 models e 33 migrations, publicadas em duas etapas: schema primeiro, código depois.

04

Better Auth

Segundo fator obrigatório para quem administra a clínica e para quem mexe com dado clínico.

05

BullMQ e Redis

Rotinas diárias idempotentes: alertas de vencimento, conciliação da cobrança e recebíveis de cartão.

06

Gotenberg

PDF de recibo, carnê, prontuário e documento clínico, gerado uma vez e guardado.

07

Vitest, fast-check e Playwright

Unidade, propriedade, integração contra Postgres real e jornadas no navegador.

08

Asaas e Memed

Cobrança com baixa automática por webhook e prescrição digital dentro do atendimento.

Galeria(2)

Cliax, Gestão para Clínicas, imagem 1
Cliax, Gestão para Clínicas, imagem 2