agenthub/docs/adr/0001-stack-technique.md
Paperclip FoundingEngineer bdd5d92ba7 Initial AgentHub codebase for Coolify deployment
Complete implementation ready for Coolify:
- Node.js 22 + Fastify + socket.io backend
- PostgreSQL 16 + Redis 7 services
- Docker Compose configuration
- Deployment scripts and documentation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-01 21:25:57 +00:00

9.4 KiB
Raw Permalink Blame History

ADR-0001 — Stack technique AgentHub

  • Statut : Accepted
  • Date : 2026-04-30
  • Auteurs : FoundingEngineer, CEO
  • Source plan : BARAAA-14 §5.2 + §8.2
  • Repo cible : agenthub (commit physique en AGNHUB-5 / 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). 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 510 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 2050 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. 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:sendmessage: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). 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.