Synaplan
開源 AI 平台,供企業使用:自行託管的 AI 代理、符合 GDPR 的聊天機器人小工具、RAG 知識庫、WhatsApp 與 Outlook AI、MCP、多模型路由。Docker、Kubernetes 或託管於 Germ
AI 翻譯
尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗SaaS multi-tenant para gestão de consultório individual (agenda, prontuário, financeiro). Ver CLAUDE.md para a especificação completa do produto.
.env.example para .env.local e preencha com as credenciais do seu projeto Supabase (URL e anon key em Project Settings → API).https://www.googleapis.com/auth/calendar já solicitado no login para reuso na integração de Agenda/Meet).supabase/migrations/ no seu projeto Supabase (via SQL Editor do dashboard, ou npx supabase db push usando o Supabase CLI).npm install
npm run dev
npm run test # roda uma vez
npm run test:watch # modo watch
Os testes em tests/rls/ validam que uma psicóloga nunca acessa dados de outra conta. Exigem uma instância local do Supabase (precisa de Docker):
npx supabase start # sobe o stack local (primeira vez baixa imagens)
npx supabase db reset # aplica as migrations de supabase/migrations/
Depois, exporte as variáveis apontando para o local e rode a suíte. A anon key sai de npx supabase status:
# bash
export SUPABASE_TEST_URL="http://127.0.0.1:54321"
export SUPABASE_TEST_ANON_KEY="$(npx supabase status -o json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).ANON_KEY))')"
export SUPABASE_TEST_SERVICE_ROLE_KEY="$(npx supabase status -o json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).SERVICE_ROLE_KEY))')"
npm test
# PowerShell
$env:SUPABASE_TEST_URL = "http://127.0.0.1:54321"
$env:SUPABASE_TEST_ANON_KEY = (npx supabase status -o json | ConvertFrom-Json).ANON_KEY
$env:SUPABASE_TEST_SERVICE_ROLE_KEY = (npx supabase status -o json | ConvertFrom-Json).SERVICE_ROLE_KEY
npm test
Sem essas variáveis, os testes de RLS são pulados automaticamente (o resto da suíte roda normal). SUPABASE_TEST_SERVICE_ROLE_KEY só é usada pelo teste da trava de escrita por assinatura (liga/desliga app_config.assinatura_enforcement_ativo para testar os dois estados); sem ela, só esse teste específico pula.
Com o Supabase local de pé (npx supabase start):
npm run api-check # todas as páginas, rotas e server actions + isolamento entre contas
npm run e2e # Playwright no build de produção (porta 3200) com o Chrome instalado
O api-check precisa de um next dev -p 3100 rodando com as variáveis apontando para o Supabase local (URL e chaves de npx supabase status). Ele recria as contas [email protected] e [email protected] a cada execução. O e2e sobe o próprio servidor e recusa qualquer Supabase que não seja o local.
npx supabase start # precisa do Docker
npm run visual
Sobe o app em outra porta (3100) apontando para o Supabase local, cria um usuário e dados fictícios, abre 12 telas no Chrome em celular (390px), tablet (768px) e desktop (1366px), salva prints em .visual/ e falha se alguma tela tiver rolagem horizontal. Recusa qualquer Supabase que não seja o local. Feche o npm run dev antes de rodar.
Sem ASAAS_API_KEY, a integração roda em modo simulado — nenhuma chamada real, e /assinatura ganha um botão "Simular pagamento confirmado" pra testar o fluxo sem conta no Asaas.
Pra usar o sandbox de verdade:
ASAAS_API_KEY no .env.local (ASAAS_MODE fica sandbox automaticamente).https://<seu-domínio>/api/asaas/webhook, evento "Pagamento", e define um token — cola o mesmo valor em ASAAS_WEBHOOK_TOKEN.ngrok http 3000 ou similar) e cadastra a URL dele no passo 3. Sem isso, use o botão "Já paguei, verificar agora" em /assinatura, que consulta o Asaas direto (sem depender do webhook).A trava de escrita (somente leitura quando a assinatura vence) só entra em vigor com assinatura_enforcement_ativo = true em app_config — começa desligada de propósito. Pra ligar em produção, depois de validar a integração:
update public.app_config set assinatura_enforcement_ativo = true;