Desenvolvimento
Guia para contribuir para o codebase: setup, estrutura monorepo, scripts, convenções, i18n.
Guia para contribuir para o codebase: setup, estrutura monorepo, scripts, convenções, i18n.
Setup
git clone <repo> && cd simmetric-chat
pnpm install # instala as dependências de todos os packages
cp .env.example .env # .env raiz = única config runtime; depois edita JWT_SECRET, COLLECTOR_SECRET
pnpm db:generate # client Prisma (+ fix symlink Prisma 7/pnpm)
pnpm db:migrate # aplica as migrações (prisma migrate dev)
pnpm db:seed # roles, permissões, config, admin bootstrap
pnpm dev # arranca server/collector/widget/frontend via turborepoPostgreSQL 16 em local (p. ex. docker compose -f docker/docker-compose.infra.yml up -d postgres). pnpm db:migrate aplica as migrações Prisma (packages/server/prisma/migrations); pnpm db:seed semeia roles/permissões e o admin bootstrap (admin / admin123, mustChangePassword=true). As migrações são additive-only: as destrutivas exigem consentimento explícito (PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION) e pnpm audit:migrations regenera docs/MIGRATION_AUDIT.md para commitar na mesma PR.
Estrutura monorepo
pnpm workspaces + Turborepo. 5 package + Tauri:
| Package | Porta | Stack | Papel |
|---|---|---|---|
shared | - | TS + Zod | Tipos, schema, constantes (leaf, dep só zod) |
server | 3000 | Express + Prisma | API, RBAC, agent, RAG FTS/RRF, backup |
collector | 3210 | Express | Ingestão, parsing, embedding, vector store |
widget | 3211 | Express + Preact IIFE | Widget embutível |
frontend | 5173 | Vite + React 19 + Tailwind | SPA admin/chat |
src-tauri | - | Rust + Tauri | Desktop app |
Grafo de dependências: shared ← {server, collector, frontend, widget}. Modularidade strict: server↔collector = HTTP only (COLLECTOR_SECRET); widget↔server = API key (X-Api-Key). Nenhum import direto entre server/collector/widget.
Scripts comuns
| Script | Scope | Descrição |
|---|---|---|
pnpm dev | root | Turborepo: arranca todos os serviços em paralelo |
pnpm build | root | Build de produção de todos os package (depende de ^build) |
pnpm lint | root | ESLint 10 flat config, todos os package |
pnpm typecheck | root | TypeScript strict mode |
pnpm test | root | Jest (5 projetos, Postgres-free) via Turborepo |
pnpm test:all | root | As mesmas 5 suites via jest.config.cjs (Jest puro) |
pnpm test:e2e | root | Playwright |
pnpm db:generate | root | Regenera o client Prisma |
pnpm db:migrate | server | prisma migrate dev |
pnpm db:seed | server | Seed roles/permissões/config |
pnpm audit:migrations | server | Audit de migrações destrutivas → docs/MIGRATION_AUDIT.md |
pnpm i18n:check | root | Verifica a paridade de traduções em 8 locale |
pnpm knip | root | Gate dead-code (ficheiros/dependências/exports sem uso) |
pnpm license:check | server | Verifica a licença configurada sem boot do servidor |
Scripts por-package em packages/<pkg>/package.json. Turborepo cacheia outputs e dependências entre tasks. pnpm db:generate tem de correr antes de build/lint/typecheck/test (a task turbo build depende disso).
Convenções de código
- TypeScript strict em todo o lado; sem
anynão justificado (targetES2022). - Zod para validação de input (
shareddefine schemas reutilizáveis; valida comsafeParsenos route handler → 400 em vez de 500). - Prisma como ORM (Prisma 7, driver adapter); schema em
packages/server/prisma/schema.prisma. Nuncanew PrismaClient(): singleton desrc/utils/prisma(pool driver-adapter +withSoftDelete()). - RBAC via middleware:
requirePermission,requireAdmin,requireWorkspaceAccess(31 permissões emshared/src/constants/permissions.ts). - Error handling: respostas
{ error }(400/401/403/404/409/402/429/500); validação Zod → 400 comdetails; license gating →402 { error, feature, tier }. - SSE para streaming chat (
@microsoft/fetch-event-sourceno frontend). - Logging: env
LOG_LEVEL; usa o logger configurado, nãoconsole.logdireto em prod. - Commit: formato Conventional Commits (
feat:,fix:,docs:,refactor:...); uma alteração lógica por commit; um bullet[Unreleased]emCHANGELOG.mdpor cada alteração apackages/*/src/**(pnpm changelog:check).
Frontend (React 19)
- State 3-tier (server-persisted / session / local) - TanStack Query para REST/CRUD, React Context para o estado de UI, fetchEventSource para SSE.
- shadcn/ui + Tailwind para o admin; o widget usa Preact + Tailwind, NÃO shadcn (bundle IIFE).
- i18n via hook; ficheiros em
packages/frontend/src/i18n/<locale>/translation.json. - Shortcuts chat:
/model(paletaCmd+K), comparaçãoCmd+Shift+M. - ESLint: React Compiler + rules-of-hooks
errorno código; formato de módulo ESM (root + frontend) vs CommonJS (server/collector/shared/widget) - respeita o tsconfig por package.
Server (Express)
- Routes em
src/routes/, serviços emsrc/services/, middleware emsrc/middleware/. - Agent em
src/agent/(orchestrator.ts,builtinSkills.ts,mcpClient.ts). - Config env em
src/config/env.ts(Zod,process.exit(1)se inválida). - OpenAPI via anotações
@openapiJSDoc → Swagger em/api-docs. - Job queue pg-boss (Postgres-backed): 8 cron scheduler (backup, MCP health-check, reaper, synthesis); os pipelines OCR + synthesis ficam num poller setInterval 10s. Multi-instance-ready sem infraestrutura extra (ver 02 - Architecture).
i18n
8 locale com ficheiros concretos: en, it, ru, de, fr, es, zh, pt (EN é a baseline; paridade strict - nenhum idioma pode ficar para trás). Adiciona as chaves nos oito ficheiros. pnpm i18n:check (frontend + widget) sai 1 com chaves em falta ou a mais em qualquer locale face a en; o check do widget também falha com valores string vazios. O conjunto locale do widget está pinado contra ALL_LANGUAGES do frontend por widgetLocalesParity.test.ts - adiciona/remove idiomas nos dois sítios ao mesmo tempo.
Adicionar uma feature (workflow)
- Schema shared - tipos/Zod em
packages/shared/src/. - Prisma - modelo + migração (
pnpm db:migrate; audit se destrutiva). - Server - serviço + route + middleware RBAC/license.
- Frontend - UI + hook + i18n (os 8 idiomas).
- Test - unit (mock Prisma) + integration (worker DB) + E2E se user-facing.
- Docs - atualiza
docs/e OpenAPI@openapi; changelog[Unreleased]se tocarsrc/.
Extensões comuns
- Nova skill de agente:
registerSkillemserver/src/agent/builtinSkills.ts. - Novo endpoint: route em
server/src/routes/+ mount emsrc/index.ts. - Nova permissão:
PERMISSION_NAMESemshared/src/constants/permissions.ts+ roles. - Novo provider LLM: preset em
shared/src/constants/providerPresets.ts(seed emprovider_presets) + handler emserver/src/agent/llmStreaming.ts+providerService. - Novo destino backup: implementa
IBackupDestinationProvidernos providers backup do plugin Enterprise (services/backup/providers/).
Cross-link
- Arquitetura: 02 - Architecture
- Testing: 11 - Testing
- API: 04 - API Reference