Files
system_update/tache5.md
T
gilles 0fbca06d3d docs: roadmap tâches 1.9-8 (briefs, gates de validation, designs tâche 2) + plans d'implémentation
Cartographie complète (liste_taches/coherence_taches), briefs tacheN + gates
validation_tacheN, design tâche 2 (docs/design/tache2/), specs/plans jalon 1-2
et tâche 1.9/2 (Phase 1, Phase 2, SJ-0→3). Validations consignées (1.9 , 2-8 🟡).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:50:25 +02:00

533 lines
14 KiB
Markdown

# 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/<machineId>/...log` ou dans un stockage d'artefacts ;
- le rapport Markdown reste dans `reports/<machineId>/...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`.