Files
khadhroony-solana-project/deltas/0.1.2/pre.004-fix.003.md

132 lines
3.9 KiB
Markdown

<!-- file: deltas/0.1.2/pre.004-fix.003.md -->
<!-- version: 1 -->
# Delta 0.1.2-pre.004-fix.003
## Base requise
Livraison précédente :
```text
0.1.2-pre.004-fix.002
```
La base porte :
```text
workspace.package.version = "0.1.2-pre.4.fix.2"
Cargo.toml header version = 33
```
## Validation remontée
Après application de `pre.004-fix.002` :
```text
cargo fmt --all OK
cargo check --workspace OK
cargo clippy --workspace --all-targets OK
cargo test --workspace ECHEC
```
Le marqueur fichier précédemment absent est désormais correctement persisté et les assertions de présence du target, du callsite et d'absence d'ANSI passent. Le test runtime global échoue plus loin sur :
```text
assertion failed: !file_text.contains("external marker must remain silent")
```
Le défaut restant concerne donc exclusivement le takeover : un événement `tracing` émis directement avec le target externe `sqlx` atteint encore le sink fichier alors que la politique KSP exige son silence total.
## Cause réelle
`pre.003-fix.001` avait évité le panic `Filtered`/`FilterId` en plaçant `Targets` comme layer global distinct dans le même :
```text
Vec<Box<dyn Layer<Registry>>>
```
que les formatters.
Cette composition n'est toutefois pas correcte pour le filtrage global au niveau des callsites. L'implémentation `Layer` de `Vec<L>` agrège `register_callsite` en conservant l'intérêt le plus élevé retourné par ses enfants. Un `fmt::Layer` intéressé par le callsite peut donc produire un intérêt actif alors que `Targets` retourne `Interest::never()` pour un target externe.
Lorsque le callsite est enregistré comme toujours actif, `enabled()` n'est ensuite pas consulté à chaque émission. Le `Targets` frère du formatter ne peut donc plus bloquer l'événement externe.
Le test avec `sqlx` expose précisément cette fuite.
## Correction
Les layers de sortie sont d'abord construits dans un `Vec` :
```text
outputs
├── console fmt layer, si actif
└── file fmt layer, si actif
```
Le takeover est ensuite composé **devant tout ce groupe** :
```text
Targets
.and_then(outputs)
```
et ce composite unique devient l'élément du `Vec` reloadable :
```text
reload::Layer
└── Vec
└── Targets -> output layers
```
Cette forme rétablit la sémantique de filtre global : un `Interest::never()` produit par `Targets` court-circuite le groupe de sinks avant leur formatter.
Elle conserve simultanément les propriétés requises :
- aucun `Layer::with_filter` n'est utilisé sur un layer remplacé à chaud ;
- aucun `Filtered` et donc aucun `FilterId` reloadable n'est introduit ;
- console et fichier restent activables/désactivables dynamiquement ;
- `Handle::modify` continue de récupérer l'ancien composite avant destruction de ses `WorkerGuard` ;
- la sanitization console et le stripping ANSI fichier de `fix.002` restent inchangés ;
- l'API publique reste inchangée.
Le test d'intégration runtime conserve son assertion directe sur un événement `tracing::error!` de target `sqlx`. Il reste donc le test de non-régression du takeover effectif, au-delà du test unitaire de `Targets::would_enable`.
## Version technique
Ce correctif modifie du Rust. La version workspace devient :
```text
workspace.package.version = "0.1.2-pre.4.fix.3"
```
et l'en-tête du `Cargo.toml` racine devient :
```text
# version: 34
```
## Fichiers du delta
```text
Cargo.toml
crates/ksp-logging-lib/src/runtime.rs
crates/ksp-logging-lib/unit_tests/runtime.rs
docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md
deltas/0.1.2/pre.004-fix.003.md
```
## Validations à exécuter
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
```
Aucune dépendance n'est modifiée par ce fix. Après validation propre, la tranche suivante reste :
```text
0.1.2-pre.005 — intégration + concurrence + saturation + audits
```