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>
5.1 KiB
J4 — socket.io handshake JWT + rooms + presence — Checklist de vérification
Plan source : BARAAA-14 §7 J4
Issue : BARAAA-22 (AGNHUB-8)
Prérequis
- J3 complet : REST agents/tokens/sessions fonctionnels.
- Base Postgres lancée :
docker compose -f compose.dev.yml up -d. - Migrations appliquées :
npm run migrate. - Seed exécuté (optionnel) :
npm run seed.
Livrables
1. socket.io 4 monté sur namespace /agents avec handshake JWT
Fichiers:
src/socket/index.ts: configuration socket.io, namespace/agents, middleware handshake JWT.src/app.ts: intégration socket.io viasetupSocketIO(app.server, pool, config).
Vérification:
# Terminal 1 : lancer le serveur
npm run dev
# Terminal 2 : obtenir un JWT
curl -X POST http://localhost:3000/api/v1/sessions \
-H 'Content-Type: application/json' \
-d '{"apiToken": "ah_live_XXXX_..."}' # Remplacer par un token valide
# Terminal 2 : tester la connexion socket.io
tsx scripts/test-socket-client.ts <jwt-obtenu-ci-dessus>
Résultat attendu :
- ✅ Connexion réussie au namespace
/agents. - ✅ Réception de
agent:hello-ackavec{ agentId, rooms: [...] }.
2. Events client → serveur : room:join, room:leave
Implémentation : handlers dans src/socket/index.ts.
Vérification :
// Dans le client socket.io :
socket.emit('room:join', { roomId: '<uuid-room-valide>', requestId: 'req-1' });
// → Devrait joindre le room si l'agent est membre.
socket.emit('room:join', { roomId: '00000000-0000-0000-0000-000000000000', requestId: 'req-2' });
// → Devrait recevoir error { code: 'forbidden', requestId: 'req-2' }.
socket.emit('room:leave', { roomId: '<uuid-room-valide>', requestId: 'req-3' });
// → Devrait quitter le room.
Résultat attendu :
- ✅
room:joinavec room membre → join réussi. - ✅
room:joinavec room non-membre → erreurforbidden. - ✅
room:leaveavec room membre → leave réussi.
3. Event serveur → client : agent:hello-ack
Vérification : dès la connexion, le client reçoit :
{
"agentId": "uuid-de-l-agent",
"rooms": ["uuid-room-1", "uuid-room-2"]
}
Résultat attendu : ✅ Message reçu avec liste des rooms dont l'agent est membre.
4. Présence in-memory Phase 1
Implémentation :
- Map
presenceStoredanssrc/socket/index.ts. - Diffusion
presence:update { agentId, status: "online"|"offline" }à la connexion, déconnexion et timeout 30s.
Vérification :
# Terminal 1 : agent 1 se connecte
tsx scripts/test-socket-client.ts <jwt-agent-1>
# Terminal 2 : agent 2 se connecte (même room que agent 1)
tsx scripts/test-socket-client.ts <jwt-agent-2>
# Agent 1 devrait recevoir :
# { "agentId": "<agent-2-id>", "status": "online" }
# Terminal 2 : CTRL+C pour déconnecter agent 2
# Agent 1 devrait recevoir :
# { "agentId": "<agent-2-id>", "status": "offline" }
Résultat attendu :
- ✅ Connexion d'un agent → diffusion
onlineaux co-membres. - ✅ Déconnexion d'un agent → diffusion
offlineaux co-membres. - ✅ Timeout 30s : présence nettoyée après inactivité (vérifié par le setInterval toutes les 10s).
5. Format message commun
Implémentation : tous les events suivent { type, requestId?, ts, payload } (implicite dans les events socket.io).
Note : pour l'instant, le format est implicite dans la définition des events TypeScript. Si besoin d'un wrapper explicite, ajouter en Phase 2.
6. ADR-0003 committé
Vérification :
git log --oneline | grep -i "adr-0003\|auth-tokens"
Résultat attendu :
- ✅ Commit
29f758b Add ADR-0003: AgentHub auth (API token long-lived + JWT court)présent. - ✅ Fichier
docs/adr/0003-auth-tokens.mdexiste et contient le design complet.
Tests automatisés
Fichier : test/socket.test.ts
Lancer les tests (nécessite Postgres) :
npm test -- socket.test.ts
Tests inclus :
- ✅ Connexion avec JWT valide →
agent:hello-ackreçu. - ✅ Connexion sans JWT → refus (
Missing JWT). - ✅ Connexion avec JWT invalide → refus (
Invalid or expired JWT). - ✅ Deux agents dans le même room →
presence:updatemutuelle. - ✅
room:joinsur room non-membre → erreurforbidden.
Done quand
- Namespace
/agentsfonctionne avec handshake JWT. - Events
room:join,room:leaveimplémentés avec vérification membre. - Event
agent:hello-ackémis à la connexion. - Présence in-memory diffuse
presence:updateà connect/disconnect. - ADR-0003 committé (
docs/adr/0003-auth-tokens.md). - Test manuel : 2 sockets se connectent, joignent même room, présence visible des deux côtés.
Blocage actuel : Docker non disponible dans l'environnement de test actuel. Les tests automatisés passent en typecheck, mais nécessitent une base Postgres pour l'exécution réelle.
Recommandation : lancer docker compose -f agenthub/compose.dev.yml up -d et exécuter npm test dans le dossier agenthub/ pour valider l'intégration complète.