118 lines
7.3 KiB
Markdown
118 lines
7.3 KiB
Markdown
# Export système pour revue
|
||
|
||
`scripts/backup.sh` produit un **candidat privé hors du dépôt**. La commande
|
||
sans argument ne met plus à jour `pkglist/`, `inventory/`, `rootfs/` ni
|
||
`templates/` suivis par Git. Elle ne sauvegarde ni données personnelles,
|
||
dotfiles, clés Secure Boot, connexions réseau, secrets, ni fichiers Trainlog.
|
||
La zone locale d’export n’est pas une preuve de sauvegarde hors disque ou de
|
||
restauration possible. Ce code n’a été testé ici que sur des fixtures.
|
||
|
||
## Interface et destination
|
||
|
||
```text
|
||
backup.sh [--output-dir REPERTOIRE_PARENT]
|
||
backup.sh --dry-run [--output-dir REPERTOIRE_PARENT]
|
||
backup.sh --help
|
||
```
|
||
|
||
`--output-dir` désigne un **parent** : chaque invocation crée un sous-répertoire
|
||
unique. Par défaut, le parent est
|
||
`${XDG_STATE_HOME:-$HOME/.local/state}/arch-system/exports`. Un
|
||
`XDG_STATE_HOME` relatif est ignoré avec diagnostic, selon la
|
||
[spécification XDG](https://specifications.freedesktop.org/basedir/0.8/) ;
|
||
le chemin par défaut sous `HOME` est alors employé. Un parent explicite
|
||
relatif est résolu depuis le répertoire courant. Les chemins sont normalisés ;
|
||
la destination égale au dépôt ou située dedans, les alias vers celui-ci et les
|
||
parents traversant un lien symbolique sont refusés. Un parent final existant
|
||
doit appartenir à l’utilisateur et ne pas être ouvert au groupe ou aux autres.
|
||
Les nouveaux répertoires sont créés privés, sans `chmod`/`chown` des ancêtres.
|
||
Un parent contenant des espaces ou un antislash littéral reste accepté ; le
|
||
calcul des empreintes ne dépend pas de la représentation de son nom.
|
||
|
||
`--dry-run` affiche les sources, les catégories obligatoire/facultatif, le
|
||
parent et les transformations ; il ne crée rien et ne lance ni sudo, ni
|
||
collecteur, ni demande de mot de passe. Il ne prouve pas la réussite des
|
||
lectures futures. La collecte refuse une invocation en root ; les fichiers de
|
||
sortie sont écrits par l’utilisateur sous `umask 077`. Les lectures privilégiées
|
||
utilisent `sudo -n`, un contrôle d’état strict et seulement les sources
|
||
explicitement autorisées. Aucun résultat n’est installé avec sudo.
|
||
|
||
## Collecteurs et états
|
||
|
||
| Classe | Collecteurs | Raison |
|
||
|---|---|---|
|
||
| Obligatoire | `pacman -Qqen`, `-Qqem` ; unités système activées, en cours et timers ; `lsblk`, `findmnt`, `/etc/fstab`, Btrfs subvolumes/usage, mémoire et swap ; `pacman.conf`, `makepkg.conf`, `mkinitcpio.conf` | Sans ces éléments, le candidat annoncé manquerait son noyau d’inventaire et de configuration. |
|
||
| Facultatif | `pacman -Qdtq` ; unités en échec et unités utilisateur ; scrub Btrfs ; SMART de `/dev/nvme0` ; `nftables.conf`, limine-snapper-sync, TLP, zram-generator, Snapper, deux helpers root ; modèle Limine | Leur absence ou indisponibilité peut être légitime selon la machine, l’utilisateur ou le matériel. Elle reste visible dans le manifeste. |
|
||
|
||
`SUCCESS` indique un fichier collecté non vide ; `EMPTY`, une commande
|
||
réussie avec résultat vide permis ; `ABSENT`, une absence effectivement
|
||
établie pour une source facultative ; `UNAVAILABLE`, un outil ou `nvme0`
|
||
indisponible ; `CHECK_ERROR`, un contrôle impossible ou une réponse
|
||
invalide ; `COLLECT_ERROR`, une commande ou lecture échouée.
|
||
`PORTABILITY_REVIEW` marque le modèle Limine à relire, même après une
|
||
transformation reconnue. Une erreur obligatoire interdit la finalisation ;
|
||
une erreur facultative produit `COMPLETE_WITH_WARNINGS` si le noyau
|
||
obligatoire a réussi. `COMPLETE` est réservé à un ensemble sans avertissement.
|
||
En pratique, un modèle Limine présent entraîne une alerte de portabilité.
|
||
|
||
Les listes sont des **observations** : « natif » ne prouve pas dans tous les
|
||
cas « dépôt officiel », et « étranger » ne prouve pas « AUR ».
|
||
`pacman -Qdtq` désigne les dépendances orphelines selon
|
||
[pacman(8)](https://man.archlinux.org/man/pacman.8.en). La documentation
|
||
primaire ne justifie pas une règle générale « code 1 = aucun orphelin » :
|
||
une sortie vide avec code non nul reste `COLLECT_ERROR`, avec une cause à
|
||
examiner. Les résultats vides de commandes revenues avec succès sont
|
||
distingués. Le relevé SMART éventuel concerne **seulement** `/dev/nvme0`,
|
||
pas tous les disques.
|
||
|
||
## Finalisation, manifeste et limites
|
||
|
||
La collecte commence dans un répertoire `.incomplete.*` privé, doté d’un
|
||
`manifest.tsv` au statut `INCOMPLETE`. Les sorties sont d’abord reçues dans
|
||
une zone de travail privée ; une commande qui écrit partiellement puis échoue
|
||
ne publie pas ce fichier comme relevé valide. Après les éléments obligatoires,
|
||
le manifeste est terminé et le répertoire est renommé localement en
|
||
`export-*` sans remplacer un nom existant. Chaque invocation a son espace ;
|
||
avant un renommage réussi, une erreur ou un `INT`/`TERM` conserve son reliquat
|
||
marqué `INCOMPLETE` et annoncé. Après le renommage réussi, un `INT`/`TERM`
|
||
conserve le candidat complet et annonce son chemin avec le diagnostic
|
||
« finalisation acquise, terminaison interrompue ». L'exporteur reconnaît ce
|
||
renommage par la disparition du staging et l'identité de l'objet au chemin
|
||
final ; la simple présence d'une destination préexistante ne suffit pas.
|
||
Une collision conserve le staging incomplet sans revendiquer cet autre export.
|
||
Les exports antérieurs ne sont ni supprimés ni remplacés. Les codes sont `0` pour
|
||
simulation ou candidat finalisé, `1` pour erreur, `2` pour usage invalide,
|
||
`130`/`143` pour `INT`/`TERM`. `SIGKILL` et une coupure d’alimentation
|
||
ne sont pas interceptés ; aucune garantie de durabilité après coupure n’est
|
||
revendiquée.
|
||
|
||
Le manifeste contient version, début/fin UTC, révision source, statut global,
|
||
état de chaque collecteur et SHA-256 des **fichiers de sortie finalisés**.
|
||
Chaque empreinte est calculée via l'entrée standard, après vérification de
|
||
l'ouverture du fichier et du succès de la commande ; seule une réponse de
|
||
64 chiffres hexadécimaux est acceptée. Un échec ou une réponse malformée
|
||
interdit la finalisation. Le manifeste ne contient pas son propre hash.
|
||
Vérifier les empreintes et lire le contenu
|
||
avant toute utilisation. Les lectures ne forment pas un instantané atomique :
|
||
services et fichiers peuvent changer pendant la collecte. Les vérifications
|
||
de chemins réduisent les risques d’alias et de liens ; elles ne remplacent pas
|
||
une exclusion des modifications concurrentes de la machine.
|
||
|
||
Le modèle Limine candidat est produit **uniquement dans l’export**. La section
|
||
commençant par `### Auto-generated by limine-snapper-sync` est retirée.
|
||
Les formes `root=UUID=<hexadécimal/tirets>` et
|
||
`root=PARTUUID=<hexadécimal/tirets>` deviennent des placeholders distincts.
|
||
Une forme `root=` non reconnue est signalée ; tous les autres champs
|
||
demeurent soumis à revue. Ni `ESP_PATH`, ni signatures, ni snapshots ne sont
|
||
changés. Le modèle n’est pas déclaré universellement portable.
|
||
|
||
## Revue avant toute promotion manuelle
|
||
|
||
Examiner les fichiers et le manifeste hors du dépôt, particulièrement
|
||
identifiants de stockage, noms de services, `nftables.conf`, `fstab` et
|
||
Limine. Aucun filtrage simple ne certifie l’absence de secrets ; **ne pas
|
||
publier automatiquement**. Les listes de déploiement et la politique réseau
|
||
restent des décisions de reconstruction distinctes de l’état observé.
|
||
Une éventuelle reprise manuelle dans Git demande une revue spécifique des
|
||
contenus et de leur portée. L’existence du candidat n’apporte ni copie
|
||
externe, ni restauration testée.
|