# BRIEF — Agent App · lot **Connexions multi-HEMS** (`etm-powersync-app`) Gestionnaire d'installations : découverte mDNS, liste persistée, bascule, auth par box. > **À lancer APRÈS le lot Rôles & appareils, pas en parallèle.** Ce lot retouche > `nymea_service.dart`, la persistance des tokens et le chargement au switch — les fichiers que > le lot rôles vient de toucher. Deux agents dessus en même temps = collision. ## Fichiers de référence (joints) 1. **`installations_mockup.html`** — écrans Installations + Connexion (intention visuelle). 2. `jsonRpc.txt` — introspect (namespaces `Authentication.*`, mDNS, `System.GetServerUuid`/About). ## Modèle (décisions verrouillées) - **Identité stable d'une installation = Server UUID**, jamais l'IP (DHCP → l'IP change). Une installation enregistrée = `{ uuid (clé), nom, host, port, token, lastSeen }`. - **Une seule connexion active à la fois.** `nymea_service` reste mono-connexion ; un **`ConnectionManager`** au-dessus gère la liste + le switch (déconnecte l'active, connecte la cible). **Pas** de N sockets parallèles. - **Token par UUID.** La persistance actuelle stocke *un* token → passer à un token **par UUID** (clé = uuid de la box). En basculant, réutiliser le token de la box cible. C'est le piège mono→multi : ne pas réutiliser le token de la box précédente. - **Découverte mDNS** (`_nymea._tcp`) **+ ajout manuel** (host/port) en repli. Au scan, matcher par **UUID** : box connue → réutiliser son token ; nouvelle → proposer de l'ajouter. - **Auth à deux branches**, détectées au handshake : box neuve (pas d'admin) → **créer** un utilisateur (`Authentication.CreateUser`) ; box initialisée → **login** (`Authentication.Authenticate`). Le segmenteur UI n'est qu'un repli ; la détection est auto. ## Transport — attention - En LAN c'est **`ws://IP:4444`** (clair). Le code actuel ne fait **pas** de TLS (`Socket.connect` nu, `ws://`). Ne pas coder un champ `wss://` qui ne marche pas encore — le TLS (port 2222 `nymeas://`) est une dette séparée. Champ « port » par défaut **4444**. ## Routage / gate - Condition du gate = **« pas de connexion active »** (≠ « liste vide »). - Pas de connexion active au démarrage → **Installations en racine** (plein écran). - Connexion active → **dashboard** ; Installations reste accessible. - **Réentrée** : le **nom de la box active dans l'en-tête du drawer** (le « Site démo » déjà présent sous le logo) devient **cliquable → ouvre Installations** pour basculer. Pas d'entrée de menu dédiée à enfouir : l'en-tête du drawer EST l'accès. ## Trois états de l'écran Installations 1. **Vierge** (liste vide, 1ʳᵉ fois) → découverte mDNS + « Ajouter manuellement » au premier plan. 2. **Liste sans active** (box connues, aucune connectée) → liste en « hors-ligne », tap = reconnecter. 3. **Liste avec active** (ouvert depuis le drawer) → une box « actif », les autres pour basculer. Mêmes composants, trois configurations. ## Niveaux d'accès (client vs installateur) - **Client / général** : lister + **basculer** entre installations. Pas de déverrouillage requis. - **Installateur** (gated) : **ajout manuel**, **créer l'admin**, **supprimer** une installation. Mêmes écran ; ces actions grisées/masquées hors mode installateur. ## Bascule (switch) — invalidation - Switcher = déconnecter l'active → connecter la cible (token par UUID) → **ré-déclencher le chargement** (rôles, things, powerbalance) pour la nouvelle box. - **Vider les caches** des écrans (dashboard, rôles, things) au switch : aucune donnée de la box précédente ne doit subsister. C'est le vrai risque d'intégration. - Transition courte avec le **nom de la box cible** (« Connexion à Client Kutzenhausen… ») avant d'atterrir sur le dashboard, pour que l'installateur soit sûr d'être sur la bonne installation. ## Hors lot (séparé, plus tard) - **Wizard de commissioning d'une box neuve** (réseau filaire/wifi de nymea:core, façon nymea-app écrans 2-3). C'est l'installation d'un système, distinct de « connecter l'app à un HEMS existant ». Pas dans ce lot. ## Avant de coder Explore le repo (`nymea_service.dart`, `etm_tokens.dart`, `nymea_user.dart`, le drawer, le routeur), `flutter analyze`, et **propose un plan ordonné** (modèle installation + persistance par UUID → `ConnectionManager` + switch → mDNS → écran Installations 3 états → auth 2 branches → gate/routage → en-tête drawer cliquable) **avant** d'écrire. Lis `jsonRpc.txt` pour les signatures `Authentication.*`. Ne devine pas.