# Delta 0.1.3-pre.011 ## Base requise Livraison précédente validée : ```text 0.1.3-pre.010-fix.001 ``` Version technique de cette base : ```text workspace.package.version = "0.1.3-pre.10.fix.1" Cargo.toml header version = 53 ``` Validations utilisateur exécutées le 2026-08-15 : ```text cargo fmt --all OK cargo check --workspace OK cargo clippy --workspace --all-targets OK cargo test --workspace OK cargo tree -p ksp-config-lib OK cargo tree -p ksp-config-lib -d OK, doublon transitif syn 2/3 déjà connu cargo tree -p ksp-config-lib -e features OK ``` `cargo test --workspace` confirme notamment 53 tests unitaires + 8 tests publics pour `ksp-config-lib`. ## Objet de pre.011 Ajouter la couche de sécurité/provenance qui manquait au resolver environnemental : ```text Config source string / JSON + process > .env > fallback -> real runtime value safe diagnostic value Public | Internal | Secret ordered / JSON-Pointer provenance ``` Cette tranche ne modifie pas encore les documents Config, ne construit pas `LoggingSettings` et ne persiste rien. ## Classification de sensibilité `ConfigSensitivity` expose : ```text Public Internal Secret ``` Classification nominale : ```text KSP_SECRET_* / KSPB_SECRET_* -> Secret KSP_PUBLIC_* / KSPB_PUBLIC_* -> Public autre KSP_* / KSPB_* -> Internal ``` Ordre : ```text Secret > Internal > Public ``` La sensibilité d'une chaîne contenant des placeholders est la sensibilité la plus forte des placeholders effectivement référencés. Une chaîne littérale sans placeholder est `Internal`. Un fallback hérite toujours de la sensibilité du nom de variable référencé. Ainsi : ```text ${KSP_SECRET_TOKEN:-false-secret} ``` reste `Secret` même si la valeur réelle vient du fallback. ## Valeur réelle et représentation sûre `ConfigEnvironmentValue` conserve désormais : ```text variable_name value réel runtime safe_value diagnostic sûr sensitivity source Process | DotEnv | Fallback provenance ``` Pour `Secret` : ```text value = valeur réelle safe_value = ******** ``` Pour `Public` et `Internal`, la représentation sûre conserve la valeur réelle dans cette tranche. `ConfigEnvironmentValue` possède un `Debug` manuel qui n'affiche jamais `value`; il affiche `safe_value`, sensibilité, source et nom de variable. ## Chaînes composées Nouveau contrat : ```text ResolvedConfigText ``` Il conserve : ```text value safe_value sensitivity provenance[] ``` Exemple : ```text source: https://${KSP_PUBLIC_HOST}/?token=${KSP_SECRET_TOKEN} real: https://rpc.example.test/?token=secret-canary safe: https://rpc.example.test/?token=******** ``` La redaction est réalisée par segment de substitution. Les fragments littéraux et non secrets restent visibles dans la représentation sûre. `ConfigEnvironment::resolve_text_detailed()` expose ce contrat. L'API existante : ```text resolve_text(...) ``` reste compatible et retourne uniquement la valeur réelle. ## Provenance `ConfigValueProvenance` distingue : ```text DocumentLiteral EnvironmentProcess { variable_name } EnvironmentDotEnv { variable_name } EnvironmentFallback { variable_name } ``` La provenance n'embarque jamais la valeur d'environnement elle-même. Une chaîne composée conserve l'ordre des segments/références ayant participé à sa construction. ## JSON détaillé Nouveau contrat : ```text ResolvedConfigJson ``` Il conserve : ```text value arbre JSON réel safe_value arbre JSON redacted sensitivity plus forte sensibilité contenue provenance map JSON Pointer -> provenance[] ``` `ConfigEnvironment::resolve_json_detailed()` parcourt récursivement objets et tableaux sans modifier les clés. Les JSON Pointer suivent RFC 6901 pour les clés contenant `~` ou `/`. L'API existante : ```text resolve_json(...) resolve_map(...) ``` reste compatible et retourne uniquement la valeur réelle. ## Profil effectif `ResolvedConfigProfile` ajoute : ```text resolve_effective_environment_detailed(...) ``` La provenance top-level déjà existante : ```text Global Profile ``` reste attachée au profil source via `origin(key)`. La résolution détaillée ajoute séparément la provenance de la couche environnement : ```text DocumentLiteral Process DotEnv Fallback ``` L'ancienne méthode `resolve_effective_environment()` reste disponible et retourne seulement la map réelle. ## Non-divulgation Les tests canary vérifient notamment : - secret venant du process : réel disponible, safe redacted, `Debug` sans canary ; - secret venant d'un fallback : fallback réel disponible mais safe redacted ; - URL composée public + secret : seul le segment secret est masqué ; - JSON imbriqué : arbre réel complet, arbre safe redacted, `Debug` sans canary ; - provenance de la variable sans transport de la valeur elle-même. `ksp-logging-lib` ne reçoit aucune logique générique de redaction de messages arbitraires. La valeur sûre est construite par Config avant qu'un diagnostic ne l'utilise. ## Clarification `KSP_LOGS_DIRECTORY` La décision préparatoire de l'adapter `pre.012` est enregistrée dans le plan : - après interpolation, `logs_directory` pourra être absolu ou relatif ; - un chemin relatif sera interprété relativement au current working directory du processus qui initialise Logging, pas automatiquement au répertoire du binaire ; - le fallback `logs` s'applique seulement si `KSP_LOGS_DIRECTORY` est absent ; - une valeur explicitement présente mais invalide ne déclenche pas le fallback et devra produire un diagnostic de configuration effective invalide ; - les paths de sinks restent relatifs sous `logs_directory` sans traversal. Aucun code de validation/conversion Logging correspondant n'est ajouté dans `pre.011`; cette responsabilité appartient à `pre.012`. ## `.env.example` Aucune nouvelle variable runtime n'est introduite. `.env.example` reste donc inchangé et contient toujours la seule variable actuellement utilisée : ```text KSP_LOGS_DIRECTORY=logs ``` ## Dépendances Aucune dépendance ou feature Cargo n'est ajoutée/modifiée. La direction reste : ```text ksp-config-lib -> ksp-logging-lib -> ksp-core-lib ksp-config-lib -> ksp-core-lib ``` Logging ne dépend toujours pas de Config. ## Version technique La prerelease devient : ```text workspace.package.version = "0.1.3-pre.11" Cargo.toml header version = 54 ``` ## Fichiers ajoutés ```text crates/ksp-config-lib/src/sensitivity.rs crates/ksp-config-lib/unit_tests/sensitivity.rs deltas/0.1.3/pre.011.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-config-lib/src/environment.rs crates/ksp-config-lib/src/lib.rs crates/ksp-config-lib/src/profile.rs crates/ksp-config-lib/tests/public_api.rs crates/ksp-config-lib/unit_tests/environment.rs docs/plans/000-README.md docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md docs/rules/RULES_KSP.md ``` ## Fichiers supprimés Aucun. ## Contrôles exécutés dans l'environnement de génération - comparaison statique avec la base validée `pre.010-fix.001` ; - absence de nouvelle dépendance/feature Cargo ; - absence de nouvelle variable runtime nécessitant une modification de `.env.example` ; - audit statique du nouveau code Config contre `unsafe`, `unwrap`, `expect`, `panic!` et opérateur `?` de production ; - contrôle des headers/version ; - contrôle des lignes Rust à 160 colonnes maximum ; - contrôle canary dans les tests : les représentations safe/Debug attendues ne contiennent pas le secret ; - reproduction du delta sur la base précédente avant packaging. Le toolchain Rust n'est pas disponible dans l'environnement de génération. `cargo fmt/check/clippy/test` doivent donc être exécutés par l'utilisateur. ## Étape suivante Après validation utilisateur : ```text 0.1.3-pre.012 — adapter Config -> Logging ``` Cette tranche devra notamment valider/résoudre `logs_directory`, convertir le profil Logging effectif vers les contrats publics `ksp_logging_lib::*` et démontrer `initialize/reinitialize` sans créer de dépendance Logging -> Config.