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-040 — Format de l’artefact binaire de configuration : Cap’n Proto

Statut : Accepté (2026-06-25, validé par le BDFL). Companion d’ADR-033 (modèle de configuration : source typée → compilateur → artefact binaire). Tranche la question laissée ouverte par ADR-033 §4 (« famille Cap’n Proto / FlatBuffers / protobuf, à auditer sous la règle des 80 % »). Cohérent avec ADR-001 (AirCom encode déjà en Cap’n Proto), ADR-024 (règle des 80 %), ADR-025 (builds reproductibles) et le Principe 9 (budget runtime sur matériel modeste).

Catégorie : Architecture (transverse — air-config, couche 1).

Contexte

ADR-033 a posé le modèle : la configuration Air a pour source de vérité une source typée validée par un compilateur de config, qui en dérive un artefact binaire reproductible consommé par le runtime ; le texte (JSON/YAML/TOML) n’est qu’une projection. Le format de cet artefact binaire restait à choisir, sous trois exigences d’ADR-033 §4 :

  • schema-first à évolution intégrée (numérotation de champs, optionnalité — compat avant/arrière par construction) ;
  • version de schéma + checksum (corruption détectée, jamais lue en silence) ;
  • lecture zéro-copie / mmap privilégiée (budget runtime, Principe 9 — important au boot, en particulier sur Raspberry Pi).

ADR-033 rejette déjà le format binaire maison sans politique d’évolution (dette de schéma sur 20 ans). Restaient trois candidats éprouvés : Cap’n Proto, FlatBuffers, protobuf.

Décision

L’artefact binaire de air-config est encodé en Cap’n Proto.

Comparaison :

Critère (ADR-033 §4)Cap’n ProtoFlatBuffersprotobuf
Zéro-copie / mmap✅ natif✅ natif❌ decode + alloc à chaque lecture
Évolution de schéma
Coût lecture (boot, Pi)très faibletrès faibleparse + alloc
Déjà adopté dans AirAirCom (ADR-001)

Deux raisons, dont une décisive :

  1. Cohérence projet (décisive). Air s’engage déjà sur Cap’n Proto pour AirCom (ADR-001). Réutiliser le même langage de schéma, la même chaîne de codegen et la même dépendance pour la configuration donne un seul modèle mental et une seule dépendance à auditer sur tout le stack — un atout majeur sur l’horizon 20 ans. La dépendance Cap’n Proto étant de toute façon justifiée pour AirCom, air-config la réutilise sans coût d’exception supplémentaire (l’audit règle-des-80 % est partagé).
  2. Zéro-copie / mmap (ADR-033 §4, Principe 9) : on mmap l’artefact compilé et on lit les champs sans parser — gain réel au boot sur matériel modeste.

Écartés : protobuf — pas zéro-copie (decode + allocation à chaque lecture), contraire au §4 et au Principe 9. FlatBuffers — techniquement équivalent (zéro-copie), mais introduit un second écosystème alors que Cap’n Proto est déjà adopté ; ne serait préféré que si l’audit révélait capnp (Rust) nettement pire sous la règle des 80 % et qu’AirCom abandonnait Cap’n Proto.

Conséquences

  • Audit règle des 80 % (ADR-024) : exception nommée à acter pour la crate Cap’n Proto Rust (capnp), partagée avec AirCom (à consigner dans docs/EXCEPTIONS.md au moment de l’implémentation, conjointement avec la spec AirCom — cf. ADR-001). On n’utilisera qu’une fraction de l’API, mais la dépendance est mutualisée et son adoption est large.
  • Placement de crate (à trancher au cadrage air-config). ADR-033 situe le cœur dans air-base-lib. Faire tirer Cap’n Proto par air-base-lib — la crate la plus consommée — l’alourdirait. Recommandation : air-config en crate dédiée (couche 1) pour ne pas imposer Cap’n Proto à tout consommateur d’air-base-lib. Décision formelle reportée à la spec de composant.
  • Version + checksum dans l’artefact (ADR-033 §4) : portés par l’en-tête de l’artefact, vérifiés à l’ouverture (corruption → erreur, jamais lecture silencieuse).
  • Reproductibilité (ADR-025) : l’encodage Cap’n Proto doit être déterministe (ordre des champs stable, pas de padding non initialisé exposé) — à vérifier par le gate cargo xtask repro.

Hors périmètre (traités ailleurs)

  • La projection / les backends d’émission vers le monde C-Unix (régénération des fichiers texte /etc lus par la libc et les services Unix classiques — resolv.conf, nsswitch.conf, hosts, unit files systemd…), de sorte que ces fichiers deviennent des artefacts générés (lecture seule), jamais édités à la main : c’est le modèle de backends d’ADR-033 §7, à détailler dans la spec air-config (et au-delà de systemd). Cet ADR ne fixe que le format de l’artefact binaire Air-natif, pas la stratégie de coexistence /etc.
  • Le langage de la source typée et l’ergonomie du compilateur (diagnostics, GUI contrainte par schéma) : spec air-config.

Adoption

Édition documentaire immédiate (ADR-040 + registre/INDEX/SUMMARY). La spec de composant air-config (couche 1) détaillera : schéma Cap’n Proto de la config, en-tête version+ checksum, backends d’émission (dont coexistence /etc pour la libc/legacy), placement de crate, et l’exception EXCEPTIONS.md partagée avec AirCom.

Addendum (2026-06-25) — outil de compilation de schéma : exigence build-time + code généré committé

Constat (vérifié empiriquement sur l’arbre réel, capnp/capnpc v0.26).

  • Runtime — propre. Le crate capnp (runtime, linké dans les binaires Air) a ZÉRO dépendance, pur Rust, no_std-capable. Aucun C linké ; check-c-surface (zéro surface C/C++) n’est pas affecté.
  • Build-time — exige le binaire C++ capnp. Le codegen capnpc est un backend qui shelle vers le front-end C++ capnp pour parser les schémas .capnp (échec cargo build sans le tool : « Please verify that version 0.5.2 or higher of the capnp executable is installed »). Ce n’est pas propre à Cap’n Proto — FlatBuffers exige flatc, protobuf protoc (sauf prost+protox) ; les formats schema-first binaires ont tous un compilateur de schéma. Cela ne renverse donc pas la décision (Cap’n Proto conserve l’avantage zéro-copie + cohérence AirCom).

Décision (gravée) — politique « code généré committé ».

  1. Les schémas .capnp sont versionnés dans le repo.
  2. Un mainteneur (disposant du tool C++ capnp, version pinnée, ADR-025) régénère le code Rust uniquement quand un schéma change, et commite le .rs généré.
  3. Les builds normaux et la CI consomment le .rs committé → aucun tool C++ requis ; le build reste pur-Rust, cargo-only, reproductible. Le .rs généré ne dépend que du crate capnp runtime (propre).
  4. Le binaire C++ capnp est donc confiné à une opération mainteneur rare (changement de schéma), documentée et version-pinnée — hors du chemin de build critique et hors CI.

Portée. Ce constat et cette politique valent identiquement pour AirCom (ADR-001, qui encode aussi en Cap’n Proto) : régler une fois pour les deux (à consigner aussi dans la spec AirCom). L’exigence du tool C++ au build — et la politique de code généré committé — seront détaillées dans la spec air-config (et la spec AirCom), avec le mode de pinning du tool (ADR-025).