Vértice Health Platform
Sistema Mestre
Como o ecossistema funciona, como fazer a engrenagem girar sem computador ligado, como criar novos clientes e como manter tudo saudável.
Como o Ecossistema Funciona
Arquitetura geral — o que existe e onde fica
GitHub (main)
→
GitHub Actions
→
Hostinger
Eriane + Vértice Core
+
Eriane + Vértice Core
Supabase
por cliente
por cliente
Repositório
vertice-health-platform
GitHub:
Branch único: main
Local:
vertice-health/vertice-health-platformBranch único: main
Local:
D:\vertice\platform\vertice-health-platformIsolamento total
Cada cliente = ecossistema próprio
Supabase próprio · Gemini próprio · Domínio próprio · Chaves próprias. Zero dados compartilhados entre clientes.
Stack
HTML · Supabase · Gemini
Frontend: HTML5 + CSS3 + JS ES6+ vanilla (sem frameworks)
Backend: Supabase (Auth + DB + Storage + Edge Functions)
IA: Gemini 2.5 Flash via gemini-proxy Edge Function
Deploy: SCP/rsync para Hostinger via GitHub Actions
Backend: Supabase (Auth + DB + Storage + Edge Functions)
IA: Gemini 2.5 Flash via gemini-proxy Edge Function
Deploy: SCP/rsync para Hostinger via GitHub Actions
Estrutura de pastas
Onde fica o quê
apps/admin/ → Painel Vértice
apps/master/ → Painel médico
apps/tenant/ → Área paciente
apps/client/ → Painel secretaria
core/ → Auth, Supabase, UI
modules/ → Repos + presets
clientes/ → Instâncias por cliente
supabase/ → Patches SQL
scripts/ → Automações Node.js
Processos Automáticos
Tudo que roda sem o computador ligado — GitHub Actions na nuvem
O computador não precisa estar ligado. Todos os deploys, testes e health checks rodam na nuvem via GitHub Actions. O único momento que precisa de computador é para fazer git push (commitar uma mudança).
| Workflow | Gatilho | O que faz | Destino |
|---|---|---|---|
| deploy-eriane-faria.yml | Push em clientes/eriane-faria/** ou core/** |
Faz rsync de clientes/eriane-faria/ para o servidor. Verifica HTTP 200 após deploy. |
draerianefaria.com.br 82.25.67.107:65002 |
| deploy-vertice-core.yml | Push em apps/admin/** |
Faz rsync de apps/admin/ para o servidor. Exclui vertice.config.json. |
core.vertice-ecossistema.com.br 82.180.153.142:65002 |
| health-check.yml | Cron: todo hora (0 * * * *) | Verifica HTTP dos sites. Salva snapshot em client_health_snapshots no vertice-admin. Envia e-mail se offline. |
Supabase vertice-admin wddojycpndvatvqtpiwt |
| playwright.yml | Push em tests/** ou dispatch manual |
Roda 25+ testes Playwright: auth, roles, redirects, secretaria, funcional, unidade. | GitHub (sem deploy) |
| lint.yml | Push em core/**, modules/** |
Roda ESLint + Prettier check nos arquivos JS do core. | GitHub (sem deploy) |
Deploy atrasado ou falhando? O GitHub Actions pode atrasar ou falhar silenciosamente. Sempre confirme via SSH ou verificando o HTTP do site após um push importante. Se falhar, use o deploy manual na seção abaixo.
Criar Novo Cliente
Fluxo completo do zero até produção
Pré-requisito: Cliente precisa ter um projeto Supabase criado (com ref e PAT). NUNCA criar projeto na conta lcunhapereira@gmail.com — usar e-mail próprio do cliente ou criar conta
nomeclinica.vertice@gmail.com.1
Preencher formulário de onboarding
Acesse Onboarding no menu lateral → preencha os 5 passos (empresa, marca, plataforma, plano, revisão) → submeta. O sistema salva em
clientes_admin com status implementacao.2
Step 6 — Gerar e executar o comando de provisionamento
Após o submit, o onboarding avança para o Step 6. Preencha: Supabase Ref + PAT + cores. Clique Gerar Comando e copie o comando gerado. Execute no PowerShell local:
node scripts/provisioning/tenant.js \
--slug joao-silva \
--nome "Dr. João Silva" \
--especialidade "Cardiologia" \
--ref xsffqlbpiwzxkxakjgmb \
--pat sbp_xxxx \
--cor-primaria "#1B3A6B" \
--cor-acento "#C0392B" \
--host 82.25.67.107 --port 65002 \
--ssh-user u707423342 \
--remote-path "/home/u707423342/domains/joao.com.br/public_html"
O script executa 4 etapas: estrutura de arquivos → schema SQL → deploy SSH → ativação. Monitorável via Monitorar progresso no Step 6.
3
Aplicar módulo específico (se cardiologia, etc.)
Para especialidades com schema extra (ex: cardiologia), aplicar o SQL do módulo:
node scripts/provisioning/schema.js \
--ref REF --pat sbp_xxx \
--file supabase/modules/cardiologia.sql
4
Preencher anon_key no config.json e criar usuário médico
Após provisionar, preencher
clientes/[slug]/config.json com a anon_key do Supabase. Criar o usuário médico no Supabase Auth (GoTrue Admin API, não SQL direto). Nunca commitar config.json.5
Verificar e ativar
Rodar
.\scripts\verificar-cliente.ps1 -cliente joao-silva para confirmar que logo, favicon, config e tema.css estão corretos. O tenant.js já atualiza clientes_admin.status = 'ativo' automaticamente.Deploy Manual
Quando o GitHub Actions atrasa ou falha — executar do computador
Admin Vértice
core.vertice-ecossistema.com.br
# PowerShell — envia todos os HTML do admin
scp -P 65002 -i ~/.ssh/hostinger_key -o StrictHostKeyChecking=no `
apps/admin/*.html `
u627878224@82.180.153.142:/home/u627878224/domains/vertice-ecossistema.com.br/public_html/core/
Manual via SCP
Dra. Eriane Faria
draerianefaria.com.br
# PowerShell
powershell -ExecutionPolicy Bypass -File scripts\deploy.ps1 -cliente eriane-faria
Manual via deploy.ps1
Dr. Carlos (demo)
core.vertice-ecossistema.com.br/carlos-mendes
# Python com paramiko
python scripts/deploy-carlos-demo.py
Manual via Python
Novo cliente
Qualquer domínio Hostinger
# Node.js — SSH nativo
node scripts/provisioning/deploy.js `
--slug joao-silva `
--host 82.xx.xx.xx `
--user uXXXXXX `
--remote /home/.../public_html
Automático via tenant.js
Chave SSH:
~/.ssh/hostinger_key — funciona para Eriane (82.25.67.107) e Core Vértice (82.180.153.142). Para servidores de novos clientes, precisará adicionar a chave pública no ~/.ssh/authorized_keys do servidor.Banco de Dados
Patches SQL, como aplicar, o que existe onde
Regra de ouro: Patches são numerados sequencialmente (001, 002…) e NUNCA alterados após aplicação. Para corrigir, criar um novo patch. Sempre confirmar qual projeto Supabase está selecionado antes de rodar.
📋
Aplicar patch SQL em qualquer cliente
node scripts/provisioning/schema.js \
--ref fwqjelwrayxqnxnzlxxj # ref do projeto
--pat sbp_xxx # PAT do projeto
--file supabase/patch-041-ai-usage-log-anon-select.sql
📋
Criar novo patch
Criar arquivo em
supabase/patch-NNN-descricao.sql com o próximo número. Rodar via schema.js. Commitar o arquivo no Git. O patch só vai para o banco via execução manual — não é automático.| Patches importantes | Aplica em | O que cria |
|---|---|---|
| schema.sql | Qualquer novo cliente | 18 tabelas base: usuarios, pacientes, consultas, prontuarios… |
| patch-033 | Clientes (eriane, carlos) | tenant_config, tenant_theme, tenant_modules (config no banco) |
| patch-034 | Clientes | ai_cache — cache de respostas Gemini por 24h |
| patch-035 | Clientes | ai_usage_log — log de chamadas IA (latência, cache, erro) |
| patch-036 | vertice-admin | client_health_snapshots — pings horários do health-check |
| patch-037 | Clientes | error_log — captura window.onerror do JS em produção |
| patch-040 | vertice-admin | provisioning_log — rastreio do provisionamento de tenants |
| patch-041 | Clientes | Política anon SELECT em ai_usage_log (monitoramento do admin) |
| supabase/modules/cardiologia.sql | Clientes cardiologia | 10 tabelas do módulo cardiológico |
Monitoramento (APM)
Saúde dos sites, erros JS, status da IA — tudo visível no dashboard
Health Check horário
health-check.yml
Roda automaticamente todo hora. Pinga os 3 sites (Eriane, Carlos, Core). Salva o resultado em
Automático
client_health_snapshots no vertice-admin. Se offline → e-mail automático via GitHub.Erros JS em produção
error-logger.js
Captura
Automático
window.onerror e unhandledrejection em todas as 39 páginas da Eriane. Salva silenciosamente em error_log no Supabase do cliente. Visível no dashboard → Monitoramento.Status da IA Gemini
ai_usage_log 🟢🟡🔴
Cada chamada ao gemini-proxy registra: tokens, latência, cache hit, erro. O dashboard admin mostra 🟢 (OK) / 🟡 (sem chamadas) / 🔴 (chave inválida ou quota) por cliente.
Automático
Ver tudo
Dashboard → Monitoramento
No dashboard.html, seção Monitoramento: status de cada servidor, uptime %, status da chave Gemini por cliente e últimas chamadas de IA.
Manual — verificar
IA — Gemini Proxy
Como a IA funciona, onde fica a chave, como monitorar
Browser (página)
→
gemini-proxy
Edge Function Supabase
→
Edge Function Supabase
ai_cache
24h TTL
→
24h TTL
Gemini API
google.com
google.com
🔑
Chave Gemini — onde fica
A chave fica somente nos secrets do Supabase do cliente (nunca no código). Para ver/editar: Supabase Dashboard → Edge Functions → gemini-proxy → Secrets →
GEMINI_API_KEY. Começa com AQ.Ab (formato novo Google), nunca AIzaSy.🔄
Cache de 24h
Respostas com mais de 500 tokens são cacheadas na tabela
ai_cache por 24h. Se a mesma pergunta chegar novamente, o proxy responde do cache sem chamar a Gemini API. Economiza quota e reduz latência.🚨
Chave inválida ou quota esgotada
O dashboard mostra 🔴 no cliente. Verificar em
ai_usage_log o campo error — se contiver HTTP 429 = quota esgotada; HTTP 401 = chave inválida. Corrigir o secret no Supabase e re-deployar a Edge Function se necessário:supabase functions deploy gemini-proxy --project-ref REF --no-verify-jwtPropagação de Código
Como as atualizações chegam de template-master para todos os clientes
Regra Template Master First: Nenhuma feature vai direto em cliente. Sempre:
template-master/ → teste → aprovação → rodar update-all.js → deploy.1
Sincronizar core/ → template-master + clientes
# Propaga core/supabase/, core/auth/, core/ui/ para todos os clientes
node scripts/sync-core.js
2
Propagar template-master → clientes
# Todos os clientes
node scripts/update-all.js --todos
# Cliente específico
node scripts/update-all.js --cliente eriane-faria
# Simular sem alterar
node scripts/update-all.js --todos --dry-run
O update-all.js também propaga automaticamente
apps/tenant/sw.js → clientes/[slug]/sw.js (raiz). Nunca sobrescreve: config.json, branding/, arquivos mais novos no cliente.3
Verificar cliente antes de commitar
.\scripts\verificar-cliente.ps1 -cliente eriane-faria
Verifica: logo.svg · favicon.svg · config.json preenchido · config-loader.js · tema.css. Não commitar se falhar.
Testes Automáticos
Playwright — 25+ testes cobrindo fluxos críticos de negócio
▶
Rodar todos os testes
# Subir servidor do carlos-mendes na 3001 antes
node scripts/_serve-carlos.js # em outro terminal
# Rodar os testes
npm test # playwright test
npm run test:auth # só T-01, T-04, T-17
npm run test:redirects # 10 rotas protegidas
npm run test:medico # médico navega páginas
npm run test:unit # testes unitários (sem browser)
| Arquivo | Testes | O que cobre |
|---|---|---|
| auth.spec.ts | T-01, T-04, T-17 | Login médico, sessão expirada, prontuário sem auth |
| redirects.spec.ts | T-06 (10 rotas) | Páginas protegidas → redirect login sem sessão |
| roles.spec.ts | T-03, T-18 | Paciente e secretaria não acessam prontuário |
| medico.spec.ts | T-11 a T-16 | Médico navega agenda, mensagens, financeiro, IA, monitoramento |
| secretaria.spec.ts | T-02, T-05 | Secretaria login e cadastro de paciente |
| modulos.spec.ts | T-07 | Módulo desativado → comportamento correto |
| unit/provisioning.spec.ts | T-02 (8 testes) | Scripts de provisionamento: args, SQL, integridade |
| unit/update-all.spec.ts | T-08, T-09 | update-all.js preserva config.json e customizações |
Troubleshooting
Problemas comuns e como resolver
Admin retorna 401 do Supabase em todas as páginas ▼
Causa: CDN do supabase-js não carregado →
Fix: Verificar que
window.supabase undefined → todas as chamadas falham.Fix: Verificar que
apps/admin/dashboard.html tem a tag <script src="cdn.jsdelivr.net/...supabase.min.js">. Fazer deploy manual se necessário.Deploy do admin não chegou ao servidor após push ▼
Causa: GitHub Actions com delay, falha silenciosa ou chave SSH não autorizada no servidor Vértice.
Fix: Verificar data do arquivo no servidor via SSH:
Fix: Verificar data do arquivo no servidor via SSH:
ssh -p 65002 -i ~/.ssh/hostinger_key u627878224@82.180.153.142 "stat /home/u627878224/.../core/dashboard.html". Se a data for anterior ao commit, fazer deploy manual via SCP.Multiple GoTrueClient warnings no console ▼
Causa: Múltiplos clientes Supabase criados no mesmo contexto de browser sem
Fix: Ao criar clientes para health checks, usar:
storageKey único.Fix: Ao criar clientes para health checks, usar:
{ auth: { persistSession: false, autoRefreshToken: false, storageKey: 'vertice_health_REF' } }.401 em ai_usage_log no admin dashboard ▼
Causa: A tabela
Fix: Aplicar patch-041:
ai_usage_log foi criada sem política anon SELECT (patch-035 só tem service_role).Fix: Aplicar patch-041:
node scripts/provisioning/schema.js --ref REF --pat PAT --file supabase/patch-041-ai-usage-log-anon-select.sqlSite da Eriane com tela em branco após update-all.js ▼
Causa provável: Arquivo core com
Fix: Verificar
import ESModule foi propagado para clientes/eriane-faria/assets/js/. Scripts com import causam SyntaxError quando carregados como <script src> (não module).Fix: Verificar
clientes/eriane-faria/assets/js/supabase.js com grep "^import" clientes/eriane-faria/assets/js/supabase.js. Se tiver import, restaurar da versão anterior no git: git checkout HEAD~1 -- clientes/eriane-faria/assets/js/supabase.js. Os arquivos em core/ NÃO devem ter import/export de ES6 até o build Vite estar configurado em produção.Ping do monitoramento retorna 403 no Core Vértice ▼
Causa: A URL de ping estava apontando para a raiz
Fix: URL de ping deve ser
/ que retorna 403 (Hostinger bloqueia listagem de diretório).Fix: URL de ping deve ser
https://core.vertice-ecossistema.com.br/login.html (um arquivo específico, não a raiz). Já corrigido em dashboard.html.Supabase Management API retorna 429 (rate limit) ▼
Causa: Muitas chamadas em sequência rápida (ex: aplicar schema com muitos statements).
Fix: O schema.js já usa 130ms de delay entre statements. Para operações manuais em lote, aguardar 120–150ms entre chamadas à API.
Fix: O schema.js já usa 130ms de delay entre statements. Para operações manuais em lote, aguardar 120–150ms entre chamadas à API.
Criar usuário no Supabase retorna "Database error querying schema" ▼
Causa: Tentativa de criar usuário via SQL direto no Supabase ao invés da GoTrue Admin API.
Fix: Usar sempre a GoTrue Admin API (service_role key):
Fix: Usar sempre a GoTrue Admin API (service_role key):
POST https://[ref].supabase.co/auth/v1/admin/users com body {"email":"...", "password":"...", "email_confirm":true}. NUNCA inserir direto em auth.users via SQL.Credenciais e Referências Rápidas
Onde encontrar o quê (nunca commitar senhas/chaves)
Segurança: Nenhuma senha ou chave API aparece nesta página. Todas as credenciais ficam localmente em
config.json (gitignored) ou nos secrets do Supabase/GitHub.| O que | Onde encontrar |
|---|---|
| Supabase URLs e anon_keys | Arquivo local clientes/[slug]/config.json (nunca commitado). Ou Supabase Dashboard → Settings → API |
| Supabase PATs (Management API) | supabase.com/dashboard/account/tokens — cada conta tem o seu |
| Chave Gemini API | Secrets da Edge Function gemini-proxy no Supabase do cliente. Nunca no código. |
| SSH Eriane (82.25.67.107) | Chave: ~/.ssh/hostinger_key · Usuário: u707423342 · Porta: 65002 |
| SSH Vértice Core (82.180.153.142) | Mesma chave hostinger_key · Usuário: u627878224 · Porta: 65002 |
| Config admin (vertice.config.json) | Arquivo local apps/admin/vertice.config.json (gitignored) |
| Login admin Léo | lcunhapereira@gmail.com / senha no Supabase vertice-admin |
| GitHub Actions secrets | github.com/vertice-health/vertice-health-platform/settings/secrets/actions |
Sistema Mestre — Vértice Health Platform · Atualizado em