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

Spec couche 1 — Format de source air-config (grammaire, design)

Spécification technique — Version 0.1 (design ; décision #1 d’air-config validée : format maison minimal, hand-rolled, zéro-dép, fuzzé). Couche 1. Companion de air-config.md.

Objet

Définit la grammaire du format de source qu’air-config-compile parse, valide contre un schéma Cap’n Proto (ADR-040), et compile en artefact binaire (ADR-033). C’est la forme canonique éditée par l’humain/le technicien (versionnable, diffable, greppable) — pas la forme runtime.

Principes de conception (et pourquoi)

  1. Schema-directed (l’idée maîtresse). Le schéma Cap’n Proto connaît les types. Le parseur ne fait donc aucune inférence de type : il lit des lexèmes et le compilateur les valide/convertit selon le type attendu par le schéma. Cela élimine d’un coup la classe d’ambiguïtés de TOML/YAML (dates, types inférés) → grammaire régulière, petite, fuzzable.
  2. Familier mais maison. Surface inspirée de TOML (sections, clé = valeur, tableaux) → l’admin reconnaît ; mais sous-ensemble strict hand-rollé (pas de dépendance toml/serde), sans les pièges de TOML (cf. exclusions §4).
  3. Défensif (Principe 3). UTF-8 validé, slicing borné get(), bornes anti-DoS (taille document, profondeur d’imbrication, longueur de ligne), arithmétique checked_* (entiers validés vs le type cible du schéma → rejet d’overflow), aucun panic sur octets arbitraires (fuzzé).
  4. Déterministe (ADR-025). L’ordre des clés dans la source n’affecte pas l’artefact (encodage canonique Cap’n Proto) → même source ⇒ artefact bit-pour-bit.
  5. Diagnostics qualité compilateur : ligne/colonne, type attendu (issu du schéma), suggestion (did-you-mean sur clés/valeurs d’enum).

Section 1 — Lexique

  • Commentaire : # jusqu’à fin de ligne.
  • Identifiant (clé, nom de section, valeur d’enum) : [A-Za-z][A-Za-z0-9_-]*.
  • Fin de ligne : \n (les \r finaux tolérés). Encodage UTF-8 obligatoire (sinon erreur de lexing, pas de panic).
  • Espaces : insignifiants hors chaînes.
  • Bornes (valeurs par défaut, configurables, anti-DoS) : document ≤ N Mio, ligne ≤ 64 Kio, profondeur de sections ≤ 32, longueur de tableau ≤ N. Dépassement → erreur diagnostiquée.

Section 2 — Structure

# En-tête OBLIGATOIRE : quel schéma + version cette source cible (évolution, ADR-040)
schema = "air.network@1"

# Affectation simple (clé = valeur)
ipv6_first = true

# Section = struct imbriqué du schéma ; chemin pointé autorisé
[resolver]
  timeout_ms = 5000
  servers = ["2001:db8::1", "192.0.2.1"]

[resolver.cache]            # sous-struct (chemin pointé)
  max_entries = 100_000

# Tableau de structs (liste de structs du schéma) — double crochet
[[rules]]
  name   = "allow-dns"
  action = allow            # valeur d'enum (identifiant nu, validé vs le schéma)
[[rules]]
  name   = "deny-all"
  action = deny
  • En-tête schema = "domaine@version" : obligatoire, première directive signifiante. Détermine le schéma de validation + la version (compat avant/arrière).
  • [section] ↔ struct/sous-struct (chemin pointé [a.b]).
  • [[liste]]List(Struct) (chaque bloc = un élément).
  • clé = valeur ↔ champ. Champ absent = non défini (défaut du schéma / optionnel).

Section 3 — Valeurs (lexèmes ; types résolus par le schéma)

Lexème sourceTypes schéma acceptés (validés par le compilateur)
true / falseBool
123, 0xFF, 1_000, -5Int8..64 / UInt8..64checked_* vs le type, rejet d’overflow/signe
1.5, 1e9Float32/64
"texte\n\u{1F600}" (guillemets, échappements définis)Text (UTF-8)
hex:"00ff…" ou b64:"…"Data (octets bruts)
nom_nuvaleur d’enum (validée vs les valeurs du schéma ; did-you-mean sinon)
[ v, v, … ]List(T)homogène, T donné par le schéma
(absent)champ optionnel non posé / défaut
  • Échappements de chaîne : ensemble défini et borné (\n \t \r \" \\ \u{...}) ; tout autre → erreur (pas d’interprétation permissive).
  • Sucre typé optionnel (à confirmer) : durées (5s, 250ms) et tailles (10MiB) reconnues uniquement si le champ schéma porte l’annotation correspondante → converties en entier par le compilateur. Sinon, entier nu. (Différable si jugé trop large pour v1.)

Section 4 — Exclusions volontaires (anti-pièges TOML, minimalisme)

Pour rester petit, non-ambigu, fuzzable :

  • Pas de dates/heures natives (le piège de TOML) → durées via sucre typé ci-dessus.
  • Pas de tables inline {…} → utiliser des sections.
  • Pas de tableaux hétérogènes → le schéma impose l’homogénéité.
  • Pas d’inférence de type → schema-directed.
  • Pas de clés dupliquées (erreur), pas de redéfinition de section.

Section 5 — Sémantique & déterminisme

  • Validation en amont (Principe 4) : chaque valeur convertie/validée vers le type schéma ; champ inconnu → erreur (did-you-mean) ; champ requis manquant → erreur.
  • Cascade (XDG, ADR-033) : fusion système < utilisateur au niveau de la source (fusion de documents typés), puis une seule compilation → artefact.
  • Déterminisme : l’artefact ne dépend pas de l’ordre des clés/sections de la source (ordre canonique d’encodage) → repro bit-pour-bit (gate repro, ADR-025).
  • Secrets (backend passwd/shadow, ADR-041) : les valeurs marquées « secret » dans le schéma sont zeroizées dans les tampons du parseur/compilateur après usage, jamais loggées dans les diagnostics (valeur élidée).

Section 6 — Stratégie de test

  • Fuzzing obligatoire : source arbitraire (octets) → parse ne panique jamais, ne produit jamais un AST invalide ; source + schéma → compile ne panique jamais.
  • Property-based : ordre des clés indifférent (artefact identique) ; round-trip source→artefact→relecture ; bornes respectées.
  • Diagnostics : tests d’erreurs (type incompatible, enum inconnue, champ requis manquant, overflow entier, UTF-8 invalide, profondeur/taille dépassée) → message ligne/colonne correct.
  • Conformité : un corpus de sources valides/invalides de référence (par domaine).

Décisions / à confirmer

  • Extension de fichier : .airconf (proposé) — à valider.
  • Sucre durées/tailles (§3) : inclus v1 ou différé ?
  • Multi-lignes de texte ("""…""") : utile pour certaines valeurs ? (sinon \n).
  • Inclusion de fichiers (include) : exclue v1 (surface + risques de cycle) — la cascade XDG couvre la composition.

Travail à reprendre

  • Définir les schémas .capnp des domaines v1 (cf. backends ADR-041 : resolver/hosts, systemd, passwd) — c’est l’autre pré-requis d’implémentation d’air-config.
  • Geler la grammaire ci-dessus en BNF complète + table de lexèmes avant codage du parseur.

Licence du document : MPL 2.0 Statut : design v0.1 — grammaire du format de source air-config (maison, schema-directed, fuzzé). À geler en BNF + définir les schémas .capnp avant implémentation. Bases : ADR-033 / ADR-040 / ADR-041 + spec air-config.