This commit is contained in:
2026-07-23 16:37:12 +02:00
parent 99c345f2f2
commit 0da75c1311
2159 changed files with 230833 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
<!-- file: RUST_RULES.md -->
<!-- version: 3 -->
# Règles Rust générales
Ce fichier contient les règles normatives applicables à tous les projets Rust. Elles sont indépendantes de `khadhroony-bot2` 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.
## 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.
## Visibilité et API de crate
- Aucun `pub mod` n'est autorisé. Les modules restent privés et l'API est constituée par des réexports explicites.
- 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.