# Delta `0.3.3-pre.003` — V001 RawTransaction physique et binding réseau ## 1. Base requise ```text 0.3.3-pre.002 ``` Le gate opérateur fourni pour `pre.002` est entièrement vert : ```text cargo fmt --all PASS audit Rust général / exports / workspace PASS audit Markdown PASS — 214 tables / 132 files cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-store-api PASS cargo test -p ksp-store-lib PASS cargo test -p ksp-store-postgres-lib PASS cargo test -p ksp-config-lib PASS cargo check -p ksp-store-lib --no-default-features PASS ``` Le test PostgreSQL foundation reste `#[ignore]` dans ce gate ordinaire. La preuve live complète de la vertical slice `0.3.3` reste réservée à `pre.009`. ## 2. Objectif Matérialiser le design physique décidé en `pre.001` sur le moteur multi-version acquis en `pre.002`, sans commencer encore les repositories/capabilities métier. La tranche livre : ```text V001__raw_transaction.sql registre embedded réel V000 + V001 binding mono-réseau atomique contraintes/indexes RAW exacts checksum/inventory/bounds statiques code stable PostgreSQL Compacted unsupported ``` ## 3. Version Le workspace passe à : ```text 0.3.3-pre.3 ``` ## 4. Migration V001 La migration ajoutée est : ```text crates/ksp-store-postgres-lib/migrations/V001__raw_transaction.sql ``` Le registre embedded contient désormais exactement : ```text V000 bootstrap V001 raw_transaction ``` La version courante dérivée du registre vaut donc : ```text 1 ``` V000 reste byte-identique avec son checksum historique : ```text d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450 ``` Checksum SHA-256 V001 : ```text 6fe57ed0313d2ed295280dd6e49f6d86695d4e4effee2724a25e36db1ea17761 ``` ## 5. Inventaire physique V001 V001 crée exactement les tables métier/identité suivantes : ```text ksp_store_identity ksp_raw_transactions ksp_raw_transaction_observations ksp_raw_transaction_archive_payloads ``` et l'index secondaire suivant : ```text ix_ksp_raw_transactions_slot_signature ON ksp_raw_transactions(slot, signature) WHERE retention_state <> 'purged' ``` Les clés physiques restent : ```text ksp_store_identity(singleton) ksp_raw_transactions(signature) ksp_raw_transaction_observations(observation_key) ksp_raw_transaction_archive_payloads(signature) ``` Aucun ID SQL auxiliaire n'est ajouté. ## 6. Bornes et contraintes Les contraintes SQL matérialisent les invariants backend-agnostiques déjà acquis : ```text network/code UTF-8 ASCII sûr 1..=128 octets signature transaction 64 octets observation key 32 octets content/source hash 32 octets slot NUMERIC(20,0), 0..=u64::MAX format_version BIGINT, 1..=u32::MAX RawTimestamp BIGINT, 0..=253402300799999 payload canonical/archive 1..=16 MiB lorsqu'il existe source payload size 0..=64 MiB origin backfill/import/live/repair/replay retention physique full/archived/purged ``` `slot` n'est jamais réduit en `BIGINT` signé. La cohérence de rétention physique impose : ```text full -> payload hot présent archived -> payload hot absent purged -> payload hot absent + block_time absent ``` La relation archive reste séparée du hot path. V001 ne prétend jamais représenter `Compacted`. ## 7. Binding mono-réseau atomique V001 déclare le hook privé : ```text MigrationHook::StoreIdentity ``` Le comportement est distinct selon le contexte déjà acquis en `pre.002`. ### `AppliedNow` Sous la même transaction et le même advisory lock : ```text batch_execute(V001) -> INSERT singleton=1 + network runtime -> relire exactement l'identité -> valider singleton + RawNetworkId + égalité réseau -> INSERT history V001 -> commit final ``` L'insertion n'utilise aucun upsert : une divergence physique ne peut pas être absorbée silencieusement. ### `Existing` Une réouverture V001 effectue uniquement : ```text SELECT singleton, network -> exactement une ligne -> singleton = 1 -> network valide RawNetworkId -> network == backend.network ``` Une identité absente, multiple, illisible, malformée ou différente devient `MigrationMismatch` avec une phase statique. La valeur réseau persistée et les erreurs PostgreSQL ne sont jamais retenues/rendues. Une base V001 dont l'identité a disparu n'est donc jamais réclamée/rebindée automatiquement. ## 8. `Compacted` PostgreSQL non supporté Le code stable suivant est désormais matérialisé par valeur dans le backend et la façade : ```text store.postgres_retention_compaction_unsupported ``` Exports : ```text ksp_store_postgres_lib::ERROR_CODE_POSTGRES_RETENTION_COMPACTION_UNSUPPORTED ksp_store_lib::ERROR_CODE_POSTGRES_RETENTION_COMPACTION_UNSUPPORTED ``` Les deux crates construisent le même `ErrorCode` KSP sans créer de dépendance inverse `ksp-store-postgres-lib -> ksp-store-lib`. L'utilisation opérationnelle de ce code par `RawTransactionRetentionWrite` reste réservée à `pre.007`. ## 9. Tests statiques ajoutés/actualisés Les tests de migration couvrent désormais : ```text registre réel [V000,V001] V000 checksum immuable V001 checksum exact version courante = 1 V000 seul = préfixe valide / V001 pending historique complet V000+V001 valide mismatch/newer toujours terminaux inventaire exact des quatre tables index partiel exact slot u64 max sans narrowing bornes u32/timestamp/payload/source payload retention physique sans compacted hook StoreIdentity réel contextes AppliedNow / Existing absence de repository/capability dans la tranche ``` Les canaris de surface publique sont actualisés : ```text ksp-store-postgres-lib root pub use : 7 -> 8 ksp-store-lib root pub use : 84 -> 85 ``` La seule nouvelle surface est le code d'erreur PostgreSQL `Compacted` explicitement planifié. Le test live foundation hérité de `0.3.2` est maintenu cohérent avec V001 sans devenir la preuve métier de cette release : ```text version health attendue 0 -> 1 refus de départ toute table Store V000/V001 déjà présente cleanup ensemble des tables Store V000/V001 possédées preuve de rollback historique V000 inchangée statut dans le gate ordinaire toujours #[ignore] ``` Il n'est pas exécuté dans cette tranche ; les scénarios V001 spécifiques restent réservés à `pre.009`. ## 10. Preuves volontairement différées Cette tranche ne prétend pas avoir exécuté PostgreSQL réel pour V001. Restent au gate live `pre.009` : ```text upgrade réel V000 -> V001 rollback réel si hook échoue réouverture même réseau réouverture réseau différent identity supprimée/malformée sur DB réelle checksum V001 divergent sur DB réelle concurrence réelle du bootstrap V001 ``` Ces points ne sont donc pas marqués PASS dans la validation `pre.003`. ## 11. Fichiers modifiés ```text Cargo.toml crates/ksp-store-lib/src/error.rs crates/ksp-store-lib/src/lib.rs crates/ksp-store-lib/tests/hardening_completeness.rs crates/ksp-store-lib/tests/public_api.rs crates/ksp-store-postgres-lib/src/error.rs crates/ksp-store-postgres-lib/src/lib.rs crates/ksp-store-postgres-lib/src/migration.rs crates/ksp-store-postgres-lib/tests/dependency_boundary.rs crates/ksp-store-postgres-lib/tests/hardening_completeness.rs crates/ksp-store-postgres-lib/tests/postgres_foundation_live.rs crates/ksp-store-postgres-lib/tests/public_api.rs crates/ksp-store-postgres-lib/unit_tests/migration.rs docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md ``` ## 12. Fichiers ajoutés ```text crates/ksp-store-postgres-lib/migrations/V001__raw_transaction.sql deltas/0.3.3/pre.003.md ``` ## 13. Fichiers supprimés Aucun. ## 14. Hors scope confirmé Aucun changement n'implémente encore : ```text RawTransactionRead RawTransactionWrite RawTransactionObservationRead RawTransactionObservationWrite RawTransactionRetentionRead RawTransactionRetentionWrite row codecs SQL métier get/list/cursor canonical+observation writes archive/purge/rehydrate behavior ksp-store-lib capability dispatch RawAccountState PostgreSQL Config std.store workers/jobs/apps ``` ## 15. Validations exécutées dans l'environnement de génération ```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/0.3.3 Markdown table audit: clean (214 table(s), 133 file(s)) ``` Les commandes Cargo ne sont pas disponibles dans l'environnement de génération. Elles restent **NON EXÉCUTÉES** ici et doivent être exécutées côté opérateur. ## 16. 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.3 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-store-api cargo test -p ksp-store-lib cargo test -p ksp-store-postgres-lib cargo test -p ksp-config-lib cargo check -p ksp-store-lib --no-default-features ``` Le test PostgreSQL live demeure hors gate ordinaire jusqu'à la tranche dédiée `pre.009`. ## 17. Suite prévue après gate vert ```text 0.3.3-pre.004 — mapping SQL privé + lectures RawTransaction/observation/rétention/tombstone ```