ADR-041 — Coexistence /etc : projection générée, lecture seule sélective, air-config seul écrivain
Statut : Accepté (2026-06-25, validé par le BDFL). Companion d’ADR-033 (modèle de configuration : source typée → compilateur → artefact binaire) — détaille la règle 7 (backends d’émission) au-delà de systemd. Cohérent avec ADR-005 (systemd socle V1), ADR-040 (artefact Cap’n Proto), ADR-032 (zéro discard) et le Principe 4 (valider en amont).
Catégorie : Architecture (transverse — air-config couche 1 + intégration OS couche 5).
Contexte
ADR-033 a posé que la configuration Air a pour source de vérité une source typée
compilée en artefact binaire (Cap’n Proto, ADR-040), le texte n’étant qu’une
projection. Reste un problème de coexistence avec le monde C-Unix : tant qu’Air
n’apporte pas sa propre libc et ne recompile pas les outils C contre elle, on ne peut
pas empêcher un programme C de lire — ni de tenter d’écrire — sous /etc. La libc
(glibc/musl) et les services Unix classiques lisent directement /etc/resolv.conf,
/etc/nsswitch.conf, /etc/hosts, /etc/passwd, /etc/systemd/system/…, etc. au
runtime, indépendamment d’Air.
L’objectif : un utilisateur faillible ne doit modifier la configuration qu’à travers
l’outil Air validant (Principe 4) ; mais les consommateurs C doivent continuer à
lire leur config. Il faut donc que /etc reflète la source Air sans redevenir une
surface d’édition libre.
Décision
Les fichiers
/etcque possède Air sont des projections générées parair-config(backend d’émission, ADR-033 §7), protégés en lecture seule sélective ;air-configen est le seul écrivain (réécriture par swap atomique). Les consommateurs C les lisent, ne les écrivent jamais. C’est un garde-fou, pas une frontière de sécurité.
Six règles :
-
Projection générée, pas source. Les fichiers
/etcpossédés par Air sont dérivés de la source typée par le backend d’air-config(cohérent ADR-033 §7) ; jamais édités à la main. La source typée (compilée en artefact Cap’n Proto, ADR-040) reste canonique. -
air-configseul écrivain, par swap atomique. Les régénérations passent parair-filesystem::write_atomic(tmpfile + fsync + rename). Le runtime Air-natif ne lit pas/etc(il lit l’artefact binaire) ;/etcn’existe que pour le monde C. -
Lecture seule SÉLECTIVE, pas globale. Seuls les fichiers possédés par Air sont rendus immuables-aux-autres (bind
ropar fichier,chattr +i, ou overlay à lower RO). Un/etcentièrement RO est rejeté : il casserait des écrivains runtime légitimes (passwd/useradd→/etc/shadow/passwd;ldconfig→ld.so.cache; installations de paquets). Donnée du réel : même les OS « immuables » (Fedora Silverblue, openSUSE MicroOS) gardent/etcinscriptible (overlay) et rendent/usrimmuable — précisément pour cette raison. -
Mutables-runtime → redirigés vers
/run. Les fichiers qu’un service réécrit en continu (resolv.conf…) sont des symlinks vers/run(tmpfs inscriptible), pattern systemd-resolved./etc/machine-id: symlink/runou pré-provisionné (premier boot). -
systemd :
air-configpossède/etc/systemd/system. L’activation de services (enable/disable/mask), les drop-ins (edit) ethostnamectl/localectl/timedatectlécrivent normalement sous/etc; dans le modèle Air, l’humain les déclare dans la source Air et le backend systemd d’air-configémet les symlinks/etc/systemd/system/*.wants+ drop-ins. systemd ne fait que LIRE cette zone ⇒ elle peut être RO-aux-autres,air-configseul écrivain. Les opérations runtime (start/stop/restart/status, via sd-bus → état dans/run) ne touchent pas/etcet restent intactes sous/etcRO. -
Garde-fou, pas frontière de sécurité. root peut
mount -o remount,rw. Le RO sélectif empêche les accidents et le «vim /etc/resolv.conf» distrait, et signale « fichier généré » (le tool C reçoitEROFS, échec bruyant plutôt qu’écrasement silencieux). La contrainte dure viendra avec air-launchd (sandbox/Landlock) ou le bit immuable — hors périmètre ici.
Conséquences
- Deux responsabilités distinctes.
air-config(couche 1) génère les projections/etc; la protection (montage RO sélectif /chattr/ overlay / symlinks/run) est une décision d’intégration OS (couche 5) — réalisable par une unit systemd de montage dès maintenant, avantair-launchd. - Périmètre croissant (progressif). Au début, peu de fichiers gérés/verrouillés ; une
zone
/etcne passe en RO-sélectif qu’une fois que le backend d’air-configcouvre les mutations correspondantes (mêmes incréments que ADR-033 §7). Tant qu’une mutation n’est pas couverte, sa zone reste inscriptible. - Bootstrap bidirectionnel. Sur installation/migration existante, l’outil doit
importer
/etcexistant → source Air (sens inverse) avant d’émettre. Import et émission. - Périmètre de possession explicite. Tout
/etcn’appartient pas à Air (des paquets en possèdent) ;air-configdéclare les fichiers qu’il possède — les autres restent hors de sa gestion.
Alternatives rejetées
/etcglobalement read-only. Cassepasswd/useradd/ldconfig/installations ; plus agressif que l’état de l’art (Silverblue/MicroOS gardent/etcinscriptible).- Régénération qui écrase en silence (sans RO). L’écriture d’un tool C « réussit » puis
est écrasée plus tard → surprise, dérive non signalée. Le RO sélectif échoue tout de
suite (
EROFS), plus honnête (Principe 4 / ADR-032). - Interdiction dure par défaut (Landlock/sandbox) dès maintenant. Prématuré sans air-launchd ; le garde-fou par montage suffit pour la phase de coexistence.
Hors périmètre
- L’enforcement dur (air-launchd, Landlock, bit immuable) — couche 5, ADR ultérieur.
- Le langage de la source typée, l’ergonomie du compilateur, le schéma Cap’n Proto et
la liste précise des backends/fichiers possédés — spec
air-config(couche 1).
Adoption
Documentaire immédiat (ADR-041 + registre/INDEX/SUMMARY). Mise en œuvre échelonnée : la
spec air-config détaillera les backends d’émission (dont /etc/systemd/system), l’import
inverse et le périmètre de possession ; l’intégration OS (unit de montage RO sélectif +
symlinks /run) viendra côté couche 5, de façon progressive.