Files
2026-08-16 05:01:33 +02:00

7.9 KiB

Delta 0.1.3-pre.012

Base requise

Livraison précédente validée :

0.1.3-pre.011-fix.001

Version technique de cette base :

workspace.package.version = "0.1.3-pre.11.fix.1"
Cargo.toml header version = 55

Validations utilisateur exécutées le 2026-08-16 :

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-logging-lib -d         OK, aucun doublon

cargo test --workspace confirme notamment 61 tests unitaires + 9 tests publics pour ksp-config-lib.

Objet de pre.012

Construire la première frontière runtime complète possédée par Config :

cfg.std.logging
    -> JSON + schema + invariants source
    -> profil sélectionné
    -> process > .env > fallback
    -> real/safe/sensitivity/provenance
    -> validation effective
    -> ksp_logging_lib::LoggingSettings

Cette tranche ne modifie pas encore les documents Config et ne persiste rien.

ResolvedLoggingConfig

Nouveau contrat public :

ResolvedLoggingConfig

Il conserve :

file_id
source_path
profile_id
selection_source
effective ResolvedConfigJson
logs_directory résolu
LoggingSettings

Son Debug manuel n'affiche pas directement LoggingSettings ni le root réel. Il s'appuie sur ResolvedConfigJson::Debug, donc sur l'arbre sûr/redacted.

Les consumers légitimes peuvent obtenir :

settings()
into_settings()
logs_directory()
effective()

Le LoggingGuard n'est jamais stocké par Config : il reste détenu par l'orchestration qui appelle ksp_logging_lib::initialize/reinitialize.

Entrée de l'adapter

ConfigDocumentEngine ajoute :

load_resolved_logging_config(requested_profile, environment)

La méthode :

  1. charge cfg.std.logging ;
  2. applique le profil par défaut ou le profil explicite ;
  3. résout les placeholders avec le snapshot ConfigEnvironment ;
  4. conserve la vue réelle/sûre et la provenance ;
  5. valide la configuration effective ;
  6. mappe les valeurs vers les contrats publics ksp_logging_lib::* ;
  7. exécute enfin LoggingSettings::validate().

Mapping Logging

Le mapping couvre explicitement :

LogFilterLevel
SpanEvents
ConsoleOutput
LogFormat
FileRotation
OutputFilter
TargetFilter
ConsoleSettings
FileSettings[]
LoggingSettings

Le document commité local_dev doit donc produire les deux sinks fichier déjà déclarés et leurs filtres level/target/domain, ainsi que les deux overrides globaux de target.

logs_directory

Après interpolation :

  • un chemin absolu est conservé ;
  • un chemin relatif est ancré sur le current working directory du processus au moment de l'adaptation ;
  • un root inexistant est accepté : Logging créera les répertoires requis lors de l'initialisation des appenders ;
  • un root existant qui n'est pas un directory est rejeté ;
  • une erreur filesystem autre que NotFound pendant l'inspection est rejetée.

Le fallback ${KSP_LOGS_DIRECTORY:-logs} s'applique uniquement si KSP_LOGS_DIRECTORY est absent.

Une valeur explicitement présente mais vide :

KSP_LOGS_DIRECTORY=

reste une valeur présente et produit :

config.effective_config_invalid

Elle ne retombe jamais silencieusement sur logs.

Chemins des sinks

Les files[].path restent relatifs sous logs_directory.

L'invariant est désormais contrôlé deux fois :

  1. sur le document source ;
  2. après interpolation environnementale.

La seconde validation empêche par exemple une valeur environnementale de transformer dynamiquement un path relatif en :

../outside.log
/var/log/outside.log

L'adapter sépare ensuite le path relatif en :

directory relatif
file-name prefix

puis construit FileSettings sous le root Logging résolu.

Frontière secrets

Le document standard Logging n'a aucun besoin fonctionnel de secret.

L'adapter refuse donc toute configuration effective dont ResolvedConfigJson::sensitivity() est Secret.

Cette règle évite de transmettre une vraie valeur secrète à LoggingSettings, puis potentiellement à des diagnostics filesystem de ksp-logging-lib.

Les erreurs finales de LoggingSettings::validate() sont encapsulées dans config.effective_config_invalid avec seulement :

logging_error_domain
logging_error_code

Les contextes internes de l'erreur Logging ne sont pas recopiés par Config.

Démonstration runtime

Un test Config utilise le document commité, un root temporaire et le vrai runtime Logging afin de démontrer :

Config -> LoggingSettings -> initialize -> reinitialize

Le test vérifie aussi que l'initialisation des appenders crée les sous-répertoires configurés lorsqu'ils n'existent pas, puis recharge une configuration sans outputs avant cleanup.

Diagnostics et erreurs

Nouveau code stable :

config.effective_config_invalid

Il distingue une source JSON/schema valide d'une configuration devenue invalide après environnement/adaptation runtime.

Les diagnostics Config de paths utilisent une représentation sûre lorsque la valeur pourrait provenir d'un resolver détaillé.

Règles documentaires

Deux règles KSP deviennent durables :

KSP-CONFIG-012
KSP-CONFIG-013

Elles fixent respectivement :

  • la sémantique absolu/relatif/CWD/fallback de logs_directory ;
  • l'interdiction de secrets dans le standard Logging effectif.

FILE_CONTRACTS.md enregistre également la revalidation post-interpolation de files[].path.

.env.example

Aucune nouvelle variable runtime n'est introduite.

.env.example reste inchangé :

KSP_LOGS_DIRECTORY=logs

Dépendances

Aucune nouvelle dépendance Cargo.

La direction reste :

ksp-config-lib -> ksp-logging-lib
ksp-logging-lib -X-> ksp-config-lib

Tests ajoutés

Le nouveau module unit_tests/logging.rs couvre notamment :

  • mapping complet du profil local_dev ;
  • root relatif ancré au CWD ;
  • root absolu conservé ;
  • valeur explicite vide rejetée sans fallback ;
  • root existant non-directory rejeté ;
  • paths fichier effectifs sans escape ;
  • frontière Secret de Logging et canary sans fuite ;
  • Debug de ResolvedLoggingConfig ;
  • initialize/reinitialize réel et création des répertoires de sinks.

La surface publique ajoute un test d'adressabilité de ResolvedLoggingConfig, de la méthode adapter et du nouveau code d'erreur.

Après ajout, la crate contient 70 tests unitaires Config et 10 tests publics à exécuter chez l'utilisateur.

Fichiers ajoutés

crates/ksp-config-lib/src/logging.rs
crates/ksp-config-lib/unit_tests/logging.rs
deltas/0.1.3/pre.012.md

Fichiers modifiés

Cargo.toml
crates/ksp-config-lib/src/environment.rs
crates/ksp-config-lib/src/error.rs
crates/ksp-config-lib/src/lib.rs
crates/ksp-config-lib/tests/public_api.rs
docs/rules/RULES_KSP.md
docs/rules/FILE_CONTRACTS.md
docs/plans/000-README.md
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md

Hors scope

Toujours hors pre.012 :

  • mutation/persistence JSON ;
  • create/update/remove .env ;
  • reveal secret de management ;
  • application desktop Config ;
  • watcher/reload automatique de Config ;
  • autres documents standard Store/Wallet/Transport.

Ces sujets commencent avec pre.013 ou les releases prévues ultérieurement.

Validation demandée

cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
cargo tree -p ksp-config-lib
cargo tree -p ksp-config-lib -d
cargo tree -p ksp-config-lib -e features
cargo tree -p ksp-logging-lib -d

Aucune validation Cargo locale n'est revendiquée dans l'environnement de génération de ce delta.