Retour à la documentation
Guide 10

Développement

Guide pour contribuer au codebase : setup, structure monorepo, scripts, conventions, i18n.

4 min de lecture

Guide pour contribuer au codebase : setup, structure monorepo, scripts, conventions, i18n.

Setup

bash
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 turborepo

PostgreSQL 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 :

PackagePortStackRôle
shared-TS + ZodTypes, schema, constantes (leaf, dép zod seule)
server3000Express + PrismaAPI, RBAC, agent, RAG FTS/RRF, backup
collector3210ExpressIngestion, parsing, embedding, vector store
widget3211Express + Preact IIFEWidget embarquable
frontend5173Vite + React 19 + TailwindSPA admin/chat
src-tauri-Rust + TauriDesktop 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

ScriptScopeDescription
pnpm devrootTurborepo : lance tous les services en parallèle
pnpm buildrootBuild production tous les package (dépend de ^build)
pnpm lintrootESLint 10 flat config, tous les package
pnpm typecheckrootTypeScript strict mode
pnpm testrootJest (5 projets, Postgres-free) via Turborepo
pnpm test:allrootMêmes 5 suites via jest.config.cjs (Jest pur)
pnpm test:e2erootPlaywright
pnpm db:generaterootRégénère le client Prisma
pnpm db:migrateserverprisma migrate dev
pnpm db:seedserverSeed rôles/permissions/config
pnpm audit:migrationsserverAudit des migrations destructives → docs/MIGRATION_AUDIT.md
pnpm i18n:checkrootVérifie la parité traductions 8 locale
pnpm kniprootGate dead-code (fichiers/dépendances/exports inutilisés)
pnpm license:checkserverVé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 any non justifié (target ES2022).
  • Zod pour la validation d'input (shared définit les schema réutilisables ; valide avec safeParse dans les route handler → 400 au lieu de 500).
  • Prisma comme ORM (Prisma 7, driver adapter) ; schema dans packages/server/prisma/schema.prisma. Jamais new PrismaClient() : singleton depuis src/utils/prisma (pool driver-adapter + withSoftDelete()).
  • RBAC via middleware : requirePermission, requireAdmin, requireWorkspaceAccess (31 permissions dans shared/src/constants/permissions.ts).
  • Error handling : réponses { error } (400/401/403/404/409/402/429/500) ; validation Zod → 400 avec details ; license gating → 402 { error, feature, tier }.
  • SSE pour le streaming chat (@microsoft/fetch-event-source côté frontend).
  • Logging : env LOG_LEVEL ; utilise le logger configuré, pas console.log direct en prod.
  • Commit : format Conventional Commits (feat:, fix:, docs:, refactor:...) ; une modification logique par commit ; un bullet [Unreleased] dans CHANGELOG.md pour chaque modification de packages/*/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 (palette Cmd+K), comparaison Cmd+Shift+M.
  • ESLint : React Compiler + rules-of-hooks error dans 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 dans src/services/, middleware dans src/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 @openapi JSDoc → 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)

  1. Schema shared - types/Zod dans packages/shared/src/.
  2. Prisma - modèle + migration (pnpm db:migrate ; audit si destructive).
  3. Server - service + route + middleware RBAC/license.
  4. Frontend - UI + hook + i18n (les 8 langues).
  5. Test - unit (mock Prisma) + integration (worker DB) + E2E si user-facing.
  6. Docs - mets à jour docs/ et OpenAPI @openapi ; changelog [Unreleased] si ça touche src/.

Extensions communes

  • Nouvelle skill agent : registerSkill dans server/src/agent/builtinSkills.ts.
  • Nouvel endpoint : route dans server/src/routes/ + mount dans src/index.ts.
  • Nouvelle permission : PERMISSION_NAMES dans shared/src/constants/permissions.ts + rôles.
  • Nouveau provider LLM : preset dans shared/src/constants/providerPresets.ts (seedé dans provider_presets) + handler dans server/src/agent/llmStreaming.ts + providerService.
  • Nouvelle destination backup : implémente IBackupDestinationProvider dans les providers backup du plugin Enterprise (services/backup/providers/).