# J4 — socket.io handshake JWT + rooms + presence — Checklist de vérification Plan source : [BARAAA-14 §7 J4](/BARAAA/issues/BARAAA-14#document-plan) Issue : [BARAAA-22 (AGNHUB-8)](/BARAAA/issues/BARAAA-22) ## 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 via `setupSocketIO(app.server, pool, config)`. **Vérification**: ```bash # 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 ``` **Résultat attendu** : - ✅ Connexion réussie au namespace `/agents`. - ✅ Réception de `agent:hello-ack` avec `{ agentId, rooms: [...] }`. ### 2. Events client → serveur : `room:join`, `room:leave` **Implémentation** : handlers dans `src/socket/index.ts`. **Vérification** : ```typescript // Dans le client socket.io : socket.emit('room:join', { roomId: '', 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: '', requestId: 'req-3' }); // → Devrait quitter le room. ``` **Résultat attendu** : - ✅ `room:join` avec room membre → join réussi. - ✅ `room:join` avec room non-membre → erreur `forbidden`. - ✅ `room:leave` avec room membre → leave réussi. ### 3. Event serveur → client : `agent:hello-ack` **Vérification** : dès la connexion, le client reçoit : ```json { "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 `presenceStore` dans `src/socket/index.ts`. - Diffusion `presence:update { agentId, status: "online"|"offline" }` à la connexion, déconnexion et timeout 30s. **Vérification** : ```bash # Terminal 1 : agent 1 se connecte tsx scripts/test-socket-client.ts # Terminal 2 : agent 2 se connecte (même room que agent 1) tsx scripts/test-socket-client.ts # Agent 1 devrait recevoir : # { "agentId": "", "status": "online" } # Terminal 2 : CTRL+C pour déconnecter agent 2 # Agent 1 devrait recevoir : # { "agentId": "", "status": "offline" } ``` **Résultat attendu** : - ✅ Connexion d'un agent → diffusion `online` aux co-membres. - ✅ Déconnexion d'un agent → diffusion `offline` aux 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** : ```bash 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.md` existe et contient le design complet. ## Tests automatisés **Fichier** : `test/socket.test.ts` **Lancer les tests** (nécessite Postgres) : ```bash npm test -- socket.test.ts ``` **Tests inclus** : 1. ✅ Connexion avec JWT valide → `agent:hello-ack` reçu. 2. ✅ Connexion sans JWT → refus (`Missing JWT`). 3. ✅ Connexion avec JWT invalide → refus (`Invalid or expired JWT`). 4. ✅ Deux agents dans le même room → `presence:update` mutuelle. 5. ✅ `room:join` sur room non-membre → erreur `forbidden`. ## Done quand - [x] Namespace `/agents` fonctionne avec handshake JWT. - [x] Events `room:join`, `room:leave` implémentés avec vérification membre. - [x] Event `agent:hello-ack` émis à la connexion. - [x] Présence in-memory diffuse `presence:update` à connect/disconnect. - [x] 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.