Ignore les dépôts de référence imbriqués (linux-update-dashboard, nas-ops). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
34 KiB
Étude d’architecture pour une webapp de mise à jour distante Linux
Ce que montrent les deux dépôts
Le dépôt linux-update-dashboard est déjà très proche de votre besoin sur la partie orchestration web : il s’agit d’une application TypeScript presque entièrement composée d’un frontend React 19 + Vite 8 + Tailwind CSS 4 et d’un backend Hono, avec Drizzle ORM, SQLite, SSH2, WebSocket, highlight.js, Mustache, OIDC, WebAuthn, MQTT et des scripts de planification. Le README et l’arborescence indiquent aussi des dossiers client/, server/, ssh/, services/, routes/ et db/, ce qui montre une séparation assez propre entre UI, API, logique métier, stockage et exécution SSH. citeturn24view1turn39view0turn6view0turn6view1turn25search4turn25search5
Sur le plan d’exécution, linux-update-dashboard expose des routes API pour les systèmes, les mises à jour, les scripts, les réglages et les credentials, ainsi qu’une route WebSocket /api/ws/systems/:id/output dédiée au flux live des commandes. Son service output-stream publie des messages structurés (started, output, phase, done, error, warning) et conserve un buffer rejouable pour les clients qui se reconnectent. La couche SSH encapsule les commandes via sh -c, force LC_ALL=C et un PATH minimal pour stabiliser les sorties, et sait lancer des scripts détachés nohup avec fichiers de log et d’exit code, ce qui permet aux opérations longues de survivre à une coupure SSH. citeturn7view0turn12view1turn12view3turn11view0
Le dépôt nas-ops apporte l’autre moitié de la solution : des scripts Bash simples, ciblés et JSON-friendly. nas-system-update exécute apt-get update -qq, simule un full-upgrade, extrait les paquets upgradables et retourne un JSON avec count, packages et reboot_required en mode non interactif. nas-system-upgrade applique apt-get full-upgrade -y avec options dpkg défensives, puis renvoie un JSON de résultat. Côté Docker, nas-docker-pull inspecte les conteneurs, compare les IDs d’image avant/après docker pull, lit des labels comme le dépôt source et les versions, puis émet un JSON listant uniquement les conteneurs réellement concernés ; nas-docker-up remonte ensuite les stacks via docker compose up -d --remove-orphans avec gestion des fichiers d’environnement OMV et renvoie à son tour un JSON d’exécution. citeturn2view4turn3view3turn3view4turn4view0turn4view1turn4view2turn18view0turn18view1turn18view2
Le point important est donc le suivant : linux-update-dashboard apporte un excellent modèle d’application web agentless par SSH, tandis que nas-ops apporte un excellent modèle de scripts shell déterministes qui produisent des JSON compacts. Pour votre cas Debian, Ubuntu, Proxmox et Raspberry Pi, je recommande clairement de fusionner les deux approches, plutôt que de n’en reprendre qu’une seule. citeturn24view1turn3view3turn3view4turn4view1turn4view2
Il faut aussi noter une contrainte juridique : linux-update-dashboard affiche explicitement une licence AGPL-3.0 sur GitHub. En revanche, sur la page consultée de nas-ops, je n’ai pas trouvé de mention explicite de licence dans la navigation GitHub. Concrètement, cela plaide pour mettre les deux dépôts en références de travail dans le dossier de l’app, mais en les considérant d’abord comme sources d’inspiration et de vérification, pas comme du code à recopier sans revue de licence. citeturn24view1turn24view0turn24view2
Principes d’architecture à retenir
Le meilleur pattern pour votre projet est, à mon avis, un backend Node.js/TypeScript qui orchestre, mais ne connaît pas la logique métier fine des mises à jour. Toute la logique “comment mettre à jour APT”, “comment détecter les paquets”, “comment lister les stacks Docker”, “comment appliquer un docker compose up -d dans un dossier précis” doit vivre dans des templates shell versionnés, dérivés de l’esprit nas-ops, tandis que le backend gère l’inventaire, les droits, les jobs, les logs live, le chiffrement des secrets, l’historique et l’API. C’est exactement la séparation de responsabilités que la combinaison des deux dépôts rend possible. citeturn24view1turn3view3turn3view4turn4view1turn4view2
Je vous recommande donc une architecture en quatre couches. La première est la couche UI, sans machine prédéfinie au démarrage, où l’utilisateur ajoute des machines via un bouton +. La deuxième est la couche API, qui stocke les machines, les credentials, les templates, les jobs et les rapports. La troisième est la couche worker, qui lance les refreshs et les opérations longues en arrière-plan. La quatrième est la couche SSH/script runtime, qui pousse des commandes vers les hôtes et normalise leurs retours en JSON. Le dépôt linux-update-dashboard montre que ce schéma fonctionne bien pour du pilotage SSH multi-machines ; nas-ops montre qu’un script shell bien écrit peut déjà servir d’API machine. citeturn24view1turn7view0turn12view1turn3view3turn4view0turn4view1turn4view2
Pour votre cas précis, je garderais la règle suivante : update/check en tâche de fond, upgrade/full-upgrade/dist-upgrade/docker apply/reboot en déclenchement manuel. Cette séparation est cohérente avec la documentation APT, qui distingue nettement la resynchronisation des index (update) des opérations qui modifient réellement l’état de la machine (upgrade, dist-upgrade, autoremove, clean). Elle colle aussi à l’approche de linux-update-dashboard, qui distingue déjà les checks, les upgrades, l’autoremove et le reboot, avec certaines opérations exécutées en mode SSH-safe détaché. citeturn23view0turn24view1turn11view0turn12view3
Je déconseille en revanche de stocker vos commandes critiques uniquement dans la base. Il vaut mieux avoir un registre de templates versionnés sur disque, éditables depuis le frontend mais sauvegardés comme des ressources de projet, avec éventuellement des overrides par machine, exactement dans l’esprit des “script customizations” et des “per-system script overrides” du dépôt de référence. Cela facilitera énormément le travail avec Claude Code, les revues Git et l’évolution future vers des scripts de post-install, de réseau ou d’installation de paquets. citeturn24view1turn8view2
Stack technique recommandée
Pour le frontend, je vous recommande de rester dans le même univers que linux-update-dashboard : React + TypeScript + Vite. React reste une base solide pour un dashboard à composants, Vite apporte une boucle de dev rapide, et le dépôt étudié montre déjà qu’un tel couple tient bien la charge sur ce type d’outil. Pour le design system, je recommande shadcn/ui plutôt qu’une grosse librairie opaque : la documentation officielle le présente comme une plateforme de distribution de composants accessibles et ouverts, avec un composant Resizable basé sur react-resizable-panels, ce qui est très utile pour votre volet terminal à droite. Pour les icônes, Lucide React est un très bon choix, avec composants SVG tree-shakables et typed. citeturn39view0turn19search3turn20search13turn20search1turn26search1turn26search2
Pour l’éditeur de templates, je prendrais Monaco Editor. Pour le terminal live, en revanche, je prendrais xterm.js. La raison est simple : Monaco est excellent pour éditer des scripts et des snippets avec coloration, tandis que xterm.js est un vrai émulateur de terminal web, avec support des séquences ANSI et un addon d’attache WebSocket. Autrement dit, Monaco pour éditer les templates, xterm.js pour voir l’exécution en direct. Votre intuition du “web terminal à droite avec coloration syntaxique” est donc réalisable, mais la bonne implémentation est plutôt “coloration terminal ANSI + thème terminal” que “éditeur de code live”. citeturn19search6turn19search1turn19search12turn7view0turn12view1
Pour le backend HTTP/API, Hono est une proposition cohérente. Le projet de référence l’utilise déjà, et sa documentation officielle le présente comme un framework small/simple/ultrafast, multi-runtime. Si vous voulez rester proche des patterns déjà observés, Hono est un bon choix. Si vous cherchiez un framework plus “entreprise”, Fastify ou NestJS seraient défendables, mais au vu des deux dépôts étudiés, Hono est le choix le plus naturel pour un premier jet propre et rapide. citeturn25search0turn25search4turn7view0
Pour le stockage, je vous recommande plutôt PostgreSQL que SQLite pour votre projet final, même si le repo étudié utilise SQLite. SQLite est parfait pour une app solo simple ; votre besoin, lui, évoque déjà plusieurs machines, rapports archivés, templates, logs, états de jobs, déduplication, intégration agent et évolution fonctionnelle. PostgreSQL + Drizzle ORM me paraît donc un meilleur point d’équilibre. Si vous voulez minimiser l’infrastructure, utilisez pg-boss pour la file de jobs sur PostgreSQL ; si vous avez déjà Redis et que vous voulez davantage de fonctions de queue natives comme dedup/throttle/flows, BullMQ est une alternative robuste. citeturn25search5turn25search13turn27search2turn27search5turn27search0turn27search12
Pour l’exécution distante, je recommande agentless SSH en v1, avec un compte dédié de maintenance, chiffrement des credentials côté serveur, vérification de host key, bastion/ProxyJump optionnel, et règles sudo minimales. linux-update-dashboard montre déjà des credentials chiffrés au repos, du host-key approval explicite et du ProxyJump ; son README précise aussi que l’application n’est pas pensée pour être exposée directement sur Internet, mais pour un réseau de confiance protégé par reverse proxy/TLS/VPN. Je reprendrais cette discipline de sécurité presque telle quelle. citeturn24view1turn13search0turn12view3
Flux fonctionnels et contrats JSON
Votre flux de base peut être très simple côté produit. La page d’accueil démarre vide. Un bouton + ouvre un formulaire d’ajout machine contenant : nom, OS, IP/hostname, port SSH, username, mode d’authentification (mot de passe, clé SSH plus tard), sudo password si nécessaire, activation de l’update automatique, templates activables (update, upgrade, full-upgrade, dist-upgrade, clean, autoremove, reboot, docker scan, docker pull, docker up, docker prune), proxy APT / apt-cacher-ng, et un ou plusieurs répertoires Docker Compose à surveiller. Le backend effectue un test-connection, détecte les capacités, puis crée la tuile machine avec le cache d’état initial. Les routes et le workflow d’ajout de système déjà visibles dans linux-update-dashboard rendent cette approche très crédible. citeturn8view2turn24view1
Pour APT, il faut distinguer les sens exacts des commandes. Le manpage officiel d’APT rappelle que update resynchronise les index, que upgrade n’enlève pas de paquets installés et n’en installe pas de nouveaux, que dist-upgrade gère intelligemment les changements de dépendances, que clean vide le cache local des paquets récupérés, et que autoremove supprime les dépendances devenues inutiles. Pour Proxmox, les docs officielles insistent fortement sur la qualité des dépôts configurés et montrent des upgrades CLI autour de apt update puis apt dist-upgrade. Pour Raspberry Pi OS, la documentation officielle confirme qu’APT est bien le gestionnaire natif. Votre moteur de templates doit donc faire de l’OS profile-aware, pas du simple collage de commandes. citeturn23view0turn31search1turn31search11turn31search0turn31search2
Pour apt-cacher-ng, la doc Debian le décrit comme un proxy de cache pour les téléchargements de paquets, et la doc APT précise que les proxys APT se configurent via Acquire::http::Proxy et les options apparentées. Je vous conseille donc un réglage frontend par machine ou par template avec trois modes : direct, proxy temporaire à l’exécution, ou proxy persistant dans /etc/apt/apt.conf.d/. Cela vous donne la souplesse nécessaire pour les Debian/Ubuntu/Raspberry Pi classiques et les cas Proxmox où vous voudrez parfois verrouiller davantage les comportements de dépôt. citeturn21search0turn29search0
Pour Docker, la sémantique officielle est claire : docker compose pull récupère les images des services, docker compose up peut être relancé en détaché avec --remove-orphans, et docker image prune / docker system prune suppriment certaines ressources inutilisées. Le très bon enseignement de nas-ops est qu’il ne faut pas seulement “tirer une commande Docker”, mais d’abord détecter les updates, identifier la stack, puis retourner un JSON compact. En revanche, nas-ops s’appuie principalement sur les labels des conteneurs déjà en cours d’exécution (com.docker.compose.project.working_dir) ; pour votre app, comme vous voulez déclarer les dossiers Docker depuis le frontend, j’ajouterais un fallback par scan de répertoires configurés pour lister les stacks même si aucun conteneur n’est encore lancé. citeturn21search2turn32search1turn32search4turn4view1turn4view2
Le contrat JSON doit devenir votre langage commun entre scripts distants, backend, frontend, serveur MCP et agent. Je vous propose deux messages canoniques : un snapshot de disponibilité et un résultat d’exécution. Ce choix est directement inspiré par le fait que nas-ops renvoie déjà des JSON structurés, tandis que linux-update-dashboard sait piloter des opérations longues et diffuser un flux live séparé. citeturn3view3turn3view4turn4view0turn4view1turn4view2turn12view1
{
"machineId": "pve-01",
"hostname": "192.168.1.20",
"os": {
"family": "proxmox",
"version": "8.x"
},
"checkedAt": "2026-06-04T12:00:00Z",
"status": "updates_available",
"apt": {
"enabled": true,
"count": 12,
"rebootRequired": false,
"packages": [
{
"name": "pve-manager",
"currentVersion": "8.4-1",
"targetVersion": "8.4-3",
"origin": "pve-no-subscription",
"severityHint": "normal"
}
]
},
"docker": {
"enabled": true,
"count": 2,
"stacks": [
{
"name": "media",
"path": "/opt/stacks/media",
"containers": [
{
"containerName": "jellyfin",
"image": "jellyfin/jellyfin:latest",
"currentImageId": "sha256:aaa",
"targetImageId": "sha256:bbb",
"currentVersion": "10.10.0",
"targetVersion": "10.10.1",
"sourceUrl": "https://github.com/jellyfin/jellyfin"
}
]
}
]
},
"rawHints": {
"logImportantLines": [
"Inst pve-manager [8.4-1] (8.4-3 ...)",
"Downloaded newer image for jellyfin/jellyfin:latest"
]
}
}
{
"executionId": "exec_20260604_001245",
"machineId": "pve-01",
"startedAt": "2026-06-04T12:12:45Z",
"finishedAt": "2026-06-04T12:19:10Z",
"mode": "manual",
"actions": [
{
"type": "apt_full_upgrade",
"status": "ok",
"changes": [
{
"name": "pve-manager",
"from": "8.4-1",
"to": "8.4-3"
}
]
},
{
"type": "docker_up_stack",
"stack": "media",
"status": "warning",
"changes": [
{
"containerName": "jellyfin",
"fromImageId": "sha256:aaa",
"toImageId": "sha256:bbb"
}
],
"errors": [
"Found orphan containers; removed with --remove-orphans"
]
}
],
"rebootRequiredAfterRun": true,
"importantLogLines": [
"Setting up pve-manager (8.4-3)",
"jellyfin Recreated",
"jellyfin Started"
],
"rawLogRef": "reports/2026/06/04/pve-01/exec_20260604_001245.log",
"reportRef": "reports/2026/06/04/pve-01/exec_20260604_001245.md"
}
Pour éviter les doublons côté agent, je recommande une déduplication par empreinte fonctionnelle. Pour les paquets système : os_family + package_name + current_version + target_version + origin. Pour Docker : image_ref + current_digest + target_digest ou, à défaut, image + oldImageId + newImageId. Cela permettra à l’agent de mutualiser les recherches web et de générer un seul résumé par mise à jour identique, même si elle apparaît sur plusieurs machines. Le dépôt nas-ops vous aide déjà en exposant des IDs d’image et, quand ils existent, des labels de version et de source. citeturn4view1turn28search2turn28search14
Enfin, pour limiter les tokens transmis à l’agent, il faut intercaler une étape de réduction déterministe avant tout appel LLM. Conservez seulement les lignes utiles : côté APT, les Inst, Conf, Remv, Err, E:, W:, dpkg:, reboot-required; côté Docker, les Pulling, Digest, Status, Downloaded newer image, Recreating, Started, Error. Le reste doit rester dans le log brut archivé, pas dans le prompt. C’est très cohérent avec l’esprit “JSON + flux live séparé” visible dans les deux dépôts. citeturn3view3turn3view4turn4view0turn4view1turn12view1
Frontend et expérience opérateur
L’UX que vous décrivez est réaliste et même très bonne pour l’usage homelab/prod légère : une page d’accueil vide, un bouton + pour ajouter une machine, puis des tuiles avec nom, IP, OS, compteurs de mises à jour, liste des paquets à mettre à jour, liste des stacks ou conteneurs Docker concernés, et des actions rapides distinctes pour refresh, upgrade, docker pull, docker apply, clean, autoremove et reboot. L’exemple visuel de linux-update-dashboard montre déjà bien l’intérêt d’un dashboard à tuiles, complété par une page détail plus riche. citeturn24view1turn15search0
Je verrais trois écrans majeurs. Le premier est Dashboard, centré sur les tuiles machines et l’état global. Le deuxième est Machine Detail, avec historique d’activité, templates appliqués, overrides, variables de contexte, packages, stacks Docker et rapports. Le troisième est Paramétrage, où vous gérez les préférences frontend, les credentials, les templates de commandes, les profils d’OS, les politiques d’approbation et les réglages d’agent/MCP. Cette séparation reste proche du dépôt de référence tout en étant plus ciblée sur votre périmètre Debian/Ubuntu/Proxmox/RPi + Docker Compose. citeturn24view1turn8view2
Pour le volet terminal à droite, oui, c’est totalement possible, et même recommandé. Techniquement, le plus propre est un layout Resizable avec une liste/tuiles à gauche et un panneau xterm.js à droite, alimenté par un WebSocket. xterm.js supporte les séquences de terminal et dispose d’un addon d’attache à WebSocket ; de plus, linux-update-dashboard expose déjà un flux WebSocket structuré de sortie de commande. Comme l’API navigateur WebSocket ne gère pas la rétropression toute seule, je recommanderais un buffer circulaire côté serveur, la limitation de débit au niveau worker et une compression logique des chunks plutôt qu’un caractère-par-caractère. citeturn20search1turn19search1turn19search12turn7view0turn12view1turn14search8
Pour la coloration, il faut distinguer deux besoins. Le terminal live utilisera les couleurs ANSI et le thème xterm.js. Le template editor et la vue diff avant exécution utiliseront Monaco ou à la limite highlight.js pour afficher joliment les scripts. Ce duo vous donne à la fois une expérience terminal crédible et une expérience d’édition moderne. Le dépôt de référence inclut déjà highlight.js, ce qui confirme que la brique “rendu coloré” est déjà dans son ADN. citeturn39view4turn19search6turn19search1
Agent IA, skill Hermes et serveur MCP
Pour la partie agent, je recommande de ne pas mélanger l’orchestration de mise à jour et l’intelligence de synthèse. L’application web doit rester le source of truth opérationnel. Au-dessus, vous ajoutez un serveur MCP qui expose proprement les machines, les snapshots JSON, les exécutions, les rapports, les templates et les actions autorisées. MCP est conçu pour relier des applications LLM à des outils externes, avec JSON-RPC et des transports standards comme stdio et Streamable HTTP. C’est exactement le bon niveau d’abstraction pour faire consommer votre plateforme par Claude Code, Hermes ou d’autres agents. citeturn16search3turn16search5turn34search1turn16search7
Pour Claude Code, je vous conseille un transport stdio local en priorité, car il est explicitement recommandé lorsque c’est possible, et c’est le cas d’usage le plus naturel pour un outil qui tourne au plus près du code et des commandes locales. Pour Hermes Agent, l’intérêt est double : sa documentation explique qu’il sait se connecter à des serveurs MCP externes, et ses références montrent aussi qu’il a tout un système de skills. Autrement dit, votre architecture peut être : webapp/API → MCP server → Claude Code / Hermes. citeturn34search1turn35search1turn35search20
Concernant Hermes, les docs officielles disent qu’une Skill est le bon format quand la capacité peut être exprimée comme un mélange d’instructions, commandes shell et outils existants, alors qu’un Tool est préférable pour les intégrations plus profondes, streaming temps réel, auth complexe ou logique très spécialisée. Dans votre cas, la mise à jour distante elle-même doit rester dans l’application et son MCP server, mais la planification, l’analyse des updates, la mutualisation des recherches web, l’interprétation des erreurs et la rédaction de rapports sont d’excellents candidats pour une Skill Hermes. citeturn36search2turn35search2turn35search6
Le rôle de l’agent doit rester borné. Je proposerais qu’il sache : lire un snapshot JSON machine, regrouper les updates identiques, rechercher brièvement la nature des paquets ou images quand ils sont inconnus, proposer un plan de mise à jour succinct, déclencher uniquement des actions autorisées, puis archiver un rapport Markdown. Il ne doit jamais recevoir les mots de passe, ni exécuter directement des commandes SSH brutes, ni modifier les templates sans validation opérateur. Cette séparation est cohérente avec les recommandations de Claude Code sur les fichiers CLAUDE.md, les patterns d’instructions persistantes et les bonnes pratiques de skills concises, chargées à la demande. citeturn33search5turn33search6turn33search4
Les outils MCP que je proposerais en v1 sont très peu nombreux : list_machines, get_machine_snapshot, get_execution_report, run_refresh, run_approved_action, list_templates, render_template_preview, search_archived_reports. Plus vous garderez cette surface petite, plus les agents resteront fiables. Le skill Hermes, lui, agira surtout comme un mode d’emploi intelligent de ce MCP, pas comme un exécuteur système autonome. citeturn35search1turn36search2
Fichiers de consigne proposés
Les docs officielles de Claude Code indiquent que les fichiers CLAUDE.md servent d’instructions persistantes de projet, lues au démarrage de chaque session. Les docs Hermes indiquent de leur côté qu’une skill repose sur un SKILL.md avec frontmatter et sections explicites (When to Use, Procedure, Verification, etc.). Je vous propose donc de partir avec un fichier principal de consignes pour Claude Code, une skill Hermes, et une note de contrat MCP. citeturn33search5turn36search2turn36search0
CLAUDE.md
# Projet webapp de mise à jour distante Linux
## Langue et ton
- Répondre en français.
- Favoriser des propositions concrètes, structurées et justifiées.
- Ne pas imposer une architecture finale : proposer, comparer, argumenter.
## Rôle de l’agent
- L’agent aide à concevoir et faire évoluer la webapp.
- L’agent ne décide pas seul de la structure finale du projet.
- L’agent doit expliciter les compromis techniques importants.
- L’agent doit prioriser la sécurité, la lisibilité et l’évolutivité.
## Références locales
- Les dépôts `linux-update-dashboard` et `nas-ops` sont présents comme références de travail.
- Les considérer comme des sources d’inspiration et d’analyse.
- Ne pas recopier de larges portions de code sans vérifier la compatibilité de licence et sans réécriture adaptée au projet.
## Objectif produit
Construire une webapp qui permet :
- d’ajouter des machines sans inventaire prédéfini ;
- de rafraîchir les mises à jour en tâche de fond ;
- de déclencher manuellement les upgrades système et Docker ;
- de gérer Debian, Ubuntu, Proxmox et Raspberry Pi OS en priorité ;
- de configurer apt-cacher-ng depuis le frontend ;
- de gérer des templates de commandes et des overrides par machine ;
- d’exposer des JSON propres au frontend, au MCP server et aux agents ;
- d’archiver des rapports Markdown après chaque exécution ;
- de préparer l’évolution vers post-install, réseau, installation de paquets, scripts custom.
## Principes d’architecture
- Backend TypeScript modulaire.
- Frontend React + TypeScript.
- Les opérations distantes passent par SSH agentless.
- La logique métier d’update doit vivre dans des templates shell versionnés.
- Le backend orchestre, journalise, valide, chiffre, historise.
- Les secrets ne vont jamais dans les prompts des agents.
- Les logs destinés aux agents doivent être filtrés et résumés.
## Sécurité
- Préférer la vérification des host keys.
- Prévoir bastion / ProxyJump.
- Utiliser un utilisateur dédié côté machines.
- Réduire sudo au strict nécessaire.
- Chiffrer les credentials au repos.
- Ne jamais afficher de secret brut dans les logs, l’UI ou les retours MCP.
## Règles fonctionnelles
- `update/check` = tâche de fond.
- `upgrade/full-upgrade/dist-upgrade/docker apply/reboot` = action manuelle validée.
- Toujours distinguer détection, planification et exécution.
- Toujours produire un JSON canonique par machine.
- Toujours archiver un rapport `.md` après exécution.
## UX attendue
- Page d’accueil vide au premier lancement.
- Bouton `+` pour ajouter une machine.
- Tuiles machines avec nom, IP, OS, compteurs, paquets et Docker à mettre à jour.
- Onglet Paramétrage pour templates, règles frontend, profils d’OS et options agent.
- Volet terminal à droite, redimensionnable, avec flux live.
## Contraintes agent
- Lorsqu’une proposition d’architecture est faite, toujours distinguer :
- MVP recommandé ;
- options alternatives ;
- risques / limites.
- Éviter les générateurs opaques et les abstractions inutiles.
- Préférer des noms de dossiers explicites et une convention stable.
## Livrables attendus
Quand on demande une proposition technique, fournir si pertinent :
- structure de projet ;
- schémas JSON ;
- contrats d’API ;
- templates shell ;
- plan de roadmap ;
- risques de sécurité ;
- stratégie de tests ;
- impacts UX.
hermes-skills/update-ops-planner/SKILL.md
---
name: update-ops-planner
description: Analyse les snapshots JSON de mises à jour Linux/Docker, déduplique les items, recherche brièvement leur objet, propose un plan d’exécution et génère un rapport Markdown.
version: 1.0.0
author: Projet Webapp Updates
license: Proprietary
platforms: [linux]
metadata:
hermes:
tags: [ops, updates, linux, docker, mcp, reporting]
requires_toolsets: [web]
related_skills: []
---
# Update Ops Planner
## When to Use
Charger cette skill quand l’utilisateur :
- fournit un snapshot JSON machine de mises à jour ;
- demande un plan de mise à jour système ou Docker ;
- demande une synthèse d’erreurs d’upgrade ;
- demande un rapport Markdown à archiver ;
- demande de mutualiser l’analyse sur plusieurs machines.
## Quick Reference
- Toujours lire d’abord le JSON normalisé.
- Dédupliquer les mises à jour identiques entre machines.
- Chercher sur le web uniquement pour :
- paquets ou images peu explicites ;
- composants critiques ;
- erreurs non triviales ;
- changements majeurs de version.
- Produire une réponse courte, opérationnelle et non alarmiste.
- Ne jamais demander ni afficher de secrets.
## Procedure
1. Lire le snapshot JSON fourni par le MCP server.
2. Identifier :
- updates système ;
- updates Docker ;
- reboot requis ;
- erreurs ou warnings ;
- éléments dupliqués entre machines.
3. Pour chaque item pertinent, dédupliquer par nom + version cible.
4. Pour les items inconnus ou importants, faire une recherche web brève.
5. Produire un plan de mise à jour :
- ordre recommandé ;
- éléments sûrs à appliquer en lot ;
- éléments à isoler ;
- reboot éventuel ;
- vérifications post-run.
6. Générer un rapport Markdown avec :
- résumé exécutif ;
- tableau des updates système ;
- tableau des updates Docker ;
- risques connus ;
- ordre recommandé ;
- incidents / erreurs ;
- annexes JSON utiles.
7. Si un résultat d’exécution est fourni, comparer avant/après et résumer :
- succès ;
- écarts de versions ;
- erreurs restantes ;
- actions de remédiation.
## Pitfalls
- Ne pas inférer une criticité sans source.
- Ne pas répéter la même recherche pour 10 machines identiques.
- Ne pas transmettre les logs bruts complets au modèle si une version filtrée existe.
- Ne pas confondre `refresh` et `upgrade`.
- Ne pas supposer qu’un `docker pull` implique un redéploiement réussi.
## Verification
Vérifier que la sortie contient :
- un résumé lisible ;
- un plan d’exécution ordonné ;
- la liste des mises à jour regroupées ;
- une section risques/erreurs si nécessaire ;
- un rapport Markdown archivable.
## Output Format
Toujours retourner :
- `summary`
- `deduplicated_updates`
- `recommended_plan`
- `web_notes`
- `report_markdown`
docs/MCP_CONTRACTS.md
# Contrats MCP proposés
## Principe
Le MCP server ne contient pas la logique SSH métier.
Il appelle l’API interne de la webapp et expose un outillage minimal, stable et typé.
## Tools v1
- `list_machines()`
- `get_machine_snapshot(machineId)`
- `get_machine_execution(machineId, executionId)`
- `run_refresh(machineId)`
- `run_action(machineId, action, options)`
- `list_templates()`
- `preview_template(machineId, templateName)`
- `search_reports(query)`
## Resources v1
- `machine://{id}/snapshot`
- `machine://{id}/history`
- `report://{executionId}`
## Règles
- Les tools d’exécution ne reçoivent jamais de secret brut.
- Les réponses d’exécution renvoient des références de rapport et des lignes importantes, pas uniquement du log brut.
- Le MCP server doit rester une façade de l’API métier.
- Les actions destructives doivent être explicitement approuvées côté application.
## JSON canoniques
Utiliser deux schémas principaux :
- `update availability snapshot`
- `execution result`
## Déduplication
- Système : `os_family + package + from + to + origin`
- Docker : `image + fromDigest + toDigest`
Questions ouvertes et limites
Le point le plus important à clarifier avant toute implémentation est le niveau de réutilisation autorisé des deux dépôts, car linux-update-dashboard est bien sous AGPL-3.0, tandis que la licence de nas-ops n’était pas visible dans les pages consultées. Tant que ce point n’est pas purgé, je vous conseille de garder les deux dépôts dans le projet comme références lues par les agents et les développeurs, mais de reconstruire votre propre code. citeturn24view1turn24view0turn24view2
Il reste aussi quelques choix d’architecture à trancher au début du projet : PostgreSQL seul avec pg-boss ou PostgreSQL + Redis/BullMQ, auth par mot de passe en production ou SSH key only, scope strictement agentless ou préparation d’un futur agent local, et politique exacte de stockage des rapports sur filesystem local, NAS ou bucket objet. Ces questions ne bloquent pas l’étude, mais elles influencent la structure du backend et le niveau de complexité du déploiement. citeturn27search2turn27search5turn27search0turn27search12
En synthèse, la proposition la plus robuste pour votre besoin est : webapp React/TypeScript avec design system shadcn/ui + icônes Lucide + terminal xterm.js, backend Hono/TypeScript, orchestration SSH agentless, templates shell versionnés par OS et par capacité, JSON canoniques pour frontend/MCP/agent, refresh en tâche de fond, upgrade manuel, serveur MCP en façade, et skill Hermes centrée sur l’analyse, la déduplication, la recherche web ciblée et le reporting. C’est la combinaison la plus cohérente de ce que vos deux dépôts de référence font déjà bien, tout en restant propre, évolutive et compatible avec une future collaboration structurée avec Claude Code. citeturn24view1turn3view3turn4view1turn20search13turn26search1turn19search1turn25search4turn34search1turn36search2