# Delta 0.1.1-pre.002 ## Base requise Commit de livraison attendu : ```text v0.1.1-pre.001-fix.002 ``` Le plan actif est `docs/plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md` version documentaire 4, incluant le réalignement du tableau des cas représentatifs effectué avant le commit du correctif précédent. ## Objectif Implémenter la première surface fonctionnelle de `ksp-core-lib` : le contrat commun ouvert `Error` / `Result` validé pendant `pre.001`. Cette tranche reste strictement bornée à l'erreur commune et n'ouvre aucune dépendance Solana ni aucun Program ID. ## Version Cargo `workspace.package.version` passe de : ```text 0.1.1-pre.1 ``` à : ```text 0.1.1-pre.2 ``` L'identifiant Cargo respecte SemVer sans zéro initial ; l'identifiant de livraison reste `0.1.1-pre.002`. Le header de `Cargo.toml` passe de version 18 à 19. ## Fichiers ajoutés - `crates/ksp-core-lib/src/error.rs` - `crates/ksp-core-lib/unit_tests/error.rs` - `crates/ksp-core-lib/tests/public_api.rs` - `deltas/0.1.1/pre.002.md` ## Fichiers modifiés - `Cargo.toml` - `crates/ksp-core-lib/src/lib.rs` - `docs/plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md` ## Fichiers supprimés Aucun. ## Contrat implémenté ### `ErrorCode` `ErrorCode` contient uniquement : ```text domain: &'static str code: &'static str ``` Décisions : - `ErrorCode::new(...)` est `const` afin que chaque crate supérieure puisse définir ses propres codes statiques ; - Core ne possède aucune enum centrale des domaines ; - `domain()` et `code()` exposent les deux identifiants stables ; - `ErrorCode` est `Copy`, `Clone`, `Eq`, `PartialEq`, `Hash` et `Debug` parce qu'il ne contient que deux chaînes statiques. ### `ErrorContext` `ErrorContext` contient : ```text key: &'static str value: String ``` Le contexte conserve son ordre d'insertion dans `Error`. L'API publique expose `ErrorContext::new(...)`, `key()` et `value()`. ### `Error` `Error` contient : ```text code: ErrorCode message: String context: Vec source: Option> ``` Décisions stabilisées : - `Error::new(...)` construit l'erreur minimale ; - `with_context(...)` consomme `self`, ajoute un champ puis retourne l'erreur enrichie ; - `with_source(...)` suit le même modèle pour une cause externe ; - aucune méthode mutable publique parallèle n'est ajoutée ; - aucune conversion générique `From` n'est introduite ; - `Error` ne dérive pas `Clone`, `Eq` ou `PartialEq`, afin de ne pas affaiblir le support d'une vraie cause externe ; - `Error` implémente `std::fmt::Display` et `std::error::Error` ; - le rendu `Display` est exactement : ```text .: ``` Le contexte et la chaîne de causes ne sont pas injectés automatiquement dans ce rendu. ### `Result` La façade expose : ```text ksp_core_lib::Result = std::result::Result ``` ## Façade Core `crates/ksp-core-lib/src/lib.rs` ouvre le module d'implémentation en privé puis réexporte explicitement : ```text ksp_core_lib::Error ksp_core_lib::ErrorCode ksp_core_lib::ErrorContext ksp_core_lib::Result ``` Aucun `pub mod` n'est introduit. ## Dépendances Aucune dépendance n'est ajoutée à `ksp-core-lib` pendant cette tranche. En particulier, `pre.002` n'introduit ni `thiserror`, ni `anyhow`, ni crate Solana, ni codec wire. ## Tests ajoutés ### Tests unitaires externes `crates/ksp-core-lib/unit_tests/error.rs` vérifie : - conservation de `domain` et `code` ; - possibilité de déclarer un `ErrorCode` constant ; - conservation des champs `ErrorContext` ; - conservation du message et de l'ordre du contexte ; - rendu exact de `Display` ; - absence du contexte et de la cause dans le rendu ; - conservation de la cause via `std::error::Error::source()` ; - propriété `Send + Sync` de l'erreur commune. Le fichier est rattaché au module privé de production via `#[cfg(test)]` et `#[path = "../unit_tests/error.rs"]`. ### Test d'intégration `crates/ksp-core-lib/tests/public_api.rs` consomme exclusivement la façade crate-root et vérifie que `Error`, `ErrorCode`, `ErrorContext` et `Result` sont utilisables depuis une crate externe. ## Documentation de plan Le plan passe de version documentaire 4 à 5 afin de remplacer les deux questions désormais résolues par les décisions réellement implémentées : - `with_context(...)` consomme `self` ; - `Display` utilise la forme stable `.: `. Les questions `pre.003` concernant `solana-pubkey` restent ouvertes et inchangées. ## Validations exécutées Dans l'environnement de préparation : - reconstruction de la base `0.1.1-pre.001-fix.002` depuis la release `0.0.3` et les deltas successifs ; - prise en compte de la version 4 du plan fournie après réalignement manuel du tableau ; - contrôle du périmètre des fichiers modifiés/ajoutés ; - parsing TOML statique du manifest racine ; - contrôle des headers `file:` / `version:` et des fins de ligne des fichiers livrés ; - recherche statique des usages interdits `unsafe`, `unwrap`, `expect`, `panic` et opérateur `?` dans le code de production ajouté ; - contrôle de l'absence de `use` dans le code Rust ajouté ; - contrôle de l'absence de nouvelle dépendance Cargo. ## Validations non exécutées L'environnement de préparation ne contient ni `cargo` ni `rustc`. Les commandes suivantes n'ont donc pas pu être exécutées ici : ```bash cargo fmt --all cargo check --workspace cargo test --workspace cargo clippy --workspace --all-targets ``` Elles doivent être exécutées sur le dépôt réel avant validation du commit. Aucun succès Cargo n'est déclaré par ce delta. ## Décisions prises - Le contrat Error/Result ouvert de `pre.001` est retenu sans enum centrale de domaines. - `ErrorCode::new(...)` est `const`. - Les champs des types publics restent privés et sont accessibles par API explicite. - Le contexte est ordonné et enrichi par consommation de `self`. - La cause standard est conservée avec les bornes `Error + Send + Sync + 'static`. - `Display` est volontairement court et stable ; Logging décidera plus tard comment exploiter contexte et causes. - Core ne possède aucune conversion vers les erreurs des domaines supérieurs. ## Questions ouvertes Aucune question bloquante pour `pre.002`. Les questions relatives à `Pubkey`, aux Program IDs et à leur registre restent réservées à `0.1.1-pre.003` conformément au plan actif.