v0.3.11-pre.009

This commit is contained in:
2026-09-08 16:22:40 +02:00
parent 63e1a866a3
commit 822e8fcd86
14 changed files with 747 additions and 99 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/032-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION_PLAN.md -->
<!-- version: 8 -->
<!-- version: 9 -->
# Plan v0.3.11 — fondation runtime du Worker RawTransaction ingest
@@ -738,12 +738,14 @@ Budget cible : **1520 min**. Port privé Store, mode Normal, concurrency born
Budget cible : **1520 min**. `watch` latest-value, compteurs checked, common projection, slow/no listener et terminal retained.
État après matérialisation : **implémenté, gate opérateur requis**. La crate expose `RawTransactionIngestSnapshot` et `RawTransactionIngestSnapshotSource`, ce dernier implémentant directement `ksp-worker-api::WorkerSnapshotSource`. Un unique `watch<RawTransactionIngestSnapshot>` porte la valeur latest-value concrète ; `wait_terminal()` lit ce même flux, supprimant le watch terminal spécialisé de `pre.004`. La séquence `WorkerSnapshotSequence` est donc identique pour la vue concrète et la projection commune. Les compteurs `u64` sont incrémentés par checked-add au point exact où le supervisor dequeue/canonicalise ou récolte une persistence ; l'épuisement devient `worker_raw_transaction_ingest.counter_exhausted`. Les profondeurs de queue et de persistence sont dérivées des structures bornées existantes, sans tâche de monitoring ni seconde event queue. `source_failure_total` et `backpressure_wait_total` existent dans le contrat sûr mais restent à zéro dans cette tranche source-neutral ; `pre.009` est propriétaire du fault source et de l'instrumentation de saturation. Les tests couvrent projection common/concrete, listener lent coalescé, terminal retenu, counters de pipeline réussi et Store fault projeté `Unhealthy`.
État après matérialisation : **implémenté et gate opérateur validé après `pre.008-fix.001`**. La crate expose `RawTransactionIngestSnapshot` et `RawTransactionIngestSnapshotSource`, ce dernier implémentant directement `ksp-worker-api::WorkerSnapshotSource`. Un unique `watch<RawTransactionIngestSnapshot>` porte la valeur latest-value concrète ; `wait_terminal()` lit ce même flux. La séquence `WorkerSnapshotSequence` est identique pour la vue concrète et la projection commune. Les compteurs `u64` utilisent checked-add ; `source_failure_total` et `backpressure_wait_total` existent mais restent à zéro jusqu'à `pre.009`. Le correctif `pre.008-fix.001` a uniquement résolu `clippy::collapsible_if` dans `runtime.rs`, sans modifier comportement, dépendance ni feature. Le gate communiqué le 8 septembre 2026 est vert sur `fmt`, audits, `check`, Clippy strict, 38 tests de crate et doc-tests. Aucun arbre Cargo n'a été requis car aucune dépendance/feature n'avait changé.
### `pre.009` — hardening shutdown/backpressure/fault races
Budget cible : **1520 min**. Drain deadline, stop/fault ordering, saturation, source failure, Store slow/failure, abort+join au timeout, no orphan tasks. Scinder immédiatement si le gate réel dépasse le budget.
État après matérialisation : **implémenté, gate opérateur requis**. Les tâches source privées retournent désormais `ksp_core_lib::Result<()>` dans le `JoinSet` du supervisor ; une erreur source ou un `JoinError` devient `worker_raw_transaction_ingest.source_failed` et incrémente `source_failure_total` sans exposer de texte provider. Le shutdown possède une deadline stricte `shutdown_drain_timeout` ; au timeout, admission, persistences et sources sont fermées/abortées puis toutes rejointes avant `Faulted(worker_raw_transaction_ingest.drain_timeout)`. Le stop reste prioritaire dans le `select!`, mais un Store fault découvert pendant le drain n'est pas masqué par un stop antérieur ; un fault terminal déjà décidé n'est pas remplacé par un stop tardif. La saturation est instrumentée de façon source-neutral au dequeue d'une queue `mpsc` pleine via `backpressure_wait_total`, sans drop ni queue non bornée. Les tests déterministes couvrent source failure, stop/Store fault, saturation et timeout avec absence de tâches orphelines. Aucune source live, aucun Transport, aucun backend direct et aucune nouvelle dépendance/feature ne sont introduits.
### `pre.010` — hardening public/release/security
Budget cible : **1015 min**. Tests externes exacts : API root, dependencies, historical-surface absence, redaction, error codes, module inventory et scans Config/secret/backend.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/028-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION.md -->
<!-- version: 11 -->
<!-- version: 12 -->
# Validation v0.3.11 — fondation runtime du Worker RawTransaction ingest
@@ -1301,3 +1301,106 @@ cargo test -p ksp-worker-raw-transaction-ingest-lib
Critère de passage : snapshots common/concrete latest-value, compteurs checked, terminal retenu et absence de nouveau boundary crossing sont verts.
## 20. `pre.009` — hardening shutdown/backpressure/fault races
### 20.1 Clôture opérateur de `pre.008-fix.001`
Le gate communiqué le 8 septembre 2026 est vert :
```text
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
Markdown table audit: clean (340 table(s), 785 file(s))
cargo check --workspace: PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings: PASS
29 unit tests: PASS
3 dependency-boundary tests: PASS
6 public API tests: PASS
doc-tests: PASS
```
Aucune dépendance ni feature n'avait changé ; aucun `cargo tree` intermédiaire n'était requis.
### 20.2 Classification des faults source
Les tâches source privées sont possédées par :
```text
tokio::task::JoinSet<ksp_core_lib::Result<()>>
```
Une `Err` source ou un `JoinError` est réduite à :
```text
worker_raw_transaction_ingest.source_failed
```
Le texte de l'erreur source n'est jamais recopié. `source_failure_total` est incrémenté avec la même discipline checked que les autres compteurs.
### 20.3 Deadline de drain et absence d'orphelins
Le drain complet est borné par `shutdown_drain_timeout` via `tokio::time::timeout`. Si la deadline expire :
```text
fermeture admission
abort_all des persistences
abort_all des tâches source
join complet des deux JoinSet
Faulted(worker_raw_transaction_ingest.drain_timeout)
```
Aucun terminal n'est publié avant la récolte des tâches possédées.
### 20.4 Priorité stop/fault
Le stop reste la branche prioritaire du `select!`. Cette priorité n'efface cependant pas un Store fault découvert pendant le drain déjà engagé. Réciproquement, un fault terminal décidé avant un stop tardif demeure le terminal retenu. Le timeout de drain prévaut lorsqu'il empêche la fermeture coopérative complète.
### 20.5 Saturation et backpressure
La queue d'admission demeure le `mpsc` borné de `pre.006`. Le supervisor observe, avant dequeue, si la queue est à sa capacité configurée ; cette observation source-neutral incrémente `backpressure_wait_total`. Aucun élément n'est droppé, aucune seconde queue et aucun `unbounded_channel` ne sont introduits.
### 20.6 Preuves ajoutées
Les tests `pre.009` couvrent :
```text
source failure -> source_failed + source_failure_total
stop tardif ne remplace pas source_failed
stop avant Store fault -> Store fault terminal après drain
queue capacity=1 + persistence concurrency=1 -> saturation observable sans drop
drain timeout -> abort + join source et persistence
aucune tâche source/persistence active après terminal timeout
projection snapshot conserve les compteurs source/backpressure
error codes source_failed/drain_timeout publics et stables
aucun nouvel edge de dépendance
```
### 20.7 Hors scope conservé
`pre.009` n'introduit toujours aucun :
```text
source live
Transport
Config
backend Store direct
retry / reconnect
gap repair / replay live
provider capability public
```
### 20.8 Gate opérateur demandé pour `pre.009`
Aucune dépendance ni feature n'est modifiée ; aucun `cargo tree` intermédiaire n'est requis :
```bash
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p ksp-worker-raw-transaction-ingest-lib
```
Critère de passage : races stop/fault déterministes, timeout borné sans tâche orpheline, saturation observable sans drop et frontières de dépendances inchangées.