Files
system_update/deep-research-report(7).md
T
gilles 1e1be7f627 docs: fondation projet (CLAUDE.md, design system, spec + plan jalon 1)
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>
2026-06-05 04:41:30 +02:00

34 KiB
Raw Blame History

Étude darchitecture 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 sagit dune application TypeScript presque entièrement composée dun frontend React 19 + Vite 8 + Tailwind CSS 4 et dun backend Hono, avec Drizzle ORM, SQLite, SSH2, WebSocket, highlight.js, Mustache, OIDC, WebAuthn, MQTT et des scripts de planification. Le README et larborescence 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. citeturn24view1turn39view0turn6view0turn6view1turn25search4turn25search5

Sur le plan dexécution, linux-update-dashboard expose des routes API pour les systèmes, les mises à jour, les scripts, les réglages et les credentials, ainsi quune 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 dexit code, ce qui permet aux opérations longues de survivre à une coupure SSH. citeturn7view0turn12view1turn12view3turn11view0

Le dépôt nas-ops apporte lautre 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 dimage 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 denvironnement OMV et renvoie à son tour un JSON dexécution. citeturn2view4turn3view3turn3view4turn4view0turn4view1turn4view2turn18view0turn18view1turn18view2

Le point important est donc le suivant: linux-update-dashboard apporte un excellent modèle dapplication 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 nen reprendre quune seule. citeturn24view1turn3view3turn3view4turn4view1turn4view2

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 nai 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 lapp, mais en les considérant dabord comme sources dinspiration et de vérification, pas comme du code à recopier sans revue de licence. citeturn24view1turn24view0turn24view2

Principes darchitecture à 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 lesprit nas-ops, tandis que le backend gère linventaire, les droits, les jobs, les logs live, le chiffrement des secrets, lhistorique et lAPI. Cest exactement la séparation de responsabilités que la combinaison des deux dépôts rend possible. citeturn24view1turn3view3turn3view4turn4view1turn4view2

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ù lutilisateur 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 quun script shell bien écrit peut déjà servir dAPI machine. citeturn24view1turn7view0turn12view1turn3view3turn4view0turn4view1turn4view2

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 à lapproche de linux-update-dashboard, qui distingue déjà les checks, les upgrades, lautoremove et le reboot, avec certaines opérations exécutées en mode SSH-safe détaché. citeturn23view0turn24view1turn11view0turn12view3

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 lesprit 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 dinstallation de paquets. citeturn24view1turn8view2

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à quun tel couple tient bien la charge sur ce type doutil. Pour le design system, je recommande shadcn/ui plutôt quune 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. citeturn39view0turn19search3turn20search13turn20search1turn26search1turn26search2

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 dattache WebSocket. Autrement dit, Monaco pour éditer les templates, xterm.js pour voir lexé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”. citeturn19search6turn19search1turn19search12turn7view0turn12view1

Pour le backend HTTP/API, Hono est une proposition cohérente. Le projet de référence lutilise 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. citeturn25search0turn25search4turn7view0

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 linfrastructure, 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. citeturn25search5turn25search13turn27search2turn27search5turn27search0turn27search12

Pour lexé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 lapplication nest 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. citeturn24view1turn13search0turn12view3

Flux fonctionnels et contrats JSON

Votre flux de base peut être très simple côté produit. La page daccueil démarre vide. Un bouton + ouvre un formulaire dajout machine contenant: nom, OS, IP/hostname, port SSH, username, mode dauthentification (mot de passe, clé SSH plus tard), sudo password si nécessaire, activation de lupdate 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 dajout de système déjà visibles dans linux-update-dashboard rendent cette approche très crédible. citeturn8view2turn24view1

Pour APT, il faut distinguer les sens exacts des commandes. Le manpage officiel dAPT rappelle que update resynchronise les index, que upgrade nenlève pas de paquets installés et nen 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 quAPT est bien le gestionnaire natif. Votre moteur de templates doit donc faire de lOS profile-aware, pas du simple collage de commandes. citeturn23view0turn31search1turn31search11turn31search0turn31search2

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 à lexé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. citeturn21search0turn29search0

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 quil ne faut pas seulement “tirer une commande Docker”, mais dabord détecter les updates, identifier la stack, puis retourner un JSON compact. En revanche, nas-ops sappuie principalement sur les labels des conteneurs déjà en cours dexécution (com.docker.compose.project.working_dir); pour votre app, comme vous voulez déclarer les dossiers Docker depuis le frontend, jajouterais un fallback par scan de répertoires configurés pour lister les stacks même si aucun conteneur nest encore lancé. citeturn21search2turn32search1turn32search4turn4view1turn4view2

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 dexé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é. citeturn3view3turn3view4turn4view0turn4view1turn4view2turn12view1

{
  "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 à lagent 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 dimage et, quand ils existent, des labels de version et de source. citeturn4view1turn28search2turn28search14

Enfin, pour limiter les tokens transmis à lagent, 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. Cest très cohérent avec lesprit “JSON + flux live séparé” visible dans les deux dépôts. citeturn3view3turn3view4turn4view0turn4view1turn12view1

Frontend et expérience opérateur

LUX que vous décrivez est réaliste et même très bonne pour lusage homelab/prod légère: une page daccueil 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. Lexemple visuel de linux-update-dashboard montre déjà bien lintérêt dun dashboard à tuiles, complété par une page détail plus riche. citeturn24view1turn15search0

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 dactivité, 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 dOS, les politiques dapprobation et les réglages dagent/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. citeturn24view1turn8view2

Pour le volet terminal à droite, oui, cest 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 dun addon dattache à WebSocket ; de plus, linux-update-dashboard expose déjà un flux WebSocket structuré de sortie de commande. Comme lAPI 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 quun caractère-par-caractère. citeturn20search1turn19search1turn19search12turn7view0turn12view1turn14search8

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. citeturn39view4turn19search6turn19search1

Agent IA, skill Hermes et serveur MCP

Pour la partie agent, je recommande de ne pas mélanger lorchestration de mise à jour et lintelligence de synthèse. Lapplication 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. Cest exactement le bon niveau dabstraction pour faire consommer votre plateforme par Claude Code, Hermes ou dautres agents. citeturn16search3turn16search5turn34search1turn16search7

Pour Claude Code, je vous conseille un transport stdio local en priorité, car il est explicitement recommandé lorsque cest possible, et cest le cas dusage le plus naturel pour un outil qui tourne au plus près du code et des commandes locales. Pour Hermes Agent, lintérêt est double: sa documentation explique quil sait se connecter à des serveurs MCP externes, et ses références montrent aussi quil a tout un système de skills. Autrement dit, votre architecture peut être: webapp/APIMCP serverClaude Code / Hermes. citeturn34search1turn35search1turn35search20

Concernant Hermes, les docs officielles disent quune Skill est le bon format quand la capacité peut être exprimée comme un mélange dinstructions, commandes shell et outils existants, alors quun 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 lapplication et son MCP server, mais la planification, lanalyse des updates, la mutualisation des recherches web, linterprétation des erreurs et la rédaction de rapports sont dexcellents candidats pour une Skill Hermes. citeturn36search2turn35search2turn35search6

Le rôle de lagent doit rester borné. Je proposerais quil 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 dinstructions persistantes et les bonnes pratiques de skills concises, chargées à la demande. citeturn33search5turn33search6turn33search4

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 demploi intelligent de ce MCP, pas comme un exécuteur système autonome. citeturn35search1turn36search2

Fichiers de consigne proposés

Les docs officielles de Claude Code indiquent que les fichiers CLAUDE.md servent dinstructions persistantes de projet, lues au démarrage de chaque session. Les docs Hermes indiquent de leur côté quune 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. citeturn33search5turn36search2turn36search0

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 lagent
- Lagent aide à concevoir et faire évoluer la webapp.
- Lagent ne décide pas seul de la structure finale du projet.
- Lagent doit expliciter les compromis techniques importants.
- Lagent 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 dinspiration et danalyse.
- 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 :
- dajouter 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 ;
- dexposer des JSON propres au frontend, au MCP server et aux agents ;
- darchiver des rapports Markdown après chaque exécution ;
- de préparer l’évolution vers post-install, réseau, installation de paquets, scripts custom.

## Principes darchitecture
- Backend TypeScript modulaire.
- Frontend React + TypeScript.
- Les opérations distantes passent par SSH agentless.
- La logique métier dupdate 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, lUI 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 daccueil 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 dOS et options agent.
- Volet terminal à droite, redimensionnable, avec flux live.

## Contraintes agent
- Lorsquune proposition darchitecture 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 dAPI ;
- 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 dexé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 lutilisateur :
- fournit un snapshot JSON machine de mises à jour ;
- demande un plan de mise à jour système ou Docker ;
- demande une synthèse derreurs dupgrade ;
- demande un rapport Markdown à archiver ;
- demande de mutualiser lanalyse sur plusieurs machines.

## Quick Reference
- Toujours lire dabord 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 dexé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 quun `docker pull` implique un redéploiement réussi.

## Verification
Vérifier que la sortie contient :
- un résumé lisible ;
- un plan dexé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 lAPI 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 dexécution ne reçoivent jamais de secret brut.
- Les réponses dexé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 lAPI 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 nest 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. citeturn24view1turn24view0turn24view2

Il reste aussi quelques choix darchitecture à 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 dun 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. citeturn27search2turn27search5turn27search0turn27search12

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 lanalyse, la déduplication, la recherche web ciblée et le reporting. Cest 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. citeturn24view1turn3view3turn4view1turn20search13turn26search1turn19search1turn25search4turn34search1turn36search2