Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Mesmo modelo do site da WCR: uma página só (public/index.html), dados no Supabase.
Aba Tarefas = restrições R01-R110 da rev6. Quem edita, todos veem (salva a cada edição, confere a cada 30 s).
Este repositório é PÚBLICO. Dado real (a leitura da rev6: contrato, medido, recebido, nomes), chave e senha nunca entram nele. A leitura vai do computador direto para o banco (ver "Atualizar os números").
taf_ler_aberto, taf_edicoes_aberto e taf_tarefa_salvar_aberto (supabase/12_site_aberto.sql, com o bloco para reverter). Continuam com chave: trocar a planilha de todos (taf_snap_salvar), o ERP (tem CPF, ASO, atestado, banco de horas, salário, conta bancária, celular) e o planejador (cronograma, /ciclo, /marko: permissão por papel). Apagar as três funções abertas faz o site voltar a pedir a chave sozinho.taf_tarefa_edicao, com histórico em taf_tarefa_hist). Não mexem no arquivo da rev6: quem aplica na planilha é a gestão, com as abas MUDANÇAS e NOVAS do botão Baixar planilha.TAF - TAREFAS DO SITE - <data>.xlsx no navegador, com 3 abas: TAREFAS (lista inteira com as edições), MUDANÇAS (rev6) (campo, valor da rev6, valor de agora, linha e coluna da 05C) e NOVAS (05C) (tarefas criadas no site, na ordem das colunas da 05C). Antes de Restaurar original e de Importar JSON o site baixa essa planilha como cópia de segurança.taf_tarefa_edicao as edições já aplicadas, senão elas aparecem duas vezes.construdata-platform, só tabelas taf_* (ver supabase/schema.sql). Nada da WCR foi alterado.public. Deploy.Para o endpoint /api/leitura (abaixo) funcionar, cadastrar uma vez em Vercel > Settings > Environment Variables (Production) e fazer novo Deploy:
TAF_SUPABASE_URL: endereço do projeto Supabase (Supabase > Project Settings > API > Project URL).TAF_SUPABASE_KEY: a chave publicável (publishable/anon) do mesmo projeto. Nunca a service_role.fonte/transform.py monta public/index.html a partir de template2.html, wcr.css, extract.js e loader.html (rodar dentro de fonte/ com Python + Pillow). Ele grava fonte/index.html (copiar para public/index.html e apagar o de fonte/) e public/versao.json com o código da versão: quem está com o site aberto recebe a versão nova sozinho (confere a cada 2 minutos e ao voltar para a aba; não recarrega enquanto a pessoa digita).
A leitura não passa mais pelo Git: sem seed.js, sem commit, sem push, sem chave na URL. O script lê a rev6 no computador e envia por POST; o banco confere a chave (como sempre).
O envio (--enviar) só funciona depois que esta versão for publicada na Vercel e as duas variáveis acima estiverem cadastradas; antes disso responde 404 ou 500. Enquanto isso, atualizar pelo botão Atualizar com a rev6 do site (passo 6). Nunca voltar ao /api/seed?k=.
npm i [email protected] (fora do repositório).read -s TAF_CHAVE; export TAF_CHAVE$env:TAF_CHAVE = Read-Host "chave" (a chave aparece na tela enquanto digita)node fonte/gerar-seed.js "<caminho da rev6.xlsx>" (mostra o resumo; nada é gravado nem enviado).node fonte/gerar-seed.js "<caminho da rev6.xlsx>" --enviar. Grava a nova leitura no banco; quem está com o site aberto vê na próxima abertura.
--url http://127.0.0.1:3000/api/leitura ou variável TAF_URL. Fora de localhost só aceita https.--salvar grava leitura-local.json na raiz (o Git ignora; o script recusa gravar dentro de public/). Depois: node fonte/gerar-seed.js leitura-local.json --enviar.Como o endpoint funciona (public/api/leitura.js): só aceita POST com a chave no cabeçalho x-chave (ou Authorization: Bearer), corpo JSON { snap, fonte, quem } de até 1 MB e no formato esperado; chave na URL é recusada; GET é recusado. O endpoint não conhece a chave: repassa ao banco (taf_snap_salvar), que compara o SHA-256 com taf_chave.
Tarefas editadas no site (taf_tarefa_edicao) ficam por cima e não são apagadas por uma nova leitura.
O site manda sozinho, por e-mail, o resumo de cada obra: diário em dia útil às 7h de Brasília e semanal na segunda às 7h30 (os crons de public/vercel.json, em UTC). Duas horas depois roda a repescagem (&repescagem=1), que manda só o que não saiu. No plano Hobby da Vercel cada agendamento roda uma vez por dia e pode sair em qualquer minuto da hora marcada. [PENDENTE DE VALIDAÇÃO] Pelas regras da Vercel o Hobby é só para uso pessoal, sem fim comercial (https://vercel.com/docs/limits/fair-use-guidelines#commercial-usage): confirmar com o Felipe em que plano está o projeto. No Pro o agendamento sai no minuto marcado. Quem recebe é cadastrado na tela do ERP: Gestão e administração > Resumo para o diretor (só chave pessoal de Diretoria ou gestor). Lá também ficam "Ver prévia", "Copiar para WhatsApp" e "Mandar agora para mim".
Endpoint public/api/resumo.js (irmão do /api/leitura): GET ?quando=diario|semanal só com Authorization: Bearer <CRON_SECRET> (o agendador da Vercel manda sozinho); POST com a chave pessoal em x-chave para a prévia e o teste. O texto junta o planejador e o ERP pelo banco (fonte/erp/sql/08_resumo.sql, rascunho até o sim do Felipe). E-mail pela API da Resend, só fetch, um pedido por e-mail (/emails) com a chave de idempotência do envio, a mesma em toda tentativa: se uma execução repetir (registro no banco que falhou, resposta que não voltou), a Resend não manda de novo. A função tem até 60 s (functions em public/vercel.json). O texto do e-mail fica em public/api/_resumo_email.js (o _ faz a Vercel não publicar o arquivo como endpoint).
Para ligar (Vercel > Settings > Environment Variables, Production, e novo Deploy), além de TAF_SUPABASE_URL e TAF_SUPABASE_KEY:
CRON_SECRET: um texto sorteado de 16 caracteres ou mais (pode ser uma frase com espaço; o agendador manda o valor exato).RESEND_API_KEY: a chave da API da Resend.RESUMO_REMETENTE: por exemplo Resumo TAF <resumo@seu-dominio> (domínio conferido na Resend).TAF_CHAVE_RESUMO: a chave do robô, gerada na própria tela ("Gerar chave do robô"); aparece uma vez.Porta de entrada do WhatsApp oficial (Meta Cloud API) para o centro de comando: public/api/whatsapp.js. Só recebe e grava; nenhuma mensagem é enviada, nenhuma resposta vai ao remetente, nenhuma mídia é baixada. A única coisa que sai daqui é a cópia opcional da própria entrega para o Hermes (HERMES_WEBHOOK_URL, mais abaixo). GET responde a verificação do webhook da Meta; POST confere a assinatura X-Hub-Signature-256 (HMAC do corpo bruto) e chama a função do banco ia_whatsapp_receber (fonte/erp/sql/09_whatsapp_entrada.sql, rascunho até o sim do Felipe) uma vez por mensagem. Mensagem de texto vira uma linha em ia.fato (empresa GRUPO, tipo mensagem, título "WhatsApp de "); áudio, imagem e documento entram só com o tipo e o id da mídia. Número fora da lista whatsapp_allowlist de ia.config fica só como "WhatsApp de número não liberado" com os 4 últimos dígitos, sem texto. Reenvio da Meta não duplica (hash pelo id da mensagem). Função com 10 s (functions em public/vercel.json).
O código fica inerte (responde 503) até existirem na Vercel (Settings > Environment Variables, Production, e novo Deploy), além de TAF_SUPABASE_URL e TAF_SUPABASE_KEY:
WHATSAPP_VERIFY_TOKEN: texto sorteado, o mesmo digitado no painel da Meta ao cadastrar o webhook.WHATSAPP_APP_SECRET: o App Secret do app da Meta (assina cada POST; assinatura errada responde 401).WHATSAPP_SEGREDO_BANCO: segredo que o banco confere pelo SHA-256 guardado em ia.config (chave whatsapp_segredo_banco); sem essa linha no banco a porta fica fechada.Passo a passo e o que fica gravado: fonte/erp/sql/LEIA-ME-09-WHATSAPP.md.
Botão de aprovação e cópia para o Hermes (só no /api/whatsapp; a Bird fica como alternativa inerte): toque em botão, lista ou botão de modelo vira texto (ok 12, nao 12), e a entrega com mensagem segue, com os mesmos bytes e a assinatura original, para o webhook do Hermes em HERMES_WEBHOOK_URL (opcional, https; a falha da cópia nunca muda a resposta à Meta); construído conforme a documentação, testado só com assinatura simulada, ainda sem entrega real da Meta: fonte/erp/sql/LEIA-ME-11-WHATSAPP-HERMES.md.
Caminho pela Bird (public/api/whatsapp-bird.js, variável BIRD_WEBHOOK_SECRET; construído pela documentação da Bird, testado só com assinatura sintética, ainda sem entrega real), reenvio quando o banco falha (503 para o provedor reenviar) e aprovação por comando no celular (ok 12, não 12, não 12: motivo; frase comum não vira comando; fonte/erp/sql/10_whatsapp_aprovacao.sql, rascunho): fonte/erp/sql/LEIA-ME-10-WHATSAPP-BIRD.md.
node --test "testes/*.test.js" (Node 18 ou mais novo, sem instalar pacote). Usam Supabase e fetch simulados e leitura fictícia. Cobrem: GET recusado, sem chave, chave errada, chave na URL, corpo inválido, tamanho, POST válido gravando, o script local e uma trava que falha se dado real voltar a ser rastreado.
Ver SEED-PRIVADO-LEIA-ME.md: o seed.js antigo continua no histórico do Git público (tratar como exposto) e como limpar/trocar a chave.