ADR-077 — Managers de domaine en couche 1 (FileManager/NetworkManager/TerminalManager…) : surface objet médiatrice des toits (libc + PAL)
Statut : Accepté (2026-07-08, décision BDFL directe). Complète ADR-052 (objets couche 1), renforce la stratification (Principe 1). Encadre un descellement additif de la couche 1 (RFC, ADR-015/051/065).
Catégorie : Architecture des toits sur couche 1. Ajoute de l’API couche 1 (additif) ; n’altère aucune API existante.
Contexte
Règle non négociable : les toits (libc C-ABI, PAL std::sys) s’appuient EXCLUSIVEMENT sur la couche 1, jamais sur la couche 0 (air-sys-syscall). Seule la couche 1 parle à la couche 0.
Un audit (campagne libc-pour-std, chantier B) révèle deux crates libc qui violent la règle : air-libc-fileio (8 appels air_sys_syscall::{fs,process,ipc,system}) et air-libc-socketio (9 appels air_sys_syscall::net — codec sockaddr + sockopt, descellés en couche 0 pour la libc par ADR-070/071 : le pattern même à proscrire). Les 4 autres crates libc sont déjà propres.
Par ailleurs, la couche 1 est incomplète pour la surface visée : air-filesystem a une API riche AirFile (fd) mais pas les opérations par chemin (mkdir/unlink/rename/symlink/readlink/chmod/chown/access), ni chdir/getcwd ; air-socket/air-handle n’exposent pas le codec sockaddr ni les sockopt.
Décision
1. Ce qui manque en couche 1 s’implémente via une VRAIE API OBJET — des Managers de domaine. La couche 1 expose, par domaine, un objet Manager médiateur qui est LA surface consommée par les toits :
AirFileManager(air-filesystem) — tout l’I/O fichier : ouverture, ops par chemin (mkdir/unlink/rename/symlink/readlink/chmod/chown/access/hardlink/mkfifo/truncate/sync), répertoires, métadonnées par chemin,chdir/getcwd, fabrique de temporaires.AirNetworkManager(air-socket/air-handle) — tout le réseau : sockets, codecsockaddr↔ octets,sockopt, résolution de noms, transfert.AirTerminalManager(air-terminal) — termios/tty/PTY (cf. ADR-060/061).- … (par domaine : Process, Time…), au fil des besoins.
Le Manager prend/rend des types couche 1 (AirPath, Mode, AirResult, newtypes FD), jamais des types C. Il coordonne les briques existantes (AirFile, registre air-handle, AirSocket…) et la couche 0. La libc et le PAL bindent le Manager (le shim libc n’y ajoute que l’adaptation C-ABI : CStr↔AirPath, errno↔AirResult). Une brique couche 1 → 2 faces ([ADR-051] doctrine dual-face).
2. Correction en UN SEUL cycle de descellement. (a) Desceller la couche 1 une fois ; (b) implémenter les Managers manquants (AirFileManager, AirNetworkManager) et recâbler air-libc-fileio + air-libc-socketio dessus, en retirant leur dépendance air-sys-syscall ; (c) tests (barrière verte, couverture couche 1 à 100 %) ; (d) si OK, re-sceller la couche 1 une fois (couche-1-v1.x). Pas de descellements multiples en série.
Conséquences
- ADR-070/071 révisés en pratique : le codec
sockaddret lessockoptrestent en couche 0 (ils y sont légitimes comme wrappers typés), mais la libc ne les appelle plus directement — elle passe parAirNetworkManager(couche 1), qui, lui, peut consommer la couche 0. La frontière proscrite (libc→couche 0) disparaît. - Fondation des 71 symboles
std: la campagne libc-pour-stdbind désormais les Managers ; les ops manquantes s’ajoutent au Manager (couche 1), puis au shim — jamais un raccourci couche 0. - Coût : descellement + re-sceau couche 1 (additif, gouverné) ; extension d’
air-filesystem/air-socket(tests 100 %) ; recâblage de 2 crates libc (ABI C inchangée). - Réversibilité : purement additif côté couche 1 ; les toits gagnent une surface plus propre. Aucune API scellée retirée.
Alternatives rejetées
- Free-functions couche 1 éparses (au lieu de Managers objet) : rejeté — la directive BDFL exige une API objet cohérente par domaine (découvrabilité, invariants portés par l’objet, parité libc/PAL).
- Grand-fathering de
air-libc-fileio/socketio: rejeté (choix BDFL « remédier maintenant »). - Laisser la libc taper la couche 0 (statu quo ADR-070/071) : rejeté — casse la stratification, l’instrumentation et la doctrine dual-face.