Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.4couche-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>) et with_landlock(LandlockRuleset) ;
  • les champs publics seccomp_filter: Option<SockFprog<'static>> et landlock: 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 publics seccomp_filter / landlock.
  • AJOUT de la feature sandbox (OFF par défaut, volontairement absente de rustc-dep-of-std : le PAL de std n’a pas de cage et ne doit pas tirer air-sandboxair-logair-socket/air-stdio dans 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ûr no_new_privs → Landlock → seccomp, fail-closed (ADR-112) ; tout échec reste FATAL.

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 (AirProcessManagerAirTaskManager, 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.0 posé par le superviseur sur le commit de merge, après CI verte (barrière x86 + couverture exception-aware). Signé.
  • La surface publique d’air-process rétrécit (retrait) puis grandit (with_sandbox, feature sandbox). Aucun consommateur cassé (0 appelant prouvé).
  • Le confinement privsep d’air-sshd (ADR-122, incréments suivants) pourra s’exprimer exclusivement en types haut niveau air-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_landlock et ajouter with_sandbox (additif v2.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.5 en 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.0 ulté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 sur main n’est ni v2.4 ni v3.0.

Suite

  • Tag couche-1-v3.0 après merge. Note de re-sceau dans etat-avancement.md (registre des couches) et INDEX.md.
  • Les incréments ADR-122 suivants (refonte privsep, cage worker SFTP) consomment with_sandbox sous la feature sandbox ; ils documenteront au registre de couverture toute ligne CHILD-EXIT nouvellement compilée quand la feature devient active dans un build de couverture.