Files
pgr/docs/validation/003-RUST_EXPORT_COMPLETENESS.md
2026-09-25 00:36:24 +02:00

5.1 KiB

Audit facultatif de façade Rust et export completeness

Responsabilité

scripts/audit_rust_export_completeness.py contrôle un contrat Rust optionnel plus strict que les garanties du compilateur : les éléments publics durables d'un module fichier doivent être exposés par une façade explicite au crate-root, et le code de la même crate doit employer cette façade lorsqu'un réexport correspondant existe.

Le propriétaire normatif reste ../rules/510-RUST_CARGO.md. Le script ne définit pas une architecture à lui seul et ne doit être adopté que par un projet qui choisit ce contrat de façade.

L'audit émet seulement deux familles de diagnostics :

RUST-API-201
    élément `pub`, ou élément `pub(crate)` clairement consommé hors de son module fichier,
    sans réexport explicite correspondant au crate-root

RUST-IMPORT-201
    chemin interne long `crate::module::Item` alors que le crate-root expose déjà `crate::Item`

Il ne vérifie pas les règles générales de style, les lignes vides, l'ordre des constantes, la rustdoc, les lints Cargo/Clippy, la sûreté FFI ou le contenu métier.

Provenance et correction du corpus

KSP 0.3.16 et Games 0.3.5 contiennent un audit_rust_export_completeness.py dont le corps est identique à l'exception de sa révision de fichier. Cette convergence justifie l'extraction du concept, mais pas une copie littérale.

Le script historique découvre uniquement crates/*/Cargo.toml. Cette hypothèse couvre les 22 crates KSP situées directement sous crates/, mais elle ne couvre aucune des 23 crates Games organisées sous des sous-familles telles que crates/apps/, crates/common/ ou crates/engines/. Un résultat historique 0 candidate(s) dans Games ne constitue donc pas une preuve que ses crates avaient réellement été inspectées par cet audit.

La variante PGR corrige ce point en découvrant récursivement les packages Cargo possédant src/lib.rs ou src/main.rs, tout en ignorant les arbres générés usuels. Elle gère également correctement un module fichier mod.rs et les réexports explicites simples, groupés ou aliasés.

La réconciliation générateur réalisée pendant 0.0.5-alpha.5 donne avec la nouvelle découverte :

KSP 0.3.16   22 crate(s)   0 candidate(s)
Games 0.3.5  23 crate(s)   2 candidate(s)

Les deux candidats Games sont des constantes pub(crate) du smoke WebTransport navigateur consommées depuis d'autres modules sans façade crate-root. Games n'étant pas encore gouverné par PGR, ces signaux ne sont pas qualifiés de défauts rétroactifs ; ils montrent simplement ce qu'une adoption future de ce contrat devrait décider ou corriger.

Ce qui n'est pas repris du script historique

PGR n'importe pas les diagnostics historiques liés aux tests unitaires séparés (super::..., références non qualifiées) : leur validité dépend du layout et du contrat local des modules de test, et la baseline Games ne prouve pas une convergence opérationnelle sur ce point.

PGR n'importe pas non plus le contrôle d'un crate::Symbol non résolu. Le compilateur Rust est déjà propriétaire de la résolution de noms ; dupliquer cette erreur dans un audit Python n'apporte pas une preuve supplémentaire proportionnée.

L'audit PGR reste donc monotâche : façade crate-root et canonicalisation des chemins pour les seuls symboles qu'il sait relier explicitement.

Adoption

Pour adopter cette convention dans un projet Rust, copier :

scripts/_rust_audit_common.py
scripts/audit_rust_export_completeness.py

puis adapter les headers de fichiers au dépôt destinataire.

Commande canonique :

python3 -B scripts/audit_rust_export_completeness.py --root .

Le code de sortie est 0 lorsque le corpus est propre, 1 lorsqu'au moins un candidat est trouvé et 2 lorsque la racine est invalide, illisible ou ne contient aucune crate Rust détectable. --report-only permet une phase d'inventaire sans bloquer la gate ; --summary-only réduit la sortie aux comptes.

Une adoption progressive peut donc commencer par :

python3 -B scripts/audit_rust_export_completeness.py --root . --report-only

puis devenir bloquante une fois les exceptions ou écarts locaux explicitement résolus.

Limites

L'analyse est lexicale et non un parseur Rust complet. Elle vise les déclarations pub/pub(crate) au niveau racine de modules fichiers et les réexports explicites du crate-root. Les macros générant des items, attributs élaborés, modules inline complexes, #[path] non standard et formes de réexport imbriquées au-delà du contrat testé peuvent nécessiter une revue humaine ou les outils Rust du projet.

Un élément pub(crate) n'est exigé à la façade que lorsqu'une consommation externe au fichier est clairement détectée par un chemin crate::module::Item ou crate::Item. L'absence de diagnostic ne prouve donc pas toute la sémantique de visibilité de la crate.

L'audit ne remplace ni cargo check, ni Clippy, ni rustdoc. Il complète uniquement une convention architecturale explicitement choisie.