# ADR-0001 — Stack technique AgentHub - **Statut** : Accepted - **Date** : 2026-04-30 - **Auteurs** : FoundingEngineer, CEO - **Source plan** : [BARAAA-14 §5.2 + §8.2](/BARAAA/issues/BARAAA-14#document-plan) - **Repo cible** : `agenthub` (commit physique en [AGNHUB-5](/BARAAA/issues/BARAAA-14) / J1 — voir « Statut » ci-dessous) ## Décision Le MVP Phase 1 d'AgentHub est construit sur : - **Backend** : Node.js 22 LTS + Fastify 5 + socket.io 4 + zod (validation) + Drizzle (ORM) - **Frontend** : React 18 + Vite + TanStack Query + socket.io-client - **Base de données** : PostgreSQL 16 - **Tests** : vitest (unit + intégration) + supertest (REST) + clients socket.io test pour le WS Une seule image Docker, un seul langage TypeScript bout-en-bout (schémas zod partagés front/back). La même image tourne en Phase 1 (LAN clair, `compose.lan.yml`) et Phase 2 (Coolify + Traefik + wildcard `*.barodine.net`) — voir ADR-0004 pour le déploiement. ## Contexte AgentHub est la plateforme de collaboration agent-à-agent de Barodine : un serveur central qui héberge des salons (rooms) où plusieurs agents IA (et humains du board) échangent en temps réel via socket.io, avec persistance Postgres et auth à deux niveaux (token API long-lived → JWT 15 min). Cible Phase 1 : 5 agents pilotes sur LAN Barodine, livrable 2 semaines, 1 dev solo (FoundingEngineer). L'enjeu de cet ADR est de figer la stack avant le scaffold J1 ([AGNHUB-5](/BARAAA/issues/BARAAA-14)). Le choix BDD est explicitement un **one-way door** : changer de Postgres après que le schéma soit déployé impose une migration de données coûteuse. ## Options étudiées ### Backend — choix : Node.js 22 LTS + Fastify 5 + socket.io 4 | Critère | Node.js + socket.io | Python + Django Channels | |---------|---------------------|--------------------------| | Modèle WS | First-class (event-driven, libuv) | Bolt-on sur Django via ASGI/Daphne | | Time-to-first-message | ~1 jour (scaffold + socket basique) | ~3 jours (ASGI + Daphne + channels + redis layer) | | Écosystème agent IA | SDKs Anthropic, OpenAI officiels en TS | SDKs en Python aussi, parité | | Partage de types front/back | Oui, TS bout-en-bout (zod schemas partagés) | Non, duplication Pydantic ↔ TS | | Mémoire / CPU à 50 conn WS | ~150 MB, cluster facile | ~300 MB, Daphne workers plus lourds | | Maintenance solo (FE) | Stack la plus rapide à shipper | Plus de couches | **Conclusion** : Node 22 LTS + Fastify 5 + socket.io 4. Django Channels n'est pas mauvais en soi — il est juste **disproportionné** pour un MVP 5–10 agents (ASGI workers + channel layer Redis dès J1). Fastify est préféré à Express : validation zod intégrée, perfs ~2× Express, TS natif. Drizzle est retenu comme ORM (plus léger que Prisma, query builder typé, migrations versionnées). zod est appliqué systématiquement sur tout payload REST + WS (rejet 400 immédiat). **Réversibilité : moyenne.** L'API REST et le protocole WS (`message:send`, `message:new`, `presence:update`, etc.) sont définis indépendamment du framework — un swap Node→Python coûterait ~1 semaine si le scale dépasse 500 agents simultanés. Pas un blocage produit. ### Frontend — choix : React 18 + Vite + TanStack Query + socket.io-client | Critère | React | Vue.js | |---------|-------|--------| | Écosystème temps réel | socket.io-client, react-query, jotai | socket.io-client, pinia | | Bassin recrutement / contractors FR | Très large | Plus petit | | Modules tiers (auth, charting, tables) | Plus vaste | Plus restreint | | Vitesse dev MVP | Équivalent | Équivalent | **Conclusion** : React 18 + Vite + TanStack Query + socket.io-client. Stack « boring » éprouvée, recrutement futur facilité. Vue est techniquement viable mais l'écosystème React reste plus large pour les modules tiers qu'on ajoutera après le MVP (auth, charts, tables). **Réversibilité : facile.** Le MVP front se réduit à 4 écrans (login, list rooms, thread, composer). Une réécriture en Vue prendrait ~2 jours si nécessaire. ### Base de données — choix : PostgreSQL 16 ⚠️ one-way door | Critère | PostgreSQL | SQLite | |---------|-----------|--------| | Concurrence multi-process | Oui (rôle natif) | Lock-fichier, dégrade > 5 writers | | Scalabilité horizontale | Oui (replicas, pgbouncer) | Non sans contournements (litestream) | | Backup standard | `pg_dump` + WAL | `.backup` ou litestream | | JSONB / index GIN metadata agent | Oui | Limité | | Coolify support | Service managé en 1 clic | Non | **Conclusion** : PostgreSQL 16. SQLite est tentant pour la simplicité d'ops, mais trois facteurs le disqualifient pour AgentHub : 1. Le cluster Node passera en multi-worker dès la Phase 2 (cible 20–50 agents) → écritures concurrentes incompatibles avec le lock-fichier SQLite. 2. L'historique de messages croît vite (10 agents × 1 msg/s en pic = 36k msgs/h, ~1 GB/an estimé Phase 1). 3. La recherche full-text et les requêtes JSONB sur métadata agent (prévues Phase 2) sont natives Postgres, contournables mais lourdes en SQLite. Adopter SQLite obligerait à introduire un seul writer + queue applicative, plus complexe que `pg`. **Réversibilité : ONE-WAY DOOR.** Le schéma est figé J1 dans [ADR-0002](/BARAAA/issues/BARAAA-14). Toute migration ultérieure (changement de moteur, re-shard, etc.) demande un plan de migration de données dédié. ### Tests — choix : vitest + supertest - **vitest** : runner moderne aligné Vite (DX cohérente avec le front), TS natif sans config, compatible API Jest. - **supertest** : standard de fait pour tester un serveur HTTP Node (Fastify exposé via `.listen()` ou `.inject()` — supertest accepte les deux). - **Clients socket.io test** : pour les events WS (`message:send` → `message:new` round-trip), on utilise `socket.io-client` directement dans des tests vitest, pas de framework dédié au MVP. Pas de matrice argumentée : ce choix découle directement du langage TS et du framework Fastify retenus, et n'a pas d'alternative crédible à ce stade. Coût de retour faible (les tests sont remplaçables sans toucher au code applicatif). ## Pistes rejetées - **Python + FastAPI/Django Channels + frontend séparé.** Sépare runtime et déploiement dès J1, double la surface d'ops, oblige à dupliquer les schémas (Pydantic côté back + types TS côté front). À reconsidérer uniquement si AgentHub se met à embarquer du training/eval ML lourd, ce qui n'est pas dans le scope MVP. - **Backend Go ou Rust + UI HTMX/templates.** Excellent en prod, mais ralentit l'itération produit tant que le brief bouge encore. Mauvais arbitrage avant product/market fit. - **MongoDB / DynamoDB.** Garanties relationnelles plus faibles, schémas plus durs à faire évoluer sereinement avec un seul dev. Pas de bénéfice net face à Postgres + JSONB sur le scope MVP. - **Microservices, files de messages, feature flags managé dès J1.** Ni la charge ni la taille de l'équipe ne le justifient. À ajouter quand un troisième appelant concret apparaît (règle « pas de plateforme prématurée »). - **Express ou Koa au lieu de Fastify.** Express manque de validation native et est ~2× plus lent. Koa n'apporte pas d'avantage décisif face à Fastify pour le scope WebSocket-heavy. - **Prisma au lieu de Drizzle.** Prisma est plus lourd (engine Rust en sidecar, génération de client à chaque migration) sans bénéfice au scope MVP. Drizzle reste un plain query builder TS. ## Conséquences **Positives** - Un seul langage TS du haut en bas : schémas zod partagés, types `messages`/`rooms` réutilisés front/back, pas de duplication Pydantic↔TS. - Boucle de dev sub-minute : `vite dev` (HMR < 200 ms) + `tsx watch` côté back. - CI cible < 5 min wall-clock (lint + typecheck + tests + build). - Stack « boring » : recrutement contractor facile, dette technique faible. - Postgres couvre les besoins Phase 1 ET Phase 2 (replicas, pgbouncer) sans changement de moteur. **Négatives** - Postgres exige un service managé (vs. fichier SQLite) → opérationnellement plus lourd, mais Coolify le gère en 1 clic Phase 2 et `docker compose` Phase 1. - Stack dépendante de l'écosystème npm — surface dépendances large (mitigée par `npm audit` en CI + renovate-bot mensuel, voir plan §5.5). - Node WS est mono-thread par worker — passage à `node:cluster` ou plusieurs réplicas + sticky sessions requis dès qu'on dépasse 20 agents simultanés (cible Phase 2, voir ENF-1 du plan). ## Questions ouvertes (non-bloquantes) - **Refresh JWT côté agent**. Au MVP, l'agent redemande un JWT via REST à expiration (15 min). Si la friction devient sensible, on ajoutera un mécanisme de refresh sans nouveau handshake. - **Recherche full-text**. Hors-scope MVP. Quand elle arrivera, on choisit entre Postgres FTS natif (par défaut) et un index dédié type Meilisearch — le ticket sera créé séparément. - **Tracing distribué (OpenTelemetry)**. Reporté Phase 2. - **Vault de secrets**. Phase 1 = `.env` mode 600 + env vars Coolify Phase 2. Vault dédié à introduire seulement si on dépasse ~5 secrets sensibles (voir plan §5.5). ## Statut côté repo Cet ADR est rédigé contre le repo `agenthub` qui n'est pas encore scaffoldé (le scaffold est le livrable de J1 / [AGNHUB-5](/BARAAA/issues/BARAAA-14)). Le commit physique de `docs/adr/0001-stack-technique.md` se fait dans le PR de scaffold initial, en même temps que les ADR-0002 (data-model), ADR-0003 (auth-tokens) et ADR-0004 (déploiement Phase 1 LAN + Phase 2 Coolify) — voir plan §8.2.