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

14 KiB

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 :

0.3.3-pre.3.fix.1

Identifiant de livraison :

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 :

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 :

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 :

d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450

V001 multi-ressources :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

0.3.3-pre.004 — mapping SQL privé + lectures RawTransaction/observation/rétention/tombstone