# Consigne de dev — Backend, historique JSON et automatisations > **Type** : mission d'**investigation + design backend** (PAS d'implémentation). > **Langue** : français. > **Livrable final attendu** : spec backend prête à passer en plan d'implémentation. --- ## 0. Contexte La webapp `system_update` exécute des scripts SSH agentless sur des machines Linux et reçoit des sorties normalisées en JSON canonique : - snapshots APT ; - résultats d'exécution APT ; - snapshots Docker ; - résultats Docker ; - profils post-install ; - rapports ; - erreurs structurées ; - état reboot/reconnexion. Cette tâche vise le backend : **sauvegarde, historisation, automatisations planifiées, icônes/statuts machine, conservation et API interne**. À lire avant de travailler : - `CLAUDE.md` - `tache1.9.md` - `tache2.md` - `tache3.md` - `tache4.md` - `validation_tache2.md` - `shared/types.ts` - `server/db/schema.ts` - `server/services/refresh.ts` - `server/services/execute.ts` - `server/jobs/worker.ts` - `server/ws/outputHub.ts` --- ## 1. Objectif Concevoir le backend qui stocke et exploite tous les échanges JSON entre machine et webapp. Le backend doit permettre : - historiser chaque interrogation/action machine ; - relier snapshot, exécution, log brut et rapport Markdown ; - afficher l'état actuel des icônes/statuts par machine ; - planifier des tâches automatiques, par exemple `update/analyse` de toutes les machines à heure précise ; - déclencher les refresh Docker/APT/post-install selon un planning ; - gérer erreurs, retries, verrouillage et idempotence ; - exposer une API stable pour l'UI, Hermes/MCP et les rapports. --- ## 2. Données à sauvegarder Chaque échange machine ↔ webapp doit être sauvegardé sous forme structurée. ### Snapshots - `machine_snapshot` - `machine_probe_snapshot` - `machine_metrics_snapshot` - `apt_update_analyze_snapshot` - `docker_scan_snapshot` - `docker_pull_check_snapshot` - `post_install_manifest_snapshot` - `reboot_check_snapshot` Champs communs : ```json { "id": "snap_x", "machineId": "machine_x", "kind": "apt_update_analyze", "createdAt": "ISO", "status": "ok", "payload": {}, "importantLines": [], "rawLogRef": "reports/machine_x/snap_x.log" } ``` ### Exécutions - `apt_upgrade` - `apt_full_upgrade` - `apt_autoremove` - `apt_clean` - `docker_apply` - `docker_prune` - `post_install_profile` - `reboot_verified` Champs communs : ```json { "executionId": "exec_x", "machineId": "machine_x", "action": "apt_upgrade", "mode": "manual", "startedAt": "ISO", "finishedAt": "ISO", "status": "ok", "payload": {}, "rawLogRef": "reports/machine_x/exec_x.log", "reportRef": "reports/machine_x/exec_x.md" } ``` ### Logs, rapports et messages importants Les logs bruts et rapports doivent être accessibles à Hermes, mais par références contrôlées : - le JSON canonique complet reste en BDD ; - le log brut complet reste dans `reports//...log` ou dans un stockage d'artefacts ; - le rapport Markdown reste dans `reports//...md` ; - la BDD garde `rawLogRef`, `reportRef`, taille, checksum, dates, statut de rétention ; - Hermes reçoit par défaut un résumé réduit + des références, pas le log complet. Le backend doit extraire et stocker les messages importants rencontrés dans les sorties APT/Docker/scripts : - erreurs bloquantes : `E:`, `dpkg: error`, lock APT, maintainer script en échec ; - warnings opérationnels : `W:`, dépôt obsolète, signature, clé GPG, service non redémarré ; - messages d'évolution future : annonce de changement majeur Debian/Ubuntu, sécurité paquet, dépréciation de dépôt, changement de politique de paquet ; - messages demandant analyse agent : évolution sécurité, migration de version majeure, configuration legacy, composant bientôt non supporté. Ces messages doivent être stockés comme objets structurés, pas seulement comme lignes de log : ```json { "messageId": "msg_x", "machineId": "machine_x", "source": "apt", "category": "future_major_change", "severity": "warning", "packageName": "openssh-server", "message": "résumé nettoyé sans secret", "rawLineRef": "artifact_x#line_381", "snapshotId": "snap_x", "executionId": null, "createdAt": "ISO", "acknowledged": false } ``` Objectif : - afficher ces warnings dans la tuile machine ; - permettre à Hermes de rechercher les évolutions importantes sans relire tous les logs ; - garder une trace d'un warning même si le prochain `apt update` ne l'affiche plus ; - générer des rapports de veille, par exemple "risques Debian à traiter avant la prochaine version majeure". ### Événements machine Prévoir une table ou collection d'événements : - machine ajoutée ; - connexion testée ; - snapshot créé ; - update disponible ; - action lancée ; - action terminée ; - erreur ; - reboot demandé ; - machine revenue ; - rapport créé ; - notification envoyée. Ces événements alimentent : - timeline machine ; - audit ; - Hermes ; - notifications ; - rapports globaux. --- ## 3. État courant machine Le backend doit dériver un état courant par machine à partir des derniers snapshots/exécutions. État machine minimal : ```json { "machineId": "machine_x", "status": "ok", "apt": { "status": "updates_available", "updatesCount": 4, "lastAnalyzeAt": "ISO", "rebootRequired": false }, "docker": { "status": "updates_available", "installed": true, "stacksCount": 3, "updatesCount": 1, "lastScanAt": "ISO", "pruneAvailable": true }, "postInstall": { "availableProfiles": 12, "pendingProfiles": 0, "lastRunAt": "ISO" }, "profile": { "osFamily": "debian", "osVersion": "13", "osCodename": "trixie", "arch": "amd64", "machineKind": "vm", "virtualization": "qemu", "hardwareProfile": "generic_vm" }, "metrics": { "lastCollectedAt": "ISO", "cpuLoad1": 0.08, "memoryUsedPercent": 26, "rootUsedPercent": 29, "diskWarnings": 0 }, "lastError": null } ``` Cet état sert à mettre à jour les icônes dans les tuiles machine : - LED machine ; - badge APT update ; - badge Docker update ; - reboot requis ; - erreur ; - action running ; - prune disponible ; - warning matériel/driver/repo ; - alerte disque/RAM simple. --- ## 4. Automatisations backend ### Besoin prioritaire Planifier automatiquement : - `apt_update_analyze` de toutes les machines à heure précise ; - `machine_metrics_simple` périodique sur toutes les machines ou les machines sélectionnées ; - éventuellement Docker scan/pull-check selon configuration ; - mise à jour des icônes si des updates sont disponibles ; - notification ou rapport si anomalies. Exemple : ```json { "id": "schedule_daily_update_analyze", "name": "Analyse quotidienne", "enabled": true, "schedule": "0 6 * * *", "timezone": "Europe/Paris", "scope": { "machineIds": "all", "tags": [] }, "actions": [ "apt_update_analyze", "machine_metrics_simple", "docker_scan" ], "concurrency": 2, "notifyOn": ["updates_available", "error"] } ``` ### Moteur de planification MVP recommandé : - `croner` déjà présent dans le projet ; - jobs in-process ; - persistance des schedules en DB ; - verrou machine pour éviter deux actions simultanées sur la même machine. Alternative future : - PostgreSQL + `pg-boss` si besoin de jobs distribués, reprise robuste, retries persistants. Le design doit trancher MVP / futur. --- ## 5. Verrouillage et idempotence Règles : - une machine ne peut exécuter qu'une action à risque à la fois ; - un refresh APT ne doit pas courir pendant un upgrade ; - Docker scan peut être autorisé si aucune action Docker destructive n'est en cours ; - post-install réseau bloque toute autre action machine ; - reboot bloque tout jusqu'à reconnexion ou timeout. Prévoir : - table `machine_locks` ou statut job courant ; - `idempotencyKey` pour éviter les doubles clics ; - retries contrôlés ; - timeout global ; - timeout d'inactivité ; - reprise après redémarrage serveur selon le moteur choisi. --- ## 6. API backend attendue À spécifier : ```text GET /api/capabilities GET /api/system/status GET /api/system/metrics GET /api/machines GET /api/machines/:id/state GET /api/machines/:id/hardware GET /api/machines/:id/metrics GET /api/machines/:id/snapshots GET /api/machines/:id/snapshots/:snapshotId GET /api/machines/:id/executions GET /api/machines/:id/executions/:executionId GET /api/machines/:id/events GET /api/machines/:id/messages POST /api/machines/:id/actions GET /api/artifacts/:artifactId GET /api/artifacts/:artifactId/important-lines GET /api/reports GET /api/reports/:id GET /api/messages GET /api/schedules POST /api/schedules PATCH /api/schedules/:id POST /api/schedules/:id/run-now POST /api/schedules/:id/pause POST /api/schedules/:id/resume DELETE /api/schedules/:id GET /api/settings PATCH /api/settings GET /api/events WS /api/ws/machines/:id/output GET /api/search ``` Clients visés : - frontend web ; - Hermes/MCP via backend ; - future app locale Rust/GNOME ; - scripts d'administration internes éventuels. Chaque endpoint doit garantir : - aucun secret ; - JSON stable ; - erreurs structurées ; - pagination sur historiques longs ; - filtres par machine, action, statut, dates. - versionnement API. ### Authentification clients API Prévoir pour la future app locale : - tokens de clients distincts des credentials machines ; - scopes : `read`, `operate`, `admin`, `debug_logs` ; - révocation ; - rotation ; - audit des appels ; - stockage local côté app via trousseau système, jamais dans le navigateur. Exemple capabilities : ```json { "apiVersion": "1", "features": { "machines": true, "actions": true, "terminalOutput": true, "interactiveSsh": false, "hermes": true, "settings": true } } ``` --- ## 7. Rapports et rétention Prévoir une politique : - log brut complet conservé sous `reports/`; - JSON canonique conservé en DB ; - rapport Markdown lié à l'exécution ; - rétention configurable ; - purge manuelle ; - export global. Les logs bruts ne sont jamais envoyés à Hermes sans réduction déterministe. Règles spécifiques Hermes : - Hermes peut lire les rapports Markdown et les JSON réduits via API/MCP ; - Hermes peut demander des extraits ciblés de log par `artifactId`, plage de lignes ou recherche ; - accès log complet uniquement si l'utilisateur le demande explicitement ou si le rapport d'erreur l'exige ; - toute sortie est masquée côté backend avant exposition ; - chaque lecture Hermes est auditée. Nettoyage : - purge automatique des vieux logs selon paramètres ; - conservation plus longue des logs d'échec et warnings non acquittés ; - conservation des rapports épinglés ; - dry-run obligatoire pour purge manuelle ; - export possible avant suppression ; - suppression en BDD et fichiers cohérente, avec vérification des chemins. --- ## 8. Notifications et intégration Hermes Le backend doit pouvoir notifier : - UI via WebSocket/SSE ; - Hermes via webhook ou MCP selon tâche 6 ; - messagerie via Hermes gateway si configuré. Exemples : - "3 machines ont des updates APT disponibles" ; - "Docker prune possible sur vm_mqtt" ; - "Upgrade terminé avec erreur dpkg" ; - "Machine revenue après reboot en 74s". Les notifications doivent contenir uniquement JSON réduit et références de rapport. --- ## 9. Livrables attendus À produire sous `docs/` : 1. Schéma de données backend. 2. Modèle d'événements machine. 3. Modèle d'état courant machine. 4. Spécification des schedules automatisés. 5. Règles de verrouillage/idempotence. 6. API backend. 7. Modèle des messages importants extraits des logs. 8. Modèle snapshots hardware/profil machine/métriques simples. 9. Politique de rétention/logs/rapports/messages. 10. Intégration avec UI et Hermes. 11. Découpage en sous-jalons. --- ## 10. Définition de terminé - Tous les JSON machine ↔ webapp sont historisables. - L'état courant des tuiles peut être dérivé sans parser les logs. - Les tâches automatiques sont spécifiées. - Les métriques simples et le profil OS/type machine sont historisables. - Les actions concurrentes sont sécurisées. - Les rapports et logs ont une politique claire. - Les warnings importants, dépréciations et annonces d'évolution future sont historisés et consultables. - Aucun secret ne sort du backend. - Aucun code de production n'est livré pendant cette mission de design. --- ## 11. Technos à utiliser — checklist - [ ] Node.js runtime. - [ ] Hono pour API HTTP. - [ ] Drizzle ORM + SQLite. - [ ] WebSocket ou SSE pour events/live output. - [ ] `croner` pour schedules MVP. - [ ] Worker in-process au MVP. - [ ] Verrous machine persistants. - [ ] JSON canonique versionné. - [ ] Stockage fichiers pour reports/logs/artifacts. - [ ] Docker Compose pour packaging final webserver. - [ ] Variables d'environnement pour configuration. - [ ] Secrets chiffrés avec master key hors image. ## 12. URLs utiles - Hono Node.js : https://hono.dev/docs/getting-started/nodejs - Hono middleware : https://hono.dev/docs/guides/middleware - Drizzle SQLite : https://orm.drizzle.team/docs/get-started-sqlite - SQLite WAL : https://www.sqlite.org/wal.html - Croner : https://github.com/Hexagon/croner - MDN WebSocket : https://developer.mozilla.org/en-US/docs/Web/API/WebSocket - MDN Server-sent events : https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events - Docker Compose : https://docs.docker.com/compose/ - Compose file reference : https://docs.docker.com/reference/compose-file/ - Docker volumes : https://docs.docker.com/engine/storage/volumes/ - Node.js Docker images : https://hub.docker.com/_/node ## 13. Liens parent/enfant avec les autres tâches - Parents : - `tache1.9.md` pour schéma BDD. - `tache2.md` pour actions/templates/JSON. - `tache4.md` pour scripts post-install. - Enfants : - `tache3.md` consomme les API. - `tache6.md` consomme API/MCP. - `tache7.md` ajoute métriques/nettoyage/sécurité. - `tache8.md` consomme API/capabilities. - Validation : `validation_tache5.md`.