Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Mobile-first PWA for Swedish construction sites and plants: workers report near-misses (tillbud), hazards and accidents in three taps; the safety organisation follows up with CAPA, weekly skyddsronder (AFS 2001:1) and AML 3:3a notices to Arbetsmiljöverket.
npm install
npm run dev # http://localhost:3000 — demo mode until Supabase is configured
npm test # vitest unit tests
npm run lint
npm run typecheck
Copy .env.local.example to .env.local and set NEXT_PUBLIC_SUPABASE_URL and
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY (or ..._ANON_KEY). Both are public values.
Apply the schema (tables, RLS policies, RPCs, storage bucket, realtime):
npx supabase login
npx supabase link --project-ref <your-project-ref>
npx supabase db push
npx supabase db query -f supabase/seed.sql # optional demo sites and locations
Without the CLI, paste supabase/apply-all.sql (migrations + seed in one script) into the
SQL editor of the Supabase dashboard and run it. Regenerate it after editing a migration:
node scripts/build-apply-all.mjs
Create the safety officers' accounts under Authentication → Users (email + password, or invite by e-mail). Field workers never need an account.
| Role | Can |
|---|---|
| Anonymous visitor (field worker) | read sites and locations, submit a report through the submit_incident RPC, upload photos / voice notes |
| Signed-in user (safety officer) | read and update incidents, CAPA actions, skyddsronder and media |
The dashboard and /skyddsrond redirect to /login when Supabase is configured. Media lives in
the private incident-media bucket and is served through short-lived signed URLs.
Workers never sign in. Each company and each place has a report key; the QR code carries it (/report?k=<key>).
The submit_incident RPC refuses an anonymous report without the current key of that company or place, so the
form cannot be used for another company. A manager (or the owner) replaces a key in Settings / Projects and the
old printed code stops working at once. The RPC also limits reports per phone, per network and per company per
hour, and flags a report sent from outside the place (a flag, not a block). Signed-in people of the company
report without a key. Optional: Cloudflare Turnstile (NEXT_PUBLIC_TURNSTILE_SITE_KEY, TURNSTILE_SECRET_KEY).
Staff see only the places a manager ticks for them (People page); managers see their whole company.
With NEXT_PUBLIC_ROOT_DOMAIN set, each company gets <slug>.<root domain> (add a wildcard domain in Vercel).
Set RESEND_API_KEY, SAFETY_ALERT_RECIPIENT (comma-separated allowed), optionally RESEND_FROM
and NEXT_PUBLIC_APP_URL. The browser pings /api/alerts/critical-incident after a report; the
route calls the claim_incident_alert RPC, which returns the incident only if it is critical and
has not been alerted before, so the e-mail can be neither forged nor duplicated.
For delivery that does not depend on the reporter's browser, add a Database Webhook in
Supabase (table incidents, event INSERT, URL https://<your-app>/api/alerts/critical-incident,
HTTP header x-alert-secret: <ALERT_WEBHOOK_SECRET>) and set ALERT_WEBHOOK_SECRET in the app.
app/ routes (report, dashboard, skyddsrond, login, api/alerts)
components/ UI: report wizard, dashboard, skyddsrond checklist, auth, shell
lib/data/ repository contract + Supabase and in-memory implementations
lib/supabase/ client/server factories, row mappers, hand-maintained DB types
lib/offline/ IndexedDB queue for reports written without a connection
lib/alerts/ critical-incident payload, parsing and e-mail template
lib/compliance/ AML 3:3a notice model and print template
supabase/ migrations, seed data, CLI config
tests/ vitest unit tests for the pure modules
public/sw.js caches the app shell (network-first for pages, cache-first for static assets) and is
registered in production builds only. iOS splash screens are generated by
node scripts/generate-ios-assets.mjs.