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

Carte des chantiers, ordonnée par surface développeur

Établie le 2026-08-21, sur décision BDFL. Relevé fait contre le code, pas contre des notes : chaque chiffre vient de statuts.toml, de xtask/controleurs-reference.toml ou d’une mesure de couverture datée.

Le compte exact, remesuré le 2026-08-21 : xtask/controleurs-reference.toml porte 26 entrées d’écart sur 24 cratesair-libc-capi et air-libc-spawn en cumulent deux chacune. Et 19 crates déclarent role = "manager" quand 11 seulement en portent un : l’écart entre les deux nombres EST la dette du rang 1.

Pourquoi cette carte existe

Air produit un système d’exploitation : des APIs et des bibliothèques sur lesquelles des développeurs tiers bâtiront des applications. Le produit est libair — la surface publique stable —, pas air-sshd, qui est un démonstrateur et une fonction de forçage.

Or la roadmap au 2026-08-15 ordonnait les chantiers par ce qui débloque air-sshd, reléguant les managers manquants au point 5. Le démonstrateur devenait la spécification. Cette carte inverse l’ordre : le domaine décide la forme de l’API, le consommateur la prouve par l’usage.

Le symptôme, chiffré

Sur les 1078 branches non couvertes de la couche 2, air-sshd en concentre 553 — la moitié. Un démonstrateur qui porte la moitié de la dette de test de la couche qu’il démontre n’est pas un démonstrateur : c’est un monolithe qui implémente en son sein ce qui aurait dû être des APIs. Refonder air-sshd et air-launchd sur des managers éprouvés ne les retarde pas : cela réduit leur surface de test au profit de tests d’API réutilisables.

La règle qui commande tout le reste — et elle est déjà décidée

ADR-149 D4 :

Le contrat d’API d’Air, ce sont les managers de domaine et les types publics. Tout le reste est interne, et Air se réserve d’en changer la structure comme bon lui semble.

et D9 :

Une crate de couche N ne peut atteindre la couche N-1 que par ses managers de domaine et ses types publics. Jamais un contrôleur, jamais une fonction libre.

Ce que cette règle achète : un contrat de dix ans envers les développeurs sans figer le cœur. Tant que le tiers ne voit que des managers, les contrôleurs restent à nous — on peut les refondre de version en version. Le jour où un tiers dépend d’un contrôleur, ce contrôleur devient contractuel, et le cœur est gelé avec lui.

Les rangs :

RangVisibilitéRôle
Couche 0N’exporte rienLa couche mince où unsafe est toléré. Aucun développeur externe n’y accède
Contrôleur (couche 1)Public ou interneSémantique objet sur une portion du système, un objet du noyau
Manager (couche 1)PublicCoordonne les contrôleurs. C’est la surface offerte aux tiers

Rang 1 — Les huit managers dus et non écrits

Chaque domaine existe et fonctionne, mais sans porte : le tiers n’a que des fonctions libres, donc aucune garantie.

CrateDetteCe qu’un tiers vient y chercher
air-account38 opérations libresIdentité, comptes, groupes, credentials. Le domaine où une API laxiste devient une faille
air-terminal21 — « cas extrême »Console, TTY. Prérequis d’ADR-008/ADR-026 (air-tui), donc de tout l’applicatif texte
air-thread14Fils d’exécution — toute application non triviale
air-config-compile10La porte d’entrée stricte du Principe 11
air-crypto7Signer, chiffrer, vérifier
air-config4Lecture de configuration
air-devicesurface complète, point d’entrée manquantLe moins cher des huit
air-sandboxmécanisme livré, médiateur absentLa cage. Bloqué sur une décision, pas sur du code — voir ci-dessous

air-sandbox — ce qui bloque est une décision, et elle s’est réduite

Cette note le classait « à instruire, pas à coder ». Le mot était juste, la source manquait : l’instruction avait déjà eu lieu, et elle est datée.

L’amendement d’ADR-112 du 2026-08-03 énonce l’écart sans le farder : le mécanisme est livré et éprouvé — AirSandbox pose la cage, air-sshd la consomme en production —, mais il ne joue pas le rôle de médiateur de domaine qu’ADR-077 attend d’un manager. Et il nomme les quatre questions qui bloquent :

la largeur des enveloppes par défaut, la forme de l’arbitre de lancement, l’articulation manifeste/octroi, le sort des binaires de provenance étrangère.

Il conclut : « Dépendance de décision, pas de code. » ADR-150 (2026-08-03) en a levé trois en fixant le manifeste, l’octroi et la procédure d’arbitrage à l’exec. Restait bloquante la largeur des enveloppes par défaut — elle détermine ce que le manager doit savoir poser.

Ce qui a changé le 2026-08-21

Deux constats réduisent cette dernière question sans la trancher :

1. La dérivation octroi → cage est déjà écrite — en couche 2. air-bundle/src/ceiling.rs, crate déclarée contrôleur, traduit un octroi en catégories d’appels système. La règle qui dit quelle cage mérite quel octroi vit donc un étage au-dessus de celui qui doit la tenir. Ce n’est pas une conception qui manque : c’est une inversion de couche.

2. air-launchd::launch() porte des faits de domaine qui ne lui appartiennent pas. Il pousse dans chaque cage deux catégories qu’aucun octroi ne demande — RuntimeBootstrap, sans quoi « tout binaire natif Air meurt par SIGSYS juste après ARCH_SET_FS », et l’autorisation d’exécuter son propre programme. Ce sont des faits sur toute cage posée avant un execve, pas sur le lancement. Le commentaire dit comment ils ont été trouvés : « Constaté en supervisant un vrai service pour la première fois, le 2026-08-14 : Started puis ChannelClosed, rien d’autre. »

Un fait de domaine logé chez un appelant se paie une fois par appelant, et dans la monnaie la plus chère : un processus qui meurt muet. Le prochain — le worker privsep d’air-sshd, le shell d’Air, une application tierce — le redécouvrira par le même SIGSYS sans trace noyau.

Tranché le 2026-08-22 (BDFL). La question ne portait pas sur « la cage par défaut d’une application » — une application empaquetée n’en a jamais, la sienne vient de son octroi. Elle portait sur la racine d’une chaîne, et la seule racine encore ouverte était la session de l’utilisateur.

Décision : le lanceur médie, la session ne plafonne pas (ADR-150 D12) — motif déjà implémenté par ADR-147 pour air-sshd. L’enveloppe de session est C + Landlock $HOME en lecture-écriture, /usr et /lib en lecture, sans réseau (D13) : 65 appels système sur 92.

air-sandbox n’a donc plus de dépendance de décision. Il reste à écrire, pas à instruire.

Le patron existe et a été éprouvé deux fois : air-uring et air-keystore ont été soldés le 2026-08-11. Manager additif, route parallèle maintenue, descellement unique en fin de campagne. On rejoue la méthode, on ne la réinvente pas.

Rang 2 — Les seconds chemins : la condition du contrat de dix ans

Seize entréesla mauvaise porte est celle qu’on emprunte — 4 fuites, 7 bridges, 3 vocabulaires impurs, 2 services consommés. Ce ne sont pas des sujets ouverts : ce sont des violations de règles déjà décidées (ADR-149 D5, D7, D9).

  • Quatre fuites de contrôleur vers la couche 2air-handle, air-poll, air-random, air-stdio, consommés directement par air-libc-*, air-sshd, air-keystore-cli. Soit ils deviennent des managers, soit leurs consommateurs passent par la bonne porte. Découvertes par le gate : l’audit manuel d’ADR-077 ne regardait pas le graphe de consommation.
  • Sept bridges qui court-circuitent le manager — et le registre le dit lui-même : « ils le font au nom des développeurs C, c’est-à-dire là où la surface est la plus stable et la plus visible ». C’est la non-conformité de libair_c : à la v1, elle ne doit s’appuyer que sur nos managers. Même exigence pour le PAL de la std Rust.
  • Trois vocabulaires impursair-base-core, air-config-schema, air-json exposent des opérations dans des crates qui ne devaient porter que des types.
  • Deux services qui exposent quand même une API (service-consomme, ADR-149 D7) — air-agent, dont air-sshd consomme le protocole en dépendance livrée, et air-launchd, consommé par air-launch-temoin en dev seulement. « Ni un démon ni un outil utilisateur n’a vocation à exposer une API réutilisable ; qu’une crate les LIE signifie qu’ils portent une bibliothèque qui mérite d’être extraite » (BDFL, 2026-08-05).

Rang 3 — Les frameworks applicatifs, rien n’est commencé

DomaineADRDépend de
TUI / console007 air-console, 008 air-tui, 026 contrat 1.0air-terminal (rang 1)
Vues / UI009 air-view/air-ui, 003 Wayland, 018 imagerie
Accessibilité017 — « citoyen de première classe »002 (modèle d’objet)
i18n016
Fondations développeur084 air-url

Le chaînage est l’argument : air-terminal débloque air-tui, qui débloque tout l’applicatif console.

Rang 4 — Sécurité active

  • ADR-089SecurityManager : aujourd’hui une réservation, pas une spécification. Décision BDFL du 2026-08-21 : la couture se pose dès les managers du rang 1. L’ajouter après coup exigerait de rouvrir huit surfaces publiques — donc de rompre le contrat qu’on vient d’établir.
  • ADR-156 (Landlock v7) et ADR-148 (namespaces) élargissent le confinement offert au tiers.

Ce qui est explicitement différé

La clôture d’air-sshd : ADR-119 (extensions SFTP), ADR-120 (hostbased), ADR-121 (provisioning), ADR-107 (pipeline linux-air), et le passage sous air-launchd. Ainsi que les additifs réseau/crypto 078 à 083, qui servent le même front.

Ce n’est pas un abandon : c’est l’ordre inverse. air-sshd sera refondé sur les managers une fois ceux-ci éprouvés, et son périmètre de test se réduira d’autant.

Critères d’acceptation d’un manager

Ce qu’une session doit rendre, et sur quoi une PR sera refusée :

  1. La surface du DOMAINE, pas celle de l’appelant. Un manager qui n’expose que les verbes qu’air-sshd appelle est un manager raté, même vert.
  2. Le type force la vérification : #[must_use] partout, Result là où ça peut échouer — jamais un bool, jamais un code, jamais une sentinelle. Newtypes qui rendent le mauvais paramètre incompilable (parse, don’t validate, Principe 4). Option<T> au lieu des sentinelles du noyau (ADR-021).
  3. Les erreurs restituent ce que le noyau a dit, au lieu de l’aplatir.
  4. Le refus est précis : nous sommes intransigeants sur les données, donc le message doit dire quoi est non conforme — sans quoi le développeur devine.
  5. Les chemins d’échec sont testés, et prouvés capables d’échouer : saboter la garde, montrer le test rouge, restaurer. Un test jamais vu rouge n’a rien démontré.
  6. Fuzzing sur toute API qui lit de l’externe (CLAUDE.md, non négociable).
  7. Les tests sont pédagogiques : fonctions utilitaires nommées, noms qui énoncent la propriété, commentaire disant ce qui casserait si la garde tombait. Nos tests sont le code que nous serons en droit d’attendre des développeurs.
  8. Doc-tests qui se lisent comme du code d’appelant — c’est le seul exemple que le compilateur vérifie.

Premier mouvement

MachineChantierPourquoi celui-là
hydrogenair-terminalAirTerminalManagerLe cas extrême (21 opérations), et la clé de tout l’applicatif texte
speedyair-accountAirAccountManagerLa plus grosse dette (38), et le domaine de l’identité
carbonVérification seuleÉtalon de couverture — jamais de production
raspi-srv-2Vérification aarch64Et la mesure du délai de « prêt » d’ADR-161 D6, non mesuré

Licence du document : MPL 2.0