From 99477d0d2bc69b8a9cd7a1d1b3537a4a5ceac0c2 Mon Sep 17 00:00:00 2001 From: SinuS Von SifriduS Date: Fri, 28 Aug 2026 04:31:32 +0200 Subject: [PATCH] v0.2.13-pre.002 --- Cargo.toml | 6 +- crates/ksp-interface-lib/Cargo.toml | 14 ++ crates/ksp-interface-lib/README.md | 32 +++ crates/ksp-interface-lib/USAGE.md | 24 ++ crates/ksp-interface-lib/src/lib.rs | 16 ++ .../tests/dependency_boundary.rs | 79 +++++++ crates/ksp-interface-lib/tests/public_api.rs | 15 ++ deltas/0.2.13/pre.002.md | 205 ++++++++++++++++++ docs/plans/020-V0_2_13_INTERFACE_PLAN.md | 16 +- docs/validation/016-V0_2_13_INTERFACE.md | 50 +++-- 10 files changed, 434 insertions(+), 23 deletions(-) create mode 100644 crates/ksp-interface-lib/Cargo.toml create mode 100644 crates/ksp-interface-lib/README.md create mode 100644 crates/ksp-interface-lib/USAGE.md create mode 100644 crates/ksp-interface-lib/src/lib.rs create mode 100644 crates/ksp-interface-lib/tests/dependency_boundary.rs create mode 100644 crates/ksp-interface-lib/tests/public_api.rs create mode 100644 deltas/0.2.13/pre.002.md diff --git a/Cargo.toml b/Cargo.toml index 4d893e9..00179f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 303 +# version: 304 [workspace] resolver = "3" -members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] +members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.13-pre.1" +version = "0.2.13-pre.2" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-interface-lib/Cargo.toml b/crates/ksp-interface-lib/Cargo.toml new file mode 100644 index 0000000..979b560 --- /dev/null +++ b/crates/ksp-interface-lib/Cargo.toml @@ -0,0 +1,14 @@ +# file: crates/ksp-interface-lib/Cargo.toml +# version: 1 + +[package] +name = "ksp-interface-lib" +version.workspace = true +edition.workspace = true +repository.workspace = true + +[dependencies] +ksp-core-lib = { path = "../ksp-core-lib" } + +[lints] +workspace = true diff --git a/crates/ksp-interface-lib/README.md b/crates/ksp-interface-lib/README.md new file mode 100644 index 0000000..ab9dea4 --- /dev/null +++ b/crates/ksp-interface-lib/README.md @@ -0,0 +1,32 @@ + + + +# ksp-interface-lib + +`ksp-interface-lib` est la façade KSP destinée aux contrats wire passifs des programmes Solana. Elle est conçue pour être consommée par les implémentations Program officielles ou externes sans absorber Transport, Wallet, Store, Config ni le comportement métier Program. + +## Ownership + +La crate réutilise les primitives fondamentales déjà possédées par `ksp-core-lib`, notamment `Pubkey`. Les Program IDs fondamentaux restent également dans Core. Interface possédera progressivement les layouts, discriminants, codecs et constructeurs wire uniquement lorsqu'un protocole réel les exige. + +La foundation ne dépend pas de runtime réseau ou applicatif. Elle n'ajoute donc pas de logging runtime, de scheduler, de persistence ou de configuration. + +## Surface initiale + +La façade crate-root expose actuellement le `Pubkey` canonique de Core. Les contrats passifs d'instruction et d'account meta sont introduits séparément afin de fermer leurs bornes et leur surface publique avant les premières APIs Program. + +## Frontières + +`ksp-interface-lib` ne possède pas : + +```text +RPC / WebSocket / gRPC +wallet / signature +persistence / Store +Config / environnement +interprétation métier Program +execution policy +lifecycle réseau +``` + +La conception détaillée de la foundation est suivie dans [`../../docs/plans/020-V0_2_13_INTERFACE_PLAN.md`](../../docs/plans/020-V0_2_13_INTERFACE_PLAN.md) et sa validation dans [`../../docs/validation/016-V0_2_13_INTERFACE.md`](../../docs/validation/016-V0_2_13_INTERFACE.md). diff --git a/crates/ksp-interface-lib/USAGE.md b/crates/ksp-interface-lib/USAGE.md new file mode 100644 index 0000000..a98836e --- /dev/null +++ b/crates/ksp-interface-lib/USAGE.md @@ -0,0 +1,24 @@ + + + +# Usage de ksp-interface-lib + +Cette page décrit la surface publique actuellement matérialisée par la foundation Interface. Les APIs d'instruction sont ajoutées progressivement sans exposer les modules internes. + +## Utiliser le Pubkey canonique + +Interface réexporte le `Pubkey` possédé par Core afin que les futurs contrats wire puissent partager la même primitive sans wrapper parallèle : + +```rust +let program_id = ksp_interface_lib::Pubkey::default(); +let bytes = program_id.to_bytes(); +assert_eq!(bytes.len(), 32); +``` + +Un consumer ne doit pas reconstruire une identité Program textuelle propre à Interface. Les Program IDs fondamentaux restent possédés et répertoriés par `ksp-core-lib`. + +## Surface volontairement absente + +La foundation initiale n'expose encore aucun constructeur d'instruction fonctionnel. Elle ne fournit pas non plus de codec générique Borsh/Wincode, de sérialisation Serde, de transport ou de comportement Program. Ces surfaces sont ajoutées uniquement lorsque leur contrat réel est matérialisé et borné. + +Aucun runtime logging n'est nécessaire pour les contrats passifs actuels ; une future instrumentation comportementale devrait passer par `ksp-logging-lib` selon les règles KSP au lieu d'introduire `tracing` directement. diff --git a/crates/ksp-interface-lib/src/lib.rs b/crates/ksp-interface-lib/src/lib.rs new file mode 100644 index 0000000..2d3072f --- /dev/null +++ b/crates/ksp-interface-lib/src/lib.rs @@ -0,0 +1,16 @@ +// file: crates/ksp-interface-lib/src/lib.rs +// version: 1 + +#![warn(missing_docs)] +#![deny(unreachable_pub)] +#![forbid(unsafe_code)] + +//! Passive wire contracts shared by KSP Program implementations. +//! +//! The foundation deliberately starts with the canonical Solana [`Pubkey`] +//! owned by `ksp-core-lib`. Program-facing instruction contracts are added in +//! later slices without introducing runtime, transport, persistence or Program +//! behavior into Interface. + +/// Canonical Solana account address primitive owned by `ksp-core-lib`. +pub use ksp_core_lib::Pubkey; diff --git a/crates/ksp-interface-lib/tests/dependency_boundary.rs b/crates/ksp-interface-lib/tests/dependency_boundary.rs new file mode 100644 index 0000000..2d03807 --- /dev/null +++ b/crates/ksp-interface-lib/tests/dependency_boundary.rs @@ -0,0 +1,79 @@ +// file: crates/ksp-interface-lib/tests/dependency_boundary.rs +// version: 1 + +//! Dependency and passive-surface canaries for the Interface scaffold. + +#[test] +fn pre_002_manifest_has_exact_core_only_runtime_dependency() { + let manifest = include_str!("../Cargo.toml"); + let dependencies_tail = manifest.split("[dependencies]").nth(1); + assert!(dependencies_tail.is_some(), "Interface dependencies section must exist"); + let dependencies_tail = match dependencies_tail { + std::option::Option::Some(value) => value, + std::option::Option::None => return, + }; + let dependencies = match dependencies_tail.split("[lints]").next() { + std::option::Option::Some(value) => value, + std::option::Option::None => return, + }; + assert_eq!(manifest_dependency_names(dependencies), std::vec!["ksp-core-lib"]); + for forbidden in [ + "ksp-config-lib", + "ksp-logging-lib", + "ksp-offchain-transport-lib", + "ksp-onchain-transport-lib", + "ksp-program-api", + "ksp-program-lib", + "ksp-store-api", + "ksp-store-lib", + "ksp-wallet-lib", + "borsh", + "bincode", + "reqwest", + "serde", + "serde_json", + "solana-instruction", + "tauri", + "tokio", + "tonic", + "tracing", + "wincode", + ] { + assert!(!dependencies.contains(forbidden), "forbidden Interface dependency detected: {forbidden}"); + } + return; +} + +#[test] +fn pre_002_scaffold_remains_passive_without_runtime_logging_surface() { + let crate_root = include_str!("../src/lib.rs"); + assert!(crate_root.contains("pub use ksp_core_lib::Pubkey;")); + assert!(!crate_root.contains("ProgramAccountMeta")); + assert!(!crate_root.contains("ProgramInstruction")); + assert!(!crate_root.contains("TRACING_TARGET")); + assert!(!crate_root.contains("ksp_logging_lib")); + assert!(!std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src/constants.rs").exists()); + return; +} + +fn manifest_dependency_names(section: &str) -> std::vec::Vec<&str> { + let mut names = std::vec::Vec::new(); + for line in section.lines() { + let content = match line.split('#').next() { + std::option::Option::Some(value) => value.trim(), + std::option::Option::None => continue, + }; + if content.is_empty() { + continue; + } + let name = match content.split('=').next() { + std::option::Option::Some(value) => value.trim().trim_end_matches(".workspace"), + std::option::Option::None => continue, + }; + if !name.is_empty() { + names.push(name); + } + } + names.sort_unstable(); + return names; +} diff --git a/crates/ksp-interface-lib/tests/public_api.rs b/crates/ksp-interface-lib/tests/public_api.rs new file mode 100644 index 0000000..f45111e --- /dev/null +++ b/crates/ksp-interface-lib/tests/public_api.rs @@ -0,0 +1,15 @@ +// file: crates/ksp-interface-lib/tests/public_api.rs +// version: 1 + +//! Integration canaries for the public `ksp-interface-lib` scaffold. + +fn consume_pubkey(pubkey: ksp_interface_lib::Pubkey) -> [u8; 32] { + return pubkey.to_bytes(); +} + +#[test] +fn public_pre_002_pubkey_contract_is_available_from_crate_root() { + let pubkey = ksp_interface_lib::Pubkey::default(); + assert_eq!(consume_pubkey(pubkey), [0_u8; 32]); + return; +} diff --git a/deltas/0.2.13/pre.002.md b/deltas/0.2.13/pre.002.md new file mode 100644 index 0000000..ae21d45 --- /dev/null +++ b/deltas/0.2.13/pre.002.md @@ -0,0 +1,205 @@ + + + +# Delta `0.2.13-pre.002` — scaffold `ksp-interface-lib` + +## 1. Base requise + +Cette tranche s'applique exclusivement sur : + +```text +v0.2.12 ++ 0.2.13-pre.001 +``` + +Le gate opérateur fourni pour `pre.001` est intégralement vert : `cargo fmt --all`, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace et `cargo test --workspace` passent. + +La version workspace passe de : + +```text +0.2.13-pre.1 +``` + +à : + +```text +0.2.13-pre.2 +``` + +## 2. Objectif + +Créer uniquement le scaffold de `ksp-interface-lib` et verrouiller sa frontière avant les types wire fonctionnels. + +La tranche matérialise : + +```text +nouveau membre workspace ksp-interface-lib +manifest avec ksp-core-lib comme seule dépendance normale +façade crate-root explicite +réexport contrôlé de ksp_core_lib::Pubkey +README/USAGE initiaux +canari public API minimal +canari dependency firewall +``` + +Elle ne matérialise pas encore : + +```text +ProgramAccountMeta +ProgramInstruction +bornes instruction +codes d'erreur Interface +serde / serde_json +borsh / bincode / wincode +solana-instruction +network/runtime +Program behavior +``` + +## 3. Décision Logging + +`0.2.13` reste une foundation de contrats passifs. Aucun comportement runtime n'est actuellement prévu dans `ksp-interface-lib`, donc aucun événement/span n'a besoin d'être émis. + +En conséquence, la tranche maintient explicitement absents : + +```text +ksp-logging-lib +src/constants.rs +TRACING_TARGET +tracing direct +``` + +Cette absence est volontaire et couverte par le canari de dépendances. Si un comportement runtime réel apparaît dans une future évolution d'Interface, l'instrumentation devra être ajoutée via `ksp-logging-lib`; `DEP-LOG-010` imposera alors un `pub(crate) const TRACING_TARGET: &str` possédé par `src/constants.rs`. + +Les futures validations de bornes de `pre.003`/`pre.004` doivent retourner des erreurs structurées ; elles ne justifient pas à elles seules des logs runtime. + +## 4. Surface publique de scaffold + +La seule primitive publique nouvellement exposée est : + +```rust +pub use ksp_core_lib::Pubkey; +``` + +Ce réexport confirme l'ownership décidé : Interface n'introduit aucun wrapper `ProgramId`/`Pubkey` parallèle et utilisera la primitive Core dans ses futurs contrats wire. + +La façade ne contient aucun `pub mod`. Les types d'instruction restent absents pour éviter d'avancer `pre.003`/`pre.004`. + +## 5. Dependency firewall + +Le manifest membre possède exactement : + +```text +[dependencies] +ksp-core-lib = { path = "../ksp-core-lib" } +``` + +Le canari `tests/dependency_boundary.rs` vérifie notamment l'absence de : + +```text +ksp-logging-lib +ksp-program-* +ksp-*-transport-lib +ksp-config-lib +ksp-store-* +ksp-wallet-lib +serde / serde_json +borsh / bincode / wincode +solana-instruction +reqwest / tokio / tonic / tauri / tracing +``` + +Il verrouille aussi l'absence de `src/constants.rs` et `TRACING_TARGET` tant que la crate reste passive. + +## 6. Tests ajoutés + +`tests/public_api.rs` vérifie que le `Pubkey` canonique est consommable uniquement depuis le crate-root Interface. + +`tests/dependency_boundary.rs` vérifie : + +```text +dépendance normale exacte = ksp-core-lib +absence des dépendances interdites +absence de ProgramAccountMeta/ProgramInstruction en pre.002 +absence de surface Logging runtime +``` + +Aucun unit test métier n'est ajouté : aucune primitive fonctionnelle n'existe encore. + +## 7. Fichiers ajoutés + +```text +crates/ksp-interface-lib/Cargo.toml +crates/ksp-interface-lib/README.md +crates/ksp-interface-lib/USAGE.md +crates/ksp-interface-lib/src/lib.rs +crates/ksp-interface-lib/tests/dependency_boundary.rs +crates/ksp-interface-lib/tests/public_api.rs +deltas/0.2.13/pre.002.md +``` + +## 8. Fichiers modifiés + +```text +Cargo.toml +docs/plans/020-V0_2_13_INTERFACE_PLAN.md +docs/validation/016-V0_2_13_INTERFACE.md +``` + +## 9. Fichiers volontairement inchangés + +```text +README.md +ROADMAP.md +CHANGELOG.md +.env.example +docs/architecture/** +docs/rules/** +crates/ksp-core-lib/** +crates/ksp-logging-lib/** +crates/ksp-onchain-transport-lib/** +crates/ksp-offchain-transport-lib/** +crates/ksp-config-lib/** +crates/ksp-wallet-lib/** +crates/ksp-app-*/** +prompts/** +``` + +Aucune architecture durable n'est rouverte : le graphe `Interface -> Core`, avec Logging uniquement lorsqu'un runtime logging réel existe, est déjà documenté. + +## 10. Validations de génération + +Les audits Python sont rejoués sur l'arbre matérialisé avant livraison. Le sandbox de génération ne fournit pas `cargo`, `rustc` ou `rustfmt`; aucun PASS Cargo nouveau n'est donc revendiqué localement. + +## 11. Gate opérateur attendu + +Après application : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.13 +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-interface-lib +cargo test --workspace +cargo tree -p ksp-interface-lib --edges normal +cargo tree --duplicates +``` + +Le `cargo tree -p ksp-interface-lib --edges normal` doit montrer Core comme unique dépendance KSP directe et ne doit pas révéler de codec/runtime ajouté par Interface. + +Une correction découverte par ce gate reste un `0.2.13-pre.002-fix.NNN` et n'avance pas `pre.003`. + +## 12. Suite + +Après gate vert, `pre.003` pourra matérialiser uniquement : + +```text +ProgramAccountMeta +constante de borne account metas +modèle d'erreur Interface minimal nécessaire +unit/public canaries correspondants +``` + +`ProgramInstruction`, sa data bound et son Debug résumé restent réservés à `pre.004`. diff --git a/docs/plans/020-V0_2_13_INTERFACE_PLAN.md b/docs/plans/020-V0_2_13_INTERFACE_PLAN.md index 7367aaa..a040ef8 100644 --- a/docs/plans/020-V0_2_13_INTERFACE_PLAN.md +++ b/docs/plans/020-V0_2_13_INTERFACE_PLAN.md @@ -1,5 +1,5 @@ - + # Plan `0.2.13` — Interface / wire foundation @@ -377,13 +377,13 @@ Le scope réduit permet de supprimer le second lot wire optionnel du forecast in ### pre.001 — audit + héritage + frontières + sizing -**Statut : EN COURS / sortie du présent delta** +**Statut : réalisé ; gate opérateur `pre.001` intégralement PASS.** Relire les règles/architectures, auditer Core/Transport, classer kbot3, auditer les candidates externes, retenir la surface instruction passive, fixer bornes/firewall/threat model/tests et créer plan/validation. ### pre.002 — scaffold `ksp-interface-lib` + façade + firewall -**Statut : prévu** +**Statut : réalisé ; gate opérateur à confirmer.** Créer la crate, l'ajouter au workspace, poser `lib.rs` avec exports explicites, lints, README/USAGE initiaux et canaris manifest/firewall. Dépendance normale unique : `ksp-core-lib`. @@ -461,19 +461,21 @@ plan + validation créés implementation Program absente ``` -## 16. Gate attendu pour `pre.002` +## 16. Gate attendu pour `pre.003` -`pre.002` peut commencer si le présent delta est appliqué et le gate opérateur est vert. Il doit rester un scaffold strict : +`pre.002` matérialise le scaffold strict décidé par le gate précédent : ```text nouvelle crate membre ksp-interface-lib Cargo dépend uniquement de ksp-core-lib lints workspace hérités crate root explicite sans pub mod +Pubkey réexporté depuis Core README/USAGE initiaux canari public API minimal canari dependency firewall -aucun ProgramAccountMeta/ProgramInstruction fonctionnel si le scaffold suffit à la tranche +aucun ProgramAccountMeta/ProgramInstruction fonctionnel +aucun ksp-logging-lib / constants.rs / TRACING_TARGET ``` -Aucune question ouverte ne bloque `pre.002`. +`pre.003` peut commencer après application du delta et gate opérateur vert. Sa responsabilité reste limitée à `ProgramAccountMeta`, aux bornes communes et au modèle d'erreur Interface minimal ; `ProgramInstruction` reste réservé à `pre.004`. diff --git a/docs/validation/016-V0_2_13_INTERFACE.md b/docs/validation/016-V0_2_13_INTERFACE.md index c5583d0..df7a202 100644 --- a/docs/validation/016-V0_2_13_INTERFACE.md +++ b/docs/validation/016-V0_2_13_INTERFACE.md @@ -1,5 +1,5 @@ - + # Validation `0.2.13` — Interface / wire foundation @@ -85,9 +85,9 @@ aucun comportement Program | Contrat | Attendu final `0.2.13` | Statut | |----------------------|--------------------------------------------------------|------------------| -| crate | `ksp-interface-lib` membre workspace | TODO pre.002 | -| façade | exports explicites crate-root; aucun `pub mod` | TODO pre.002+ | -| Pubkey | réexport/usage contrôlé de Core; pas de type parallèle | TODO pre.002/003 | +| crate | `ksp-interface-lib` membre workspace | PASS pre.002 | +| façade | exports explicites crate-root; aucun `pub mod` | PASS pre.002 | +| Pubkey | réexport/usage contrôlé de Core; pas de type parallèle | PASS pre.002 | | `ProgramAccountMeta` | private fields + writable/readonly + accessors | TODO pre.003 | | `ProgramInstruction` | private fields + `try_new` + accessors | TODO pre.004 | | account bound | `<= 255` | TODO pre.003/004 | @@ -140,15 +140,15 @@ Si une nouvelle dépendance externe apparaît après `pre.001`, la présente mat ## 10. Tests de release -| Famille | Attendu | Statut | -|--------------------------|------------------------------------------------|--------| -| unit tests privés | constructeurs/bornes/order/debug/errors | TODO | -| `tests/public_api.rs` | consommation crate-root uniquement | TODO | -| external consumer canary | surface utilisable hors modules privés | TODO | -| dependency boundary | firewall exact | TODO | -| release completeness | inventaire exact, aucun domaine supplémentaire | TODO | -| round-trip codec | aucun tant qu'aucun codec | N/A | -| network smoke | aucun pour crate wire pure | N/A | +| Famille | Attendu | Statut | +|--------------------------|------------------------------------------------|--------------| +| unit tests privés | constructeurs/bornes/order/debug/errors | TODO | +| `tests/public_api.rs` | consommation crate-root uniquement | PASS pre.002 | +| external consumer canary | surface utilisable hors modules privés | TODO | +| dependency boundary | firewall exact | PASS pre.002 | +| release completeness | inventaire exact, aucun domaine supplémentaire | TODO | +| round-trip codec | aucun tant qu'aucun codec | N/A | +| network smoke | aucun pour crate wire pure | N/A | ## 11. Gate technique final attendu @@ -189,3 +189,27 @@ Aucun smoke réseau/live n'est exigé par défaut. | implémentation Program lourde | ABSENTE | Le passage à `pre.002` est autorisé après application du delta et validation opérateur. Le statut des items d'implémentation reste volontairement `TODO` jusqu'aux tranches correspondantes. + +## 13. État préparé `pre.002` + +Le scaffold matérialisé conserve volontairement une surface minimale : + +```text +workspace member PASS structurel +normal dependency ksp-core-lib uniquement +Pubkey réexport Core au crate-root +public modules aucun +ProgramAccountMeta absent par contrat pre.002 +ProgramInstruction absent par contrat pre.002 +serde / borsh / bincode / wincode absents +network/runtime dependencies absentes +ksp-logging-lib absent +constants.rs / TRACING_TARGET absents +README / USAGE initiaux +public API canary présent +dependency firewall canary présent +``` + +Le logging reste volontairement absent : la foundation `0.2.13` est passive et n'émet aucun événement/span runtime. Si une future surface comportementale démontre un besoin réel de logging, `ksp-logging-lib`, `src/constants.rs` et `TRACING_TARGET` devront être introduits ensemble conformément à `DEP-LOG-004` et `DEP-LOG-010`. + +Le passage à `pre.003` reste conditionné au gate opérateur complet sur l'overlay `pre.002`.