v0.1.0-pre.066

This commit is contained in:
2026-07-31 07:23:36 +02:00
parent 0befb170c7
commit 06fddf63b3
14 changed files with 70 additions and 50 deletions

145
docs/rules/RULES_RUST.md Normal file
View File

@@ -0,0 +1,145 @@
<!-- file: docs/rules/RULES_RUST.md -->
<!-- version: 7 -->
# Règles Rust générales
Ce fichier contient les règles normatives applicables à tous les projets Rust. Elles sont indépendantes de `khadhroony-bot3` et doivent pouvoir être réutilisées telles quelles dans un autre workspace.
## En-têtes et versions de fichiers
- Tout fichier texte qui supporte des commentaires commence par une ligne indiquant son chemin relatif dans le projet, puis une ligne `version` entière.
- La version d'un fichier est incrémentée à chaque modification après validation de sa version précédente.
- Les fichiers Rust utilisent `// file: ...` et `// version: N`.
- Les fichiers Markdown utilisent `<!-- file: ... -->` et `<!-- version: N -->`.
- Tous les fichiers texte se terminent par exactement une fin de ligne.
## Langue et documentation
- Les commentaires et rustdocs du code sont rédigés en anglais.
- Les documents Markdown du projet sont rédigés dans la langue documentaire choisie par le projet.
- Tout élément `pub` ou `pub(crate)` possède une rustdoc utile au point de déclaration.
- Toute réexportation `pub use` ou `pub(crate) use` dans `lib.rs` ou `main.rs` possède également sa propre rustdoc copiée ou reformulée de manière équivalente. La documentation du point d'entrée doit permettre de comprendre l'API sans ouvrir le module interne.
## Édition et lints obligatoires
- L'édition Rust cible est Rust 2024, sauf contrainte explicitement documentée.
- Chaque `lib.rs` et `main.rs` contient :
- `#![warn(missing_docs)]` ;
- `#![deny(unreachable_pub)]` ;
- `#![forbid(unsafe_code)]`.
- Les lints Clippy obligatoires sont déclarés au niveau workspace et hérités par toutes les crates.
- Les règles minimales sont : interdiction de `unwrap`, `expect`, `?`, retours implicites, code `unsafe`, APIs publiques inaccessibles et imports globaux non justifiés.
- Les tests peuvent disposer d'exceptions limitées pour `unwrap` et `expect` uniquement lorsqu'elles sont explicitement autorisées par la configuration Clippy.
La configuration workspace doit au minimum déclarer :
```toml
[workspace.lints.rust]
missing_docs = "warn"
unreachable_pub = "deny"
unsafe_code = "forbid"
[workspace.lints.clippy]
unwrap_used = "deny"
expect_used = "deny"
implicit_return = "deny"
needless_return = "allow"
useless_vec = "deny"
question_mark = "deny"
question_mark_used = "deny"
needless_match = "allow"
manual_ok_err = "allow"
manual_unwrap_or = "allow"
manual_map = "allow"
match_like_matches_macro = "allow"
single_match = "allow"
manual_unwrap_or_default = "allow"
manual_find = "allow"
explicit_counter_loop = "allow"
get_first = "allow"
implicit_saturating_sub = "allow"
```
## Formatage
- `cargo fmt --all` est exécuté après application de chaque delta ou correctif et avant les tests.
- Les fichiers Rust ne contiennent pas de lignes vides à l'intérieur d'une fonction, d'une structure, d'une énumération ou d'une implémentation courte.
- Les lignes vides séparent uniquement les fonctions, blocs `impl`, types et sections logiques.
- Les exports de `lib.rs` ou `main.rs` ne contiennent aucune ligne vide à l'intérieur d'une série homogène de `pub use` ou `pub(crate) use`.
- Les séries `pub use` et `pub(crate) use` forment deux groupes séparés lorsqu'elles coexistent.
- Le groupe `pub use` précède le groupe `pub(crate) use` dans une même façade.
- Lordre interne suit lordre naturel produit par `rustfmt` : les segments et mots séparés sont comparés avant leurs suffixes numériques, par exemple `U8` avant `U16` et `TOKEN` avant `TOKEN2022`.
## Assertions sur les collections
- Un test qui vérifie uniquement lappartenance à un ensemble peut trier la valeur obtenue et la valeur attendue avant `assert_eq!`, afin de ne pas dépendre dun ordre denregistrement non contractuel.
- Le tri doit être explicite dans le test et appliqué aux deux collections comparées.
- Ne jamais trier une collection lorsque lordre fait partie du contrat : comptes Solana, metas, instructions, signers, événements, étapes de pipeline, priorités, journaux ou toute autre séquence ordonnée.
## Imports et chemins
- `use` est interdit pour les constantes, fonctions, structures, énumérations, unions, alias de types, modules et macros.
- `use` est autorisé uniquement pour un trait lorsque la résolution de méthode, une macro de dérivation ou une contrainte de langage l'exige réellement.
- Un import de trait doit rester étroit et ne doit jamais importer simultanément des éléments non-traits par accolades.
- Les imports globaux, glob imports et imports groupés par accolades sont interdits.
- Pour un élément fourni par une crate externe au workspace, utiliser directement le chemin public le plus court exposé par cette crate. Exemple : utiliser `external_crate::Struct`, jamais `external_crate::module::Struct` si `external_crate::Struct` existe, et jamais `use external_crate::Struct`.
- Pour un élément `pub` déclaré dans le workspace :
- il est réexporté depuis le `lib.rs` ou `main.rs` de sa crate propriétaire ;
- depuis une autre crate, il est appelé via `owner_crate::Item` ;
- depuis sa propre crate, il est appelé via `crate::Item`, même depuis son module de déclaration.
- Pour un élément `pub(crate)` :
- il est réexporté depuis le `lib.rs` ou `main.rs` via `pub(crate) use` ;
- il est appelé via `crate::Item`, même depuis son module de déclaration.
- Un élément strictement privé à un module n'est pas réexporté et est appelé par son nom local uniquement. Il est interdit d'utiliser un chemin long comme `crate::module::helper` ou `owner_crate::module::helper` pour un helper privé du module courant.
- Dans un sous-module de tests, un élément privé du module parent est appelé via `super::Item`. Un élément `pub` ou `pub(crate)` continue dêtre appelé via le point dentrée de crate le plus court, par exemple `crate::Item`.
- Les exports ne sont jamais groupés avec des accolades. Un type, une fonction, une constante ou un alias correspond à une ligne de réexport distincte.
- Un réexport dun module interne commence par `self::`, y compris dans `lib.rs` ; `use crate::...` est réservé aux références qualifiées dans le code et ne sert pas à construire une façade.
- Les alias `as` sont interdits dans les réexports : le symbole reçoit son nom canonique dans son module propriétaire avant dêtre réexporté sans transformation.
- Un bloc homogène de `pub use` ou `pub(crate) use` ne contient aucune ligne vide et reste ordonné alphabétiquement par symbole réexporté lorsque `rustfmt` ne le réordonne pas.
## Visibilité et API de crate
- Aucun `pub mod` n'est autorisé. Les modules restent privés et l'API est constituée exclusivement par des réexports explicites depuis le point dentrée de la crate.
- Un élément `pub` inaccessible depuis le point d'entrée de sa crate est une erreur de conception, pas un simple avertissement.
- Un élément `pub(crate)` utilisé hors de son module est réexporté au niveau du point d'entrée de la crate.
- Les chemins internes de modules ne font pas partie de l'API stable.
- Les méthodes inhérentes publiques restent appelées via le type réexporté ; les fonctions libres publiques sont appelées via le point d'entrée de crate.
## Helpers et réutilisation
- Un helper répété dans plusieurs modules d'une même crate est déplacé dans un module commun explicite, généralement `helper.rs` ou un module spécialisé plus précis.
- Le nom `helpers.rs` ou `helper.rs` n'est utilisé que si aucune responsabilité métier plus précise ne convient.
- Un helper général réutilisable par plusieurs crates est déplacé dans une crate commune appropriée et exposé publiquement.
- Les types d'erreur généraux, identifiants de programme, primitives de validation et fonctions de sérialisation communes ne doivent pas être dupliqués entre crates.
- La mutualisation ne doit pas créer de dépendance cyclique ni déplacer un comportement métier spécifique dans une crate générique.
## Gestion des erreurs et contrôle de flux
- `unwrap`, `expect` et `panic` sont interdits dans le code de production.
- L'opérateur `?` est interdit dans les chemins de production ; utiliser des `match` explicites avec erreurs contextualisées.
- `anyhow` et `thiserror` ne sont pas utilisés par défaut.
- Les erreurs publiques sont typées lorsque leur contrat est stable ; les diagnostics dynamiques restent bornés.
- Les retours sont explicites conformément au lint `clippy::implicit_return`.
## Sécurité et dépendances
- Le code `unsafe` est interdit.
- Une dépendance n'est ajoutée que si elle est réellement utilisée dans le chemin de compilation concerné.
- Une dépendance utilisée uniquement dans les tests reste dans `[dev-dependencies]`.
- Les features sont minimales et explicites.
## Contrôle avant livraison
Chaque livraison Rust exécute au minimum, dans cet ordre :
```bash
cargo fmt --all
python3 scripts/audit_rust_general_rules.py
python3 scripts/audit_khadhroony_workspace_rules.py
cargo test --workspace
cargo clippy --workspace --all-targets
```
Un projet peut utiliser une sélection de tests plus étroite pendant le développement, mais la fermeture d'une version exige le contrôle global.
Le wrapper `python3 scripts/audit_rust_workspace_rules.py` exécute les deux audits sans fusionner leurs responsabilités.