Développement
Guide pour contribuer au codebase : setup, structure monorepo, scripts, conventions, i18n.
Guide pour contribuer au codebase : setup, structure monorepo, scripts, conventions, i18n.
Setup
git clone <repo> && cd simmetric-chat
pnpm install # installe les dépendances de tous les packages
cp .env.example .env # .env racine = unique config runtime; puis édite JWT_SECRET, COLLECTOR_SECRET
pnpm db:generate # client Prisma (+ fix symlink Prisma 7/pnpm)
pnpm db:migrate # applique les migrations (prisma migrate dev)
pnpm db:seed # rôles, permissions, config, admin bootstrap
pnpm dev # lance server/collector/widget/frontend via turborepoPostgreSQL 16 en local (par ex. docker compose -f docker/docker-compose.infra.yml up -d postgres). pnpm db:migrate applique les migrations Prisma (packages/server/prisma/migrations) ; pnpm db:seed sème les rôles/permissions et l'admin bootstrap (admin / admin123, mustChangePassword=true). Les migrations sont additive-only : les destructives exigent un consentement explicite (PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION) et pnpm audit:migrations régénère docs/MIGRATION_AUDIT.md à committer dans la même PR.
Structure monorepo
pnpm workspaces + Turborepo. 5 package + Tauri :
| Package | Port | Stack | Rôle |
|---|---|---|---|
shared | - | TS + Zod | Types, schema, constantes (leaf, dép zod seule) |
server | 3000 | Express + Prisma | API, RBAC, agent, RAG FTS/RRF, backup |
collector | 3210 | Express | Ingestion, parsing, embedding, vector store |
widget | 3211 | Express + Preact IIFE | Widget embarquable |
frontend | 5173 | Vite + React 19 + Tailwind | SPA admin/chat |
src-tauri | - | Rust + Tauri | Desktop app |
Graphe de dépendances : shared ← {server, collector, frontend, widget}. Modularité strict : server↔collector = HTTP only (COLLECTOR_SECRET) ; widget↔server = API key (X-Api-Key). Aucun import direct entre server/collector/widget.
Scripts communs
| Script | Scope | Description |
|---|---|---|
pnpm dev | root | Turborepo : lance tous les services en parallèle |
pnpm build | root | Build production tous les package (dépend de ^build) |
pnpm lint | root | ESLint 10 flat config, tous les package |
pnpm typecheck | root | TypeScript strict mode |
pnpm test | root | Jest (5 projets, Postgres-free) via Turborepo |
pnpm test:all | root | Mêmes 5 suites via jest.config.cjs (Jest pur) |
pnpm test:e2e | root | Playwright |
pnpm db:generate | root | Régénère le client Prisma |
pnpm db:migrate | server | prisma migrate dev |
pnpm db:seed | server | Seed rôles/permissions/config |
pnpm audit:migrations | server | Audit des migrations destructives → docs/MIGRATION_AUDIT.md |
pnpm i18n:check | root | Vérifie la parité traductions 8 locale |
pnpm knip | root | Gate dead-code (fichiers/dépendances/exports inutilisés) |
pnpm license:check | server | Vérifie la licence configurée sans boot du serveur |
Scripts par-package dans packages/<pkg>/package.json. Turborepo cache les outputs et les dépendances entre tasks. pnpm db:generate doit tourner avant build/lint/typecheck/test (la task turbo build en dépend).
Conventions de code
- TypeScript strict partout ; pas de
anynon justifié (targetES2022). - Zod pour la validation d'input (
shareddéfinit les schema réutilisables ; valide avecsafeParsedans les route handler → 400 au lieu de 500). - Prisma comme ORM (Prisma 7, driver adapter) ; schema dans
packages/server/prisma/schema.prisma. Jamaisnew PrismaClient(): singleton depuissrc/utils/prisma(pool driver-adapter +withSoftDelete()). - RBAC via middleware :
requirePermission,requireAdmin,requireWorkspaceAccess(31 permissions dansshared/src/constants/permissions.ts). - Error handling : réponses
{ error }(400/401/403/404/409/402/429/500) ; validation Zod → 400 avecdetails; license gating →402 { error, feature, tier }. - SSE pour le streaming chat (
@microsoft/fetch-event-sourcecôté frontend). - Logging : env
LOG_LEVEL; utilise le logger configuré, pasconsole.logdirect en prod. - Commit : format Conventional Commits (
feat:,fix:,docs:,refactor:...) ; une modification logique par commit ; un bullet[Unreleased]dansCHANGELOG.mdpour chaque modification depackages/*/src/**(pnpm changelog:check).
Frontend (React 19)
- State 3-tier (server-persisted / session / local) - TanStack Query pour REST/CRUD, React Context pour l'état UI, fetchEventSource pour SSE.
- shadcn/ui + Tailwind pour l'admin ; le widget utilise Preact + Tailwind, PAS shadcn (bundle IIFE).
- i18n via hook ; fichiers dans
packages/frontend/src/i18n/<locale>/translation.json. - Shortcuts chat :
/model(paletteCmd+K), comparaisonCmd+Shift+M. - ESLint : React Compiler + rules-of-hooks
errordans les sources ; module format ESM (root + frontend) vs CommonJS (server/collector/shared/widget) - respecte le tsconfig par package.
Server (Express)
- Routes dans
src/routes/, services danssrc/services/, middleware danssrc/middleware/. - Agent dans
src/agent/(orchestrator.ts,builtinSkills.ts,mcpClient.ts). - Config env dans
src/config/env.ts(Zod,process.exit(1)si invalide). - OpenAPI via annotations
@openapiJSDoc → Swagger sur/api-docs. - Job queue pg-boss (Postgres-backed) : 8 cron scheduler (backup, MCP health-check, reaper, synthesis) ; les pipelines OCR + synthesis restent sur un poller setInterval 10s. Multi-instance-ready sans infrastructure extra (voir 02 - Architecture).
i18n
8 locale avec fichiers concrets : en, it, ru, de, fr, es, zh, pt (EN est la baseline ; parité strict - aucune langue ne peut rester en arrière). Ajoute les clés dans les huit fichiers. pnpm i18n:check (frontend + widget) sort 1 sur des clés manquantes ou en trop dans n'importe quel locale par rapport à en ; le check widget échoue aussi sur des valeurs string vides. L'ensemble locale du widget est pinné contre ALL_LANGUAGES du frontend par widgetLocalesParity.test.ts - ajoute/retire des langues dans les deux endroits ensemble.
Ajouter une feature (workflow)
- Schema shared - types/Zod dans
packages/shared/src/. - Prisma - modèle + migration (
pnpm db:migrate; audit si destructive). - Server - service + route + middleware RBAC/license.
- Frontend - UI + hook + i18n (les 8 langues).
- Test - unit (mock Prisma) + integration (worker DB) + E2E si user-facing.
- Docs - mets à jour
docs/et OpenAPI@openapi; changelog[Unreleased]si ça touchesrc/.
Extensions communes
- Nouvelle skill agent :
registerSkilldansserver/src/agent/builtinSkills.ts. - Nouvel endpoint : route dans
server/src/routes/+ mount danssrc/index.ts. - Nouvelle permission :
PERMISSION_NAMESdansshared/src/constants/permissions.ts+ rôles. - Nouveau provider LLM : preset dans
shared/src/constants/providerPresets.ts(seedé dansprovider_presets) + handler dansserver/src/agent/llmStreaming.ts+providerService. - Nouvelle destination backup : implémente
IBackupDestinationProviderdans les providers backup du plugin Enterprise (services/backup/providers/).
Cross-link
- Architecture : 02 - Architecture
- Testing : 11 - Testing
- API : 04 - API Reference