# Delta `0.3.1-pre.006` — queries, outcomes et lifecycle RAW ## Base requise ```text 0.3.1-pre.5 ``` Le gate opérateur de `pre.005` est intégralement vert : audits Rust/Markdown, `cargo check --workspace`, `cargo clippy --workspace --all-targets` et `cargo test -p ksp-store-api` passent. ## Recalibrage pagination Le brainstorming opérateur précise une règle durable : Store fournit une primitive de query/pagination, **pas une policy d'exécution**. Une limitation physique réelle d'un backend peut contraindre ce qu'il sert en une opération. En revanche `ksp-store-api`, `ksp-store-lib` et les crates backend ne doivent pas inventer un plafond métier inférieur (`100`, `500`, etc.) simplement pour gouverner le travail d'un futur executor. `pre.006` matérialise donc : ```text RawPageLimit > 0 aucun maximum fonctionnel KSP arbitraire RawPageCursor opaque <= 4 KiB ``` La borne du cursor protège un token d'entrée hostile ; elle ne limite pas le nombre de résultats. Le futur job/worker choisira sa taille de travail et son backlog via ses propres policies/processing contracts. ## Objectif Finaliser les contrats N1 encore nécessaires avant le hardening de release : ```text queries/list cursorisés outcomes idempotents conflit stable atomic acquisition finalisée rétention logique transactionnelle tombstone anti-rebackfill normal skip / force rehydrate explicite ``` Aucune compression, archive physique, base de données, policy de purge ou executor n'est implémenté. ## Fichiers ajoutés ```text crates/ksp-store-api/src/capability/raw_retention.rs crates/ksp-store-api/src/model/raw_outcome.rs crates/ksp-store-api/src/model/raw_pagination.rs crates/ksp-store-api/src/model/raw_retention.rs crates/ksp-store-api/unit_tests/model/raw_pagination.rs crates/ksp-store-api/unit_tests/model/raw_retention.rs deltas/0.3.1/pre.006.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-store-api/src/capability.rs crates/ksp-store-api/src/capability/raw_account.rs crates/ksp-store-api/src/capability/raw_transaction.rs crates/ksp-store-api/src/error.rs crates/ksp-store-api/src/lib.rs crates/ksp-store-api/src/model.rs crates/ksp-store-api/tests/dependency_boundary.rs crates/ksp-store-api/tests/external_backend.rs crates/ksp-store-api/tests/public_api.rs docs/plans/022-V0_3_1_STORE_RAW_PLAN.md docs/validation/018-V0_3_1_STORE_RAW.md ``` ## Fichiers supprimés ```text aucun ``` ## Version ```text workspace.package.version = 0.3.1-pre.6 ``` ## Queries et pagination Surface ajoutée : ```text RawPageCursor RawPageLimit RawPageRequest RawPage RawSlotRange RawSortDirection RawTransactionQuery RawAccountStateQuery ``` `RawPageLimit::new(0)` est invalide. Aucun maximum KSP n'est imposé ; `u64::MAX` reste représentable par le contrat. Les queries sont network-scoped et peuvent borner les slots ; les account queries peuvent en plus sélectionner un pubkey. Les capabilities read gagnent : ```text list_raw_transactions(query) list_raw_account_states(query) ``` Les pages retournent des références compactes et un cursor opaque, pas des rows/PK/SQL backend. ## Outcomes et conflits Surface ajoutée : ```text RawEntityWriteOutcome Inserted AlreadyPresent Rehydrated SkippedPurged RawObservationWriteOutcome Inserted AlreadyPresent NotRecorded RawAcquisitionWriteOutcome entity + observation ``` Les opérations `persist_raw_*_acquisition` retournent désormais l'outcome combiné et conservent le contrat all-or-nothing RAW + observation. Une même identité avec un contenu divergent doit produire : ```text ERROR_CODE_RAW_CONFLICT ``` et jamais un overwrite silencieux. Les écritures d'observation seules retournent `RawObservationWriteOutcome`. ## Lifecycle RAW transaction Surface ajoutée : ```text RawRetentionState Full Compacted Archived Purged RawTransactionTombstone RawTransactionRetentionTransition RawRetentionWriteOutcome RawTransactionAcquisitionMode Normal ForceRehydrate RawTransactionRetentionRead RawTransactionRetentionWrite ``` Transitions génériques admises : ```text Full -> Compacted Full -> Archived Compacted -> Archived Archived -> Purged ``` Interdits : ```text Full -> Purged direct Purged -> Full via transition générique ``` La réhydratation est un mode d'acquisition explicitement forcé. En mode normal, un tombstone purgé doit rester connu et produire `SkippedPurged` sans rebackfill automatique. Le tombstone conserve uniquement l'identité transactionnelle, slot, format/version et hash canonique nécessaires au contrat anti-rebackfill ; aucun payload RAW n'y subsiste. ## Ownership rétention Le Store applique la transition demandée mais ne décide jamais que les couches supérieures sont terminées. L'éligibilité compression/archive/purge appartient à un futur worker/job/maintenance policy fondé sur les preuves de processing versionnées. La policy reste family-specific ; `RawAccountState` ne reçoit donc aucun lifecycle de purge copié artificiellement depuis `RawTransaction` dans cette tranche. ## Canari backend externe Le backend externe de test est mis à jour pour : ```text queries/pages outcomes détaillés mode Normal/ForceRehydrate retention read/write ``` Il reste implémentable sans `ksp-store-lib`, PostgreSQL, runtime DB ou dépendance async supplémentaire. ## Hors scope confirmé ```text ksp-store-lib ksp-store-postgres-lib PostgreSQL/tokio-postgres Config/std.store policy executor/backlog métier processing ledger concret compression/archive/purge physique health runtime TransactionStatusObservation commun models event-only logs/slot/vote RawBlock persistence Yellowstone Entry persistence N2 STRUCTURAL N3 DECODED N4 DOMAIN ``` ## Validations opérateur de la base ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-store-api PASS ``` ## Validations de génération Les audits structurels/Markdown sont rejoués sur l'overlay `pre.006`. `cargo`, `rustc` et `rustfmt` ne sont pas installés dans l'environnement de génération ; le gate Cargo final reste donc opérateur. ## Suite `0.3.1-pre.007` effectue le hardening adversarial/completeness : cursor/provenance hostile, races de rétention, exact exports/modules, frontière Interface/Store, dependency firewall et scope négatif N2/N3/N4.