v0.2.1-pre.005-fix.001

This commit is contained in:
2026-08-17 20:40:08 +02:00
parent ac1b1033c4
commit 14bcbf2cfb
16 changed files with 238 additions and 29 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml
# version: 103
# version: 104
[workspace]
resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib"]
[workspace.package]
version = "0.2.1-pre.5"
version = "0.2.1-pre.5.fix.1"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -0,0 +1,7 @@
// file: crates/ksp-config-lib/src/constants.rs
// version: 1
//! Config-owned tracing constants.
/// Owning tracing target for events emitted by the Config crate.
pub(crate) const TRACING_TARGET: &str = "ksp-config-lib";

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/src/environment.rs
// version: 4
// version: 5
/// Default local environment file read by Config from the process launch directory.
pub const DEFAULT_DOTENV_PATH: &str = ".env";
@@ -7,7 +7,6 @@ pub const DEFAULT_DOTENV_PATH: &str = ".env";
/// Versioned environment contract template expected at the repository/runtime root.
pub const DEFAULT_DOTENV_EXAMPLE_PATH: &str = ".env.example";
const LOGGING_TARGET: &str = "ksp-config-lib";
const LOGGING_DOMAIN: &str = "config.environment";
/// Source that supplied one resolved Config environment variable.
@@ -556,7 +555,7 @@ fn is_generic_dotenv_name(variable_name: &str) -> bool {
}
fn emit_missing_variable_warning(variable_name: &str) {
ksp_logging_lib::warn!(target: LOGGING_TARGET, domain = LOGGING_DOMAIN, variable_name = variable_name, "Config environment variable is missing");
ksp_logging_lib::warn!(target: crate::TRACING_TARGET, domain = LOGGING_DOMAIN, variable_name = variable_name, "Config environment variable is missing");
}
fn missing_variable_error(variable_name: &str) -> ksp_core_lib::Error {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/src/lib.rs
// version: 10
// version: 11
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
@@ -13,6 +13,7 @@
mod bootstrap;
mod composite;
mod constants;
mod document;
mod environment;
mod error;
@@ -23,6 +24,8 @@ mod profile;
mod registry;
mod sensitivity;
pub(crate) use self::constants::TRACING_TARGET;
/// Bootstrap argument used to replace the configuration document root.
pub use self::bootstrap::ARG_CFG_PATH;
/// Bootstrap argument used to replace the schema root.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/src/persistence.rs
// version: 2
// version: 3
static NEXT_TEMPORARY_FILE_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
@@ -99,7 +99,7 @@ fn cleanup_temporary_file(path: &std::path::Path) {
&& error.kind() != std::io::ErrorKind::NotFound
{
ksp_logging_lib::warn!(
target: "ksp-config-lib",
target: crate::TRACING_TARGET,
domain = "config.persistence",
path = %path.to_string_lossy(),
error = %error,

View File

@@ -0,0 +1,121 @@
// file: crates/ksp-core-lib/tests/workspace_logging.rs
// version: 1
//! Workspace-level logging ownership canaries for KSP behavioral crates.
fn workspace_root() -> std::path::PathBuf {
let manifest_directory = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
let parent = manifest_directory.parent();
assert!(parent.is_some(), "core crate must have a crates directory parent");
let parent = match parent {
std::option::Option::Some(value) => value,
std::option::Option::None => return manifest_directory.to_path_buf(),
};
let root = parent.parent();
assert!(root.is_some(), "core crate must have a workspace root");
return match root {
std::option::Option::Some(value) => value.to_path_buf(),
std::option::Option::None => parent.to_path_buf(),
};
}
fn rust_source_files(directory: &std::path::Path) -> std::vec::Vec<std::path::PathBuf> {
let mut files = std::vec::Vec::new();
let entries = std::fs::read_dir(directory);
if entries.is_err() {
return files;
}
let entries = match entries {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return files,
};
for entry in entries {
let entry = match entry {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => continue,
};
let path = entry.path();
if path.is_dir() {
files.extend(rust_source_files(path.as_path()));
} else if path.extension() == std::option::Option::Some(std::ffi::OsStr::new("rs")) {
files.push(path);
}
}
return files;
}
fn package_name(manifest: &str) -> std::option::Option<&str> {
for line in manifest.lines() {
let trimmed = line.trim();
if !trimmed.starts_with("name = ") {
continue;
}
return trimmed.split('"').nth(1);
}
return std::option::Option::None;
}
#[test]
fn behavioral_crates_own_explicit_tracing_targets() {
let crates_root = workspace_root().join("crates");
let entries = std::fs::read_dir(crates_root.as_path());
assert!(entries.is_ok(), "workspace crates directory must be readable");
let entries = match entries {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
for entry in entries {
let entry = match entry {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => continue,
};
let crate_root = entry.path();
if !crate_root.is_dir() {
continue;
}
let source_root = crate_root.join("src");
let source_files = rust_source_files(source_root.as_path());
let mut emits_ksp_logs = false;
for source_file in source_files.iter() {
let source = std::fs::read_to_string(source_file.as_path());
assert!(source.is_ok(), "Rust source must be readable: {}", source_file.display());
let source = match source {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => continue,
};
if source.contains("ksp_logging_lib::") {
emits_ksp_logs = true;
}
assert!(
!source.contains("target: env!(\"CARGO_PKG_NAME\")"),
"KSP tracing target must be explicit rather than derived from Cargo metadata: {}",
source_file.display()
);
assert!(!source.contains("target: \"ksp-"), "KSP tracing target literals must be owned by src/constants.rs: {}", source_file.display());
}
if !emits_ksp_logs {
continue;
}
let manifest = std::fs::read_to_string(crate_root.join("Cargo.toml"));
assert!(manifest.is_ok(), "behavioral crate manifest must be readable: {}", crate_root.display());
let manifest = match manifest {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => continue,
};
let package_name = package_name(manifest.as_str());
assert!(package_name.is_some(), "behavioral crate package name must be discoverable: {}", crate_root.display());
let package_name = match package_name {
std::option::Option::Some(value) => value,
std::option::Option::None => continue,
};
let constants_path = source_root.join("constants.rs");
let constants = std::fs::read_to_string(constants_path.as_path());
assert!(constants.is_ok(), "behavioral crate must own src/constants.rs: {}", crate_root.display());
let constants = match constants {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => continue,
};
let expected = std::format!("pub(crate) const TRACING_TARGET: &str = \"{package_name}\";");
assert!(constants.contains(expected.as_str()), "behavioral crate must own its Cargo-name tracing target: {}", crate_root.display());
}
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/client.rs
// version: 3
// version: 4
/// Passive runtime availability reported for one logical HTTP endpoint or role.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -224,7 +224,7 @@ impl HttpEndpointClient {
role_runtimes.push(std::sync::Arc::new(crate::resilience::HttpRoleRuntime::new(role, std::sync::Arc::clone(&notify))));
}
ksp_logging_lib::debug!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = settings.name(),
provider = settings.provider().as_str(),
cluster = settings.cluster().as_str(),

View File

@@ -0,0 +1,7 @@
// file: crates/ksp-onchain-transport-lib/src/constants.rs
// version: 1
//! Transport-owned tracing constants.
/// Owning tracing target for events emitted by the on-chain transport crate.
pub(crate) const TRACING_TARGET: &str = "ksp-onchain-transport-lib";

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/executor.rs
// version: 1
// version: 2
const HTTP_REQUEST_TIMEOUT: u16 = 408;
const HTTP_TOO_MANY_REQUESTS: u16 = 429;
@@ -147,7 +147,7 @@ impl crate::HttpTransportPool {
};
permit.record_success();
ksp_logging_lib::debug!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = permit.selection().endpoint_name(),
role = permit.selection().role().as_str(),
rpc_method = method.method(),

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/lib.rs
// version: 4
// version: 5
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
@@ -12,6 +12,7 @@
//! JSON-RPC requests while the remaining audited methods stay staged by subsequent `0.2.x` releases.
mod client;
mod constants;
mod error;
mod executor;
mod json_rpc;
@@ -21,6 +22,8 @@ mod rpc_canary;
mod rpc_method;
mod settings;
pub(crate) use self::constants::TRACING_TARGET;
/// Passive runtime availability reported for one logical HTTP endpoint.
pub use self::client::HttpEndpointAvailability;
/// Shareable logical HTTP endpoint client owned by KSP Transport.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/pool.rs
// version: 4
// version: 5
/// Safe snapshot of the logical HTTP endpoint pool.
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -105,7 +105,7 @@ impl HttpRequestPermit {
pub fn record_success(&self) {
self.role_runtime.record_success();
ksp_logging_lib::trace!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = self.selection.endpoint_name(),
role = self.selection.role().as_str(),
request_kind = self.selection.request_kind().as_str(),
@@ -118,7 +118,7 @@ impl HttpRequestPermit {
pub fn record_failure(&self) {
self.role_runtime.record_failure();
ksp_logging_lib::warn!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = self.selection.endpoint_name(),
provider = self.selection.client().provider().as_str(),
cluster = self.selection.client().cluster().as_str(),
@@ -136,7 +136,7 @@ impl HttpRequestPermit {
let pause = self.role_runtime.record_rate_limited(provider_retry_after);
let cooldown_ms = duration_millis_u64(pause);
ksp_logging_lib::warn!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = self.selection.endpoint_name(),
provider = self.selection.client().provider().as_str(),
cluster = self.selection.client().cluster().as_str(),
@@ -200,7 +200,7 @@ impl HttpTransportPool {
}),
};
ksp_logging_lib::debug!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_count = pool.inner.clients.len(),
available_endpoint_count = pool.snapshot().available_endpoint_count(),
max_retries = pool.inner.retry.max_retries(),
@@ -376,7 +376,7 @@ impl HttpTransportPool {
std::result::Result::Err(_) => return RuntimeSelectionAttempt::Unavailable,
};
ksp_logging_lib::debug!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = selection.endpoint_name(),
role = role.as_str(),
request_kind = request_kind.as_str(),
@@ -491,7 +491,7 @@ impl HttpTransportPool {
std::option::Option::None => return selection_failed(role, request_kind),
};
ksp_logging_lib::debug!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_name = client.name(),
role = role.as_str(),
request_kind = request_kind.as_str(),
@@ -601,7 +601,7 @@ fn selection_error(role: &crate::HttpRoleName, request_kind: &crate::HttpRequest
fn request_timeout(role: &crate::HttpRoleName, request_kind: &crate::HttpRequestKind, message: &str) -> ksp_core_lib::Result<crate::HttpRequestPermit> {
ksp_logging_lib::warn!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
role = role.as_str(),
request_kind = request_kind.as_str(),
"HTTP request admission deadline expired"

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/rpc_method.rs
// version: 1
// version: 2
/// Functional category used by the audited Solana HTTP JSON-RPC registry.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -244,7 +244,7 @@ impl HttpRpcMethodDescriptor {
std::option::Option::None => "none",
};
ksp_logging_lib::warn!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
rpc_method = self.method,
documentation_status = self.documentation_status.code(),
runtime_status = self.runtime_status.code(),
@@ -265,7 +265,7 @@ impl HttpRpcMethodDescriptor {
std::option::Option::None => "none",
};
ksp_logging_lib::warn!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
rpc_method = self.method,
documentation_status = self.documentation_status.code(),
runtime_status = self.runtime_status.code(),

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/settings.rs
// version: 4
// version: 5
/// Runtime HTTP endpoint URL owned by Transport.
///
@@ -437,7 +437,7 @@ impl HttpTransportSettings {
return invalid_settings("at least one HTTP endpoint must be enabled", "endpoints.enabled");
}
ksp_logging_lib::debug!(
target: env!("CARGO_PKG_NAME"),
target: crate::TRACING_TARGET,
endpoint_count = self.endpoints.len(),
enabled_endpoint_count,
"validated HTTP transport settings"

View File

@@ -0,0 +1,63 @@
<!-- file: deltas/0.2.1/pre.005-fix.001.md -->
<!-- version: 1 -->
# `0.2.1-pre.005-fix.001` — normalisation des targets Logging KSP
## Base
- base fonctionnelle : `0.2.1-pre.005` ;
- validations utilisateur avant correctif : `cargo fmt --all`, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, tests Transport, Core et workspace propres ;
- le correctif répond à l'audit manuel du code de logging après cette validation.
## Problème corrigé
Transport utilisait `target: env!("CARGO_PKG_NAME")` dans ses émissions `ksp-logging-lib`. Ce mécanisme produit actuellement le bon texte mais ne matérialise pas le target comme contrat d'observabilité possédé par la crate. Config présentait en parallèle un target local dans `environment.rs` et un littéral équivalent dans `persistence.rs`.
## Décision
- toute crate KSP comportementale qui émet via `ksp-logging-lib` possède son target principal dans `src/constants.rs` sous `pub(crate) const TRACING_TARGET: &str` ;
- le target principal est égal au nom Cargo de la crate ;
- les callsites utilisent `crate::TRACING_TARGET` ou un target spécialisé également possédé par `constants.rs` ;
- `env!("CARGO_PKG_NAME")` reste autorisé lorsqu'il représente réellement une metadata Cargo, notamment le User-Agent HTTP ;
- les règles sont figées par `DEP-LOG-010` et `DEP-LOG-011`.
## Modifications
### Transport
- ajout de `crates/ksp-onchain-transport-lib/src/constants.rs` ;
- export crate-private de `TRACING_TARGET` depuis `lib.rs` ;
- remplacement des targets `env!("CARGO_PKG_NAME")` dans `settings.rs`, `rpc_method.rs`, `client.rs`, `pool.rs` et `executor.rs` ;
- conservation volontaire de `env!("CARGO_PKG_NAME")`/`CARGO_PKG_VERSION` pour le User-Agent HTTP.
### Config
- ajout de `crates/ksp-config-lib/src/constants.rs` ;
- export crate-private de `TRACING_TARGET` depuis `lib.rs` ;
- suppression du `LOGGING_TARGET` local de `environment.rs` ;
- remplacement du target littéral de `persistence.rs`.
### Gouvernance
- ajout de `DEP-LOG-010/011` dans `docs/rules/RULES_DEPENDENCIES.md` ;
- ajout de `crates/ksp-core-lib/tests/workspace_logging.rs`, canarie workspace vérifiant l'ownership explicite des targets des crates comportementales et interdisant les targets dérivés de `CARGO_PKG_NAME` ou les littéraux dispersés ;
- correction du plan actif `008` pour refléter la feature `reqwest/rustls` locale à Transport et la convention de target explicite ;
- aucun changement de `ROADMAP.md`.
## Version
`workspace.package.version` passe à `0.2.1-pre.5.fix.1` car le correctif modifie du code Rust participant au runtime.
## Validation requise après application
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-config-lib
cargo test -p ksp-core-lib
cargo test --workspace
```
Aucun `cargo tree` supplémentaire n'est requis : le graphe de dépendances et les features ne changent pas.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# `0.2.1-pre.001` — plan `ksp-onchain-transport-lib` HTTP Solana foundation
@@ -718,7 +718,7 @@ ksp-core-lib path/workspace
ksp-logging-lib path/workspace
```
`pre.002` utilisait `reqwest` uniquement pour le parsing/validation robuste de `HttpEndpointUrl`. `pre.003` crée réellement les clients HTTP logiques et active donc la feature `rustls` de `reqwest 0.13` au workspace, toujours avec `default-features = false`. Aucune feature `json` n'est nécessaire : KSP possède déjà son encodage JSON-RPC via `serde_json`. Aucune dépendance Tokio directe n'est ajoutée tant que `pre.004` n'utilise pas effectivement ses primitives de concurrence/attente.
`pre.002` utilisait `reqwest` uniquement pour le parsing/validation robuste de `HttpEndpointUrl`. `pre.003` crée réellement les clients HTTP logiques et active donc localement la feature `rustls` de `reqwest 0.13` dans `ksp-onchain-transport-lib`, tandis que le workspace conserve `default-features = false` sans feature dusage globale. Aucune feature `json` n'est nécessaire : KSP possède déjà son encodage JSON-RPC via `serde_json`. Aucune dépendance Tokio directe n'est ajoutée tant que `pre.004` n'utilise pas effectivement ses primitives de concurrence/attente.
Ne pas ajouter :
@@ -741,6 +741,8 @@ Target KSP :
ksp-onchain-transport-lib
```
Ce target est possédé explicitement par `src/constants.rs` via `pub(crate) const TRACING_TARGET: &str = "ksp-onchain-transport-lib"`; les appels de logging utilisent `crate::TRACING_TARGET` conformément à `DEP-LOG-010/011`. `env!("CARGO_PKG_NAME")` reste réservé aux usages où lidentité Cargo est réellement la donnée recherchée, par exemple le User-Agent HTTP.
Événements :
- création client/pool ;
@@ -947,6 +949,8 @@ Restent à `pre.005` : exécution HTTP JSON-RPC réelle et wrappers typés `getH
- les deux canaries de dépendances générales quittent `ksp-onchain-transport-lib/tests/dependency_boundary.rs` et sont centralisées sous `ksp-core-lib/tests/workspace_dependencies.rs`, conformément à `DEP-CARGO-007` ;
- Transport compte désormais **78 tests déclarés** ; Core porte 2 canaries workspace supplémentaires dans sa surface d'intégration.
`pre.005-fix.001` normalise ensuite le contrat de target KSP : Transport et Config possèdent désormais leur `TRACING_TARGET` principal dans `src/constants.rs`, les targets comportementaux ne dépendent plus de `env!("CARGO_PKG_NAME")` ni de littéraux dispersés, et une canarie workspace Core protège cette convention. Lusage Cargo de `CARGO_PKG_NAME` pour le User-Agent Transport reste volontaire et autorisé.
Restent à `pre.006` : document/schema/exemple `std.transport`, enregistrement Config, adapter Config -> Transport et tests de sensibilité/provenance/env.
## 23. Séquence `0.2.x` recalibrée

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/RULES_DEPENDENCIES.md -->
<!-- version: 13 -->
<!-- version: 14 -->
# Règles des dépendances KSP
@@ -54,6 +54,8 @@ Elles complètent les règles Rust générales et le graphe de `docs/architectur
- **DEP-LOG-007** — Une application/framework peut exceptionnellement intégrer directement un plugin/dépendance tracing imposé par son framework, notamment Tauri, sans créer une seconde politique de logging parallèle à `ksp-logging-lib`; les événements KSP restent émis via la façade KSP.
- **DEP-LOG-008** — `ksp-logging-lib` possède ses settings runtime et son hot reload ; `ksp-config-lib` peut plus tard construire ces settings et demander une reconfiguration sans créer de dépendance inverse Logging -> Config.
- **DEP-LOG-009** — Tout bridge `tracing` public mais caché de la documentation rendu techniquement nécessaire par lexpansion des macros de `ksp-logging-lib` est un détail dimplémentation réservé à ces macros ; une crate consommatrice ne lutilise jamais directement et reste limitée à la façade KSP documentée.
- **DEP-LOG-010** — Toute crate KSP comportementale qui émet des événements/spans via `ksp-logging-lib` possède un target principal explicite `pub(crate) const TRACING_TARGET: &str` dans `src/constants.rs`, égal au nom Cargo de la crate. Les appels utilisent ce symbole (ou un target spécialisé possédé par le même `constants.rs`) plutôt quun littéral dispersé.
- **DEP-LOG-011** — `env!("CARGO_PKG_NAME")` ne sert pas de target de tracing/logging KSP : le target appartient au contrat dobservabilité et doit rester explicite dans le code. Les metadata Cargo restent autorisées lorsquelles sont réellement la donnée recherchée, par exemple pour un User-Agent ou une information de build.
## Program / Execution