From 1e1be7f627ecd6f397af940af282c7ff8f5bb374 Mon Sep 17 00:00:00 2001 From: Gilles Soulier Date: Fri, 5 Jun 2026 04:41:30 +0200 Subject: [PATCH] docs: fondation projet (CLAUDE.md, design system, spec + plan jalon 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ignore les dépôts de référence imbriqués (linux-update-dashboard, nas-ops). Co-Authored-By: Claude Opus 4.8 --- .claude/settings.json | 7 + .gitignore | 4 + CLAUDE.md | 100 + ajout.md | 150 ++ deep-research-report(7).md | 401 +++ design_system/README.md | 304 +++ design_system/components/ui-kit.jsx | 656 +++++ design_system/consigne_design_system.md | 363 +++ design_system/examples/exemple-minimal.html | 115 + design_system/examples/exemple-tout.html | 1015 ++++++++ design_system/tokens/tokens.css | 204 ++ design_system/tokens/tokens.gnome.css | 378 +++ design_system/tokens/tokens.json | 136 + ...2026-06-04-jalon1-tranche-verticale-apt.md | 2267 +++++++++++++++++ ...-04-jalon1-tranche-verticale-apt-design.md | 179 ++ 15 files changed, 6279 insertions(+) create mode 100644 .claude/settings.json create mode 100644 CLAUDE.md create mode 100644 ajout.md create mode 100644 deep-research-report(7).md create mode 100644 design_system/README.md create mode 100644 design_system/components/ui-kit.jsx create mode 100644 design_system/consigne_design_system.md create mode 100644 design_system/examples/exemple-minimal.html create mode 100644 design_system/examples/exemple-tout.html create mode 100644 design_system/tokens/tokens.css create mode 100644 design_system/tokens/tokens.gnome.css create mode 100644 design_system/tokens/tokens.json create mode 100644 docs/superpowers/plans/2026-06-04-jalon1-tranche-verticale-apt.md create mode 100644 docs/superpowers/specs/2026-06-04-jalon1-tranche-verticale-apt-design.md diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..7d752e4 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(git checkout *)" + ] + } +} diff --git a/.gitignore b/.gitignore index 856bab6..fbd5246 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ data/ .env reports/* !reports/.gitkeep + +# Dépôts de référence (git imbriqués) — inspiration uniquement, gérés séparément +linux-update-dashboard/ +nas-ops/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6670430 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,100 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Langue de travail + +Répondre et documenter **en français**. C'est la langue du projet et de l'utilisateur. + +## Nature du projet et état actuel + +Objectif : construire une **webapp de mise à jour distante de machines Linux** (Debian, Ubuntu, Proxmox, Raspberry Pi OS) + Docker Compose, pilotée par SSH agentless, avec un copilote IA (« Hermes ») branché via un serveur MCP. + +**Le projet est en phase de conception — l'application n'est pas encore initialisée.** Le dépôt ne contient pour l'instant que : + +- `deep-research-report(7).md` — l'étude d'architecture de référence (stack, contrats JSON, flux, sécurité). **À lire avant toute décision d'architecture.** +- `ajout.md` — l'ajout du volet Hermes et le périmètre du serveur MCP. +- `design_system/` — le design system **Gruvbox seventies** à utiliser pour tout le frontend (voir section dédiée). +- `linux-update-dashboard/` et `nas-ops/` — **dépôts de référence en lecture seule** (voir ci-dessous). + +Avant d'écrire du code applicatif, proposer/valider une structure avec l'utilisateur : ne pas figer l'architecture finale seul. + +## Dépôts de référence (inspiration, PAS copie) + +Ces deux dossiers sont des **sources d'analyse**, pas du code à recopier. Ne pas réutiliser de larges portions sans réécriture adaptée et vérification de licence. + +- **`linux-update-dashboard/`** — licence **AGPL-3.0**. Excellent modèle d'**orchestration web agentless par SSH** : front React 19 + Vite + Tailwind 4, backend Hono, Drizzle + SQLite, SSH2, WebSocket de flux live (`/api/ws/systems/:id/output` avec messages `started`/`output`/`phase`/`done`/`error` et buffer rejouable), exécution détachée `nohup` survivant aux coupures SSH, credentials chiffrés au repos, host-key approval, ProxyJump. La contrainte AGPL impose de **reconstruire notre propre code**. +- **`nas-ops/`** — scripts Bash déterministes **JSON-friendly** (`nas-system-update`, `nas-system-upgrade`, `nas-docker-pull`, `nas-docker-up`). Modèle pour la **logique métier dans des scripts shell** qui détectent puis émettent un JSON compact (compare les image IDs avant/après pull, lit les labels compose). Licence non confirmée — traiter en référence. + +Principe directeur issu de l'étude : **fusionner les deux** — orchestration web façon `linux-update-dashboard` + logique métier en templates shell versionnés façon `nas-ops`. + +## Architecture cible (à construire) + +Quatre couches, le backend **orchestre mais ne connaît pas la logique fine des mises à jour** : + +1. **UI** — React + TypeScript + Vite. Pas de machine pré-déclarée ; ajout via bouton `+`. +2. **API** — Hono/TypeScript. Stocke machines, credentials (chiffrés), templates, jobs, rapports. +3. **Worker** — refresh et opérations longues en arrière-plan (file de jobs ; pg-boss sur Postgres recommandé en MVP). +4. **SSH/script runtime** — pousse les commandes, normalise les retours en **JSON canonique**. + +La logique « comment mettre à jour APT / lister les stacks Docker » vit dans des **templates shell versionnés sur disque** (OS profile-aware), éditables depuis le front mais sauvegardés comme ressources de projet, avec overrides par machine. Ne pas stocker les commandes critiques uniquement en base. + +Stack recommandée par l'étude : front shadcn/ui + Lucide, **Monaco** pour éditer les templates, **xterm.js** (couleurs ANSI, addon WebSocket) pour le terminal live à droite, layout `Resizable`. Backend Hono. Stockage **PostgreSQL + Drizzle** (plutôt que SQLite pour le projet final). Ces choix restent à confirmer avec l'utilisateur (cf. « Questions ouvertes » du rapport). + +## Règles fonctionnelles (invariants) + +- **`update`/`check` = tâche de fond** ; **`upgrade`/`full-upgrade`/`dist-upgrade`/`docker apply`/`reboot` = action manuelle validée** dans l'UI. +- Toujours distinguer **détection → planification → exécution**. +- Toujours produire un **JSON canonique par machine**. Deux schémas pivots : *update availability snapshot* et *execution result* (exemples complets dans `deep-research-report(7).md`). +- Après chaque exécution, **archiver un rapport `.md`** (et garder le log brut référencé, pas inliné). +- **Réduction déterministe avant tout appel LLM** : ne garder que les lignes utiles (APT : `Inst`/`Conf`/`Remv`/`Err`/`E:`/`W:`/`dpkg:`/`reboot-required` ; Docker : `Pulling`/`Digest`/`Status`/`Downloaded newer image`/`Recreating`/`Started`/`Error`). Le reste reste dans le log archivé. +- **Déduplication** des updates entre machines par empreinte fonctionnelle — système : `os_family + package + from + to + origin` ; Docker : `image + fromDigest + toDigest`. +- Docker : détecter via labels compose des conteneurs *en cours*, mais prévoir un **fallback par scan des répertoires Compose déclarés** (stacks non démarrées). + +## Sécurité (non négociable) + +- **Aucun secret ne transite vers un agent/LLM ni dans un prompt** : mots de passe SSH, sudo password, tokens, clés privées restent côté backend. +- **Aucun secret en clair** dans les logs, l'UI ou les retours MCP. +- Credentials **chiffrés au repos**. Vérification des host keys. Bastion/ProxyJump prévu. Utilisateur dédié de maintenance, sudo réduit au strict nécessaire. +- App pensée pour un **réseau de confiance** derrière reverse proxy/TLS/VPN, pas exposée directement à Internet. + +## Hermes / serveur MCP + +Hermes est un **copilote d'analyse**, la **webapp reste le chef d'orchestre**. Layout 3 zones : volet gauche = Hermes (chat, actions rapides, liens rapports), centre = dashboard machines, droite = terminal live. + +- **Hermes n'exécute jamais de SSH directement.** Il passe uniquement par l'API interne / le serveur MCP, sur des actions explicitement autorisées, en consommant les JSON normalisés. +- Le **MCP est une façade** de l'API métier (pas de logique SSH dedans). Il ne reçoit jamais de secret ; les actions destructives exigent une validation côté webapp. +- Surface MCP volontairement **petite** (v1) : `list_machines`, `get_machine_snapshot`, `get_machine_execution`, `run_refresh`, `run_action`, `list_templates`, `preview_template`, `search_reports`. Contrats détaillés dans `deep-research-report(7).md` → `docs/MCP_CONTRACTS.md`. +- Le rôle d'Hermes : lire un snapshot, regrouper les doublons, recherche web ciblée sur les inconnus, proposer un plan court, rédiger un rapport Markdown. La skill `update-ops-planner` (gabarit dans le rapport) encapsule ce mode d'emploi. + +## Design system — Gruvbox seventies (frontend) + +**Tout le frontend doit suivre `design_system/consigne_design_system.md` — le lire en entier avant d'écrire du JSX.** Vibe rétro-industriel / console de monitoring. Règles dures : + +- **Variables CSS uniquement**, jamais de hex en dur (`var(--accent)`, pas `#fe8019`). Toujours un `data-theme` (`dark`/`light`) sur un parent, et vérifier les deux thèmes. +- **Réutiliser les composants existants** de `design_system/components/ui-kit.jsx` (Button, IconButton, Toggle, StatusLed, RadialGauge, BatteryGauge, Popup, TreeNav, Sparkline, LineChart, Tooltip, Icon) avant d'en créer. +- **Icônes** via `` (noms mappés Font Awesome) — **jamais d'emoji ni de SVG inline custom**. +- **Pas de hover** sur boutons/tuiles (sauf jauges) — seulement la pression 3D `.interactive`. IconButton seul → `label` obligatoire (tooltip). Jamais `window.alert`/`confirm` → ``. +- Polices strictes : **Inter** (UI), **JetBrains Mono** (données/IDs/IPs), **Share Tech Mono** (logs/terminal). Labels en uppercase `.label`. +- Tokens : `design_system/tokens/tokens.css` (web), `tokens.gnome.css` (GTK4/libadwaita), `tokens.json`. + +## Commandes (dépôt de référence uniquement) + +Le projet principal n'a pas encore de toolchain. Les commandes ci-dessous concernent **`linux-update-dashboard/`** (pnpm, Node 24, à lancer depuis ce sous-dossier) et servent de modèle pour notre futur setup : + +```bash +pnpm install +pnpm dev # serveur (tsx watch) + client (vite) en parallèle +pnpm build # vite build && tsup +pnpm start # node dist/server/index.js +pnpm test # vitest run (un seul test : pnpm test -- ) +pnpm check # tsc --noEmit +``` + +## Fichiers de consigne à créer au démarrage + +L'étude (`ajout.md`) liste les fichiers à mettre en place : `docs/CONSIGNE_PROJET.md`, `docs/ARCHITECTURE.md`, `docs/MCP_CONTRACTS.md`, `docs/HERMES_INTEGRATION.md`, `docs/SECURITY.md`, `docs/JSON_SCHEMAS.md`, `docs/TEMPLATES_UPDATE.md`, `hermes-skills/update-ops-planner/SKILL.md`, `mcp/README.md`, et les `templates/apt/*.sh.tpl` + `templates/docker/*.sh.tpl`. Les dépôts de référence sont à déplacer sous `references/` une fois le projet structuré. + +## Posture attendue de l'agent + +Pour toute proposition technique, distinguer **MVP recommandé / alternatives / risques**. Éviter les abstractions et générateurs opaques. Préférer des noms de dossiers explicites et une convention stable. En cas de doute sur l'architecture finale, **demander** plutôt que figer. diff --git a/ajout.md b/ajout.md new file mode 100644 index 0000000..7ea7281 --- /dev/null +++ b/ajout.md @@ -0,0 +1,150 @@ +À prévoir dans les consignes : un volet gauche “Hermes” intégré à la webapp. + +Architecture proposée : + +Frontend Webapp +├─ Centre : dashboard machines / tuiles / actions +├─ Droite : terminal live xterm.js +└─ Gauche : panneau Hermes + ├─ chat avec Hermes + ├─ envoi d’ordres structurés + ├─ retour d’analyse + ├─ plan de mise à jour proposé + └─ liens vers rapports Markdown + +Principe important : Hermes ne doit pas exécuter directement les commandes SSH. Il dialogue avec la webapp via API/MCP, analyse les snapshots JSON, propose un plan, puis l’utilisateur valide les actions dans l’interface. + +À ajouter dans les fichiers de consigne : + +Ajout : intégration Hermes dans la webapp + +Prévoir un panneau latéral gauche dédié à Hermes Agent. + +Objectif + +Permettre à l’utilisateur de dialoguer avec Hermes depuis la webapp pour : + +transmettre des messages ; +demander une analyse des mises à jour disponibles ; +demander un plan de mise à jour ; +analyser les erreurs après exécution ; +générer ou consulter un rapport Markdown ; +demander une synthèse globale multi-machines. +Règle de sécurité + +Hermes ne doit jamais exécuter directement de commandes SSH. + +Hermes doit uniquement passer par : + +l’API interne de la webapp ; +le serveur MCP du projet ; +les actions explicitement autorisées ; +les JSON normalisés produits par la webapp. + +Les secrets SSH, mots de passe, sudo password, tokens et clés privées ne doivent jamais être transmis à Hermes. + +UX attendue + +Le layout principal doit prévoir trois zones : + +volet gauche : assistant Hermes ; +zone centrale : dashboard machines ; +volet droit : terminal live. + +Le volet Hermes doit permettre : + +historique de conversation ; +saisie de message ; +boutons d’actions rapides : +analyser les mises à jour ; +proposer un plan ; +analyser les erreurs ; +générer rapport ; +comparer plusieurs machines ; +affichage des réponses Hermes ; +lien vers les rapports Markdown archivés. +Flux recommandé +La webapp collecte les mises à jour disponibles. +Elle produit un snapshot JSON par machine. +Le frontend peut transmettre à Hermes une version filtrée et dédupliquée. +Hermes analyse les mises à jour. +Hermes propose un plan. +L’utilisateur valide manuellement. +La webapp exécute les actions. +La webapp remonte un JSON de résultat. +Hermes peut analyser le résultat et générer un rapport Markdown. +Fichiers à prévoir dans le projet + +Créer les fichiers suivants dès le démarrage du projet : + +CLAUDE.md +docs/CONSIGNE_PROJET.md +docs/ARCHITECTURE.md +docs/MCP_CONTRACTS.md +docs/HERMES_INTEGRATION.md +docs/SECURITY.md +docs/JSON_SCHEMAS.md +docs/TEMPLATES_UPDATE.md +hermes-skills/update-ops-planner/SKILL.md +mcp/README.md +templates/apt/update.sh.tpl +templates/apt/upgrade.sh.tpl +templates/apt/full-upgrade.sh.tpl +templates/apt/dist-upgrade.sh.tpl +templates/apt/clean.sh.tpl +templates/apt/autoremove.sh.tpl +templates/apt/reboot-check.sh.tpl +templates/docker/scan-compose.sh.tpl +templates/docker/pull.sh.tpl +templates/docker/up.sh.tpl +templates/docker/prune-images.sh.tpl + +Les fichiers importants doivent être modifiables par l’agent Claude Code, mais la structure finale sera décidée après échange avec l’agent. + +Les dépôts de référence doivent être placés dans un dossier dédié : + +references/ +├─ linux-update-dashboard/ +└─ nas-ops/ + +Ils servent d’inspiration et de comparaison technique, pas de copie directe. + +Ajout : rôle du MCP server pour Hermes + +Le serveur MCP doit exposer une interface stable entre la webapp et les agents. + +Tools MCP proposés +list_machines +get_machine_snapshot +get_all_snapshots +get_machine_execution_result +get_report +search_reports +run_refresh +request_action_plan +run_approved_action +list_templates +preview_template +Règles +Le MCP ne reçoit jamais de secret. +Le MCP ne donne accès qu’aux actions prévues. +Les actions dangereuses nécessitent validation côté webapp. +Hermes peut proposer, analyser et documenter. +La webapp reste responsable de l’exécution réelle. +Exemple de commande agent + +L’utilisateur peut écrire dans le volet Hermes : + +Analyse les mises à jour disponibles sur toutes les machines Debian et Proxmox, regroupe les doublons, puis propose un ordre de mise à jour. + +Hermes doit alors : + +récupérer les snapshots via MCP ; +dédupliquer les paquets et images Docker ; +rechercher les composants importants si besoin ; +produire un plan court ; +générer un rapport Markdown archivable. + + + +Je retiendrais donc : Hermes comme copilote d’exploitation, mais webapp comme chef d’orchestre sécurisé. diff --git a/deep-research-report(7).md b/deep-research-report(7).md new file mode 100644 index 0000000..1eff94e --- /dev/null +++ b/deep-research-report(7).md @@ -0,0 +1,401 @@ +# É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. citeturn24view1turn39view0turn6view0turn6view1turn25search4turn25search5 + +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. citeturn7view0turn12view1turn12view3turn11view0 + +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. 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 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. 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 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. citeturn24view1turn24view0turn24view2 + +## 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. 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ù 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. 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 à 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é. 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 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. 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à 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. 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 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”. citeturn19search6turn19search1turn19search12turn7view0turn12view1 + +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. 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 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. citeturn25search5turn25search13turn27search2turn27search5turn27search0turn27search12 + +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. citeturn24view1turn13search0turn12view3 + +## 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. citeturn8view2turn24view1 + +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. 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 à 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. 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 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é. 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 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é. citeturn3view3turn3view4turn4view0turn4view1turn4view2turn12view1 + +```json +{ + "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" + ] + } +} +``` + +```json +{ + "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. citeturn4view1turn28search2turn28search14 + +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. citeturn3view3turn3view4turn4view0turn4view1turn12view1 + +## 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. 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 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. citeturn24view1turn8view2 + +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. 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 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. citeturn16search3turn16search5turn34search1turn16search7 + +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**. citeturn34search1turn35search1turn35search20 + +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**. citeturn36search2turn35search2turn35search6 + +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. 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 d’emploi 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 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**. citeturn33search5turn36search2turn36search0 + +### `CLAUDE.md` + +```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` + +```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` + +```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. citeturn24view1turn24view0turn24view2 + +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. 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 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. citeturn24view1turn3view3turn4view1turn20search13turn26search1turn19search1turn25search4turn34search1turn36search2 \ No newline at end of file diff --git a/design_system/README.md b/design_system/README.md new file mode 100644 index 0000000..a0ee628 --- /dev/null +++ b/design_system/README.md @@ -0,0 +1,304 @@ +# mon design system — Gruvbox seventies + +> Design system rétro-futuriste pour applications de monitoring, ops, IoT, domotique. +> Orange brûlé, fond brun délavé en sombre / gris clair usé en clair. +> **Version 1.0** · deux thèmes (dark + light), 14+ composants React, palette GTK pour GNOME. + +--- + +## 🚀 Démarrage rapide (web) + +```html + + + + + + + + + + + + + + + + + + +
+ + + + + +``` + +Pour voir tout fonctionner, ouvre `examples/exemple-minimal.html`. + +--- + +## 📂 Contenu du package + +``` +export/ +├── README.md ← Ce fichier +├── consigne_design_system.md ← Brief pour agents IA (Claude, ChatGPT…) +├── tokens/ +│ ├── tokens.css ← Variables CSS web (dark + light) +│ ├── tokens.gnome.css ← GTK 4 / libadwaita (apps GNOME) +│ └── tokens.json ← Format générique (Tailwind, Figma…) +├── components/ +│ └── ui-kit.jsx ← 14 composants React (Button, IconButton, Toggle, Tooltip, +│ StatusLed, BatteryGauge, RadialGauge, BigRadialGauge, +│ Popup, TreeNav, Sparkline, LineChart, Icon, …) +└── examples/ + └── exemple-minimal.html ← Démo minimale autoportante +``` + +--- + +## 🎨 Ce qui est paramétrable + +### 1. Thème global + +```html + +``` + +Tu peux mettre `data-theme` sur **n'importe quel parent** pour basculer un sous-arbre uniquement (utile pour une preview en mode opposé dans un menu de réglages). + +### 2. Toutes les couleurs (CSS variables) + +Édite `tokens.css` ou surcharge dans ton propre CSS : + +```css +:root[data-theme="dark"] { + --accent: #fe8019; /* Couleur principale (orange seventies) */ + --accent-soft: #d65d0e; + --bg-1: #2a231d; /* Fond app */ + --bg-3: #3c332a; /* Cartes */ + --ink-1: #f2e5c7; /* Texte */ + --ok: #4dbb26; + --warn: #fabd2f; + --err: #fb4934; + --blue: #3db0d1; /* Datavis additionnel */ + --purple: #c882c8; +} +``` + +**4 statuts** (ok / warn / err / info) + **2 couleurs datavis** (blue / purple) + **6 niveaux de fond** + **4 niveaux d'encre** + **3 niveaux de bordure**. + +### 3. Polices + +Trois familles, toutes substituables : + +| Variable | Usage | Défaut | +|-----------------|-------------------------------------|---------------------| +| `--font-ui` | Interface (titres, corps, boutons) | Inter | +| `--font-mono` | Données, code, valeurs numériques | JetBrains Mono | +| `--font-terminal` | Logs, terminal embarqué, vibe rétro | Share Tech Mono | + +Pour changer, remplace simplement les `@import` Google Fonts et redéfinis les variables. + +### 4. Ombres et relief + +```css +--tile-3d /* Relief 3D marqué pour cartes */ +--shadow-1, -2, -3 /* Niveaux d'élévation */ +--shadow-press /* Inset pour état pressé */ +--hover-glow /* Halo accent au survol */ +``` + +### 5. Composants — props paramétrables + +Chaque composant accepte des props pour personnaliser sans toucher au CSS. Exemples : + +```jsx + + + + + + + + + + + + + Contenu + + + +``` + +Voir la doc complète des props : `Component Reference.html` dans le projet original. + +--- + +## 🐧 Utilisation dans une app GNOME (GTK 4 / libadwaita) + +Charge `tokens/tokens.gnome.css` comme provider CSS au démarrage de l'app. + +**Python (PyGObject)** : +```python +from gi.repository import Gtk, Gdk + +css_provider = Gtk.CssProvider() +css_provider.load_from_path("tokens.gnome.css") +Gtk.StyleContext.add_provider_for_display( + Gdk.Display.get_default(), + css_provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION +) +``` + +**GJS** : +```javascript +const provider = new Gtk.CssProvider(); +provider.load_from_path('tokens.gnome.css'); +Gtk.StyleContext.add_provider_for_display( + Gdk.Display.get_default(), + provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION +); +``` + +**Rust (gtk4-rs)** : +```rust +let provider = gtk::CssProvider::new(); +provider.load_from_path("tokens.gnome.css"); +gtk::style_context_add_provider_for_display( + &gdk::Display::default().unwrap(), + &provider, + gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, +); +``` + +Le fichier override directement les couleurs sémantiques de libadwaita (`@window_bg_color`, `@accent_color`, etc.) ET ajoute des styles spécifiques pour les widgets courants : `button.suggested-action`, `entry`, `switch`, `scale`, `progressbar`, `notebook`, `popover`… + +Classes CSS supplémentaires à appliquer via `add_css_class()` : +- `.tile` / `.card` — Tuile en relief 3D +- `.mono` — Texte monospace JetBrains Mono +- `.terminal` — Texte terminal Share Tech Mono +- `.status.ok` / `.status.warn` / `.status.error` / `.status.info` — Badge de statut + +--- + +## 🔧 Intégration dans d'autres outils + +### Tailwind CSS + +Convertis `tokens.json` en `tailwind.config.js` : + +```js +const tokens = require('./tokens/tokens.json'); +module.exports = { + theme: { + extend: { + colors: { + accent: tokens.themes.dark.accent.primary.value, + ok: tokens.themes.dark.status.ok.value, + // … + }, + fontFamily: { + sans: [tokens.typography.fonts.ui.family, ...tokens.typography.fonts.ui.fallback], + mono: [tokens.typography.fonts.mono.family], + }, + }, + }, +}; +``` + +### Figma / outils de design + +`tokens.json` suit un schéma compatible avec la plupart des plugins de tokens (Figma Tokens, Style Dictionary). Importe-le directement. + +### Variables Sass / SCSS + +```scss +@use 'sass:map'; +$tokens: ( + accent: #fe8019, + bg-1: #2a231d, + ok: #4dbb26, +); +// … +``` + +--- + +## ⚙️ Personnalisation avancée + +### Créer un thème dérivé + +Duplique `tokens.css`, change le nom du sélecteur (`[data-theme="ocean"]` par exemple) et modifie les variables. Charge les deux fichiers — `data-theme` choisira automatiquement. + +### Ajouter une couleur status custom + +```css +:root[data-theme="dark"] { + --critical: #ff0080; + --critical-glow: rgba(255, 0, 128, 0.45); +} +``` + +Utilisable ensuite partout : `` nécessite une PR dans `ui-kit.jsx` (carte `map` dans `StatusLed`), mais en raw CSS tu peux utiliser la variable directement. + +### Désactiver les effets + +Tous les effets de `transition` / `transform` / `box-shadow` sont concentrés dans les classes `.interactive`, `.bg-hover`, `.gauge-hover`. Surcharge-les en CSS si besoin : + +```css +.interactive { transition: none !important; } +``` + +--- + +## ✅ Checklist d'intégration + +- [ ] Polices Google Fonts chargées (Inter, JetBrains Mono, Share Tech Mono) +- [ ] Font Awesome 6 chargé +- [ ] `tokens.css` (web) **ou** `tokens.gnome.css` (GTK) chargé +- [ ] Attribut `data-theme="dark"` (ou "light") sur `` ou un parent +- [ ] React 18 + Babel chargés (uniquement pour `ui-kit.jsx`) +- [ ] `ui-kit.jsx` chargé en `type="text/babel"` + +--- + +## 📋 Statuts du système + +| Couleur | Token | Hex (dark) | Hex (light) | Usage | +|---------|--------|------------|-------------|-----------------------------| +| Accent | `--accent` | `#fe8019` | `#af3a03` | Primaire, focus, sélection | +| OK | `--ok` | `#4dbb26` | `#3c911c` | Succès, état nominal | +| Warn | `--warn` | `#fabd2f` | `#b57614` | Attention, latence élevée | +| Err | `--err` | `#fb4934` | `#9d0006` | Erreur, alerte critique | +| Info | `--info` | `#83a598` | `#427b58` | Information neutre | +| Blue | `--blue` | `#3db0d1` | `#2d82a3` | Datavis catégorie 2 | +| Purple | `--purple` | `#c882c8` | `#8c468c` | Datavis catégorie 3 | + +--- + +## 🤖 Pour les agents IA + +Si tu utilises ce design system avec une IA (Claude, GPT, Copilot, etc.), partage-lui le fichier **`consigne_design_system.md`**. Il y trouvera toutes les règles d'utilisation, conventions, contre-exemples à éviter. + +--- + +**Licence** · Usage libre dans tes projets. Pas de garantie. diff --git a/design_system/components/ui-kit.jsx b/design_system/components/ui-kit.jsx new file mode 100644 index 0000000..92f9e76 --- /dev/null +++ b/design_system/components/ui-kit.jsx @@ -0,0 +1,656 @@ +/* ============================================================ + ui-kit.jsx + Composants haute-fid Gruvbox Seventies. + Tout est purement décoratif/interactif côté composant. + Effets : transparence (glass), hover glow, click 3D, tooltips. + ============================================================ */ + +const { useState, useRef, useEffect } = React; + +/* ============================================================ + Icônes — Font Awesome 6 Free. + Mapping nom logique → classe FA. Le CSS de FA est chargé en CDN + dans le . Le composant garde la MÊME API qu'avant (name, + size, style) pour ne rien casser ailleurs. + ============================================================ */ +const ICON_MAP = { + cpu: 'microchip', + memory: 'memory', + disk: 'hard-drive', + network: 'network-wired', + clock: 'clock', + grid: 'table-cells', + list: 'list', + cog: 'gear', + alert: 'triangle-exclamation', + bell: 'bell', + server: 'server', + chart: 'chart-line', + bars: 'chart-simple', + terminal: 'terminal', + refresh: 'arrows-rotate', + play: 'play', + pause: 'pause', + power: 'power-off', + sun: 'sun', + moon: 'moon', + search: 'magnifying-glass', + close: 'xmark', + chevR: 'chevron-right', + chevL: 'chevron-left', + chevD: 'chevron-down', + chevU: 'chevron-up', + plus: 'plus', + filter: 'filter', + download: 'download', + folder: 'folder', + node: 'circle-nodes', + user: 'user', +}; + +const Icon = ({ name, size = 16, style }) => { + const fa = ICON_MAP[name] || 'circle-question'; + return ( +