Files
khadhroony-solana-project/deltas/0.3.3/pre.003-fix.001.md

274 lines
14 KiB
Markdown

<!-- file: deltas/0.3.3/pre.003-fix.001.md -->
<!-- version: 1 -->
# Delta `0.3.3-pre.003-fix.001` — Store/PostgreSQL schema compatibility hardening
## 1. Base et objectif
Ce correctif s'applique **par-dessus le commit `0.3.3-pre.003` déjà réalisé**. Il ne réécrit ni ne remplace ce commit dans l'historique.
Le gate opérateur de `pre.002` est vert. Le gate opérateur de `pre.003` n'a pas été fourni avant l'ouverture de ce fix ; aucune commande Cargo du fix n'est donc déclarée PASS dans ce document.
Objectif du fix : conserver les bonnes garanties fonctionnelles historiques d'inspection/réconciliation du schéma PostgreSQL sans reprendre l'architecture kbot3, et corriger V001 avant l'ouverture du repository `RawTransaction` de `pre.004`.
Version workspace après application :
```text
0.3.3-pre.3.fix.1
```
Identifiant de livraison :
```text
0.3.3-pre.003-fix.001
```
## 2. Décisions corrigées
### 2.1 Migration logique vs ressources physiques
V000 et V001 restent des **migrations logiques** versionnées. Les objets physiques ne deviennent pas chacun une version de migration.
Arborescence retenue :
```text
crates/ksp-store-postgres-lib/migrations/
v000_bootstrap/
tables/
001_ksp_store_schema_migrations.sql
v001_raw_transaction/
tables/
001_ksp_store_identity.sql
002_ksp_raw_transactions.sql
003_ksp_raw_transaction_observations.sql
004_ksp_raw_transaction_archive_payloads.sql
constraints/
001_...sql -> 035_...sql
indexes/
001_ix_ksp_raw_transactions_slot_signature.sql
```
V001 contient exactement :
```text
4 tables
35 contraintes
1 index
40 ressources embedded
```
V000 est seulement déplacée : ses bytes restent strictement identiques.
### 2.2 Checksums
V000 historique :
```text
d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450
```
V001 multi-ressources :
```text
31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51
```
Le checksum V001 est calculé sur le préfixe de format du registre puis, dans l'ordre embedded, sur l'identifiant relatif et les bytes exacts de chaque ressource. Le checksum monolithique `pre.003` n'est pas réutilisé.
Une base ayant réellement enregistré l'ancien checksum V001 du commit `pre.003` n'est jamais réécrite silencieusement : elle doit être réinitialisée si elle est jetable ou réconciliée manuellement.
### 2.3 `IF NOT EXISTS` n'est pas une preuve de compatibilité
Les ressources utilisent `CREATE ... IF NOT EXISTS`, `ADD COLUMN IF NOT EXISTS` ou des guards catalogue lorsque cela permet une création additive idempotente.
Après et avant mutation, le backend introspecte néanmoins le catalogue PostgreSQL. Chaque ressource est classée :
```text
Compatible
Missing
Incompatible
```
Un objet préexistant du bon nom mais de mauvaise définition est donc refusé.
### 2.4 Contrat physique vérifié
Le module backend-private `schema` contrôle notamment :
- tables gérées et nature `BASE TABLE` ;
- colonnes obligatoires, type, nullabilité et absence d'identity/generated sur le contrat KSP ;
- précision/scale `NUMERIC(20,0)` du slot ;
- PK, FK et CHECK ;
- définition canonique des contraintes à partir de leur propre ressource SQL ;
- index partiel `(slot, signature)` hors `purged` ;
- RLS ;
- triggers utilisateur actifs ;
- rewrite rules ;
- contraintes/indexes uniques externes susceptibles de modifier la sémantique de write.
Les marqueurs COMMENT ne servent pas de preuve de compatibilité et ne sont pas requis.
### 2.5 Extensions externes compatibles
KSP ne requiert pas une égalité byte-for-byte du schéma complet avec son propre DDL. Les extensions externes qui sont prouvées non bloquantes restent admises.
Le correctif tolère notamment :
- une colonne externe nullable, sans default, identity ni generated expression ;
- un index externe non unique ;
- une contrainte attendue physiquement équivalente même si son nom diffère.
Le correctif bloque conservativement les extensions susceptibles de modifier/contraindre les writes KSP lorsqu'il ne peut pas en prouver l'innocuité : mauvais type/nullabilité sur une colonne KSP, colonne externe write-blocking, contrainte non équivalente, unique index autonome, trigger actif, rule ou RLS.
### 2.6 Politiques `schema_autocreate` / `schema_autoupdate`
`std.store` passe en format V2 et sépare :
```text
schema_autocreate
schema_autoupdate
```
`schema_autocreate` autorise l'initialisation ou l'adoption contrôlée d'une base sans metadata KSP.
`schema_autoupdate` autorise les migrations pending et les réparations additives sûres de ressources manquantes sur un schéma KSP existant.
Une incompatibilité exigeant une mutation destructive, ambiguë ou non prouvée sûre reste bloquante même avec `schema_autoupdate=true`; le backend émet uniquement une phase/resource sûre pour permettre l'intervention manuelle.
Le format V1 reste lisible : `auto_migrate` est mappé vers les deux politiques. Les constructeurs Rust historiques restent également disponibles et mappent leur booléen vers les deux politiques.
### 2.7 Identité réseau
Le binding V001 reste sous la même transaction et le même advisory lock.
Une `ksp_store_identity` absente alors que V001 est déjà enregistrée n'est jamais reconstruite automatiquement, même avec `schema_autoupdate=true`, afin d'interdire tout rebind réseau silencieux.
## 3. Suppressions explicites après application de l'overlay
L'extraction d'un zip n'efface pas les anciens fichiers. Après extraction du delta à la racine du dépôt, supprimer explicitement :
```bash
rm crates/ksp-store-postgres-lib/migrations/V000__bootstrap.sql
rm crates/ksp-store-postgres-lib/migrations/V001__raw_transaction.sql
```
Fichiers supprimés :
- `crates/ksp-store-postgres-lib/migrations/V000__bootstrap.sql`
- `crates/ksp-store-postgres-lib/migrations/V001__raw_transaction.sql`
## 4. Fichiers modifiés
- `Cargo.toml`
- `config/examples/std.store.example.json`
- `config/schemas/std.store.schema.json`
- `config/std.store.json`
- `crates/ksp-config-lib/src/store.rs`
- `crates/ksp-config-lib/unit_tests/fixtures/std.store.json`
- `crates/ksp-config-lib/unit_tests/store.rs`
- `crates/ksp-store-lib/src/settings.rs`
- `crates/ksp-store-lib/src/store.rs`
- `crates/ksp-store-lib/unit_tests/settings.rs`
- `crates/ksp-store-postgres-lib/src/lib.rs`
- `crates/ksp-store-postgres-lib/src/migration.rs`
- `crates/ksp-store-postgres-lib/src/runtime.rs`
- `crates/ksp-store-postgres-lib/tests/dependency_boundary.rs`
- `crates/ksp-store-postgres-lib/tests/hardening_completeness.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`
## 5. Fichiers ajoutés
- `crates/ksp-store-postgres-lib/migrations/v000_bootstrap/tables/001_ksp_store_schema_migrations.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/001_pk_ksp_store_identity.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/002_ck_ksp_store_identity_singleton.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/003_ck_ksp_store_identity_network.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/004_pk_ksp_raw_transactions.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/005_ck_ksp_raw_transactions_signature.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/006_ck_ksp_raw_transactions_slot.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/007_ck_ksp_raw_transactions_block_time.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/008_ck_ksp_raw_transactions_format_id.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/009_ck_ksp_raw_transactions_format_version.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/010_ck_ksp_raw_transactions_content_hash.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/011_ck_ksp_raw_transactions_payload.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/012_ck_ksp_raw_transactions_retention_state.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/013_ck_ksp_raw_transactions_payload_state.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/014_ck_ksp_raw_transactions_purged_block_time.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/015_pk_ksp_raw_transaction_observations.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/016_fk_ksp_raw_transaction_observations_transaction.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/017_ck_ksp_raw_transaction_observations_key.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/018_ck_ksp_raw_transaction_observations_signature.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/019_ck_ksp_raw_transaction_observations_provider.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/020_ck_ksp_raw_transaction_observations_protocol.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/021_ck_ksp_raw_transaction_observations_method.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/022_ck_ksp_raw_transaction_observations_origin.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/023_ck_ksp_raw_transaction_observations_received_at.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/024_ck_ksp_raw_transaction_observations_capture_session.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/025_ck_ksp_raw_transaction_observations_commitment.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/026_ck_ksp_raw_transaction_observations_endpoint.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/027_ck_ksp_raw_transaction_observations_filter.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/028_ck_ksp_raw_transaction_observations_observed_at.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/029_ck_ksp_raw_transaction_observations_time_order.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/030_ck_ksp_raw_transaction_observations_source_hash.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/031_ck_ksp_raw_transaction_observations_source_size.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/032_pk_ksp_raw_transaction_archive_payloads.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/033_fk_ksp_raw_transaction_archive_payloads_transaction.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/034_ck_ksp_raw_transaction_archive_payloads_signature.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/constraints/035_ck_ksp_raw_transaction_archive_payloads_payload.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/indexes/001_ix_ksp_raw_transactions_slot_signature.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/tables/001_ksp_store_identity.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/tables/002_ksp_raw_transactions.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/tables/003_ksp_raw_transaction_observations.sql`
- `crates/ksp-store-postgres-lib/migrations/v001_raw_transaction/tables/004_ksp_raw_transaction_archive_payloads.sql`
- `crates/ksp-store-postgres-lib/src/schema.rs`
- `crates/ksp-store-postgres-lib/unit_tests/schema.rs`
- `deltas/0.3.3/pre.003-fix.001.md`
## 6. Validation de génération
Les validations réalisables dans l'environnement de génération doivent être propres avant publication de l'archive :
```text
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
validation JSON/JSON Schema std.store V1+V2
inventaire/checksum migration V000/V001
```
L'environnement de génération ne possède pas `cargo`/`rustfmt`. Les gates Cargo ci-dessous restent donc **NON EXÉCUTÉS** jusqu'au passage opérateur.
## 7. Gate opérateur demandé
Après extraction de l'overlay, suppression explicite des deux fichiers monolithiques puis application du formatage :
```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
```
Canaris de suppression :
```bash
test ! -e crates/ksp-store-postgres-lib/migrations/V000__bootstrap.sql
test ! -e crates/ksp-store-postgres-lib/migrations/V001__raw_transaction.sql
```
Le vrai PostgreSQL live du contrat V001, des dérives et des réparations reste volontairement réservé au gate live prévu plus tard dans `0.3.3`; ce fix ne le présente pas comme PASS.
## 8. Suite
Après gate opérateur vert de `pre.003-fix.001`, reprendre le séquencement avec :
```text
0.3.3-pre.004 — mapping SQL privé + lectures RawTransaction/observation/rétention/tombstone
```