274 lines
14 KiB
Markdown
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
|
|
```
|