Files
khadhroony-solana-project/deltas/0.3.6/pre.007.md
2026-09-01 14:47:23 +02:00

287 lines
9.0 KiB
Markdown

<!-- file: deltas/0.3.6/pre.007.md -->
<!-- version: 1 -->
# Delta `0.3.6-pre.007` — persistance Store atomique et idempotence Backfill
## Base requise
```text
0.3.6-pre.006-fix.002 appliquée
workspace.package.version = 0.3.6-pre.6.fix.2
```
Le gate opérateur fourni pour cette base confirme :
```text
cargo fmt --all PASS
python3 scripts/audit_rust_workspace_rules.py PASS / clean
python3 scripts/audit_markdown_tables.py ... PASS / clean (264 tables / 151 fichiers)
cargo check --workspace PASS
cargo clippy --workspace --all-targets PASS / aucun warning
cargo test -p ksp-job-backfill-lib PASS
unitaires 20 PASS
dependency_boundary 2 PASS
public_api 3 PASS
release_completeness 2 PASS
cargo tree -p ksp-job-backfill-lib --edges normal exécuté
cargo tree -p ksp-job-backfill-lib -e features exécuté
```
## Objectif
Matérialiser exclusivement `pre.007` du plan 027 : composer la persistance normale d'un résultat d'hydratation Backfill avec les contrats Store déjà existants, sans prélecture, sans second chemin d'écriture et sans ouvrir la concurrence, la frontier ou le checkpoint de `pre.008`.
L'identité canonique reste :
```text
RawTransactionReference = (RawNetworkId, RawTransactionSignature)
```
Provider, endpoint et protocole ne participent toujours qu'à la provenance de l'observation.
## Contrat public Backfill
La tranche ajoute :
```text
persist_backfill_hydration
BackfillPersistenceOutcome
BackfillEntityPersistence
BackfillObservationPersistence
ERROR_CODE_BACKFILL_PERSISTENCE_INVALID
```
`BackfillPersistenceOutcome` conserve la référence réseau + signature et projette séparément l'état de l'entité canonique et celui de l'observation. Cette projection évite de réduire un conflit, une purge ou une nouvelle observation à un compteur `skip` ambigu.
Dispositions entité :
```text
Inserted
AlreadyPresent
SkippedPurged
Missing
Conflict
```
Dispositions observation :
```text
Inserted
AlreadyPresent
NotRecorded
NotApplicable
```
## Composition Store atomique
Pour `BackfillHydrationOutcome::Available`, la bibliothèque consomme l'acquisition en mémoire puis appelle exclusivement :
```text
ksp_store_lib::RawTransactionWrite::persist_raw_transaction_acquisition
```
avec :
```text
RawTransactionAcquisitionMode::Normal
```
La transaction et son observation restent donc une seule opération logique atomique possédée par Store. La tranche n'appelle jamais `record_raw_transaction_observation` séparément et n'introduit aucune prélecture `get_raw_transaction` avant écriture.
`ForceRehydrate` n'est pas exposé par le chemin Backfill normal.
## Réseau
Avant toute écriture, le réseau logique exposé par le snapshot du Store doit être identique au `RawNetworkId` de la référence hydratée. Un mismatch est rejeté par :
```text
ERROR_CODE_BACKFILL_PERSISTENCE_INVALID
field = store.network
```
Ce contrôle n'utilise ni endpoint, ni provider, ni protocole comme identité.
Une incohérence interne entre la référence annoncée, la transaction et l'observation est également rejetée avant soumission Store.
## Outcomes Store admis
En mode normal, les combinaisons Store suivantes sont acceptées et projetées explicitement :
```text
RawEntityWriteOutcome::Inserted
+ RawObservationWriteOutcome::Inserted
-> Inserted / Inserted
RawEntityWriteOutcome::AlreadyPresent
+ RawObservationWriteOutcome::Inserted
-> AlreadyPresent / Inserted
RawEntityWriteOutcome::AlreadyPresent
+ RawObservationWriteOutcome::AlreadyPresent
-> AlreadyPresent / AlreadyPresent
RawEntityWriteOutcome::SkippedPurged
+ RawObservationWriteOutcome::NotRecorded
-> SkippedPurged / NotRecorded
```
`RawEntityWriteOutcome::Rehydrated` est impossible dans le chemin normal et est rejeté, comme toute autre combinaison incohérente.
## Missing
`BackfillHydrationOutcome::Missing(reference)` devient :
```text
Missing / NotApplicable
```
sans aucune écriture Store. La tranche ne persiste toujours ni observation `missing`, ni observation d'échec fabriquée ; ces contrats n'existent pas dans le Store RAW transaction actuel.
## Conflit et erreurs
Une erreur Store dont le code stable est :
```text
ERROR_CODE_RAW_CONFLICT
```
est projetée en :
```text
Conflict / NotRecorded
```
Elle reste donc visible et distincte de l'idempotence. Les tranches de frontier/snapshot pourront ensuite la traiter comme trou/échec sans parsing de message d'erreur.
Toutes les autres erreurs Store sont propagées telles quelles.
## Idempotence
La même acquisition déterministe peut produire successivement :
```text
Inserted / Inserted
AlreadyPresent / AlreadyPresent
```
sans doublon logique. Une entité déjà présente peut aussi recevoir une nouvelle observation légitime :
```text
AlreadyPresent / Inserted
```
La distinction repose entièrement sur les outcomes Store officiels ; Job ne reconstruit aucune logique d'idempotence physique.
## Tests matérialisés
La tranche ajoute **9 tests unitaires**, portant le total de `ksp-job-backfill-lib` à **29 unitaires** :
- `Missing` ne soumet aucune écriture ;
- mismatch réseau rejeté avant Store ;
- insert atomique `Inserted/Inserted` ;
- entité existante + nouvelle observation ;
- relance idempotente `AlreadyPresent/AlreadyPresent` ;
- purge normale `SkippedPurged/NotRecorded` ;
- conflit Store explicite et non confondu avec idempotence ;
- erreur Store non conflit propagée ;
- combinaisons impossibles et mismatch transaction/observation rejetés.
Une canarie publique supplémentaire porte les canaries d'intégration à **8** :
```text
dependency_boundary 2
public_api 4
release_completeness 2
```
Les canaries statiques verrouillent l'usage de l'écriture atomique, du mode `Normal`, l'absence d'écriture d'observation séparée, l'absence de `ForceRehydrate`, l'absence de backend Store direct et la fermeture du checkpoint/runtime de `pre.008`.
## Fichiers ajoutés
```text
crates/ksp-job-backfill-lib/src/persistence.rs
crates/ksp-job-backfill-lib/unit_tests/persistence.rs
deltas/0.3.6/pre.007.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-job-backfill-lib/src/error.rs
crates/ksp-job-backfill-lib/src/lib.rs
crates/ksp-job-backfill-lib/tests/dependency_boundary.rs
crates/ksp-job-backfill-lib/tests/public_api.rs
crates/ksp-job-backfill-lib/tests/release_completeness.rs
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md
```
## Versions d'en-tête
Les fichiers Rust/TOML modifiés incrémentent tous leur version d'en-tête exactement d'une unité :
```text
Cargo.toml 404 -> 405
crates/ksp-job-backfill-lib/src/error.rs 2 -> 3
crates/ksp-job-backfill-lib/src/lib.rs 2 -> 3
crates/ksp-job-backfill-lib/tests/dependency_boundary.rs 2 -> 3
crates/ksp-job-backfill-lib/tests/public_api.rs 2 -> 3
crates/ksp-job-backfill-lib/tests/release_completeness.rs 2 -> 3
```
Les deux nouveaux fichiers Rust commencent à `version: 1`. Le plan 027 et la validation 023 passent de `12` à `13`. Le présent delta commence à `version: 1`.
## Version workspace
La tranche modifie du Rust :
```text
workspace.package.version = 0.3.6-pre.7
delivery = 0.3.6-pre.007
commit = v0.3.6-pre.007
```
Aucun tag prerelease.
## Fichiers supprimés
Aucun.
## Frontières conservées
- aucune prélecture Store avant hydratation/persistance ;
- aucun backend Store direct ;
- aucun `ForceRehydrate` ;
- aucune persistence de missing/failed artificielle ;
- aucune concurrence d'hydratation concrète ;
- aucune frontier contiguë ;
- aucun checkpoint/reprise runtime ;
- aucun snapshot Backfill concret ;
- aucune nouvelle dépendance ou feature ;
- aucune modification Transport, Store, Job API, Config, README, USAGE, CHANGELOG ou ROADMAP ;
- aucun code kbot3 copié.
## Validations dans l'environnement d'assemblage
L'environnement d'assemblage exécute les audits statiques et contrôles d'archive mais ne possède ni `cargo`, ni `rustc`, ni `rustfmt`. Les tests Rust matérialisés ne sont donc pas annoncés comme exécutés localement.
## Gate opérateur demandé
```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/0.3.6
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-job-backfill-lib
cargo tree -p ksp-job-backfill-lib --edges normal
cargo tree -p ksp-job-backfill-lib -e features
```
Résultat attendu : **29 tests unitaires + 8 canaries d'intégration**, aucun warning Clippy, et dépendance Store toujours limitée à `ksp-store-lib` avec `default-features = false`.
## Questions ouvertes
Aucune pour `pre.007`. `pre.008` reste fermé tant que ce gate n'est pas vert.