# Delta `0.3.3-pre.009-fix.004` — normalisation du CHECK NUMERIC déparsée par PostgreSQL 17 ## 1. Base et diagnostic réel Base opérateur : ```text 0.3.3-pre.9.fix.3 ``` Le gate standard fourni le 2026-08-30 est entièrement propre. Le live PostgreSQL réel atteint PostgreSQL 17 puis identifie précisément la ressource V001 rejetée après application : ```text constraints/006_ck_ksp_raw_transactions_slot.sql ``` La ressource crée : ```sql CHECK (slot >= 0 AND slot <= 18446744073709551615) ``` La colonne `slot` est `NUMERIC(20,0)`. PostgreSQL peut déparser un littéral `NUMERIC` hors plage bigint sous forme quotée avec cast explicite, notamment : ```text '18446744073709551615'::numeric ``` L'ancien `normalize_catalog_sql` supprimait `::numeric` mais conservait les quotes simples. Le contrat embarqué devenait donc `18446744073709551615` tandis que le catalogue pouvait devenir `'18446744073709551615'`, ce qui produisait un faux `Incompatible` immédiatement après création. ## 2. Version ```text workspace.package.version = 0.3.3-pre.9.fix.4 ``` ## 3. Correction d'introspection `schema.rs` ajoute une normalisation ciblée avant la normalisation générale : - seules les chaînes composées d'un signe ASCII optionnel et de chiffres ASCII ; - uniquement lorsqu'elles sont immédiatement suivies de `::numeric` ; - voient leurs quotes simples et leur cast `::numeric` retirés dans cette étape ciblée ; - les autres casts continuent d’être traités par la normalisation existante. Cette règle ne retire donc pas les quotes des littéraux métier/textuels tels que : ```text 'full'::text 'archived'::text 'purged'::text ``` Le canari unitaire existant du CHECK `slot` couvre désormais explicitement la forme PostgreSQL 17 quotée et vérifie également qu'un littéral texte conserve ses quotes. ## 4. Pourquoi la migration reste inchangée Le SQL V001 est sémantiquement correct et PostgreSQL l'applique avant que KSP ne le rejette. Le défaut est donc dans l'équivalence du catalogue, pas dans la contrainte elle-même. Modifier la ressource SQL ferait inutilement varier le checksum V001 et réécrirait le contrat de migration pour un problème de déparsing. `fix.004` ne modifie donc aucune ressource V000/V001. ## 5. Invariants Aucun changement de : - tables, contraintes ou indexes V001 ; - ordre ou nombre des 40 ressources V001 ; - Store API / façade ; - RawTransaction read/write/pagination/rétention ; - cursor ; - Config ; - scope `RawAccountState`. Checksums attendus inchangés : ```text V000 d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450 V001 31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51 ``` ## 6. Fichiers modifiés ```text Cargo.toml crates/ksp-store-postgres-lib/src/schema.rs crates/ksp-store-postgres-lib/unit_tests/schema.rs docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md deltas/0.3.3/pre.009-fix.004.md ``` Aucune suppression. ## 7. Gate opérateur attendu ```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 ``` Puis : ```bash read -rsp "Dedicated PostgreSQL URI: " KSP_PG_TEST_URI; echo printf '%s\n' "$KSP_PG_TEST_URI" | cargo test -p ksp-store-postgres-lib --test postgres_raw_transaction_live -- --ignored --nocapture --test-threads=1 unset KSP_PG_TEST_URI ```