@Terdious I wrote an entire spec with Fable 5 for managing sub-containers.
The general idea is that an external integration can declare in JSON the « sub-containers » it needs. In our case, this would allow us, for example, to declare Frigate + Mosquitto directly from the integration.
The spec is available here:
# Intégrations externes dans Gladys Assistant
## Contexte
RFC communautaire (topic 10343) : ouvrir Gladys aux intégrations développées et publiées par n'importe qui, installables en un clic, sans review du mainteneur — sans sacrifier la stabilité. Quatre exigences non négociables : (1) une intégration qui plante ne fait jamais planter Gladys, (2) aucun état zombie (état toujours visible et actionnable dans l'UI), (3) UI cohérente sans code injecté par les intégrations, (4) zéro manipulation technique pour l'utilisateur.
Décisions de cadrage validées avec le mainteneur :
- **Périmètre** : architecture d'ensemble + détail exécutable de la **phase 1** (API-hôte + superviseur Docker + PoC + **store**).
- **Store décentralisé, zéro approbation** : la source de vérité est le topic GitHub `gladys-assistant-integration` (publier = taguer son repo public) ; un indexeur 100 % automatique (GitHub Action publique) valide mécaniquement les manifestes et publie un `index.json` statique que les Gladys consomment. Le mainteneur n'approuve rien et n'est jamais un goulot d'étranglement. Images Docker sur **n'importe quel registre public** ; **aucune modération en v1** (la sandbox Docker est la défense, assumé et documenté).
- **Canal retour core→intégration** : WebSocket sortant depuis l'intégration (pas de serveur HTTP dans le conteneur).
- **SDK v1** : API-hôte REST/WS documentée et ouverte à tous les langages ; SDK officiel + template en Node.js uniquement.
- **Pas de création de device par l'intégration** : elle publie des appareils découverts, l'utilisateur crée/modifie/supprime depuis l'interface (pattern des intégrations internes).
- **Modèle de données fusionné** : pas de table dédiée — une intégration externe **est** une ligne `t_service` (colonne `type`), pour éviter toute double identité à synchroniser.
- **Auth par JWT d'intégration stateless** : non lié à un user, hors `t_session` (réservée aux sessions utilisateur), régénéré à chaque recréation du conteneur.
- **Front au même niveau que les intégrations internes** : présence dans le catalogue d'intégrations avec un simple badge « externe », puis une page générique à 3 écrans — Appareils / Découverte / Configuration (formulaire défini en JSON par l'intégration). Un seul type d'intégration en v1 : « Appareils ».
- **Intégrations multi-conteneurs** : certaines intégrations ont besoin de conteneurs additionnels (cas Frigate : conteneur Frigate + broker Mosquitto, avec UI web accessible sur le LAN et accès au Coral). Le manifeste **déclare** ce qui peut tourner — images, limites, ports publiés, accès matériel — et c'est ce que l'utilisateur approuve à l'installation ; l'intégration **pilote ensuite le cycle de vie via l'API-hôte** (créer/démarrer/arrêter/redémarrer, uniquement dans les bornes déclarées). Données confinées au dossier de l'intégration, suppression totale à la désinstallation, et **jamais** d'accès à la socket Docker.
## A. Architecture d'ensemble
```
Ce fichier a été tronqué. afficher l'original
(see the Sub-containers section)
Then, it’s Gladys that handles the entire lifecycle of these containers: creation, startup, shutdown, deletion… And if the integration is deleted, everything is automatically cleaned up (containers + volumes).
For the specific case of Mosquitto, there is an interesting constraint: it needs files present on the disk before it can start (especially for passwords). So, the declared containers can be created but stopped by default, then explicitly started by the integration when it has finished its configuration. An API /start is provided for this.
What do you think?