# orchestrator — backend CHLOVA Le cerveau : LLM en boucle tool-calling. **Phase 1 = lecture seule.** Seule surface exposée de la stack (voir `../CLAUDE.md`, `../docs/architecture.md`). ## Stack Node 22, TypeScript (ESM, NodeNext, strict), Fastify, MCP SDK officiel, pino (audit), zod (config), Vitest (tests). Toutes deps **épinglées** ; `npm audit` doit rester à 0 vuln. ## Démarrage (dev) ```bash cp ../.env.example ../.env # renseigner les secrets (jamais commités) npm install npm run dev # tsx watch npm run typecheck npm test ``` ## Modules | Fichier | Rôle | |---|---| | `src/config.ts` | Config **fail-closed** (zod). Refuse de démarrer si secret manquant. `assertReadOnlyPhase()` verrouille la lecture seule P1. `redactedConfig()` masque les secrets. | | `src/audit/log.ts` | Logger pino + journal d'audit des exécutions d'outils. | | `src/index.ts` | Bootstrap : config → verrou RO → logger → (P1) MCP + agent + Telegram. Healthcheck interne. | | `src/llm/`, `src/agent/` | Client Ollama + boucle agent + prompt phase-aware. | | `src/mcp/` | Registry MCP (`listReadOnlyTools` P1 / `listAllTools` P2) + readonly-filter. | | `src/gatekeeper/` | Paliers de risque, table assets SQLite (`repository`), `Gatekeeper`+`GatekeeperGuard`, `ReviewService` + cron (`review`). | | `src/surfaces/` | Surface Telegram + commandes de review owner (`commands`). | ## Phases - `CHLOVA_PHASE=1` (défaut) : lecture seule, `ReadOnlyGuard`, aucun outil mutant. - `CHLOVA_PHASE=2` : écriture sous gatekeeper + cycle need-review (cron + commandes `/pending`, `/approve`, `/refuse`). Voir `../docs/need-review.md`. ## Sécurité - Secrets par référence uniquement, jamais loggés (`redactedConfig` + redact pino). - Phase 1 : `PORTAINER_READ_ONLY=false` fait **échouer** le démarrage. - Aucun port publié (Telegram long-polling) ; Fastify n'écoute qu'en interne. ## Palier de risque `reversible` (lecture seule). Aucune capacité d'écriture branchée en Phase 1.