# Delta 0.1.3-pre.006 ## Base requise Livraison précédente validée : ```text 0.1.3-pre.005-fix.001 ``` Version technique de cette base : ```text workspace.package.version = "0.1.3-pre.5.fix.1" Cargo.toml header version = 46 ``` 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-logging-lib OK cargo tree -p ksp-logging-lib -d OK — aucune duplication cargo tree -p ksp-logging-lib -e features OK ``` Le fix JSON de `pre.005` est donc clos avant ouverture de cette tranche. ## Objet de pre.006 Fermer la troisième dimension de routing déjà représentée par `OutputFilter` : ```text level target domain ``` `domain` reste un champ structuré indépendant du target. Cette tranche ne change pas les contrats Config et ne crée encore aucun document JSON Config. ## Domain effectif Le runtime applique la sémantique suivante : 1. un event portant directement `domain` utilise cette valeur ; 2. sinon l'event hérite du domain effectif de son span ; 3. un span portant directement `domain` définit son domain effectif ; 4. un span sans `domain` hérite du domain effectif de son parent au moment de sa création ; 5. un span enfant explicite peut donc remplacer le domain hérité ; 6. les lifecycle events `NEW`, `ENTER`, `EXIT` et `CLOSE` utilisent le domain effectif du span concerné. Un domain direct d'event ne modifie pas le domain mémorisé du span. ## Routing par output Le writer routé applique maintenant conjointement : ```text OutputFilter.level OutputFilter.targets[] OutputFilter.domains[] ``` Pour `domains[]` : - `["*"]` signifie aucune restriction et accepte aussi un event/span sans domain ; - un selector nommé correspond par préfixe ; - un selector nommé ne correspond jamais à une entrée sans domain. La politique globale existante reste distincte : ```text default_filter + TargetFilter[] ↓ DomainContextLayer + groupe de sinks ↓ OutputFilter level/target/domain de chaque sink ``` Aucune convention de pseudo-target domain n'est introduite. ## Couche interne de contexte `DomainContextLayer` est une couche privée de `ksp-logging-lib` installée avant les formatters lorsque le runtime possède au moins un output actif. Elle : - capture le champ `domain` des events et spans ; - conserve le domain effectif d'un span dans ses extensions runtime ; - expose uniquement au routing interne le domain effectif correspondant au callback en cours ; - conserve les champs originaux pour les formatters Human/Compact/Pretty/Json ; - n'ajoute aucun type public et ne change pas la façade consommateur. Le contexte courant utilisé par le routing reste interne au thread de dispatch Logging et n'est pas une variable globale Config/applicative. ## Runtime préservé Cette tranche conserve sans changement de contrat : - subscriber global unique ; - takeover des targets externes ; - multi-sink ; - formats Human/Compact/Pretty/Json ; - ANSI console et stripping fichier ; - writers non bloquants ; - guards et compteurs par `output_id` ; - hot reload transactionnel ; - comportement de saturation. Le refus transitoire `domains != ["*"]` introduit en `pre.005` est supprimé puisque la dimension domain est maintenant exécutée réellement. ## Tests Les tests unitaires couvrent : - wildcard domain avec ou sans domain courant ; - selector nommé absent sans domain ; - correspondance par préfixe ; - acceptation runtime d'un filtre domain spécifique. Le test d'intégration global ajoute trois sinks simultanés : ```text file.domain.logging -> domains = ["logging"] file.domain.store -> domains = ["store"] file.domain.any -> domains = ["*"] ``` Il couvre : - domain direct d'event ; - event sans domain ; - héritage depuis un span parent ; - override direct d'event ; - enfant sans domain ; - enfant avec domain explicite ; - lifecycle de spans Logging/Store ; - maintien des compteurs à zéro dans le scénario nominal. ## Dépendances Aucune nouvelle dépendance et aucune nouvelle feature Cargo ne sont ajoutées. `ksp-logging-lib` reste le seul propriétaire direct de la stack `tracing*` et ne dépend toujours pas de `ksp-config-lib`. ## Plan Les trois tranches Logging nécessaires avant le premier schema Config sont désormais fonctionnellement couvertes : ```text pre.004 contrats/settings multi-output pre.005 runtime multi-sink + level/target/formats pre.006 routing structuré domain ``` Après validation utilisateur de `pre.006`, la prochaine tranche est : ```text pre.007 JSON/JSON Schema + std.logging.json ``` ## Version technique La prerelease devient : ```text workspace.package.version = "0.1.3-pre.6" Cargo.toml header version = 47 ``` ## Fichiers ajoutés ```text crates/ksp-logging-lib/src/domain.rs crates/ksp-logging-lib/unit_tests/domain.rs deltas/0.1.3/pre.006.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-logging-lib/README.md crates/ksp-logging-lib/TODO.md crates/ksp-logging-lib/USAGE.md crates/ksp-logging-lib/src/lib.rs crates/ksp-logging-lib/src/runtime.rs crates/ksp-logging-lib/src/writer.rs crates/ksp-logging-lib/tests/runtime.rs crates/ksp-logging-lib/unit_tests/runtime.rs docs/plans/000-README.md docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md ``` ## Hors scope Cette tranche ne modifie pas : - `ksp-config-lib` ; - le registre `file_id` ; - JSON/JSON Schema ; - `std.logging.json` ; - profils/composites ; - `.env` ou les variables d'environnement ; - persistence Config. ## Validations à exécuter ```bash cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets cargo test --workspace cargo tree -p ksp-logging-lib cargo tree -p ksp-logging-lib -d cargo tree -p ksp-logging-lib -e features ``` Aucune validation Cargo n'est déclarée réussie tant qu'elle n'a pas été exécutée sur le workspace utilisateur.