Synaplan
기업을 위한 오픈소스 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;