# Delta `0.3.16-pre.002` — contrats Store API RAW multi-variantes ## Base requise ```text 0.3.16-pre.001 appliquée 0.3.16-pre.001-fix.001 appliqué workspace.package.version = 0.3.16-pre.1 ``` Le gate Markdown du fix précédent a été fourni propre le 20 septembre 2026 : ```text Markdown table audit: clean (352 table(s), 942 file(s)) ``` ## Objet Figer les contrats backend-neutral indispensables à la persistance RAW transaction multi-variantes avant d'introduire la migration PostgreSQL V003. Cette tranche ajoute uniquement des modèles/types Store API. Elle ne modifie encore : - aucune migration SQL ; - aucun backend PostgreSQL ; - aucun `RawTransactionWrite` existant ; - aucun Worker ; - aucun comparateur de contenu `logMessages` ; - aucune UI Store Desk. ## Version workspace `Cargo.toml` : ```text header version : 638 -> 639 workspace : 0.3.16-pre.1 -> 0.3.16-pre.2 ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-store-api/src/lib.rs crates/ksp-store-api/src/model/raw_outcome.rs crates/ksp-store-api/src/model/raw_transaction.rs crates/ksp-store-api/tests/release_completeness.rs crates/ksp-store-api/unit_tests/model/raw_transaction.rs docs/plans/038-V0_3_16_RAW_RESILIENCE_CONFLICT_PLAN.md ``` ## Fichier ajouté ```text deltas/0.3.16/pre.002.md ``` ## Contrats ajoutés ### Identité de variante ```text RawTransactionVariantId RawTransactionVariantReference ``` `RawTransactionVariantId` est un surrogate backend-neutral strictement non nul. Il ne dérive ni de `content_hash`, ni du provider, ni d'une clé physique SQL. `RawTransactionVariantReference` conserve explicitement : ```text RawTransactionReference + RawTransactionVariantId ``` Le hash reste donc un attribut de contenu et jamais l'identité métier de la variante. ### Origine de variante ```text RawTransactionVariantOrigin::Native RawTransactionVariantOrigin::Synthetic ``` Les codes persistables stables sont respectivement : ```text native synthetic ``` Une variante synthétique est seulement un contrat réservé ; aucune fusion synthétique n'est implémentée dans cette tranche. ### Relation de qualité ```text RawTransactionVariantRelation::Exact RawTransactionVariantRelation::CompatibleLessComplete RawTransactionVariantRelation::CompatibleMoreComplete RawTransactionVariantRelation::Conflict RawTransactionVariantRelation::Incomparable ``` La direction du contrat est toujours : ```text current canonical vs incoming variant ``` Aucune heuristique provider-majority ou source authority n'est introduite. ### Reason codes `RawTransactionVariantRelationReason` fige les raisons backend-neutral suivantes : ```text ExactCanonicalContent IncomingLogMessagesTruncated CanonicalLogMessagesTruncated SlotMismatch BlockTimeMismatch PayloadFormatMismatch CanonicalPayloadConflict ContentHashCollision UnsupportedCanonicalDifference ``` Chaque raison possède un `code()` stable destiné à la persistance et aux diagnostics sûrs. Les reason codes ne transportent ni URL, ni provider concret, ni secret, ni payload RAW. ### Couple relation/reason validé ```text RawTransactionVariantComparison ``` `try_new(...)` refuse les couples incohérents. Contrats actuellement admis : ```text Exact <-> ExactCanonicalContent CompatibleLessComplete <-> IncomingLogMessagesTruncated CompatibleMoreComplete <-> CanonicalLogMessagesTruncated Conflict <-> SlotMismatch | BlockTimeMismatch | CanonicalPayloadConflict | ContentHashCollision Incomparable <-> PayloadFormatMismatch | UnsupportedCanonicalDifference ``` Cette validation ne constitue pas encore le comparateur de contenu. Le comparateur pur est prévu en `0.3.16-pre.005`. ### Outcome de persistance variant-aware ```text RawTransactionVariantWriteOutcome::InsertedCanonical RawTransactionVariantWriteOutcome::ObservedExact RawTransactionVariantWriteOutcome::ObservedCompatibleLessComplete RawTransactionVariantWriteOutcome::PromotedCompatibleMoreComplete RawTransactionVariantWriteOutcome::QuarantinedConflict RawTransactionVariantWriteOutcome::Rehydrated RawTransactionVariantWriteOutcome::SkippedPurged ``` `QuarantinedConflict` est explicitement un succès durable Store : une divergence conservée ne doit pas être transformée en faute Transport ou en erreur terminale Worker. Aucune capability existante ne retourne encore ce nouvel outcome dans `pre.002`; son adoption backend intervient après V003. ### Statut minimal du conflict case ```text RawTransactionConflictStatus::Open RawTransactionConflictStatus::Resolved ``` Le détail des actions opérateur, revisions attendues, reopen et historique append-only reste réservé au programme `0.3.17`. ## Compatibilité Les contrats historiques restent intacts : ```text RawTransaction RawTransactionObservation RawTransactionReference RawAcquisitionWriteOutcome RawEntityWriteOutcome RawObservationWriteOutcome RawTransactionWrite RawTransactionRead ``` `pre.002` n'impose donc aucune migration immédiate aux consumers existants. Tous les nouveaux enums évolutifs sont `#[non_exhaustive]` et les exports restent disponibles uniquement depuis la racine `ksp-store-api` conformément aux règles KSP. ## Tests/canaris ajoutés ou étendus Les tests couvrent notamment : ```text variant_id = 0 rejeté variant_id non nul conservé sans encoder content_hash référence variante conserve le scope transaction codes Native/Synthetic stables couples relation/reason valides acceptés couples incohérents rejetés codes relation/reason/status stables outcomes variant-aware distincts inventaire exact des exports crate-root mis à jour nouveaux enums evolutifs maintenus #[non_exhaustive] absence de nouveau module production dans ksp-store-api ``` ## Validation de l'assemblage L'environnement d'assemblage ne fournit ni `cargo`, ni `rustc`, ni `rustfmt`. Aucun gate Rust n'est donc déclaré PASS localement. Ont été vérifiés localement : ```text inventaire exact du delta workspace.package.version = 0.3.16-pre.2 headers file/version des fichiers modifiés newline finale lignes Rust <= 160 caractères absence de lockfile/cache/secret cohérence statique exports <-> release_completeness cohérence du plan 038 avec les noms Rust désormais figés ``` ## Gate requis après application Comme cette tranche modifie du Rust et le manifest workspace, exécuter : ```bash cargo fmt --all cargo fmt --all -- --check 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-store-api --all-targets --all-features ``` Ne pas exécuter `npm run build` pour ce gate ; aucune application Desk n'est modifiée. ## Prochaine tranche Après gate propre : ```text 0.3.16-pre.003 ``` Objet prévu : migration PostgreSQL V003, registre/resources et schéma minimal variant ledger + selector + conflit, avec canaris garantissant l'immuabilité byte/checksum des migrations V000/V001/V002.