尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Dutiva is a Canadian HR-compliance platform — AI-assisted, jurisdiction-aware,
bilingual EN/FR. This repo implements the dutiva.ca marketing site and the
product workspace (AI Advisor, cases, employees, compliance, policies,
document studio, hiring and the careers portal, and supporting modules) —
backed by Supabase Postgres + edge functions, with row-level security
across the org-scoped data.檢視完整 README ↗Dutiva is a Canadian HR-compliance platform — AI-assisted, jurisdiction-aware, bilingual EN/FR. This repo implements the dutiva.ca marketing site and the product workspace (AI Advisor, cases, employees, compliance, policies, document studio, hiring and the careers portal, and supporting modules) — backed by Supabase Postgres + edge functions, with row-level security across the org-scoped data.
npm install
npm run dev # start the dev server
/ — marketing landing page (/fr in French)/demo — public read-only demo workspace, Northgate fixtures (/fr/demo)/pricing — plan comparison + Stripe checkout (/fr/tarifs)/templates — template catalogue preview (/fr/modeles)/help — Help Centre (/fr/aide)/careers — public job board (/fr/carrieres)/employer — employer sign-in, leads into the workspace (/fr/employeur)/workspace → /workspace/home — the workspaceNo env vars are needed for the marketing pages or the demo — both run on
bundled fixtures. Sign-in and the production workspace need
VITE_SUPABASE_URL + VITE_SUPABASE_ANON_KEY: copy .env.example to .env
and fill them in. The full route map is in CONVENTIONS.md.
Both surfaces are fully bilingual and themed (light/dark, persisted as
dutiva-theme). Public pages are language-scoped by URL (English unprefixed,
French under /fr) and prerendered to static HTML at build time for SEO;
the app surface follows the persisted dutiva-lang preference. See
docs/SEO_GEO_IMPLEMENTATION.md.
| Command | What it does |
|---|---|
npm run dev | Vite dev server |
npm run build | Typecheck + client/SSR builds + prerender + SEO validation |
npm run preview | Serve the production build |
npm run typecheck | tsc -b (strict) |
npm run lint | oxlint |
npm run test | Vitest (jsdom + Testing Library) |
npm run test:e2e | Playwright smoke on dist/ (hermetic — no Supabase; see e2e/README.md) |
npm run test:e2e:auth | Playwright production CRUD matrix (Supabase env required; skips cleanly when unset) |
npm run format | Prettier |
npm run db:types | Regenerate src/lib/supabase/database.types.ts (and the edge-function copy) from the linked project |
npm run db:snapshot | supabase db dump → supabase/schema.sql; db:document regenerates the schema doc from it |
npm run check | typecheck + lint + test + check:migrations + check:rls + check:facts + check:message-scopes + check:brand-assets + check:architecture + check:workspace-links + check:advisor-golden + check:db-types + check:edge-types |
Two Playwright suites run against the production build — see e2e/README.md.
npm run test:e2e — hermetic smoke (routing, hydration, consent, CSP). No credentials.npm run test:e2e:auth — signed-in admin production CRUD matrix (employees, cases, tasks, communications, memory). Requires Supabase env at build time plus SUPABASE_SERVICE_ROLE_KEY; exits 0 and skips when unset.Woodpecker: .woodpecker/e2e.yml (hermetic) and .woodpecker/e2e-auth.yml (auth).
The app has two modes. Demo — the Northgate Logistics fixture workspace —
is the public /demo surface and the signed-out default; it never touches a
database. Production is a real org's own records, persisted to Supabase
with RLS; a signed-in org member switches via Settings, and new employers
self-provision at /employer (capacity-gated). Demo views live in
*DemoView.tsx / *DemoFixtures.tsx, never inline in *View.tsx.
A production workspace starts empty on purpose — nothing is sample data.
Home leads with a five-step setup path (company profile → first-hire
documents → policies → a guided process → people when ready), with an inline
profile form as step one, a Keep-going card that persists after the first
record, and a one-tap plan→Tasks bridge. Progress syncs per-user across
devices via workspace_preferences.onboarding. See
docs/EMPTY_WORKSPACE_ONBOARDING.md.
Schema lives in supabase/migrations/; npm run check:migrations fails on
any repo migration not applied to the linked project — a migration merged
is not a migration applied. npm run check:rls probes the sensitive tables
as the anonymous role. Edge functions under
supabase/functions/ run the Advisor, the law monitor, Stripe webhooks and
scheduled jobs — merging one does not deploy it. Quirks of the applied
history are recorded in docs/MIGRATION_LEDGER.md;
the schema itself in docs/DATABASE_SCHEMA.md.
The Advisor can propose real workspace actions — creating a task, for
instance — rendered as confirm cards the user approves or dismisses. Nothing
executes unattended; every commit is role-gated and audited. It ships behind
ADVISOR_AGENT_ACTIONS on the advisor-chat edge function — flag set, live
emission pending an authenticated turn. Design and status:
docs/AGENT_LAYER.md.
Below 768px the app shell is a hamburger topbar, slide-in drawer and bottom tab nav with safe-area insets; primary controls carry 44px touch targets and form controls a 16px floor so iOS Safari doesn't zoom on focus. Marketing pages are fluid at the same widths.
The production build ships a service worker (dist/sw.js, generated by
scripts/generate-sw.mjs) so the site keeps working in the browser after you
go offline and can be installed like an app — handy for demoing/testing with
no connectivity. It only runs in production builds, so test it with
npm run build && npm run preview: load the page once online, then go offline
(DevTools → Network → Offline) and click around. Everything runs on the
built-in demo data; live-backend features (sign-in, production Supabase data)
stay online-only by design. Full details in docs/OFFLINE_PWA.md.
Production client-side crashes are reported to a first-party Supabase edge function (no third-party error-tracking vendor, no new data processor). Payloads are privacy-scrubbed — route patterns not resolved paths, coarse user-agent, no DOM/input/token/storage capture, no persistent id. Inert in dev and tests. Full privacy rationale and source-map handling in docs/ERROR_REPORTING.md.
Every export (Document Studio PDF/Word, "Copy link", the Advisor memory
JSON) is watermarked — visible identity line, invisible zero-width
fingerprint, and file metadata all carrying a unique export ID — velocity
rate-limited against bulk exfiltration, and recorded in an audit trail
(server-side export_events when signed in, plus a device trail surfaced in
Settings → Export activity). A leaked copy, even a pasted excerpt, resolves
back to who exported it and when. This is deterrence + attribution, not DRM
— the threat model and the runbook for tracing a leak are in
docs/EXPORT_PROTECTION.md.
A daily sweep of 19 legislation pages across all 14 Canadian jurisdictions
detects amendments, moved pages and dead links, and writes them to
law_updates — surfaced in the Knowledge view's "Live legal sources" panel.
Scheduling lives in the database (pg_cron → pg_net → the
monitor-law-changes edge function), not in the host. It used to be a Vercel
cron defined in the retired Dutiva-Website repo; when the Vercel project was
re-pointed at this repo the schedule silently ceased to exist and the monitor
stopped for 52 days without anything failing or alerting. Scheduling in
Postgres keeps it beside the data it writes, where a hosting or repo move
can't take it away.
Check it in one query — select * from public.law_monitor_status(); — and
watch hours_since_check. The panel also states its own currency: every entry
shows its detection date, and stale results carry a warning instead of reading
as current. Setup, verification and the deploy checklist are in
docs/LAW_MONITORING.md.
Sweeping a page is not the same as detecting an amendment on it. A
2026-07-30 audit found no supported jurisdiction with confirmed working
detection: Ontario's source serves a JavaScript shell whose statute text never
reaches a server-side fetch, Québec's refuses automated requests, and Federal
is unconfirmed. The product says so rather than implying coverage — see
src/features/app/guidance/monitoringCoverage.ts, which the Knowledge panel
renders for signed-out readers too. Update it and the audit date together when
a source strategy lands.
Running in dev or on a Vercel preview, an in-app Dev Annotations overlay (bottom-left ◎ pill, or ⌘/Ctrl+Shift+D) lets you click any element to pin a comment to it. Each note captures the element's source file + line, a description, and the route, and Copy brief exports them as a Markdown block to paste into an AI chat — so "change that button" becomes an exact, file-anchored instruction. It's compiled out of the production build entirely. Details in docs/DEV_ANNOTATIONS.md.
docs/CANONICAL_FACTS.md is the source of record
for Dutiva's load-bearing facts — template and jurisdiction counts, pricing,
company and legal details, launch status, and the claims that must not be made.
Where it disagrees with the code, the code wins and the file gets corrected in
the same PR — and npm run check enforces that, via
src/canonicalFacts.test.ts for the rows backed by TypeScript values and
npm run check:facts for the brand palette. Check it before publishing any
number about Dutiva, anywhere — repo, deck, or media kit.
Related standing rule: public /guides and /blog articles deliberately
publish no statutory figures, because those go stale and become compliance
representations the moment they are wrong. The rule is stated in
src/features/marketing/articles/articleModel.ts and enforced by
articles.test.ts.
Working on this repo with an AI coding agent? Start with AGENTS.md. See CONVENTIONS.md for the full engineering conventions: directory layout, route map, theming/surface model, i18n rules, data layer, and the quality bar, and docs/README.md for the documentation index. In short:
src/styles/;
two themed surface scopes (.surface-marketing, .surface-app) feed Tailwind
utilities via @theme inline.{ en, fr } pair — parity is enforced
by the type system.src/data/ power the /demo surface and
signed-out demo mode; production persists to Supabase behind RLS, reached
through feature-level api.ts modules — the swap the fixtures were built
for is done.Approved design handoffs under docs/design-handoff-*/ are the source of
truth for visual fidelity and feature-specific handoff copy. They do not
override docs/CANONICAL_FACTS.md for product facts or
docs/NATURAL_LANGUAGE_COPY.md for writing rules. Documented deviations,
each marked with a comment at the site:
var(--ink) (a border
tone, near-invisible in both themes) and toasts used var(--ink) fills
(illegible in the light theme). Titles use var(--text); toasts pin the
dark-ink pill in both themes.noValidate) so the
prototype's own regex + styled error actually run.Self-authored Québec French (strings with no FR anywhere in the prototype) is
marked [FR self-authored] in the src/i18n/messages/ modules.
Dutiva provides practical HR workflow support and compliance-oriented guidance. It does not provide legal advice.