diff --git a/Cargo.toml b/Cargo.toml index 2720751..bd9dcc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 477 +# version: 478 [workspace] resolver = "3" members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api"] [workspace.package] -version = "0.3.9-pre.2" +version = "0.3.9-pre.2.fix.1" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-worker-api/src/identity.rs b/crates/ksp-worker-api/src/identity.rs index a6f19ea..8601270 100644 --- a/crates/ksp-worker-api/src/identity.rs +++ b/crates/ksp-worker-api/src/identity.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-api/src/identity.rs -// version: 1 +// version: 2 /// Maximum UTF-8 byte length admitted for one Worker identifier. pub const MAX_WORKER_ID_BYTES: usize = 128; @@ -10,7 +10,7 @@ pub const MAX_WORKER_KIND_CODE_BYTES: usize = 128; #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct WorkerId(std::string::String); -impl WorkerId { +impl crate::WorkerId { /// Creates one non-empty Worker identifier using the KSP safe-code alphabet. pub fn new(value: impl std::convert::Into) -> crate::Result { let value = value.into(); @@ -27,7 +27,7 @@ impl WorkerId { } } -impl std::fmt::Debug for WorkerId { +impl std::fmt::Debug for crate::WorkerId { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { return formatter.write_str("WorkerId(..)"); } @@ -37,7 +37,7 @@ impl std::fmt::Debug for WorkerId { #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct WorkerKindCode(std::string::String); -impl WorkerKindCode { +impl crate::WorkerKindCode { /// Creates one non-empty Worker kind using the KSP safe-code alphabet. pub fn new(value: impl std::convert::Into) -> crate::Result { let value = value.into(); @@ -54,7 +54,7 @@ impl WorkerKindCode { } } -impl std::fmt::Debug for WorkerKindCode { +impl std::fmt::Debug for crate::WorkerKindCode { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { return formatter.debug_tuple("WorkerKindCode").field(&self.0).finish(); } diff --git a/crates/ksp-worker-api/src/lifecycle.rs b/crates/ksp-worker-api/src/lifecycle.rs index 6ed85e6..d92d28d 100644 --- a/crates/ksp-worker-api/src/lifecycle.rs +++ b/crates/ksp-worker-api/src/lifecycle.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-api/src/lifecycle.rs -// version: 1 +// version: 2 /// Current lifecycle state of one continuous Worker. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] @@ -19,7 +19,7 @@ pub enum WorkerState { Faulted(crate::ErrorCode), } -impl WorkerState { +impl crate::WorkerState { /// Returns the stable safe lifecycle code without rendering Worker data. #[must_use] pub const fn code(&self) -> &'static str { @@ -63,7 +63,7 @@ pub enum WorkerHealth { Unhealthy, } -impl WorkerHealth { +impl crate::WorkerHealth { /// Returns the stable safe code for this health classification. #[must_use] pub const fn code(&self) -> &'static str { @@ -88,7 +88,7 @@ pub enum WorkerActivity { Active, } -impl WorkerActivity { +impl crate::WorkerActivity { /// Returns the stable safe code for this activity classification. #[must_use] pub const fn code(&self) -> &'static str { @@ -108,7 +108,7 @@ pub struct WorkerLifecycle { state: crate::WorkerState, } -impl WorkerLifecycle { +impl crate::WorkerLifecycle { /// Creates one lifecycle in [`WorkerState::Created`] state. #[must_use] pub const fn new(id: crate::WorkerId, kind: crate::WorkerKindCode) -> Self { @@ -167,7 +167,7 @@ impl WorkerLifecycle { } } -impl std::fmt::Debug for WorkerLifecycle { +impl std::fmt::Debug for crate::WorkerLifecycle { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { return formatter.debug_struct("WorkerLifecycle").field("id", &self.id).field("kind", &self.kind).field("state", &self.state).finish(); } diff --git a/crates/ksp-worker-api/src/snapshot.rs b/crates/ksp-worker-api/src/snapshot.rs index d830212..61269d7 100644 --- a/crates/ksp-worker-api/src/snapshot.rs +++ b/crates/ksp-worker-api/src/snapshot.rs @@ -1,11 +1,11 @@ // file: crates/ksp-worker-api/src/snapshot.rs -// version: 1 +// version: 2 /// Monotone sequence attached to one latest-value Worker snapshot stream. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct WorkerSnapshotSequence(u64); -impl WorkerSnapshotSequence { +impl crate::WorkerSnapshotSequence { /// Creates the initial sequence position for one Worker snapshot stream. #[must_use] pub const fn initial() -> Self { @@ -50,7 +50,7 @@ pub struct WorkerSnapshot { activity: crate::WorkerActivity, } -impl WorkerSnapshot { +impl crate::WorkerSnapshot { /// Creates one immutable common Worker snapshot from already validated values. #[must_use] pub const fn new( @@ -101,7 +101,7 @@ impl WorkerSnapshot { } } -impl std::fmt::Debug for WorkerSnapshot { +impl std::fmt::Debug for crate::WorkerSnapshot { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { return formatter .debug_struct("WorkerSnapshot") @@ -130,7 +130,7 @@ pub trait WorkerSnapshotSource: std::marker::Send + std::marker::Sync { #[cfg(test)] fn exhausted_snapshot_sequence() -> crate::WorkerSnapshotSequence { - return WorkerSnapshotSequence(u64::MAX); + return crate::WorkerSnapshotSequence(u64::MAX); } #[cfg(test)] diff --git a/crates/ksp-worker-api/src/stop.rs b/crates/ksp-worker-api/src/stop.rs index 5e55256..58b809d 100644 --- a/crates/ksp-worker-api/src/stop.rs +++ b/crates/ksp-worker-api/src/stop.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-api/src/stop.rs -// version: 1 +// version: 2 /// Runtime-neutral cloneable token carrying cooperative Worker stop intent. #[derive(Clone)] @@ -7,7 +7,7 @@ pub struct WorkerStopToken { requested: std::sync::Arc, } -impl WorkerStopToken { +impl crate::WorkerStopToken { /// Creates a token with no stop request. #[must_use] pub fn new() -> Self { @@ -27,13 +27,13 @@ impl WorkerStopToken { } } -impl std::default::Default for WorkerStopToken { +impl std::default::Default for crate::WorkerStopToken { fn default() -> Self { return Self::new(); } } -impl std::fmt::Debug for WorkerStopToken { +impl std::fmt::Debug for crate::WorkerStopToken { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { return formatter.debug_struct("WorkerStopToken").field("stop_requested", &self.is_stop_requested()).finish(); } diff --git a/crates/ksp-worker-api/tests/dependency_boundary.rs b/crates/ksp-worker-api/tests/dependency_boundary.rs index 3fed900..989851a 100644 --- a/crates/ksp-worker-api/tests/dependency_boundary.rs +++ b/crates/ksp-worker-api/tests/dependency_boundary.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-api/tests/dependency_boundary.rs -// version: 1 +// version: 2 //! Dependency and runtime-neutrality canaries for the Worker API foundation. @@ -59,6 +59,47 @@ fn pre_002_production_sources_forbid_job_runtime_domain_and_wire_dependencies() return; } +#[test] +fn pre_002_fix_001_shared_visible_items_use_crate_root_facade_inside_owner_modules() { + let identity = include_str!("../src/identity.rs"); + let lifecycle = include_str!("../src/lifecycle.rs"); + let snapshot = include_str!("../src/snapshot.rs"); + let stop = include_str!("../src/stop.rs"); + for expected in [ + "impl crate::WorkerId {", + "impl std::fmt::Debug for crate::WorkerId {", + "impl crate::WorkerKindCode {", + "impl std::fmt::Debug for crate::WorkerKindCode {", + ] { + assert!(identity.contains(expected), "missing crate-root Worker identity impl target: {expected}"); + } + for expected in [ + "impl crate::WorkerActivity {", + "impl crate::WorkerHealth {", + "impl crate::WorkerLifecycle {", + "impl crate::WorkerState {", + "impl std::fmt::Debug for crate::WorkerLifecycle {", + ] { + assert!(lifecycle.contains(expected), "missing crate-root Worker lifecycle impl target: {expected}"); + } + for expected in [ + "impl crate::WorkerSnapshotSequence {", + "impl crate::WorkerSnapshot {", + "impl std::fmt::Debug for crate::WorkerSnapshot {", + "return crate::WorkerSnapshotSequence(u64::MAX);", + ] { + assert!(snapshot.contains(expected), "missing crate-root Worker snapshot reference: {expected}"); + } + for expected in [ + "impl crate::WorkerStopToken {", + "impl std::default::Default for crate::WorkerStopToken {", + "impl std::fmt::Debug for crate::WorkerStopToken {", + ] { + assert!(stop.contains(expected), "missing crate-root Worker stop impl target: {expected}"); + } + return; +} + fn manifest_dependency_names(section: &str) -> std::vec::Vec<&str> { let mut names = std::vec::Vec::new(); for line in section.lines() { diff --git a/deltas/0.3.9/pre.002-fix.001.md b/deltas/0.3.9/pre.002-fix.001.md new file mode 100644 index 0000000..e234466 --- /dev/null +++ b/deltas/0.3.9/pre.002-fix.001.md @@ -0,0 +1,114 @@ + + + +# Delta `0.3.9-pre.002-fix.001` — conformité crate-root de `ksp-worker-api` + +## Base requise + +```text +0.3.9-pre.002 +workspace.package.version = 0.3.9-pre.2 +``` + +Le gate opérateur de `pre.002` est vert : format et audits propres, `cargo check --workspace` PASS, Clippy workspace `--all-targets --all-features -- -D warnings` PASS, `cargo test -p ksp-worker-api` PASS avec 17 tests, et les deux `cargo tree` ciblés confirment la frontière Core-only. + +## Défaut corrigé + +La nouvelle crate respectait les réexports crate-root dans ses signatures inter-types, mais les modules propriétaires implémentaient encore les types partagés par nom local nu, par exemple : + +```rust +impl WorkerId { +``` + +`RUST-IMPORT-009` impose qu'un élément `pub` ou `pub(crate)` partagé soit appelé via `crate::Item`, y compris depuis son module de déclaration lorsque le contrat est crate-wide. La forme canonique est donc : + +```rust +impl crate::WorkerId { +``` + +Le même défaut existait pour les autres targets d'`impl` de `identity.rs`, `lifecycle.rs`, `snapshot.rs` et `stop.rs`. + +## Corrections Rust + +Les targets sont normalisées sans modifier la surface ni le comportement : + +```text +identity.rs + WorkerId + Debug for WorkerId + WorkerKindCode + Debug for WorkerKindCode + +lifecycle.rs + WorkerState + WorkerHealth + WorkerActivity + WorkerLifecycle + Debug for WorkerLifecycle + +snapshot.rs + WorkerSnapshotSequence + WorkerSnapshot + Debug for WorkerSnapshot + +stop.rs + WorkerStopToken + Default for WorkerStopToken + Debug for WorkerStopToken +``` + +Le helper `exhausted_snapshot_sequence()` construit aussi explicitement `crate::WorkerSnapshotSequence(u64::MAX)`. + +Une troisième canarie `dependency_boundary` vérifie les références crate-root attendues dans les quatre modules propriétaires afin d'éviter une régression locale lors de `pre.003`. + +## Version + +Ce correctif modifie du code Rust : + +```text +workspace.package.version = 0.3.9-pre.2.fix.1 +``` + +Le header du `Cargo.toml` racine passe de `477` à `478`. + +## Hors scope + +Aucun changement de lifecycle, identity bounds, snapshot shape, stop semantics, ErrorCode, dépendance, feature ou API publique. Aucun travail `pre.003` n'est anticipé. + +L'auditeur Python global n'est pas étendu dans ce fix : une généralisation immédiate ferait remonter la dette historique de crates antérieures et élargirait artificiellement cette correction locale. La canarie Worker ferme le défaut nouveau sans masquer cette distinction. + +## Fichiers modifiés + +```text +Cargo.toml +crates/ksp-worker-api/src/identity.rs +crates/ksp-worker-api/src/lifecycle.rs +crates/ksp-worker-api/src/snapshot.rs +crates/ksp-worker-api/src/stop.rs +crates/ksp-worker-api/tests/dependency_boundary.rs +docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md +docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md +``` + +## Fichier ajouté + +```text +deltas/0.3.9/pre.002-fix.001.md +``` + +## Fichiers supprimés + +Aucun. + +## Gate opérateur demandé + +```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 +cargo check --workspace +cargo clippy --workspace --all-targets --all-features -- -D warnings +cargo test -p ksp-worker-api +cargo tree -p ksp-worker-api --edges normal +cargo tree -p ksp-worker-api -e features +``` diff --git a/docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md b/docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md index 0e6b328..fc9042f 100644 --- a/docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md +++ b/docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md @@ -1,5 +1,5 @@ - + # Plan v0.3.9 — Worker API générique + audit RAW Transaction @@ -561,6 +561,12 @@ reexports Error / ErrorCode / ErrorContext / Result La crate dépend uniquement de `ksp-core-lib`, ne possède aucune feature/dev/build dependency et n'ouvre ni runtime, ni Job, ni Transport/Store/Config, ni contrat Solana. Le snapshot commun reste fixe et sans payload métier. Les preuves adversariales, object-safety, implémentation externe et latest-value multi-listener restent volontairement dans `pre.003`. +#### `pre.002-fix.001` — chemins crate-root dans les modules propriétaires + +**Statut : réalisé ; correctif de conformité Rust.** + +Correction de la nouvelle crate Worker selon `RUST-IMPORT-009` : tout `impl` d'un type partagé/exporté cible désormais explicitement `crate::Type`, y compris les implémentations de traits `Debug`/`Default`. Le helper de test de séquence emploie également `crate::WorkerSnapshotSequence`. Une canarie dependency-boundary dédiée verrouille ces références sans élargir la surface fonctionnelle de `pre.002`. `workspace.package.version` devient `0.3.9-pre.2.fix.1`. + ### `pre.003` — hardening, races, object-safety, impl externe et freeze **Statut : prévu.** diff --git a/docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md b/docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md index 00b47af..93033d1 100644 --- a/docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md +++ b/docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md @@ -1,5 +1,5 @@ - + # Validation v0.3.9 — Worker API + audit RAW Transaction @@ -95,6 +95,27 @@ Les cases cochées de cette sous-section attestent la matérialisation de la sur - [X] Public API consumer depuis crate root testée. - [X] Dependency firewall initial testée. +#### Gate opérateur de `pre.002` avant fix + +- [X] `cargo fmt --all` exécuté. +- [X] audits Rust complets propres. +- [X] audit Markdown propre : 320 tables / 731 fichiers. +- [X] `cargo check --workspace` PASS. +- [X] `cargo clippy --workspace --all-targets --all-features -- -D warnings` PASS. +- [X] `cargo test -p ksp-worker-api` PASS : 13 unitaires + 2 dependency boundary + 2 public API. +- [X] `cargo tree -p ksp-worker-api --edges normal` confirme `ksp-worker-api -> ksp-core-lib` uniquement côté KSP. +- [X] `cargo tree -p ksp-worker-api -e features` ne révèle aucune feature Worker propre ni dépendance runtime/domain ajoutée. + +#### `pre.002-fix.001` + +- [X] Violation `RUST-IMPORT-009` identifiée sur les targets d'`impl` des types Worker exportés. +- [X] `identity.rs` utilise `impl crate::WorkerId` et `impl crate::WorkerKindCode`, y compris pour `Debug`. +- [X] `lifecycle.rs` utilise la façade crate-root pour les cinq targets d'`impl` visibles. +- [X] `snapshot.rs` utilise la façade crate-root pour les trois targets d'`impl` visibles et le helper de séquence. +- [X] `stop.rs` utilise la façade crate-root pour l'impl inhérent, `Default` et `Debug`. +- [X] Canarie dependency-boundary ajoutée contre cette régression. +- [ ] Gate Cargo du fix exécuté par l'opérateur. + ### `pre.003` - [ ] Stop-vs-fault ordres adversariaux couverts. @@ -213,10 +234,10 @@ Aucun item ci-dessous n’est déclaré exécuté en `pre.001`. La livraison initiale `pre.001` avait conservé `workspace.package.version = 0.3.8` en suivant l’exception du prompt 028. Cette exception est supplantée par la règle normative `VER-ID-009`. -Après `pre.002`, l’état courant est : +Après `pre.002-fix.001`, l’état courant est : ```text -workspace.package.version = 0.3.9-pre.2 +workspace.package.version = 0.3.9-pre.2.fix.1 ``` -`pre.002` est une nouvelle tranche non-fix et synchronise donc Cargo conformément à `VER-ID-006` et `VER-ID-009`. L'état précédent `0.3.9-pre.1.fix.2` reste documenté dans `pre.001-fix.002`. +`pre.002` reste la tranche non-fix `0.3.9-pre.2`. Son correctif de conformité Rust porte `0.3.9-pre.2.fix.1` conformément à `VER-ID-007` et `VER-ID-010`. L'état précédent `0.3.9-pre.1.fix.2` reste documenté dans `pre.001-fix.002`.