v0.3.11-pre.007

This commit is contained in:
2026-09-08 11:32:41 +02:00
parent 355c5d1e9a
commit ed6c0ac10c
12 changed files with 1239 additions and 58 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/028-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION.md -->
<!-- version: 9 -->
<!-- version: 10 -->
# Validation v0.3.11 — fondation runtime du Worker RawTransaction ingest
@@ -1014,3 +1014,162 @@ cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features
Critère de passage : admission bornée/backpressure, stop-preemption, canonicalisation common, golden observation et assembly sont verts ; aucune persistence Store, source live, Transport ou snapshot concret n'apparaît.
## 18. Fermeture opérateur `pre.006-fix.001` et matérialisation `pre.007`
### 18.1 Fermeture opérateur de `pre.006-fix.001`
Le journal opérateur communiqué le 8 septembre 2026 ferme `0.3.11-pre.006-fix.001` (`workspace.package.version = 0.3.11-pre.6.fix.1`) :
```text
cargo fmt --all : terminé sans erreur
python3 scripts/audit_rust_workspace_rules.py : clean, export completeness 0
python3 scripts/audit_markdown_tables.py ... : clean (340 tables, 782 files)
cargo check --workspace : terminé sans erreur
cargo clippy --workspace --all-targets --all-features -- -D warnings : terminé sans erreur
cargo test -p ksp-worker-raw-transaction-ingest-lib : 15 unit + 3 dependency-boundary + 4 public API PASS, 0 échec
doc-tests : PASS
```
Aucun `cargo tree` n'a été rejoué après ce fix. Ce choix ne laisse pas de gap de dépendance : `pre.006-fix.001` modifie uniquement `Cargo.toml` pour le numéro de version, un test Rust et son delta ; aucune dépendance ni feature n'est ajoutée, retirée ou modifiée.
`pre.007` peut donc être ouverte.
### 18.2 Port Store privé et mode Normal
`pre.007` ajoute `RawTransactionIngestPersistencePort`, strictement crate-private. Son implémentation productive vise uniquement `ksp_store_lib::Store` et délègue à :
```text
RawTransactionWrite::persist_raw_transaction_acquisition(..., RawTransactionAcquisitionMode::Normal)
```
Le port ne connaît aucun backend concret. Il vérifie le network avant write et l'alignement exact entre transaction et observation. Le Store reste source de vérité ; aucun cache de déduplication mémoire n'est ajouté.
### 18.3 Classification entity + observation
Les succès Store admis en mode Normal sont classifiés exactement :
```text
Inserted + Inserted -> entity Inserted / observation Inserted
AlreadyPresent + Inserted -> entity AlreadyPresent / observation Inserted
AlreadyPresent + AlreadyPresent -> entity AlreadyPresent / observation AlreadyPresent
SkippedPurged + NotRecorded -> entity SkippedPurged / observation NotRecorded
```
`Rehydrated` est interdit en mode Normal. Toute combinaison non définie ci-dessus devient `worker_raw_transaction_ingest.runtime_invalid` et n'est jamais traitée comme un succès silencieux.
### 18.4 Content conflict et Store failure
Deux ErrorCode publics sont ouverts parce qu'ils deviennent réellement observables dans cette tranche :
```text
worker_raw_transaction_ingest.content_conflict
worker_raw_transaction_ingest.store_failed
```
Mapping :
```text
ksp_store_lib::ERROR_CODE_RAW_CONFLICT -> content_conflict
autre erreur Store -> store_failed
```
Pour `store_failed`, le Worker ne conserve que `store_domain` et `store_code`, issus du `ErrorCode` inférieur déjà sûr. Le message/source arbitraire Store n'est pas copié dans l'erreur Worker, le handle ou le terminal.
### 18.5 Concurrence bornée de persistence
Le supervisor possède un `JoinSet` privé de futures de persistence. Il n'exécute la branche admission que lorsque :
```text
persistence.len() < settings.persistence_concurrency()
```
Il n'existe ni sémaphore supplémentaire, ni queue de persistence non bornée. Sous saturation de persistence, le supervisor attend une complétion Store avant de retirer une nouvelle acquisition de la queue centrale ; la backpressure remonte ainsi jusqu'au `mpsc` borné.
Le harness avec `persistence_concurrency = 2` bloque volontairement les écritures Store et prouve que `max_active == 2` avec quatre acquisitions admises.
### 18.6 Drain et terminal de `pre.007`
Lors d'un stop normal, d'un content conflict ou d'une erreur Store :
```text
signaler le stop privé aux sources si fault
fermer les nouvelles admissions
canonicaliser/persister les acquisitions déjà admises
attendre toutes les persistences en vol
attendre toutes les tâches source
publier Stopped ou le premier Faulted retenu
```
Cette tranche ne fige pas encore la priorité complète des courses stop/fault et n'introduit aucun timeout/abort ; ces responsabilités restent dans `pre.009`.
### 18.7 Preuves ajoutées
Les tests `pre.007` couvrent :
```text
mode Store exactement Normal
Inserted / AlreadyPresent / SkippedPurged
observation Inserted / AlreadyPresent / NotRecorded
Rehydrated et couples impossibles -> runtime_invalid
network mismatch avant write
content conflict -> ErrorCode Worker terminal dédié
Store failure -> ErrorCode Worker dédié sans texte distant
persistence_concurrency réellement bornée à 2
content conflict runtime -> terminal Faulted(content_conflict)
Store failure runtime -> terminal Faulted(store_failed)
public API -> deux ErrorCode stables depuis crate-root
dependency boundary -> persistence privée requise, backend/Transport/snapshot interdits
```
### 18.8 Frontière volontaire de `pre.007`
La tranche n'introduit toujours aucun :
```text
backend Store direct
ForceRehydrate
source live
Transport
Config
snapshot concret / compteurs publics
source_failed
counter_exhausted
drain_timeout / abort forcé
retry / reconnect / gap repair
```
`pre.008` reste propriétaire des snapshots/counters. `pre.009` reste propriétaire du hardening shutdown, du timeout/abort et des courses fault/stop.
### 18.9 Preuves locales d'assemblage `pre.007`
Exécuté dans l'environnement d'assemblage :
```text
python3 scripts/audit_rust_workspace_rules.py
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
Markdown table audit: clean
scan production : aucun unwrap, expect, panic, unbounded_channel
scan scope : aucun ksp-store-postgres-lib, aucun Transport, aucun snapshot concret
```
L'environnement d'assemblage ne fournit ni `cargo`, ni `rustc`, ni `rustfmt`. Aucun gate Cargo de `pre.007` n'est déclaré PASS localement.
### 18.10 Gate opérateur demandé pour `pre.007`
Aucune dépendance ni feature n'étant modifiée par `pre.007`, aucun `cargo tree` intermédiaire n'est requis. Le gate demandé est :
```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 : persistence Normal, outcomes/idempotence/purge, concurrence bornée et terminaux conflict/Store sont verts, sans backend direct, Transport ni snapshot concret.