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

3.9 KiB

Delta 0.1.2-pre.004-fix.003

Base requise

Livraison précédente :

0.1.2-pre.004-fix.002

La base porte :

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 :

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 :

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 :

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 :

outputs
├── console fmt layer, si actif
└── file fmt layer, si actif

Le takeover est ensuite composé devant tout ce groupe :

Targets
    .and_then(outputs)

et ce composite unique devient l'élément du Vec reloadable :

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 :

workspace.package.version = "0.1.2-pre.4.fix.3"

et l'en-tête du Cargo.toml racine devient :

# version: 34

Fichiers du delta

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

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 :

0.1.2-pre.005 — intégration + concurrence + saturation + audits