# Delta `0.3.16-pre.005` — comparateur backend-neutral des variantes RAW ## Base requise ```text 0.3.16-pre.004 appliquée workspace.package.version = 0.3.16-pre.4 ``` Le gate opérateur de `pre.004` est confirmé propre : audits Rust/export/KSP/Markdown, `cargo check --workspace`, Clippy `-D warnings`, 85 tests unitaires `ksp-store-postgres-lib` et toutes les suites d'intégration ciblées passent. Les trois preuves PostgreSQL live restent opt-in. ## Version Cette tranche modifie le contrat Store API et son intégration PostgreSQL : ```text workspace.package.version = 0.3.16-pre.5 ``` ## Portée Cette tranche rend effectif le comparateur pur backend-neutral prévu depuis `pre.002`. `ksp-store-api` expose désormais : ```text compare_raw_transaction_variants(canonical, incoming) -> RawTransactionVariantComparison ``` Le comparateur produit exclusivement les relations déjà figées : ```text Exact CompatibleLessComplete CompatibleMoreComplete Conflict Incomparable ``` Le comparateur n'ajoute aucune dépendance runtime à `ksp-store-api`. En particulier, `serde_json` reste interdit par le canari de dépendances existant. L'analyse du payload RAW v1 utilise un scanner JSON privé, borné en profondeur et fondé uniquement sur `std`. ## Ordre de décision La comparaison est fail-closed et applique l'ordre suivant : 1. les deux variantes doivent appartenir à la même identité `network + signature`, sinon l'appel est invalide ; 2. `slot` différent -> `Conflict / SlotMismatch` ; 3. `block_time` différent -> `Conflict / BlockTimeMismatch` ; 4. format id/version différent -> `Incomparable / PayloadFormatMismatch` ; 5. payload bytes exactement égaux -> `Exact / ExactCanonicalContent` ; 6. hash égal mais bytes différents -> `Conflict / ContentHashCollision` ; 7. seulement ensuite, analyse structurelle du RAW v1 pour une éventuelle preuve de troncature `logMessages` ; 8. toute autre divergence est `Conflict` ou `Incomparable` sans dominance automatique. Le `content_hash` reste donc un marqueur d'intégrité/préfiltre, jamais une preuve d'égalité. ## Preuve `logMessages` La seule dominance automatique admise reste la troncature SVM strictement prouvée. Pour reconnaître une variante tronquée, toutes les conditions suivantes sont nécessaires : - les autres composantes top-level sont identiques ; - les autres champs `meta` sont identiques ; - les deux `logMessages` sont des tableaux de chaînes JSON valides ; - le côté tronqué contient exactement un marqueur exact `"Log truncated"` ; - ce marqueur est le dernier élément ; - le côté complet ne contient aucun marqueur exact ; - le préfixe avant le marqueur est byte-identique ; - le côté complet possède au moins une ligne au-delà de ce préfixe. Ainsi : ```text canonique complet + entrant tronqué -> CompatibleLessComplete canonique tronqué + entrant complet -> CompatibleMoreComplete ``` Une liste plus courte sans marqueur, un préfixe divergent, un marqueur non exact ou du matériel placé après `"Log truncated"` ne prouve aucune dominance. ## Politique fail-closed des autres champs Les différences de présence/omission ou `null` contre une valeur concrète ne sont pas transformées en score de qualité. Elles produisent `Incomparable / UnsupportedCanonicalDifference`. Les valeurs concrètes présentes des deux côtés mais contradictoires produisent `Conflict / CanonicalPayloadConflict`. Cette politique couvre notamment les champs optionnels documentés dans le plan (`innerInstructions`, `loadedAddresses`, `returnData`, unités consommées, token balances, rewards) sans inventer de hiérarchie de complétude. ## Intégration PostgreSQL `ksp-store-postgres-lib` ne possède plus l'heuristique privée unidirectionnelle `raw_transaction_incoming_truncated_log_messages_compatible`. `compare_existing_transaction` appelle désormais directement : ```text ksp_store_api::compare_raw_transaction_variants(...) ``` Comportement de cette tranche : - `Exact` -> idempotence canonique existante ; - `CompatibleLessComplete` -> conservation du canonique et persistance/rattachement de la variante entrante comme en `pre.004` ; - `CompatibleMoreComplete` -> relation reconnue mais encore fail-closed côté mutation, car la promotion atomique appartient à `pre.006` ; - `Conflict` / `Incomparable` -> conflit PostgreSQL existant, sans ouverture de conflict case durable avant `pre.007`. Aucune mise à jour du selector, de `canonical_revision` ou de la projection V001 n'est ajoutée ici. ## Canaris Les tests Store API ajoutés verrouillent : - la relation bidirectionnelle `LessComplete` / `MoreComplete` ; - le marqueur exact, unique et terminal ; - le rejet d'une simple liste plus courte ; - le rejet d'un préfixe divergent ; - le rejet d'un marqueur provider non exact ; - le rejet de matériel après le marqueur ; - la politique `Incomparable` sur optionalité `null`/valeur ; - le `Conflict` sur valeurs concrètes contradictoires ; - l'égalité par bytes même si les hashes fournis diffèrent ; - la détection d'une collision de hash lorsque les bytes diffèrent. Les canaris PostgreSQL verrouillent en plus : - l'usage exclusif du comparateur Store API pour la décision de convergence ; - l'absence des anciens helpers privés de compatibilité ; - l'absence de promotion/écriture canonique dans `pre.005` ; - le refus temporaire de `CompatibleMoreComplete` jusqu'à `pre.006`. ## Hors scope maintenu Cette tranche n'ajoute pas : - promotion du selector canonique ; - incrément de `canonical_revision` ; - remplacement atomique de la projection V001 ; - journal de transition canonique ; - ouverture de `ksp_raw_transaction_conflicts` ; - outcome Worker non terminal pour les conflits ; - Store Desk ; - retry Store/Transport ; - politique de rétention des variantes. Aucune migration SQL ni ressource V003 n'est modifiée. ## Validation exécutée lors de la génération Les scripts Python réels du checkout complet sont exécutés sur l'état final puis sur le ZIP rejoué sur une copie fraîche de `pre.004`. Le toolchain Rust n'est pas disponible dans l'environnement de génération ; les gates Cargo restent opérateur. ## Validation opérateur demandée ```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 cargo test -p ksp-store-postgres-lib --all-targets --all-features ``` ## Suite Après gate propre : `0.3.16-pre.006` — selector canonique et promotion atomique avec revision, projection V001 cohérente, conservation de l'ancien canonique et journal minimal des transitions.