Zurück zur Dokumentation
Guide 10

Entwicklung

Leitfaden für Beiträge zum Codebase: Setup, Monorepo-Struktur, Skripte, Konventionen, i18n.

3 Min. Lesezeit

Leitfaden für Beiträge zum Codebase: Setup, Monorepo-Struktur, Skripte, Konventionen, i18n.

Setup

bash
git clone <repo> && cd simmetric-chat
pnpm install            # installiert die Abhängigkeiten aller Packages
cp .env.example .env    # Root-.env = einzige Runtime-Config; dann JWT_SECRET, COLLECTOR_SECRET bearbeiten
pnpm db:generate        # Prisma Client (+ Fix Prisma 7/pnpm Symlink)
pnpm db:migrate         # Migrationen anwenden (prisma migrate dev)
pnpm db:seed            # Rollen, Berechtigungen, Config, Bootstrap-Admin
pnpm dev                # startet server/collector/widget/frontend via turborepo

PostgreSQL 16 lokal (z. B. docker compose -f docker/docker-compose.infra.yml up -d postgres). pnpm db:migrate wendet die Prisma-Migrationen an (packages/server/prisma/migrations); pnpm db:seed sät Rollen/Berechtigungen und den Bootstrap-Admin (admin / admin123, mustChangePassword=true). Die Migrationen sind additive-only: destruktive erfordern explizite Zustimmung (PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION) und pnpm audit:migrations regeneriert docs/MIGRATION_AUDIT.md zum Commit in derselben PR.

Monorepo-Struktur

pnpm workspaces + Turborepo. 5 Packages + Tauri:

PackagePortStackRolle
shared-TS + ZodTypen, Schema, Konstanten (Leaf, nur zod)
server3000Express + PrismaAPI, RBAC, Agent, RAG FTS/RRF, Backup
collector3210ExpressIngestion, Parsing, Embedding, Vector Store
widget3211Express + Preact IIFEEinbettbares Widget
frontend5173Vite + React 19 + TailwindSPA Admin/Chat
src-tauri-Rust + TauriDesktop-App

Abhängigkeitsgraph: shared ← {server, collector, frontend, widget}. Strikte Modularität: server↔collector = HTTP only (COLLECTOR_SECRET); widget↔server = API key (X-Api-Key). Kein direkter Import zwischen server/collector/widget.

Gemeinsame Skripte

SkriptScopeBeschreibung
pnpm devrootTurborepo: startet alle Services parallel
pnpm buildrootProduktions-Build aller Packages (hängt von ^build ab)
pnpm lintrootESLint 10 Flat Config, alle Packages
pnpm typecheckrootTypeScript Strict Mode
pnpm testrootJest (5 Projekte, Postgres-free) via Turborepo
pnpm test:allrootDieselben 5 Suiten via jest.config.cjs (reines Jest)
pnpm test:e2erootPlaywright
pnpm db:generaterootRegeneriert den Prisma Client
pnpm db:migrateserverprisma migrate dev
pnpm db:seedserverSeed Rollen/Berechtigungen/Config
pnpm audit:migrationsserverAudit destruktiver Migrationen → docs/MIGRATION_AUDIT.md
pnpm i18n:checkrootPrüft Übersetzungsparität über 8 Locales
pnpm kniprootDead-Code-Gate (unbenutzte Dateien/Abhängigkeiten/Exports)
pnpm license:checkserverPrüft die konfigurierte License ohne Server-Boot

Skripte pro Package in packages/<pkg>/package.json. Turborepo cached Outputs und Abhängigkeiten zwischen Tasks. pnpm db:generate muss vor build/lint/typecheck/test laufen (die Turbo-Task build hängt davon ab).

Code-Konventionen

  • TypeScript strict überall; kein ungerechtfertigtes any (Target ES2022).
  • Zod für Input-Validierung (shared definiert wiederverwendbare Schemas; validiert mit safeParse in Route Handlern → 400 statt 500).
  • Prisma als ORM (Prisma 7, Driver Adapter); Schema in packages/server/prisma/schema.prisma. Nie new PrismaClient(): Singleton aus src/utils/prisma (Driver-Adapter-Pool + withSoftDelete()).
  • RBAC via Middleware: requirePermission, requireAdmin, requireWorkspaceAccess (31 Berechtigungen in shared/src/constants/permissions.ts).
  • Error Handling: Antworten { error } (400/401/403/404/409/402/429/500); Zod-Validierung → 400 mit details; License Gating → 402 { error, feature, tier }.
  • SSE für Chat-Streaming (@microsoft/fetch-event-source im Frontend).
  • Logging: Env LOG_LEVEL; nutze den konfigurierten Logger, kein direktes console.log in Prod.
  • Commit: Conventional Commits (feat:, fix:, docs:, refactor:...); eine logische Änderung pro Commit; ein [Unreleased]-Bullet in CHANGELOG.md für jede Änderung an packages/*/src/** (pnpm changelog:check).

Frontend (React 19)

  • 3-Tier-State (server-persisted / session / local) - TanStack Query für REST/CRUD, React Context für UI-State, fetchEventSource für SSE.
  • shadcn/ui + Tailwind für Admin; das Widget nutzt Preact + Tailwind, KEIN shadcn (IIFE-Bundle).
  • i18n via Hook; Dateien in packages/frontend/src/i18n/<locale>/translation.json.
  • Chat-Shortcuts: /model (Palette Cmd+K), Vergleich Cmd+Shift+M.
  • ESLint: React Compiler + rules-of-hooks error im Quellcode; Modulformat ESM (Root + Frontend) vs CommonJS (server/collector/shared/widget) - respektiere die tsconfig pro Package.

Server (Express)

  • Routes in src/routes/, Services in src/services/, Middleware in src/middleware/.
  • Agent in src/agent/ (orchestrator.ts, builtinSkills.ts, mcpClient.ts).
  • Config Env in src/config/env.ts (Zod, process.exit(1) bei ungültigen Werten).
  • OpenAPI via @openapi JSDoc-Annotationen → Swagger auf /api-docs.
  • Job Queue pg-boss (Postgres-backed): 8 Cron-Scheduler (Backup, MCP Health-Check, Reaper, Synthesis); die OCR- + Synthesis-Pipelines bleiben auf setInterval-10s-Poller. Multi-Instance-ready ohne Extra-Infrastruktur (siehe 02 - Architecture).

i18n

8 Locales mit konkreten Dateien: en, it, ru, de, fr, es, zh, pt (EN ist die Baseline; strikte Parität - keine Sprache darf zurückfallen). Füge die Keys in allen acht Dateien hinzu. pnpm i18n:check (Frontend + Widget) endet mit 1 bei fehlenden oder überzähligen Keys in irgendeinem Locale gegenüber en; der Widget-Check schlägt auch bei leeren String-Werten fehl. Das Locale-Set des Widgets ist gegen ALL_LANGUAGES des Frontends durch widgetLocalesParity.test.ts gepinnt - füge Sprachen an beiden Stellen gemeinsam hinzu/entferne sie.

Eine Feature hinzufügen (Workflow)

  1. Shared Schema - Typen/Zod in packages/shared/src/.
  2. Prisma - Modell + Migration (pnpm db:migrate; Audit wenn destruktiv).
  3. Server - Service + Route + RBAC/License-Middleware.
  4. Frontend - UI + Hook + i18n (alle 8 Sprachen).
  5. Test - Unit (Prisma Mock) + Integration (Worker DB) + E2E wenn user-facing.
  6. Docs - aktualisiere docs/ und OpenAPI @openapi; Changelog [Unreleased] wenn src/ berührt wird.

Gängige Erweiterungen

  • Neue Agent-Skill: registerSkill in server/src/agent/builtinSkills.ts.
  • Neuer Endpoint: Route in server/src/routes/ + Mount in src/index.ts.
  • Neue Berechtigung: PERMISSION_NAMES in shared/src/constants/permissions.ts + Rollen.
  • Neuer LLM-Provider: Preset in shared/src/constants/providerPresets.ts (geseedet in provider_presets) + Handler in server/src/agent/llmStreaming.ts + providerService.
  • Neue Backup-Destination: implementiere IBackupDestinationProvider in den Backup-Providern des Enterprise-Plugins (services/backup/providers/).