# Delta 0.1.3-pre.010 ## Base requise Livraison précédente validée : ```text 0.1.3-pre.009-fix.001 ``` Version technique de cette base : ```text workspace.package.version = "0.1.3-pre.9.fix.1" Cargo.toml header version = 51 ``` 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 39 tests unitaires + 7 tests publics pour `ksp-config-lib`. ## Objet de pre.010 Introduire la première résolution environnementale Config réellement consommable : ```text process environment > ./.env > placeholder/API fallback -> ConfigEnvironmentValue -> ${NAME} / ${NAME:-fallback} -> JSON effective values ``` La sensibilité et les représentations sûres restent volontairement réservées à `pre.011`. ## Propriété et sources `ConfigEnvironment` est le snapshot possédé par `ksp-config-lib`. `ConfigEnvironment::load()` : 1. capture les variables supportées héritées par le processus ; 2. lit `./.env` s'il existe ; 3. ne modifie jamais l'environnement du processus, du shell, de systemd ou du parent ; 4. considère l'absence de `.env` comme une source locale vide. Une erreur de lecture réelle de `.env` reste distincte de son absence. Les seuls namespaces applicatifs acceptés sont : ```text KSP_* KSPB_* ``` ce qui couvre naturellement : ```text KSP_PUBLIC_* KSP_SECRET_* KSPB_PUBLIC_* KSPB_SECRET_* ``` ## Priorité et chaîne vide `ConfigEnvironment::resolve_variable(name, fallback)` applique : ```text process > .env > fallback > missing ``` Une chaîne vide explicitement présente dans le processus ou `.env` reste une valeur définie. Elle ne déclenche pas le fallback. `ConfigEnvironmentValue` expose : ```text variable_name value réelle source = Process | DotEnv | Fallback ``` Le type n'implémente volontairement pas `Debug` afin de ne pas créer une voie de fuite accidentelle avant l'introduction de la sensibilité/redaction en `pre.011`. ## Resolver `${...}` Config supporte : ```text ${KSP_VAR} ${KSP_VAR:-fallback} ``` Règles : - plusieurs placeholders peuvent apparaître dans une même string ; - le fallback n'est utilisé que si la variable est absente ; - le fallback est littéral dans cette tranche et n'est pas récursivement interprété ; - les placeholders imbriqués/malformés sont refusés ; - les clés JSON ne sont pas interpolées ; seules les valeurs string le sont ; - objets et tableaux JSON sont parcourus récursivement. APIs principales : ```text ConfigEnvironment::resolve_variable(...) ConfigEnvironment::resolve_text(...) ConfigEnvironment::resolve_json(...) ConfigEnvironment::resolve_map(...) ResolvedConfigProfile::resolve_effective_environment(...) ``` La résolution d'environnement d'un profil produit une nouvelle map effective et ne modifie pas la source, le `profile_id`, la provenance `Global/Profile` ni la sélection du profil déjà résolu. ## Variable manquante Une référence sans valeur process, sans valeur `.env` et sans fallback retourne : ```text config.environment_variable_missing ``` Config émet également un warning via la façade KSP : ```text target = ksp-config-lib domain = config.environment ``` Le warning et l'erreur contiennent le nom de la variable mais jamais sa valeur. `ksp-config-lib` dépend donc maintenant réellement de `ksp-logging-lib`. La dépendance inverse Logging -> Config reste interdite. ## `.env` Le parser Config de cette tranche accepte un sous-ensemble déterministe adapté au fichier KSP géré : - lignes vides et commentaires `#` ; - préfixe optionnel `export ` ; - `NAME=value` ; - valeur non quotée ; - valeur entre quotes simples ; - valeur entre quotes doubles avec escapes bornés `\\`, `\"`, `\n`, `\r`, `\t` ; - commentaire inline d'une valeur non quotée lorsqu'il commence par ` #` ; - chaîne vide ; - clés étrangères valides ignorées par Config ; - doublon d'une clé KSP/KSPB refusé pour éviter une résolution locale ambiguë. Aucune interpolation interne du fichier `.env` n'est ajoutée dans cette tranche. ## `.env.example` — nouvelle règle durable Le dépôt possède désormais à la racine : ```text .env.example ``` Ce fichier est versionné et sert d'inventaire canonique des variables runtime KSP/KSPB utilisées par les fichiers Config ou le code opérationnel. Règles enregistrées : - toute nouvelle variable runtime KSP/KSPB est ajoutée à `.env.example` dans le même delta que sa première utilisation ; - chaque variable est précédée d'un commentaire expliquant son usage/utilité ; - une entrée peut être active avec une valeur par défaut sûre, porter une valeur générique non secrète ou être commentée ; - aucun vrai secret n'y est stocké ; - le fichier local `.env` reste non versionné et non échangé ; - l'objectif est de pouvoir créer `.env` depuis `.env.example` et repérer localement les nouvelles clés par diff. La première entrée est : ```text KSP_LOGS_DIRECTORY=logs ``` car `config/std.logging.json` est actuellement le seul fichier runtime utilisant une variable d'environnement. `.gitignore` possédait déjà : ```text .env .env.* !.env.example ``` et n'a donc pas besoin d'être modifié. ## Tests Les nouveaux tests couvrent notamment : - priorité process > `.env` > fallback ; - chaîne vide process et `.env` considérée comme définie ; - variable manquante sans fallback ; - namespaces KSP/KSPB ; - résolution de plusieurs placeholders ; - placeholder malformé/imbriqué ; - résolution récursive object/array JSON ; - parsing `.env` avec commentaires, `export` et quotes ; - refus des doublons KSP dans `.env` ; - collecte process synthétique sans mutation du vrai environnement ; - résolution du fallback `${KSP_LOGS_DIRECTORY:-logs}` du document Logging commité ; - présence commentée de `KSP_LOGS_DIRECTORY` dans `.env.example` ; - disponibilité de la surface environment depuis le crate-root. Les tests n'appellent pas `std::env::set_var` / `remove_var`; aucune mutation unsafe de l'environnement n'est nécessaire en Rust 2024. ## Dépendances Aucune nouvelle dépendance externe n'est ajoutée. Dépendance KSP désormais utilisée : ```text ksp-config-lib -> ksp-logging-lib ``` pour les warnings/diagnostics runtime Config. Les dépendances externes `serde`, `serde_json` et `jsonschema` restent inchangées. ## Version technique La prerelease devient : ```text workspace.package.version = "0.1.3-pre.10" Cargo.toml header version = 52 ``` ## Fichiers ajoutés ```text .env.example crates/ksp-config-lib/src/environment.rs crates/ksp-config-lib/unit_tests/environment.rs deltas/0.1.3/pre.010.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-config-lib/Cargo.toml crates/ksp-config-lib/src/error.rs crates/ksp-config-lib/src/lib.rs crates/ksp-config-lib/src/profile.rs crates/ksp-config-lib/tests/public_api.rs docs/architecture/005-DEPENDENCY_GRAPH.md docs/plans/000-README.md docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md docs/rules/FILE_CONTRACTS.md docs/rules/RULES_KSP.md ``` ## Fichiers supprimés Aucun. ## Contrôles exécutés dans l'environnement de génération - parsing TOML du manifest racine et de `ksp-config-lib` ; - audit statique des accès `std::env::*` : seul `crates/ksp-config-lib/src/environment.rs` lit l'environnement applicatif ; - audit statique des variables runtime exactes dans `crates/*/src` + `config/` : `KSP_LOGS_DIRECTORY` est la seule clé actuelle et elle est présente dans `.env.example` ; - absence de `unsafe`, `unwrap`, `expect`, `panic!` et `?` dans le nouveau code de production Config ; - contrôle des headers/version et des lignes Rust ajoutées/modifiées ; - comparaison du delta avec la base `pre.009-fix.001` ; - aucun `Cargo.lock` ajouté. 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.011 — sensibilité Public/Internal/Secret + real/safe/provenance + redaction par segment ```