ADR-123 — Descellement breaking couche-1-v3.0 : AirPrivilegeDrop prend une cage air-sandbox
Statut : Accepté (2026-07-28, autorisation BDFL explicite). RFC de structure (ADR-015). Applique le modèle de re-sceau du sceau couche 1 (ADR-062) ; implémente le §5 d’ADR-122.
Catégorie : Descellement NON-additif (rupture) de la couche 1 scellée
(couche-1-v2.4 → couche-1-v3.0). Première rupture de la couche 1 depuis le
sceau couche-1-v1.0 (ADR-062). Hors de la délégation additive du superviseur
(ADR-065 : les changements non-additifs
sont remontés au BDFL) — d’où l’autorisation explicite ci-dessus.
Contexte
ADR-122 §5 décide que le confinement du
monitor et des workers privsep d’air-sshd s’exprime par les types haut
niveau d’air-sandbox (AirSandboxProfile + AirLandlockPolicy), et non par
les types couche 0 pré-construits.
Or AirPrivilegeDrop (crate air-process, scellée depuis couche-1-v1.0) exposait
jusqu’ici, dans sa surface publique, des types couche 0 :
- les builders
with_seccomp_filter(SockFprog<'static>)etwith_landlock(LandlockRuleset); - les champs publics
seccomp_filter: Option<SockFprog<'static>>etlandlock: Option<LandlockRuleset>.
C’est précisément la fuite de types couche 0 que le layering interdit (ADR-077 : la couche 1 est le seul consommateur de la couche 0 ; ces types ne doivent pas transparaître dans le vocabulaire d’un service couche 2). Tant que ces symboles figurent dans l’API scellée, le confinement ne peut pas être décrit uniquement par des types haut niveau — l’objectif d’ADR-122 §5 est inatteignable sans retrait.
Le retrait de symboles publics d’une crate scellée est non-additif : il casse
la surface couche-1-v2.4. C’est le point qui impose ce descellement breaking.
Décision
Descellement breaking couche-1-v3.0. Sur air-process (crate scellée) :
- RETRAIT (rupture) de
AirPrivilegeDrop::with_seccomp_filter,AirPrivilegeDrop::with_landlock, et des champs publicsseccomp_filter/landlock. - AJOUT de la feature
sandbox(OFF par défaut, volontairement absente derustc-dep-of-std: le PAL destdn’a pas de cage et ne doit pas tirerair-sandbox→air-log→air-socket/air-stdiodans son graphe) qui câble :- le champ
sandbox: Option<(AirSandboxProfile, AirLandlockPolicy)>; - le builder
with_sandbox(profile, landlock); - dans
drop_privileges, la pose de la cage déléguée àAirSandbox::apply— ordre interne sûrno_new_privs → Landlock → seccomp, fail-closed (ADR-112) ; tout échec reste FATAL.
- le champ
La compilation des types haut niveau vers la couche 0 (SockFprog/LandlockRuleset)
et l’ordre d’application restent internes à air-sandbox. Après ce descellement,
aucun type couche 0 ne figure plus dans la surface publique d’air-process.
Rupture indolore en pratique. Un grep du workspace (crates/) et de l’arbre
std (rt/) prouve zéro appelant de with_seccomp_filter/with_landlock hors
air-process lui-même : ni la libc C-ABI, ni le PAL std, ni air-sshd ne les
utilisaient (OpenSSH-scope larguait via les syscalls individuels ; la cage n’était pas
encore branchée). Le retrait purifie la surface avant que quiconque en dépende —
le meilleur moment pour une rupture.
Pourquoi un major v3.0 (et non un additif v2.x)
La convention de versionnement du sceau (ADR-012/ADR-062) réserve le bump de major
aux ruptures : le précédent couche-1-v2.0 a bumpé le major pour un renommage
breaking (AirProcessManager → AirTaskManager, ADR-088). Un retrait de symbole
public est de même nature — on honore la sémantique plutôt que de maquiller le break
en additif. couche-1-v2.4 → couche-1-v3.0.
Gouvernance — rupture remontée au BDFL
ADR-065 a délégué au superviseur les seuls re-sceaux purement additifs ; les
changements non-additifs (rupture) et les compromis de sécurité restent remontés
au BDFL. Ce descellement est une rupture : il a été présenté au BDFL (première
rupture de la couche 1, choix du numéro de version) et explicitement autorisé le
2026-07-28 (option « major dédié couche-1-v3.0 »). Il n’entre pas sous la
délégation additive.
Conséquences
- Tag git
couche-1-v3.0posé par le superviseur sur le commit de merge, après CI verte (barrière x86 + couverture exception-aware). Signé. - La surface publique d’
air-processrétrécit (retrait) puis grandit (with_sandbox, featuresandbox). Aucun consommateur cassé (0 appelant prouvé). - Le confinement privsep d’
air-sshd(ADR-122, incréments suivants) pourra s’exprimer exclusivement en types haut niveauair-sandbox. - Précédent posé : une rupture de couche 1 = major dédié + ADR de descellement + autorisation BDFL explicite (jamais sous la délégation additive).
Alternatives rejetées
- Conserver
with_seccomp_filter/with_landlocket ajouterwith_sandbox(additifv2.5). Rejeté : garder les types couche 0 dans la surface défait l’objectif d’ADR-122 §5 (fin de la fuite) ; la double API invite à contourner la cage haut niveau. - Re-sceau additif
v2.5en actant une « entorse tolérée » (retrait d’API non-consommée). Rejeté : un retrait de symbole public est une rupture ; la convention major existe pour ça. Maquiller le break en additif créerait un précédent d’entorse plus coûteux que d’assumer un major honnête. - Différer le re-sceau et batcher plusieurs ruptures ADR-122 dans un seul
v3.0ultérieur. Rejeté par le BDFL : le re-sceau dédié trace proprement la rupture au plus près de son commit (Inc.3 séparé) plutôt que de laisser une fenêtre où l’API surmainn’est niv2.4niv3.0.
Suite
- Tag
couche-1-v3.0après merge. Note de re-sceau dansetat-avancement.md(registre des couches) etINDEX.md. - Les incréments ADR-122 suivants (refonte privsep, cage worker SFTP) consomment
with_sandboxsous la featuresandbox; ils documenteront au registre de couverture toute ligne CHILD-EXIT nouvellement compilée quand la feature devient active dans un build de couverture.