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>
55 KiB
Protocole de validation — Tâche 2 (moteur de templates de mise à jour)
Type : grille de validation. Utilisée par l'agent orchestrateur (Claude Code principal) après qu'un agent sous-traitant a rendu la mission décrite dans
tache2.md. But : vérifier que les livrables de la tâche 2 sont complets, respectent le périmètre, et s'intègrent correctement à l'application existante sans rien casser. ⚠️ Gate obligatoire : cette validation doit être passée AVANT toute phase de développement. Tant que le verdict n'est pas ✅ Accepté, aucune implémentation des livrables de la tâche 2 ne démarre (ni par l'agent sous-traitant, ni par l'orchestrateur). Le design est figé et validé d'abord ; le code vient après. Rappel : la tâche 2 est une mission de design/investigation (pas d'implémentation). On valide donc des documents de design/spec, pas du code de production. Les vérifications de non-régression servent uniquement à confirmer que l'existant n'a pas été touché.
0. Quand lancer cette validation
- La mission
tache2.mdest annoncée terminée. - Le fichier
tache2.mda bien été mis à jour avec sa section « État d'avancement / Ce qui a été fait » (clôture obligatoire). - Les livrables de design sont présents sous
docs/(ou l'emplacement proposé par l'agent).
Si l'un de ces points manque → rejet immédiat, renvoyer à l'agent.
1. Discipline & périmètre (l'agent n'a pas débordé)
Vérifier via git status / git diff et lecture des commits :
- Aucun code de production modifié ou ajouté : pas de changement sous
server/,client/,shared/,templates/, ni dans les configs (package.json,tsup.config.ts,vite.config.ts, etc.). Seuls des fichiersdocs/**ettache2.mddoivent avoir changé. - Jalon 1 et jalon 2 intacts : aucun fichier de ces jalons touché.
- Aucun autre chantier démarré hors du périmètre de
tache2.md(les idées hors-scope doivent figurer comme suggestions, pas comme du travail réalisé). - Les dépôts de référence (
linux-update-dashboard/,nas-ops/) n'ont pas été copiés tels quels dans le code (respect licence AGPL).
Si du code de production a été écrit → rejet : la mission devait s'arrêter au design.
2. Complétude des livrables
Confronter au § « Livrables attendus » et aux 5 axes de tache2.md :
Axes couverts :
- Axe A — Templates APT (update, upgrade, full-upgrade, dist-upgrade, clean, autoremove, reboot) avec sémantique clarifiée et profils OS (Debian/Ubuntu/Proxmox/RPi) + gestion proxy apt-cacher-ng.
- Axe B — Capture des updates prévus (snapshot) et appliqués (diff avant/après), consommable par Hermes (déduplication + réduction).
- Axe C — Taxonomie des erreurs + stratégie de gestion/remédiation.
- Axe D — Docker : scan, pull, up, down, prune images inutilisées, détection des stacks (labels + fallback répertoires déclarés), JSON compact.
- Axe E — Scripts personnalisés (post-install, install paquets) + overrides par machine + garde-fous.
Livrables (§4 de tache2.md) :
- Inventaire des templates.
- Contenu proposé des templates clés (pseudo-shell réaliste, convention
===SU:XXX===). - Schémas JSON canoniques étendus (snapshot + résultat, APT + Docker + erreurs + custom).
- Taxonomie des erreurs.
- Modèle des profils OS + overrides.
- Modèle des scripts personnalisés.
- Note de sécurité.
- Découpage en sous-jalons priorisé.
Questions d'investigation (§3) :
- Les 8 questions sont tranchées, chacune avec MVP recommandé / alternatives / risques.
Tout livrable ou question manquant → renvoi pour complément.
3. Cohérence & intégration avec l'application existante
C'est le cœur de la validation : le design doit s'emboîter avec ce qui existe.
- Types JSON : les extensions proposées sont compatibles avec
shared/types.ts(UpdateSnapshot,ExecutionResult). Les ajouts sont rétro-compatibles (champs optionnels, pas de rupture du jalon 1). Vérifier qu'un snapshot/exécution du jalon 1 resterait valide. - Convention des templates : les templates proposés suivent la convention existante (marqueurs
===SU:XXX===,LC_ALL=C, exécution soussudo -S, sortie parsable). Cohérent avectemplates/apt/*.tpl,server/templates/render.ts,server/services/aptParse.ts. - Parsing : la stratégie retenue (JSON-in-shell vs parsing-TS) est explicite, justifiée, et compatible avec
server/services/ou propose une migration claire sans casser le refresh/upgrade actuels. - Couche SSH : le design réutilise
server/ssh/client.ts(pas de nouveau mécanisme d'exécution non justifié) ; opérations longues/détachées traitées de façon cohérente. - Frontière Hermes/MCP : aucun secret n'atteint Hermes/MCP ; la surface MCP reste minimale ; les données envoyées au LLM passent par la réduction déterministe (
aptReduce.tsou équivalent étendu). - Sécurité : actions destructives (prune, down, reboot, dist-upgrade) exigent une validation explicite côté webapp ; pas de secret en clair (logs/UI/MCP).
- Profils OS : le mécanisme proposé n'invalide pas le comportement Debian/Ubuntu prouvé en prod au jalon 1.
- Découpage en sous-jalons : chaque sous-jalon est implémentable indépendamment et produit un logiciel testable (compatible avec le workflow spec → plan → implémentation).
4. Non-régression (l'existant tourne toujours)
Confirmer que rien n'a été cassé (puisque la mission ne devait pas toucher le code) :
rtk pnpm check→ 0 erreur TypeScript.rtk pnpm test→ suite verte (au moins les tests du jalon 1, + jalon 2 s'il est mergé).rtk pnpm build→dist/index.js+dist/clientproduits.- Les flux prouvés du jalon 1 (ajout machine, refresh APT, full-upgrade, reboot, rapport) restent inchangés dans le code.
Une régression ici signifie que l'agent a touché au code malgré la consigne → rejet.
5. Verdict
Rédiger une conclusion explicite :
- ✅ Accepté : tous les blocs cochés. → On peut enchaîner sur
writing-planspour le 1ᵉʳ sous-jalon recommandé. - 🟡 Accepté avec réserves : livrables complets mais points de design à ajuster → lister les corrections, renvoyer pour itération courte.
- ❌ Rejeté : périmètre débordé, code de production écrit, livrables incomplets, ou incohérence majeure avec l'appli → renvoyer à l'agent avec les points bloquants précis.
Consigner le verdict (date, blocs en échec, actions de suite) en bas de ce fichier ou dans un commit dédié.
6. Focus de validation — scripts Docker Compose et intégration webapp
Cette section fixe la proposition attendue pour le volet Docker Compose de la tâche 2. Elle sert de point de contrôle supplémentaire au moment de valider les livrables de design : l'agent doit expliquer comment ces scripts s'insèrent dans l'application existante, sans créer un moteur parallèle.
Méthode Docker Compose retenue
- Le design retient une gestion par SSH sur la machine cible, en réutilisant la couche d'exécution existante (
server/ssh/client.ts) et les templates versionnés sur disque. La variantedocker contextover SSH peut être citée comme alternative opérateur, mais ne doit pas devenir le moteur MVP de la webapp. - Les stacks Compose sont découverts depuis des racines déclarées par machine (
composeRoots, ex./opt/stacks,/srv/docker) avec scan limité en profondeur, puis validés dans l'UI avant toute action. - La détection automatique par labels Compose (
com.docker.compose.project,com.docker.compose.service, et si présentcom.docker.compose.project.working_dir) reste un complément pour retrouver les stacks actifs, pas l'unique source de vérité. - Un stack seulement détecté reste en statut
candidate; les actionspull,up,downetprunene sont autorisées que sur un stackenabled/validé par l'utilisateur.
Scripts/templates Docker attendus
Le design doit proposer au minimum ces templates, avec pseudo-shell réaliste, marqueurs ===SU:DOCKER_*===, LC_ALL=C, sortie parsable et log brut archivé :
templates/docker/scan-compose.sh.tpl: scanne les racines déclarées, trouvecompose.yaml,compose.yml,docker-compose.yaml,docker-compose.yml, ignore.git,node_modules,backup,old,archive, puis valide chaque candidat avecdocker compose config --quiet.templates/docker/inspect-compose.sh.tpl: produit l'état actuel sans appliquer de changement :docker compose config --images,docker compose ps --format json,docker compose images --format json, puisdocker image inspectpour les images utilisées.templates/docker/pull-check.sh.tpl: exécutedocker compose pull --policy always --ignore-buildablepour récupérer les images candidates sans démarrer de conteneurs, puis compare image ID/digest/labels avant-après. Cette action est non applicative mais écrit sur le disque Docker; elle ne doit donc pas être confondue avec un scan purement passif.templates/docker/apply-compose.sh.tpl: applique après validation utilisateur avecdocker compose up -d --remove-orphans, puis recaptureps/images/inspectpour vérifier les conteneurs recréés et les erreurs.templates/docker/prune-images.sh.tpl: nettoyage prudent par défaut avecdocker image prune -f; mode agressifdocker image prune -a -f --filter "until=168h"seulement avec validation explicite côté webapp.templates/docker/down-compose.sh.tpl: action séparée et destructive;docker compose downne doit pas faire partie du chemin normal de mise à jour. Toute option--volumesou--rmidoit être interdite au MVP ou protégée par une validation forte distincte.
Flux de mise à jour Docker à valider
Le design doit formaliser ce flux, compatible avec la documentation Docker :
docker_scan: découverte des stacks candidats depuis les racines déclarées + labels Compose actifs.docker_inspect_current: capture de l'état actuel des services, conteneurs et images.docker_pull_check: téléchargement des images candidates sans démarrage de conteneurs.- Comparaison déterministe : image ref, image ID, repo digest, labels OCI (
org.opencontainers.image.version,revision,source,created) si présents. - Proposition UI/Hermes : liste des stacks/services avec update disponible, erreurs de pull, inconnues.
docker_applyaprès validation utilisateur :docker compose up -d --remove-orphans.- Vérification après application : conteneurs recréés, état
running/exited, health si disponible, erreurs. docker_prune_imagesaprès succès ou sur action séparée : images supprimées, espace récupéré, erreurs.
Points Docker à vérifier dans les livrables :
- Le design explique que
docker compose pulltélécharge les images mais ne démarre pas les conteneurs; c'est donc un bon pré-check applicatif, mais pas un scan sans effet. - Le design explique que
docker compose up -drecrée les conteneurs quand l'image ou la configuration a changé, en préservant les volumes montés;downn'est donc pas nécessaire pour une mise à jour normale. - Le design distingue
docker image prune -f(dangling images) dedocker image prune -a(toutes les images non référencées par un conteneur), et classe-acomme action destructive.
Sources Docker de référence à citer dans la spec :
docker compose pull: https://docs.docker.com/reference/cli/docker/compose/pull/docker compose up: https://docs.docker.com/reference/cli/docker/compose/up/docker compose config: https://docs.docker.com/reference/cli/docker/compose/config/docker compose ps: https://docs.docker.com/reference/cli/docker/compose/ps/docker compose images: https://docs.docker.com/reference/cli/docker/compose/images/docker compose down: https://docs.docker.com/reference/cli/docker/compose/down/docker image inspect: https://docs.docker.com/reference/cli/docker/image/inspect/docker image prune: https://docs.docker.com/reference/cli/docker/image/prune/
JSON canonique Docker attendu
UpdateSnapshotreste rétrocompatible et peut recevoir un bloc optionneldocker.- Le bloc snapshot Docker contient au minimum : stacks déclarés, stacks candidats, services, image ref actuelle, image ID actuelle, digest actuel si disponible, labels de version si disponibles, image ID/digest candidat après pull, statut
up_to_date|updates_available|warning|error. ExecutionResultreste rétrocompatible et peut recevoir un bloc optionneldocker, avec résultatspull,up,prune, erreurs, conteneurs recréés, images supprimées et octets récupérés.- Les erreurs sont structurées :
docker_not_installed,compose_not_found,compose_config_invalid,registry_auth_failed,pull_failed,image_inspect_failed,up_failed,container_unhealthy,prune_failed,disk_space_low. - La réduction Hermes ne transmet que le JSON canonique + lignes importantes (
Pulling,Digest,Status,Downloaded newer image,Recreating,Started,Error,deleted,Total reclaimed space). Le log brut complet reste archivé.
Insertion dans la webapp existante
Le design doit montrer comment Docker s'emboîte dans les surfaces déjà présentes :
- Config machine : ajouter des champs de configuration Docker par machine dans le modèle futur (
dockerEnabled,composeRoots,composeScanDepth,composeStacks[]), sans casserMachineViewexistant; les nouveaux champs doivent être optionnels ou livrés dans un endpoint dédié. - Refresh/snapshot : étendre le refresh machine pour pouvoir produire un snapshot combiné
apt+docker, ou un refresh Docker séparé si l'équipe choisit d'éviter quedocker_pull_checksoit lancé automatiquement. - Actions : étendre progressivement
ActionTypeavec des actions explicites (docker_scan,docker_pull_check,docker_compose_apply,docker_prune_images,docker_compose_down) en conservant le filtrage d'autorisation côté routePOST /api/machines/:id/actions. - Executions/rapports : réutiliser la table
executions, le WebSocket terminal,rawLogPath,reportPathet le statutok|warning|error; ne pas créer un second système de jobs Docker. - UI machine : afficher un compteur Docker séparé du compteur APT (ex. stacks avec updates), proposer une vue détail par stack/service, puis boutons d'action validés (
Pull/check,Appliquer,Prune,Down). - Validation utilisateur :
docker_compose_apply,docker_prune_imagesagressif etdocker_compose_downdoivent passer par une confirmation UI explicite; Hermes peut proposer mais ne déclenche jamais directement ces actions. - Secrets : les credentials registry éventuellement présents sur la machine (
~/.docker/config.json, helper, tokens) ne sont jamais lus ni renvoyés; les erreurs doivent être nettoyées avant UI/MCP si elles exposent une URL sensible.
7. Focus de validation — APT update/analyse, upgrade et reboot vérifié
Cette section fixe la proposition attendue pour la suite APT de la tâche 2. Elle doit valider que le design répond au besoin opérateur : voir la liste des paquets avant exécution, prouver ce qui a réellement changé après exécution, gérer les cas non interactifs, puis vérifier qu'un reboot a vraiment abouti.
update + analyse avant upgrade
- Le design introduit une action de refresh/analyse explicite, nommable
apt_update_analyze, distincte des upgrades manuels destructifs. - Cette action exécute au minimum
apt-get update, puis une simulationapt-get -s upgradeet une simulationapt-get -s dist-upgradeou équivalent profil OS. - Le snapshot produit liste les paquets qui seraient mis à jour avant validation utilisateur : nom, version actuelle, version cible, origine, architecture si disponible.
- Le snapshot distingue
upgradeetfull/dist-upgrade: paquets mis à jour, paquets nouvellement installés, paquets qui seraient supprimés, paquets retenus/held. - Le design explique que les simulations APT sont parsées via les lignes documentées
Inst,Conf,Remv, tout en gardant le log brut archivé. - Le statut snapshot APT distingue
ok,updates_available,warning,error, avecwarningsifull/dist-upgradeimplique des suppressions ou des paquets retenus.
Sources APT à citer dans la spec :
apt-getsimulation et commandes : https://manpages.debian.org/apt-getdpkgconffiles/options : https://manpages.debian.org/dpkgapt-listchangesnon-interactive : https://manpages.debian.org/bookworm/apt-listchanges/apt-listchanges.1.en.htmlneedrestartnon-interactive/list mode : https://manpages.debian.org/bookworm/needrestart/needrestart.1.en.html
Profils OS et type de machine
- Le design distingue
os_familyetmachine_kindlors de l'ajout machine. - L'UI propose un choix manuel : Debian, Ubuntu, Proxmox VE, Raspberry Pi OS, autre Linux.
- L'UI propose un choix manuel du type : VM, machine physique, hôte Proxmox, LXC/container, Raspberry Pi, serveur GPU/workstation.
- Une action
machine_probeou équivalent peut détecter/corriger :/etc/os-release, architecture, virtualisation, Proxmox, Raspberry Pi, GPU, disques, mémoire. - Les scripts proposés dépendent du couple OS/type machine : firmware/driver sur physique, guest tools sur VM, profil Proxmox sur hôte PVE, profil Raspberry Pi OS sur Pi.
- Debian avec firmware/drivers propriétaires vérifie explicitement
contrib,non-free,non-free-firmware. - Proxmox est traité comme profil dédié et pas comme Debian générique.
- Les scripts hardware/drivers/benchmark ne sont jamais installés par défaut et exigent validation.
Scripts/templates APT attendus
Le design doit proposer au minimum ces templates, en conservant LC_ALL=C, DEBIAN_FRONTEND=noninteractive, le proxy APT optionnel, les marqueurs ===SU:APT_*===, et ===SU:EXIT=N=== :
templates/apt/update-analyze.sh.tpl: update des index + simulationsupgradeetdist/full-upgrade+ reboot-check.templates/apt/upgrade.sh.tpl: applique l'upgrade simple, sans suppressions volontaires.templates/apt/full-upgrade.sh.tploudist-upgrade.sh.tpl: applique le profil complet; le design clarifie l'alias UIfull-upgradevs commande systèmeapt-get dist-upgrade/apt full-upgrade.templates/apt/autoremove.sh.tpl: retire les dépendances inutiles, avec prévisualisation ou confirmation explicite si des paquets seront supprimés.templates/apt/clean.sh.tpl: vide le cache des paquets téléchargés; action séparée.templates/apt/reboot-check.sh.tpl: vérifie/run/reboot-required,/var/run/reboot-requiredet les paquets listés sireboot-required.pkgsexiste.templates/apt/reboot.sh.tpl: planifie le reboot et émet un marqueur de sortie parsable avant coupure SSH.
Upgrade non interactif et interactions humaines
- Les upgrades réels utilisent une politique non interactive explicite :
DEBIAN_FRONTEND=noninteractive,apt-get -y, options dpkg défensives--force-confdef+--force-confold. - Le design justifie la politique par défaut : conserver les fichiers de configuration locaux quand dpkg ne peut pas résoudre automatiquement, afin d'éviter d'écraser une configuration distante.
- Les prompts potentiels (
conffile,debconf,apt-listchanges,needrestart, service restart, maintainer script) sont traités comme risques de blocage à détecter, pas comme dialogues interactifs à exposer dans le terminal. - Le design prévoit un timeout d'inactivité et/ou un timeout global pour classer l'exécution en erreur contrôlée si une action reste bloquée.
- Une erreur structurée
human_interaction_requiredou équivalent est prévue, avec lignes importantes et recommandation de reprise manuelle; aucune auto-réparation dangereuse n'est lancée sans validation.
Diff réel avant/après
- Le design ne se contente pas de l'exit code APT pour déclarer une réussite.
- Avant et après chaque action APT réelle, le template capture l'état dpkg via une commande stable du type
dpkg-query -W -f='${binary:Package}\t${Version}\t${Architecture}\n'. - Le backend ou le contrat JSON compare l'état avant/après pour produire : paquets mis à jour, installés, supprimés, inchangés malgré simulation, versions finales et anomalies.
ExecutionResultreste rétrocompatible et reçoit un bloc optionnelaptdétaillantplanned,applied,installed,removed,held,errors,rebootRequiredAfterRun.- Le rapport Markdown résume le diff réel et garde une référence au log brut, sans l'inliner entièrement.
Reboot vérifié et délai adaptatif
- Le design introduit un reboot vérifié : lire un identifiant de boot avant reboot (
/proc/sys/kernel/random/boot_id), déclencher le reboot, attendre la coupure SSH, retenter la connexion, puis relire leboot_id. - Le reboot est considéré
okuniquement si la machine redevient joignable et si leboot_ida changé. - Le résultat reboot contient au minimum :
beforeBootId,afterBootId,requestedAt,sshWentDownAt,sshCameBackAt,waitedSeconds,status,errors. - Le design prévoit un délai adaptatif par machine (
lastRebootDurationSeconds,nextRecommendedWaitSeconds) mis à jour après chaque reboot réussi, avec marge de sécurité. - En cas d'échec, le statut distingue au moins :
reboot_command_failed,ssh_never_went_down,machine_did_not_return,boot_id_unchanged,timeout. - Le reboot reste une action destructrice soumise à validation explicite côté webapp; Hermes peut recommander mais ne déclenche jamais directement.
Insertion dans la webapp existante
apt_update_analyzealimente le snapshot existant et la tuile machine avec la liste des paquets prévus avant upgrade.- Les actions
apt_upgrade,apt_full_upgrade/apt_dist_upgrade,apt_autoremove,apt_cleanetreboot_verifiedpassent par la même route d'action et la même tableexecutionsque le jalon 1. - L'UI doit afficher avant exécution : liste des paquets, suppressions éventuelles, paquets retenus, reboot déjà requis, et niveau de risque.
- L'UI doit afficher après exécution : réussite/erreur, diff réel, reboot requis après coup, lien rapport, lien log brut.
- Les actions qui peuvent supprimer des paquets ou redémarrer la machine (
dist/full-upgrade,autoremove,reboot_verified) exigent une confirmation UI explicite. - Les nouveaux champs JSON et actions sont ajoutés de manière rétrocompatible pour que les flux jalon 1 (
refresh,apt_full_upgrade,reboot) restent valides pendant la migration.
8. Focus de validation — scripts post-install et profils personnalisés
Cette section fixe la proposition attendue pour les scripts post-install de la tâche 2. Elle doit valider que le design couvre le cas concret d'une VM Debian 13 installée en netinstall CLI, joignable d'abord via DHCP, puis préparée à distance via SSH avec changement éventuel d'identité, réseau statique, paquets de base, partages réseau et Docker officiel.
Principe UX et absence d'interactivité SSH
- Le design interdit les questions interactives au milieu d'un script SSH. Toute question nécessaire est transformée en champ de formulaire dans la webapp avant exécution.
- Les scripts post-install sont présentés sous forme de profils cochables; cocher un profil déplie automatiquement ses champs obligatoires.
- Chaque profil fournit un manifeste décrivant
id,label,description,fields, valeurs par défaut, validations, prévisualisation, niveau de risque et confirmations requises. - Le bouton d'exécution reste désactivé tant que les champs requis du ou des profils cochés ne sont pas valides.
- La webapp propose une preview du template rendu avant exécution, avec masquage des secrets et signalement des changements réseau/reboot.
- Les scripts s'exécutent en mode non interactif; s'ils détectent une situation nécessitant une décision non fournie, ils échouent avec une erreur structurée au lieu de bloquer.
Profils post-install attendus
Le design doit proposer au minimum ces profils composables :
bootstrap_root: première préparation après connexion DHCP et élévation viasu -ou contexte root; installesudo,resolvconf,ca-certificates,curl; ajoute l'utilisateur opérateur au groupesudo; vérifiesudo.identity_network: modifie si besoin le hostname, le domaine/search local.home,/etc/hosts, puis configure l'IP statique dans/etc/network/interfaces.base_tools: outils de base sansvim; prévoir notammentnano,less,bash-completion,tmux,screen,htop,iotop,ncdu,tree,rsync,unzip,zip,tar.network_tools:iproute2,iputils-ping,dnsutils,traceroute,net-toolsoptionnel,tcpdump,nmap,mtr-tiny,lsof,netcat-openbsd.dev_git:git,curl,wget,jq,yq,gnupg,lsb-release;build-essentialseulement optionnel.sharing: profils de partage réseau avecsamba,nfs-kernel-server,avahi-daemon,libnss-mdns, configurables séparément si besoin.docker_official: installation Docker Engine depuis le dépôt officiel Docker Debian, avecdocker-ce,docker-ce-cli,containerd.io,docker-buildx-plugin,docker-compose-plugin, ajout utilisateur au groupedocker, création du dossier Compose dans le home, puis reboot/reconnexion si nécessaire.vm_guest_tools: paquet adapté à l'hyperviseur (qemu-guest-agentouopen-vm-tools) choisi par l'utilisateur.- Profils optionnels à prévoir mais non installés par défaut :
security_basic,backup_tools,monitoring,mail_notify,time_sync,storage_tools.
Champs dynamiques attendus dans l'interface
Le design doit préciser les champs générés lorsqu'un profil est coché :
- Pour
identity_network:newHostname,domain/search,interfaceName,staticAddressau format CIDR (ex.10.0.x.y/22),gateway(défaut10.0.0.1),dnsNameservers(défaut10.0.0.1,10.0.0.10),reconnectHost. - Pour
docker_official:dockerUser(ex.gilles),dockerHomeDiroucomposeRoot(ex./home/gilles/docker),installComposePlugin,rebootAfterInstall. - Pour
sharing: choix séparé Samba/NFS/mDNS, noms de partages éventuels, chemins autorisés, utilisateurs/groupes si nécessaire. - Pour
vm_guest_tools: type d'hyperviseur ou paquet cible. - Les champs peuvent être préremplis depuis la machine (
machine.name, IP DHCP, interface primaire détectée, utilisateur SSH), mais doivent rester modifiables avant validation.
Exemple de manifeste attendu dans la spec :
{
"id": "identity_network",
"label": "Hostname + IP statique",
"requiresConfirmation": true,
"risk": "network_change",
"fields": [
{ "name": "newHostname", "type": "hostname", "required": true },
{ "name": "domain", "type": "string", "required": true, "default": "home" },
{ "name": "interfaceName", "type": "select", "required": true, "defaultFrom": "detected.primaryInterface" },
{ "name": "staticAddress", "type": "ipv4_cidr", "required": true },
{ "name": "gateway", "type": "ipv4", "required": true, "default": "10.0.0.1" },
{ "name": "dnsNameservers", "type": "ipv4_list", "required": true, "default": ["10.0.0.1", "10.0.0.10"] },
{ "name": "reconnectHost", "type": "ipv4", "required": true, "defaultFrom": "staticAddress.ip" }
]
}
Scripts/templates custom attendus
templates/custom/bootstrap-root.sh.tpl: prépare sudo et les prérequis minimaux depuis un contexte root ou sudo.templates/custom/identity-network.sh.tpl: écrit hostname, hosts et réseau statique; sauvegarde les fichiers modifiés; signale explicitement le changement d'adresse.templates/custom/install-package-groups.sh.tpl: installe les groupes de paquets sélectionnés, sansvimpar défaut.templates/custom/docker-official-debian.sh.tpl: suit la documentation officielle Docker Debian pour le dépôt APT, la clé GPG dans/etc/apt/keyrings,docker.sources, puis les paquets Docker/Compose.templates/custom/sharing.sh.tpl: installe Samba/NFS/mDNS selon les choix, sans exposer de configuration dangereuse par défaut.templates/custom/vm-guest-tools.sh.tpl: installe l'agent invité choisi.
Sources à citer dans la spec :
- Docker Debian officiel : https://docs.docker.com/engine/install/debian/
- Docker Compose plugin : https://docs.docker.com/compose/install/linux/
- Debian network configuration : https://wiki.debian.org/NetworkConfiguration
- Debian Handbook network configuration : https://www.debian.org/doc/manuals/debian-handbook/sect.network-config
- Debian package
resolvconf: https://packages.debian.org/stable/net/resolvconf
Réseau, reboot et reconnexion
- Le design traite
identity_networkcomme une action à risque : confirmation UI explicite, preview obligatoire, sauvegarde de/etc/network/interfaceset/etc/hosts. - Lorsqu'une IP statique est appliquée, le résultat JSON contient l'ancien endpoint DHCP, le nouveau endpoint, et l'indication que la reconnexion doit se faire sur
reconnectHost. - Le script ne doit pas couper la connexion sans que la webapp ait planifié la stratégie de reconnexion; si reboot requis, utiliser le mécanisme
reboot_verified. - Après reboot ou redémarrage réseau, la webapp vérifie la reconnexion sur la nouvelle IP/hostname et met à jour la machine si le retour est confirmé.
- En cas d'échec, les erreurs distinguent
network_config_invalid,interface_not_found,dns_config_failed,reconnect_failed,hostname_failed,sudo_setup_failed.
JSON canonique post-install attendu
ExecutionResultreste rétrocompatible et peut recevoir un bloc optionnelcustomoupostInstall.- Le résultat liste les profils exécutés, les variables non sensibles utilisées, les fichiers modifiés, les paquets installés, les services activés/démarrés, les reboots demandés et les erreurs.
- Les secrets ou tokens ne sont jamais inclus dans les variables sérialisées, les logs UI, les rapports ni le MCP.
- Les modifications réseau et Docker sont clairement marquées dans le rapport Markdown avec les prochaines actions attendues, par exemple reconnexion, logout/login pour groupe Docker, ou reboot.
Insertion dans la webapp existante
- Les scripts post-install passent par la même mécanique que les autres actions : templates versionnés, preview, exécution SSH, WebSocket terminal,
executions, rapport Markdown et log brut. - La configuration des profils peut être stockée par machine ou lancée comme assistant ponctuel de provisioning, mais le design doit préciser où sont conservées les valeurs réutilisables.
- Hermes peut aider à proposer des profils ou expliquer un échec, mais ne reçoit que le JSON réduit et ne déclenche jamais les actions à risque sans validation webapp.
- Les profils post-install sont découpés en sous-jalons indépendants : bootstrap/sudo, identité+réseau, paquets de base, Docker officiel, partage réseau, outils VM/monitoring.
9. Notes de validation (à remplir au moment de la revue)
Date : 2026-06-05 Signé : (orchestrateur, revue indépendante post-design)
Note historique : une première validation (2026-06-05, délégation initiale) avait conclu au rejet faute de livrables. Les livrables ont depuis été produits. La présente revue est indépendante — elle ne s'appuie pas sur l'auto-évaluation
99-couverture-gate.mdmais sur la lecture directe de chaque livrable.
Verdict global
🟡 Accepté avec réserves mineures — les livrables sont complets, cohérents avec l'existant et couvrent l'intégralité des cases du gate. Deux réserves mineures non bloquantes sont détaillées ci-dessous (renommage de fichier à tracer dans SJ-0 ; état non committé de shared/types.ts à surveiller). Aucune incohérence majeure, aucune rupture de rétro-compatibilité, aucun manque réel. La mission peut progresser vers writing-plans pour SJ-0 dès confirmation de la non-régression (pnpm check/test/build).
Vérification §0 — Conditions préalables
- Section « État d'avancement / Ce qui a été fait » dans
tache2.md: PRÉSENTE (§10, ll. 196-241). Contient les chemins des 11 livrables, les 8 décisions, les questions tranchées, ce qui reste ouvert, les sous-jalons recommandés. Condition satisfaite. - Livrables de design présents sous
docs/: 11 fichiers présents sousdocs/design/tache2/(00→99). Condition satisfaite. tache2.mdannoncé terminé : oui (§10 statut = « mission de design terminée »). Condition satisfaite.
Conclusion §0 : toutes les conditions préalables sont remplies. La validation peut s'ouvrir.
Vérification §1 — Discipline & périmètre
- Fichiers
docs/design/tache2/**ettache2.md: seuls fichiers nouveaux liés à la tâche 2. OK. - Jalon 1 intact :
templates/apt/check.sh.tpl,full-upgrade.sh.tpl,reboot.sh.tpl,server/services/aptParse.ts,server/templates/aptReduce.ts,server/templates/render.ts,server/ssh/client.ts— aucun touché. OK. - Dépôts de référence :
linux-update-dashboard/etnas-ops/non copiés (cités en inspiration, pseudo-shell réécrit). OK. - Hors-scope listés comme suggestions uniquement :
00-synthese.md §6liste explicitement les renvois vers tâches 3/4/5/6/7. OK. shared/types.tsmodifié : le diff montre l'ajout de l'interfaceServerCapabilities(32 lignes). L'auto-évaluation affirme que l'agent tâche 2 n'a pas touché ce fichier. La vérification du diff confirme que cette modification (endpoint/capabilities, gestion d'erreur Hono, importcapabilities.ts) est cohérente avec le chantier jalon 2 en cours (polish design system) et non avec la tâche 2. Il s'agit d'une modification du contexte de travail partagé, pas d'une violation de la tâche 2. Toutefois, le fichiershared/types.tsétant dans un état non committé différent de l'état jalon 1, la vérification de rétro-compatibilité (§3) doit se faire sur l'état actuel de ce fichier (qui inclut déjàServerCapabilitiesmais conserve intégralementAptPackage,UpdateSnapshot,ExecutionResult,MachineView). Pas d'incidence sur le design de la tâche 2. Réserve de contexte, non bloquante.
Conclusion §1 : aucune violation de périmètre imputable à la tâche 2. La modification de shared/types.ts provient du jalon 2 concurrent.
Vérification §2 — Complétude des livrables
Axes :
| Axe | Couvert ? | Livrable principal | Vérification |
|---|---|---|---|
| A — Templates APT + profils OS + proxy | OUI | 10-templates-apt.md, 60-profils-os-machine.md |
7 templates inventoriés avec marqueurs, pseudo-shell pour 5, profils OS Debian/Ubuntu/Proxmox/RPi, proxy direct/runtime/persistent. |
| B — Capture prévu/appliqué, Hermes | OUI | 40-contrats-json.md |
Snapshot dpkg before/after, AptExecutionResult.planned/applied, déduplication, réducteur étendu. |
| C — Taxonomie des erreurs | OUI | 50-erreurs.md |
11 codes APT, 10 codes Docker, 6 codes réseau/post-install, stratégie de remédiation non auto. |
| D — Docker scan/pull/up/down/prune | OUI | 20-docker.md |
6 templates avec pseudo-shell, flux 8 étapes, réduction Hermes, insertion webapp. |
| E — Scripts custom + overrides + garde-fous | OUI | 30-scripts-custom.md |
9 profils post-install, manifestes, champs dynamiques, pseudo-shell 6 templates, garde-fous. |
Livrables §4 :
| # | Livrable | Présent | Fichier |
|---|---|---|---|
| 1 | Inventaire des templates | OUI | 10 §2, 20 §2, 30 §2 |
| 2 | Contenu proposé (pseudo-shell, ===SU:XXX===) |
OUI | 10 §4, 20 §4, 30 §4 |
| 3 | Schémas JSON canoniques étendus | OUI | 40 complet |
| 4 | Taxonomie des erreurs | OUI | 50 |
| 5 | Modèle profils OS + overrides | OUI | 60 §1-§4 |
| 6 | Modèle profils machine | OUI | 60 §5-§6 |
| 7 | Modèle scripts personnalisés | OUI | 30 |
| 8 | Note de sécurité | OUI | 70 |
| 9 | Découpage en sous-jalons priorisé | OUI | 80 (SJ-0→SJ-9) |
8 questions d'investigation (§3) : toutes tranchées dans 90-questions-investigation.md avec MVP / alternatives / risques. Vérification directe : Q1 (parsing hybride TS dominant), Q2 (un fichier complet par profil + fallback base), Q3 (manuel + machine_probe), Q4 (dpkg-query before/after), Q5 (extensions additives types TS), Q6 (nohup + exit-code + reboot_verified), Q7 (barrière action_requests + nettoyage secrets), Q8 (surface MCP v1 conservée). Toutes tranchées.
Conclusion §2 : complétude intégrale. Aucun livrable manquant, aucune question non tranchée.
Vérification §3 — Cohérence & intégration avec l'application existante
Types JSON — rétro-compatibilité (shared/types.ts) :
Vérification directe de l'état actuel de shared/types.ts (ll. 1-89) :
OsFamily = "debian" | "ubuntu" | "unknown"→ le design propose"proxmox" | "raspbian"en plus. Additif, aucune rupture.AptProxyMode = "direct" | "runtime"→ ajout"persistent". Additif.ActionType = "apt_full_upgrade" | "reboot"→ ajout de 12 valeurs. Additif.UpdateSnapshot.apt: bloc requis conservé tel quel ; les ajouts (status?,held?,removed?, etc.) sont tous optionnels. Un payload jalon 1 reste valide.ExecutionResult:mode: "manual"élargi en union — réserve mineure : le champmodepasse de littéral"manual"à"manual" | "scheduled" | "hermes_requested". TypeScript accepte l'union élargie sans rupture (un payload avecmode: "manual"reste valide). Non bloquant mais à noter pour la migration progressive.MachineView: non touché par le design. OK.ServerCapabilities(ajout jalon 2) : non conflictuel avec les extensions tâche 2.
Convention ===SU:XXX=== :
Vérification directe sur check.sh.tpl (marqueurs actuels : ===SU:UPDATE===, ===SU:SIMULATE===, ===SU:REBOOT===, ===SU:END===) et les pseudo-shells proposés :
update-analyze.sh.tplutilise===SU:APT_UPDATE===,===SU:APT_SIM_UPGRADE===,===SU:APT_SIM_DISTUPGRADE===, etc. — nouveaux noms, cohérents avec la convention de nommage.10-templates-apt.md §6précise explicitement le plan de migration :check.sh.tplconservé,update-analyze.sh.tplintroduit comme successeur enrichi, bascule dans un sous-jalon dédié (SJ-1). OK.full-upgrade.sh.tplexistant utilise===SU:UPGRADE===/===SU:REBOOT===/===SU:EXIT===; le design ajoute===SU:DPKG_BEFORE===et===SU:DPKG_AFTER===sans supprimer les marqueurs existants. Extension additive. OK.reboot.sh.tplexistant utilise===SU:REBOOT_NOW===; le design propose===SU:BOOT_ID_BEFORE===+===SU:REBOOT_NOW===. Ici une réserve mineure : lereboot.sh.tplproposé (10-templates-apt.md §4.5) émet uniquement===SU:BOOT_ID_BEFORE===et===SU:REBOOT_NOW===, mais n'émet pas de===SU:EXIT=N===final, contrairement à la convention établie dans les autres templates. En pratique le script se termine parecho "reboot planifié"sans marqueur de sortie — à corriger en implémentation (SJ-3). Signalé comme coquille de cohérence.
Parsing — stratégie explicite et justifiée :
Décision Q1 (90 §Q1) : hybride à dominante TS. Cohérent avec aptParse.ts et aptReduce.ts existants. La stratégie d'extension (reduceLines.ts additif, sans casser reduceAptLines) est explicite. OK.
Couche SSH (server/ssh/client.ts) :
Le design réutilise exclusivement runScriptSudo / runPlain partout (cité en 00-synthese.md §4, 90 Q6, 20 §1, 30 §6). Aucun nouveau mécanisme SSH. OK.
Frontière Hermes/MCP :
- Aucun secret (mot de passe, token, credential registry) ne transite vers Hermes/MCP :
70§1,30§5,20§6. Mécanisme de nettoyage déterministe décrit. OK. - Surface MCP minimale : 8 outils v1 conservés, nouvelles capacités via
run_actionfiltré. Aucune nouvelle primitive SSH. OK. run_actionsur action destructive non validée →action_requesten attente, pas une exécution. OK.
Sécurité — actions destructives :
Tableau complet dans 70 §2 (8 actions avec niveau de validation). --volumes/--rmi sur down interdits au MVP. Hermes propose, ne déclenche jamais. OK.
Profils OS — non-invalidation Debian/Ubuntu :
Mécanisme de fallback templates/apt/* (profil base) : les Debian/Ubuntu sans dossier dédié utilisent les templates existants. Non-régression jalon 1 assurée par convention de chemin. OK.
Sous-jalons — implémentabilité indépendante :
80-sous-jalons.md : SJ-0→SJ-9, dépendances explicites, chacun décrit en termes de contenu + testabilité + risque + priorité. SJ-0 marqué comme bloquant pour tous les autres. OK.
Alignement tache1.9.md :
00-synthese.md §5 mappe chaque bloc JSON sur les tables prévues par tache1.9.md (snapshots, executions, apt_planned_packages, apt_applied_packages, docker_compose_stacks, docker_stack_services, docker_image_events, apt_errors, important_messages, install_profiles, install_recipes, install_recipe_versions, machine_profile_state, script_variables_presets, docker_settings, docker_compose_roots, machine_hardware). Aucune table nouvelle non prévue. OK.
Conclusion §3 : cohérence globale confirmée. Deux points mineurs identifiés (mode union + marqueur EXIT manquant sur reboot.sh.tpl), non bloquants pour le design.
Vérification §4 — Non-régression
L'agent tâche 2 n'a modifié aucun fichier de production (templates, server, client, shared, configs). La non-régression formelle (pnpm check/test/build) est à exécuter par l'orchestrateur — aucun code n'ayant été touché par la mission de design, elle est attendue verte. À vérifier avant SJ-0.
Vérification §6 — Focus Docker Compose (grille détaillée)
Vérification directe sur 20-docker.md et 40-contrats-json.md :
| Case §6 | Couvert ? | Détail |
|---|---|---|
Gestion par SSH, couche existante ; docker context = alternative |
OUI | 20 §1, explicit |
Stacks depuis composeRoots, scan limité (composeScanDepth), validation UI |
OUI | 20 §1 et §4.1 (pseudo-shell scan) |
Détection labels en complément (com.docker.compose.project, .service, .working_dir) |
OUI | 20 §1 et §4.1 (section DOCKER_LABELS) |
Stack détecté = candidate ; actions sur enabled seulement |
OUI | 20 §1 et §2 tableau |
scan-compose.sh.tpl (fichiers compose, ignore .git/node_modules/backup/old/archive, config --quiet) |
OUI | 20 §4.1, pseudo-shell complet |
inspect-compose.sh.tpl (config --images, ps --format json, images --format json, image inspect) |
OUI | 20 §4.2 |
pull-check.sh.tpl (--policy always --ignore-buildable, compare ID/digest/labels, non passif) |
OUI | 20 §4.3 ; non-passivité explicitée dans §1 tableau et §3 |
apply-compose.sh.tpl (up -d --remove-orphans, recapture ps/images/inspect) |
OUI | 20 §4.4 |
prune-images.sh.tpl (safe -f ; agressif -a -f --filter until=168h validé) |
OUI | 20 §4.5 ; Mustache {{#aggressive}} |
down-compose.sh.tpl (séparé/destructif ; --volumes/--rmi interdits) |
OUI | 20 §4.6 ; commentaire explicite dans pseudo-shell |
| Flux 1→8 formalisé | OUI | 20 §3 (8 étapes numérotées) |
pull télécharge sans démarrer les conteneurs |
OUI | 20 §3 (point clé n°1) |
up -d recrée si changement, préserve volumes, down inutile |
OUI | 20 §3 (point clé n°2) |
prune -f vs -a (destructif) distingués |
OUI | 20 §2 tableau + §3 (point clé n°3) |
| Sources Docker citées (8 URLs) | OUI | 20 §1, toutes les 8 URLs listées |
UpdateSnapshot.docker rétrocompatible (bloc optionnel) |
OUI | 40 §3 ; docker? optionnel sur UpdateSnapshot |
| Bloc snapshot Docker minimal (stacks déclarés/candidats/services/IDs/digest/labels/candidat/statut) | OUI | 40 §3, interfaces DockerSnapshotStack et DockerSnapshotService |
ExecutionResult.docker (pull/up/prune/erreurs/recréés/supprimés/octets) |
OUI | 40 §4, DockerExecutionResult |
| Erreurs Docker structurées (10 codes) | OUI | 50 §3, tableau des 10 codes |
| Réduction Hermes lignes Docker + log brut archivé | OUI | 20 §5, 40 §7 |
Config machine dockerEnabled/composeRoots/composeScanDepth/composeStacks[], MachineView intact |
OUI | 20 §6 ; champs optionnels ou endpoint dédié |
| Refresh combiné apt+docker ou Docker séparé | OUI | 20 §6 (pull-check séparé recommandé) |
ActionType étendu (docker_*) + filtrage autorisation route |
OUI | 40 §2 et 20 §6 |
Réutilise executions/WS/rawLogPath/reportPath/statut, pas de second système |
OUI | 20 §1 et §6 |
| UI compteur Docker séparé + détail + boutons validés | OUI | 20 §6 |
| Validation UI apply/prune agressif/down ; Hermes ne déclenche pas | OUI | 20 §6, 70 §2 |
| Secrets registry jamais lus ; erreurs nettoyées | OUI | 20 §6, 70 §1 (filtre regex sensible) |
Conclusion §6 : toutes les cases Docker confirmées par lecture directe des livrables. Aucun manque.
Vérification §7 — Focus APT / analyse / reboot vérifié
| Case §7 | Couvert ? | Détail |
|---|---|---|
apt_update_analyze distinct des upgrades destructifs |
OUI | 10 §2 tableau (type snapshot, non destructif) |
apt-get update + -s upgrade + -s dist-upgrade |
OUI | 10 §4.1 pseudo-shell |
| Snapshot liste paquets prévus (nom/cur/cible/origine/arch) | OUI | 40 §3 AptSnapshotDetail ; arch en option |
| Distingue upgrade vs dist-upgrade (maj/install/remove/held) | OUI | 10 §4.1 parsing + 40 §3 (upgradeCount, distUpgradeCount, removed, held) |
Simulations parsées via Inst/Conf/Remv, log brut archivé |
OUI | 10 §1 et §4.1 |
Statut ok/updates_available/warning/error ; warning si remove/held |
OUI | 10 §4.1 fin de section |
| Sources APT citées (4 URLs) | OUI | 10 §1, toutes présentes |
Distingue os_family et machine_kind |
OUI | 60 §1 |
| Choix manuel OS (5 valeurs) | OUI | 60 §6 |
| Choix manuel type machine (6 valeurs) | OUI | 60 §6 |
machine_probe détecte/corrige (jamais auto) |
OUI | 60 §6 + pseudo-shell probe |
| Scripts dépendent du couple OS/type | OUI | 60 §5 tableau |
| Debian vérifie contrib/non-free/non-free-firmware | OUI | 60 §4 + 10 §5 |
| Proxmox = profil dédié | OUI | 60 §4 et §2 (dossier templates/proxmox/) |
| Scripts hardware/drivers/benchmark jamais par défaut | OUI | 60 §5 note + 30 §2 note |
| Templates APT attendus (7) | OUI | 10 §2 tableau (tous 7 listés avec pseudo-shell ou référence) |
Politique non interactive (DEBIAN_FRONTEND=noninteractive, -y, confdef/confold) |
OUI | 10 §4.2 et 50 §2 |
| Justification confdef/confold | OUI | 10 §4.2 (conserver config locale) |
| Prompts = risques de blocage, pas dialogues | OUI | 50 §2 |
Timeout inactivité/global → human_interaction_required |
OUI | 50 §2 |
human_interaction_required prévu (pas d'auto-réparation) |
OUI | 50 §2 + 50 §1 (principe) |
| Pas seulement exit code | OUI | 50 §1 (principe n°1) + 10 §4.2 |
dpkg-query -W -f=... before/after |
OUI | 10 §4.2, 40 §3 Q4 |
| Diff backend (maj/install/remove/inchangé/versions/anomalies) | OUI | 40 §4 AptExecutionResult |
ExecutionResult.apt (planned/applied/installed/removed/held/errors/rebootRequiredAfterRun) |
OUI | 40 §4 AptExecutionResult |
| Rapport Markdown résume diff + réf log | OUI | 70 §4, 40 §8 |
| Reboot vérifié (boot_id avant/après, attente, reconnexion) | OUI | 10 §4.5 (pseudo-shell + orchestration backend) |
| Reboot ok si machine revient ET boot_id changé | OUI | 10 §4.5 (expliqué en clair) |
RebootResult (beforeBootId…status/errors) |
OUI | 40 §4 interface RebootResult (8 champs requis + optionnels) |
Délai adaptatif par machine (lastRebootDurationSeconds, nextRecommendedWaitSeconds) |
OUI | 10 §4.5 + 40 §4 RebootResult |
| Statuts d'échec reboot distingués (5 valeurs) | OUI | 40 §4 union RebootResult.status |
| Reboot = validation UI ; Hermes ne déclenche pas | OUI | 70 §2 tableau |
apt_update_analyze alimente snapshot + tuile |
OUI | 10 §6 |
Actions via même route + table executions |
OUI | 20 §6, 10 §6 |
| UI avant exécution (paquets/suppressions/held/reboot/risque) | OUI | 70 §2 + 40 §3 (données disponibles) ; rendu JSX renvoyé à tâche 3 |
| UI après exécution (réussite/diff/reboot/rapport/log) | OUI | 70 §4 ; rendu JSX renvoyé à tâche 3 |
| Confirmation UI pour dist/full/autoremove/reboot | OUI | 70 §2 tableau |
| Nouveaux champs/actions rétrocompatibles | OUI | 40 §1 règles d'extension |
Conclusion §7 : toutes les cases APT/reboot confirmées par lecture directe. Aucun manque.
Vérification §8 — Focus scripts post-install
| Case §8 | Couvert ? | Détail |
|---|---|---|
| Interdit questions interactives SSH → champs formulaire | OUI | 30 §1 (interdiction stricte) |
| Profils cochables dépliant leurs champs | OUI | 30 §1 |
| Manifeste (id/label/description/fields/défauts/validations/preview/risk/confirmations) | OUI | 30 §1 + §3 (exemple JSON complet) |
| Bouton désactivé si champs invalides | OUI | 30 §1 |
| Preview avec masquage secrets + signalement réseau/reboot | OUI | 30 §1, 70 §1 |
| Échec structuré si décision manquante | OUI | 30 §1 et §4 |
| 8 profils attendus (bootstrap_root → vm_guest_tools + optionnels) | OUI | 30 §2 tableau (9 profils principaux + optionnels listés) |
Champs identity_network (7 champs) |
OUI | 30 §3 + exemple manifeste JSON |
Champs docker_official (4 champs) |
OUI | 30 §3 |
Champs sharing |
OUI | 30 §3 |
Champs vm_guest_tools |
OUI | 30 §3 |
| Champs préremplis depuis machine, modifiables | OUI | 30 §3 (dernière phrase) |
| Exemple de manifeste JSON | OUI | 30 §3 (manifeste identity_network complet, identique au gate) |
| Templates custom attendus (6) | OUI | 30 §4 (pseudo-shell pour bootstrap, identity, install-pkg-groups, docker-official ; sharing et vm-guest-tools en prose avec référence tâche 4) |
| Sources citées (5 URLs) | OUI | 30 §4 fin |
identity_network à risque (confirmation/preview/sauvegardes) |
OUI | 30 §4.2, 70 §2 |
| Résultat JSON old/new endpoint + reconnectHost | OUI | 40 §4 PostInstallResult.networkChange |
| Pas de coupure sans stratégie reconnexion ; reboot via reboot_verified | OUI | 30 §4.2 |
| Webapp vérifie reconnexion + met à jour machine | OUI | 30 §4.2 |
| Erreurs réseau distinguées (6 codes) | OUI | 50 §4 |
ExecutionResult.postInstall rétrocompatible |
OUI | 40 §4 PostInstallResult, bloc optionnel |
| Résultat liste profils/variables non sensibles/fichiers/paquets/services/reboots/erreurs | OUI | 40 §4 PostInstallResult (7 champs) |
| Secrets jamais inclus | OUI | 30 §5, 70 §1 |
| Changements réseau/Docker marqués dans rapport Markdown | OUI | 30 §5, 70 §4 |
| Même mécanique (templates/preview/SSH/WS/executions/rapport/log) | OUI | 30 §6 |
| Valeurs réutilisables stockées (où) | OUI | 30 §6 (script_variables_presets, machine_profile_state) |
| Hermes propose/explique, JSON réduit, pas de déclenchement risqué | OUI | 30 §6, 70 §2/§3 |
| Profils découpés en sous-jalons indépendants | OUI | 80 SJ-8 et SJ-9 |
Conclusion §8 : toutes les cases post-install confirmées par lecture directe. Aucun manque.
Réserves (non bloquantes pour le design)
Réserve 1 — Absence de ===SU:EXIT=N=== dans reboot.sh.tpl : comportement intentionnel, cohérent avec le jalon 1.
Le pseudo-shell de 10-templates-apt.md §4.5 ne se termine pas par ===SU:EXIT=N===. Cela est conforme au reboot.sh.tpl existant en prod (jalon 1, vérifié), qui n'en contient pas non plus : le reboot est planifié en arrière-plan (nohup sleep 2; reboot) et la connexion SSH se ferme proprement avant qu'un EXIT puisse être émis de manière fiable. Ce comportement est donc intentionnel et documenté en prose dans §4.5. Ce n'est pas une coquille. Réserve levée.
Réserve 2 — Réduction Hermes (aptReduce.ts) : renommage suggéré reduceLines.ts à confirmer.
Le design propose de renommer aptReduce.ts en reduceLines.ts tout en conservant reduceAptLines comme export. L'auto-évaluation dit « additif, sans casser reduceAptLines ». Correct sur le fond, mais le renommage de fichier implique de mettre à jour les imports existants — à vérifier que server/templates/render.ts ou tout autre consommateur est mis à jour dans SJ-0. Non bloquant pour le design, à tracer dans le plan SJ-0.
Réserve 3 — Contexte partagé : shared/types.ts modifié par jalon 2 concurrent.
La modification est imputable au jalon 2, pas à la tâche 2. Elle n'introduit aucune rupture pour les extensions prévues par la tâche 2. À surveiller : s'assurer que SJ-0 s'appuie sur l'état committé de shared/types.ts et non sur le diff non committé.
Coquilles corrigées dans les livrables
Aucune coquille textuelle ou factuelle identifiée dans les 11 fichiers de design. L'absence de ===SU:EXIT=N=== dans reboot.sh.tpl était un faux positif : comportement intentionnel cohérent avec le jalon 1 (voir réserve 1 levée ci-dessus). L'auto-évaluation 99-couverture-gate.md est globalement correcte — les trois réserves résiduelles qu'elle liste (§4 non-régression, UI JSX → tâche 3, délimiteurs Mustache/Docker) sont légitimes et non bloquantes.
Écarts avec l'auto-évaluation du producteur
L'auto-évaluation coche tout en ✅ sauf les trois réserves résiduelles. La présente revue indépendante confirme intégralement ce tableau. Aucun manque réel n'a été identifié que l'auto-évaluation aurait raté. Un faux positif initial (marqueur EXIT de reboot) a été levé après vérification du template existant en prod.
Actions de suite
- Lancer
rtk pnpm check && rtk pnpm test && rtk pnpm buildpour confirmer la non-régression formelle (§4 ; aucun code de prod touché par la tâche 2, résultat attendu vert). - Procéder à
writing-planspour SJ-0 (socle types/réduction/résolution) dès que la non-régression est confirmée. - Tracer dans le plan SJ-0 la mise à jour des imports consommateurs si
aptReduce.tsest renommé enreduceLines.ts. - S'assurer que SJ-0 s'appuie sur l'état committé de
shared/types.ts(le diff non committé provient du jalon 2 concurrent — à intégrer ou isoler avant de démarrer SJ-0).