Files
khadhroony-solana-project/docs/rules/RULES_RUST.md

8.6 KiB
Raw Blame History

Règles Rust générales

Portée

Les règles RUST-* s'appliquent aux crates, sources, tests, exemples et outils Rust de KSP. Elles sont conçues pour rester réutilisables hors de KSP lorsque la règle ne dépend pas de son architecture.

Édition et lints

  • RUST-BASE-001 — L'édition Rust est Rust 2024, sauf contrainte externe explicitement documentée.
  • RUST-BASE-002 — Chaque lib.rs et main.rs contient #![warn(missing_docs)], #![deny(unreachable_pub)] et #![forbid(unsafe_code)].
  • RUST-BASE-003 — Les lints communs sont déclarés au niveau workspace et hérités par les crates.
  • RUST-BASE-004 — Le code unsafe est interdit.

Documentation des API

  • RUST-DOC-001 — Tout élément pub ou pub(crate) possède une rustdoc utile au point de déclaration.
  • RUST-DOC-002 — Toute réexportation pub use ou pub(crate) use dans lib.rs ou main.rs possède également une rustdoc utile.
  • RUST-DOC-003 — La façade d'une crate doit permettre de comprendre son API sans dépendre de ses chemins de modules internes.

Imports et chemins

  • RUST-IMPORT-001use est interdit pour les constantes, fonctions, structures, énumérations, unions, alias de types, modules et macros.
  • RUST-IMPORT-002use est autorisé uniquement pour un trait lorsque la résolution de méthode, une macro de dérivation ou une contrainte du langage l'exige réellement.
  • RUST-IMPORT-003 — Un import de trait reste étroit et ne mélange pas de non-traits dans un import groupé.
  • RUST-IMPORT-004 — Les glob imports et imports groupés par accolades sont interdits.
  • RUST-IMPORT-005 — Pour un élément externe, utiliser directement le chemin public le plus court fourni par la crate propriétaire.
  • RUST-IMPORT-006 — Pour un élément pub d'une crate KSP, l'API est réexportée au crate-root et consommée depuis une autre crate via owner_crate::Item.
  • RUST-IMPORT-007 — Dans sa propre crate, un élément pub ou pub(crate) partagé est consommé via crate::Item après réexport approprié.
  • RUST-IMPORT-008 — Un helper strictement privé au module reste privé et est appelé localement ; dans un sous-module de tests, un élément privé du module parent est appelé via super::Item.
  • RUST-IMPORT-009 — Les réexports ne sont pas groupés par accolades et les alias as sont interdits dans les réexports.
  • RUST-IMPORT-010 — Un réexport d'un module interne commence par self::.

Visibilité et façade de crate

  • RUST-API-001 — Aucun pub mod n'est autorisé ; les modules restent privés et l'API externe est constituée par des réexports explicites au crate-root.
  • RUST-API-002pub(in ...) et pub(super) sont interdits.
  • RUST-API-003 — Un élément pub inaccessible depuis la façade de sa crate est une erreur de conception.
  • RUST-API-004 — Un élément pub(crate) utilisé hors de son module est réexporté au crate-root via pub(crate) use.
  • RUST-API-005 — Les chemins internes de modules ne constituent pas une API stable.

Contrôle de flux et erreurs

  • RUST-ERR-001unwrap, expect et panic sont interdits dans le code de production.
  • RUST-ERR-002 — L'opérateur ? est interdit dans le code de production ; les chemins d'erreur utilisent un contrôle de flux explicite.
  • RUST-ERR-003 — Les retours sont explicites conformément au lint clippy::implicit_return.
  • RUST-ERR-004anyhow et thiserror ne sont pas utilisés par défaut ; leur introduction exige une justification architecturale.
  • RUST-ERR-005 — Les erreurs publiques sont typées lorsque leur contrat est stable.
  • RUST-ERR-006 — Les tests peuvent utiliser unwrap ou expect uniquement dans la limite explicitement autorisée par la configuration Clippy.
  • RUST-ERR-007 — Avant dattacher une erreur externe comme source de ksp_core_lib::Error, la crate propriétaire vérifie que sa chaîne Debug/source ne peut pas exposer de secret ou de donnée sensible. Lorsquune dépendance fournit une primitive de neutralisation, elle est appliquée avant with_source; en particulier une reqwest::Error issue dune requête vers un endpoint potentiellement credential-bearing est attachée uniquement après without_url().

Formatage

  • RUST-FMT-001rustfmt.toml à la racine est la configuration canonique du formatage Rust.
  • RUST-FMT-002cargo fmt --all est exécuté après chaque modification Rust avant les validations de compilation et de test.
  • RUST-FMT-003 — Les fichiers Rust ne contiennent pas de lignes vides à l'intérieur d'une fonction, structure, énumération ou implémentation courte.
  • RUST-FMT-004 — Les lignes vides séparent uniquement des fonctions, types, blocs impl ou sections logiques distinctes.
  • RUST-FMT-005 — Les groupes homogènes de pub use ou pub(crate) use ne contiennent pas de ligne vide interne ; pub use précède pub(crate) use lorsqu'ils coexistent.

Helpers et duplication

  • RUST-HELP-001 — Un helper répété dans plusieurs modules d'une même crate est déplacé dans un module commun dont le nom décrit la responsabilité la plus précise possible.
  • RUST-HELP-002 — Un helper réellement général et réutilisable par plusieurs crates est déplacé dans la bibliothèque KSP appropriée.
  • RUST-HELP-003 — La mutualisation ne doit pas créer de dépendance cyclique ni déplacer une logique métier spécifique dans une bibliothèque générique.

Dépendances

  • RUST-DEP-001 — Une dépendance n'est ajoutée que si elle est réellement utilisée dans le chemin de compilation concerné.
  • RUST-DEP-002 — Une dépendance uniquement utilisée par les tests reste dans [dev-dependencies].
  • RUST-DEP-003 — Les features sont minimales et explicites.
  • RUST-DEP-004 — Les lockfiles de dépendances ne sont pas versionnés dans KSP.
  • RUST-DEP-005 — KSP privilégie les versions récentes compatibles. Toute version volontairement contrainte ou ancienne doit être documentée avec sa raison et la condition permettant de lever la contrainte.

Assertions de collections

  • RUST-TEST-001 — Un test vérifiant uniquement l'appartenance à un ensemble peut trier les valeurs obtenues et attendues avant assert_eq! lorsque l'ordre n'est pas contractuel.
  • RUST-TEST-002 — Une collection n'est jamais triée artificiellement dans un test lorsque l'ordre fait partie du contrat, notamment pour comptes Solana, metas, instructions, signers, événements, étapes de pipeline, priorités ou journaux ordonnés.

Organisation des tests

  • RUST-TEST-003 — Les sources de tests unitaires sont placées autant que possible dans un répertoire unit_tests/ à la racine de la crate et reflètent autant que possible l'arborescence et les noms des modules sous src/.
  • RUST-TEST-004 — Un fichier sous unit_tests/ reste un vrai test unitaire : il est rattaché explicitement sous #[cfg(test)] au module de production qu'il teste et peut donc tester ses éléments privés.
  • RUST-TEST-005 — Le répertoire Cargo standard tests/ est réservé aux tests d'intégration. Les fichiers qui y sont découverts comme cibles d'intégration testent la crate comme un consommateur externe et n'utilisent que son API publique.
  • RUST-TEST-006 — Toute partie pertinente de l'API publique d'une bibliothèque KSP doit, lorsque cela est techniquement possible, être couverte par de vrais tests d'intégration sous tests/, afin de valider notamment les réexports, la visibilité et le contrat réellement consommable depuis une autre crate.
  • RUST-TEST-007 — La séparation physique sous unit_tests/ est la convention préférée et doit être utilisée au maximum. La colocalisation d'un test unitaire dans le fichier/module de production n'est autorisée qu'en dernier recours lorsqu'un rattachement externe serait techniquement impossible, incorrect ou créerait une complexité disproportionnée clairement justifiable.
  • RUST-TEST-008 — Un test unitaire séparé suit autant que possible le même chemin relatif et le même nom que le module testé, afin que la correspondance src/...unit_tests/... soit immédiatement identifiable.

Contrôle de clôture Rust

Lorsqu'une tranche contient du Rust, les contrôles minimaux sont :

cargo fmt --all
cargo check --workspace
cargo test --workspace
cargo clippy --workspace --all-targets

Les audits structurels automatisés seront ajoutés lorsqu'ils existeront dans KSP ; une règle ne doit pas prétendre qu'un script inexistant a été exécuté.