# Déploiement par étapes : contrat de sécurité V1 Ce document décrit `scripts/deploy.sh`. Il ne valide pas une réinstallation et **n'autorise pas son exécution réelle sur ArchASP** tant que les décisions pertinentes de [reconstruction](reconstruction-baseline.md) (notamment réseau et signature) restent ouvertes. Le script ne restaure ni `/etc/fstab`, ni Limine, ni les clés Secure Boot, ni les données ou dotfiles. ## Options et résultat `--packages`, `--configs`, `--tools`, `--services` sélectionnent explicitement des étapes ; `--all` sélectionne les quatre dans cet ordre. Plusieurs sélections peuvent être combinées. Sans sélection, le code est `2`. `-h`/`--help` affiche l'aide. `--dry-run` s'ajoute à une sélection et affiche sources, destinations et actions sans confirmation, sudo, gestionnaire de paquets, sauvegarde ni temporaire de déploiement. Il peut lire les fichiers du dépôt et interroger sans privilèges la présence des unités systemd lorsque leur installation n'est pas demandée. Exemples de **plan uniquement** : ```bash ./scripts/deploy.sh --dry-run --configs ./scripts/deploy.sh --dry-run --all ``` Le code `0` en simulation signifie seulement « préconditions statiques connues satisfaites et plan affiché ». Les validations nftables/sudoers privilégiées, la présence future des unités apportées par les paquets et le résultat d'une installation ne sont pas vérifiés par ce code. Le code `1` signale une précondition ou une étape échouée ; le code `2`, un usage invalide ; `130`/`143`, une interruption gérable par `INT`/`TERM`. En application, `0` signifie que les commandes sélectionnées se sont terminées sans erreur signalée **ou que l'utilisateur a répondu non à la confirmation** ; dans ce dernier cas, « Déploiement annulé » est affiché et rien n'est appliqué. Un code `0` après application ne prouve pas le démarrage ni la conformité fonctionnelle. ## Préconditions et ordre Les fichiers de configuration, helpers et templates sélectionnés doivent exister, être lisibles, non vides et ne pas être des liens. Les listes de paquets et manifests doivent exister et être lisibles ; un fichier **présent mais vide** est une sélection volontairement vide. Les lignes vides et commentaires entiers sont ignorés ; chaque autre ligne doit contenir un seul nom valide, sans doublon ni option commençant par `-`. Une source manquante ou une ligne invalide arrête le lot avant toute application. Le script doit être appelé depuis un compte non root lorsque des paquets étrangers ou `--tools` sont demandés. Il obtient le bénéficiaire avec `id`, pas avec `USER` ou `SUDO_USER`, et refuse une règle sudoers au nom de root. Il n'amorce pas `yay` : une liste étrangère non vide avec `yay` absent fait échouer le précontrôle avant l'installation native. Les noms du fichier « AUR » sont des entrées à soumettre à yay, pas une preuve qu'ils proviennent tous de l'AUR ; leur compatibilité et leur source doivent être examinées séparément. Pour une application, le nom de machine est lu et validé dans `/etc/hostname` avant la confirmation et toute mutation. Un fichier absent, illisible, vide ou invalide arrête l'application avec code `1`. La commande externe `hostname` n'est pas requise. Le contrôle privilégié des cibles utilise `find` et `/usr/bin/bash`, qui doivent être disponibles ; une absence de `find` est diagnostiquée au précontrôle. Après confirmation, les validations privilégiées connues sont tentées **avant la première mutation durable** : `sudo -v`, `nft -c -f` pour `--configs`, puis rendu des deux règles sudoers et `visudo -cf` pour `--tools`. Si `--packages` est également demandé et fournit `nft`, sa disponibilité et la validation sont différées après les paquets, avant la première configuration. Les unités systemd sont vérifiées immédiatement si aucun paquet n'est demandé ; sinon elles sont vérifiées après les paquets, avant leur première utilisation. Un `--all` peut donc échouer après installation des paquets : il n'est pas garanti entièrement avant la première mutation. `--tools` et `--services` peuvent **arrêter** les quatre unités VMware/Samba du manifest à la demande avec `disable --now`. `--services` active les services et timers listés. Une unité requise absente est une erreur ; une unité à la demande déjà désactivée et inactive est laissée telle quelle. Les autres erreurs de désactivation ou d'activation ne sont pas masquées. `--configs` effectue `daemon-reload` et lance TLP si sa commande est disponible. Ces actions peuvent interrompre un service déjà utilisé : choisir les étapes et le moment en conséquence. ## Cibles, sauvegardes et reprise Les cibles existantes sont copiées **avant** remplacement dans un répertoire root privé créé paresseusement par `mktemp -d` sous `/root/arch-system-restore.*`. Chaque invocation obtient un nom atomiquement unique, y compris dans la même seconde. Les fichiers remplacés sont sous `existing/` avec leur chemin d'origine et conservent leurs métadonnées par `cp -a`. Une cible initialement absente reçoit seulement un marqueur vide sous `absent/` : ce n'est pas une fausse copie de sauvegarde. Les helpers et les deux règles sudoers suivent la même politique que les configurations. Le chemin de sauvegarde est affiché en cas d'échec et à la fin. Le script refuse une cible ou un parent qui est un lien symbolique, même cassé, ou une cible existante non régulière. Il réexamine les cibles avant sauvegarde et avant installation. Le contrôle privilégié renvoie, **uniquement après succès de l'inspection**, un état strict : `EXISTING`, `ABSENT`, `LINK` ou `INVALID`. Une erreur de sudo ou de l'inspection, une réponse vide ou inconnue, ou un état plausible accompagné d'un code d'échec arrêtent le lot ; aucun marqueur d'absence ni remplacement de la cible concernée n'est alors autorisé. Une erreur au second contrôle conserve la sauvegarde déjà faite. Cela limite les écritures inattendues mais ne garantit pas l'absence de toute course avec un autre processus privilégié. Les fichiers sudoers rendus sont gardés dans un répertoire temporaire privé et supprimés sur sortie normale, erreur, `INT` ou `TERM`. Les sauvegardes root ne sont jamais supprimées par ce nettoyage. Un `SIGKILL` ou une coupure de courant ne déclenche pas de trap. Une erreur arrête les étapes suivantes et affiche la phase, les phases achevées, les actions déjà appliquées et le répertoire de sauvegarde disponible. Sur `INT` ou `TERM`, le bilan affiche le signal, la phase, les étapes achevées, les actions **confirmées**, l'action en cours dont les effets sont à vérifier, et le chemin des sauvegardes lorsqu'il existe. Une commande interrompue peut avoir déjà eu des effets, même si elle n'est pas dans la liste des actions confirmées. Il n'y a **aucun rollback automatique global** : pacman/yay, services et fichiers n'ont pas une annulation commune. Pour reprendre, comparer l'état réel aux cibles et aux copies ou marqueurs, restaurer manuellement ce qui doit l'être, puis relancer uniquement une étape comprise. Les installations de paquets peuvent être relancées avec `--needed`, mais cela n'annule pas une transaction partielle ; les copies et activations systemd sont répétables seulement après vérification de l'état et des effets de service. ## Tests autorisés Commande unique du harnais : ```bash tests/deploy/test.sh ``` Le harnais exige `bwrap` déjà installé et vérifie les exécutables réels qu'il place dans son `PATH` fermé ; un outil manquant échoue avant la création d'un lien cassé. Il crée un dépôt synthétique et exécute **une copie** de `deploy.sh` dans un espace sans réseau, avec `/` en lecture seule, `/etc` et `/usr/local/sbin` remplacés par des fixtures privées. La doublure `sudo` reconnaît strictement le fragment de contrôle prévu et simule son résultat sans jamais exécuter librement un argument `bash -c` ; toute autre sous-commande inconnue est refusée. Paquets, yay, nftables et systemd sont simulés. Les scénarios nominaux rejettent tout stderr ; les scénarios d'erreur contrôlent les diagnostics admis. Aucun essai réel du script du dépôt sur ArchASP n'est effectué. `bash -n` complète les tests ; ShellCheck n'est utilisé que s'il est déjà présent. Les réponses simulées prouvent uniquement les branches exercées : ni déploiement, ni pare-feu, ni signature, ni démarrage, ni restauration ne sont validés.