Ajouter une crate au workspace — les sept registres
Pourquoi ce guide existe. Ajouter une crate demande de l’inscrire à quatre endroits, plus deux fichiers qui lui appartiennent. Chacun est vérifié par un gate différent, et chaque gate ne signale que le sien : les découvrir un par un coûte un aller-retour de CI chacun. C’est arrivé le 2026-08-12 avec
air-bundle-cli— trois cycles perdus pour trois lignes.Ce n’est pas une lourdeur à supprimer : chacun de ces registres existe parce que son absence provoque un échec silencieux, pas une erreur de compilation. C’est justement pourquoi on ne les découvre pas tout seul.
La liste, à dérouler d’un coup
1. Cargo.toml racine — members
Sans lui, rien ne compile. C’est le seul des cinq qu’on ne peut pas oublier.
2. La façade de la couche — crates/air-layer-N/Cargo.toml
Deux ajouts : la dépendance elle-même, et la liste
[package.metadata.cargo-machete].ignored — une façade déclare des dépendances qu’elle
n’utilise pas, c’est sa raison d’être.
Ce que son absence provoque : en mesure par couche (-p crate), l’unification des
features de Cargo disparaît. Une crate absente de la façade sort du périmètre mesuré sans
que rien ne le dise — ni couverte, ni signalée comme non couverte. Constaté le 2026-08-10
sur AirCommand::confine, dont six tests d’intégration rendaient « 0 test exécuté » en
silence.
Gate : cargo xtask check-facades.
3. L’empaquetage — xtask/src/packaging.rs ou xtask/src/check_target.rs
Tout exécutable compilé pour *-unknown-linux-air doit être soit dans PACKAGES
(livrable .deb), soit dans UNPACKAGED_LINUX_AIR avec sa justification. Une
bibliothèque sans binaire n’est concernée par aucun des deux.
Ce que son absence provoque : un binaire que personne n’a décidé de livrer — ni packagé, ni justifié comme ne l’étant pas.
Gate : cargo xtask check-target.
4. L’exclusion de couverture — pour une CLI seulement
COV_IGNORE_LINES, dans xtask/src/couvrable_vide.rs et xtask/src/barrier.rs (les
deux : deux listes qui divergeraient donneraient deux verdicts).
Concerne le src/main.rs d’un exécutable qui ne fait que lire argv, composer
l’environnement système et rendre un code de sortie — non instrumentable en process, comme
air-keystore-cli/src/main.rs et air-account-cli/src/main.rs. Si le point d’entrée
contient de la logique, la bonne réponse est de la déplacer dans la bibliothèque, pas de
l’exclure.
5. L’index général — docs/INDEX.md
Régénérer : scripts/generer-index-general.py. L’index compte les crates par couche ;
une crate neuve le périme, et le contrôle --check fait échouer le job build.
Ce point manquait à ce guide jusqu’au 2026-08-21, alors que la section s’annonce comme
« la liste, à dérouler d’un coup ». Il a été découvert deux fois en CI le même jour — une fois
sur un changement de statut d’ADR, une fois sur l’ajout d’air-security (couche 1 :
34 → 35 crates). Un guide qui se dit complet et ne l’est pas coûte exactement ce qu’il promet
d’épargner : un aller-retour de CI.
Gate : scripts/generer-index-general.py --check, dans le workflow docs.
6. Cargo.lock — parce que la CI bâtit --locked
Une crate neuve ajoute une entrée au verrou. Si elle n’y est pas, tout job de build
échoue sur error: cannot update the lock file … because --locked was passed — trois
rouges pour une seule cause, dont aucun ne nomme le fichier. Régénérer avec un simple
cargo check --workspace, puis committer le verrou.
7. xtask/couverture-exemptions.toml — la référence du cliquet
Le cliquet de couverture refuse une crate qu’il ne connaît pas :
air-security : ABSENTE de la référence — une crate mesurée doit y figurer, sinon le cliquet ne la garde pas
Ce n’est pas une formalité : sans entrée, la crate n’est gardée par rien, et sa dette pourrait croître sans que personne le voie. Une crate neuve y entre à zéro :
[air-ma-crate]
sans_justification = 0
justifiees = 0
etat = "mesuree"
Le chiffre vient de la CI, pas d’une mesure locale — une mesure locale diverge du job
couverture-pr (root ou non, tests gatés présents ou absents). Pour une crate neuve, la
question ne se pose pas : elle naît à zéro, et c’est la seule valeur qu’elle ait le droit
de porter.
Les deux fichiers qui appartiennent à la crate
[package.metadata.air]dans son propreCargo.toml:layer,role(ADR-149 D9), ettarget = "linux-air"pour tout ce qui est livré (ADR-103). Etabi_zonesi — et seulement si — la crate porte un header C committé :stableengage dix ans (ADR-012),internaletexperimentallaissent évoluer.check-abirefuse une crate à header sans zone, et refuse aussi de l’ABAISSER par la suite.DEPENDENCIES.md(ADR-024) : chaque dépendance externe avec son pourcentage d’API utilisé et sa justification (règle des 80 %), chaque dépendance interne avec son arête de couche.
Le contrôle unique, avant de pousser
cargo xtask check-facades && cargo xtask check-target && cargo xtask check-layers \
&& cargo xtask check-abi && cargo machete && cargo check --workspace --all-targets \
&& scripts/generer-index-general.py --check
Ces quatre gates vivent dans le job supply-chain, qui est le plus rapide de la CI.
Les lancer en local coûte une minute ; les découvrir en CI coûte un cycle par gate,
parce que le job s’arrête au premier échec.
Licence du document : MPL 2.0