Files
2026-08-30 08:41:26 +02:00

7.7 KiB

Delta 0.3.3-pre.002 — moteur de migrations PostgreSQL multi-version

1. Base requise

0.3.3-pre.001

Le gate opérateur fourni pour pre.001 est entièrement vert :

cargo fmt --all                                         PASS
audit Rust général / exports / workspace                PASS
audit Markdown                                           PASS — 214 tables / 131 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

Les tests live #[ignore] restent volontairement hors de ce gate ; pre.001 était documentaire et pre.002 ne crée encore aucun SQL métier V001.

2. Objectif

Généraliser le bootstrap PostgreSQL V000 acquis en 0.3.2 vers un moteur embedded multi-version avant d'introduire la première migration métier.

La tranche doit préserver :

checksum immuable
mismatch terminal
schema newer terminal
aucun down automatique
advisory transaction lock
migration timeout
statement timeout
transaction unique
metadata shape validation
erreurs externes non rendues

Elle prépare également la frontière transactionnelle du futur binding RawNetworkId, sans créer V001 ni ksp_store_identity.

3. Version

Le workspace passe à :

0.3.3-pre.2

4. Registre embedded

Le moteur ne possède plus une série de constantes spécialisées V000. Il utilise désormais :

EMBEDDED_MIGRATIONS: &[EmbeddedMigration]

Le registre réel de cette tranche contient exactement :

V000 bootstrap

Aucune V001 n'est anticipée dans les migrations physiques.

Chaque entrée possède :

version
name
sql embedded
migration hook

Le registre est validé avant I/O :

non vide
commence à 0
versions contiguës strictement ordonnées
name non vide
SQL non vide

La version courante est dérivée du dernier élément du registre.

5. Validation d'historique multi-version

L'historique PostgreSQL est maintenant validé comme préfixe exact du registre embedded.

Cas :

historique exact complet        -> prêt
préfixe exact                   -> migrations pending
nom divergent                   -> MigrationMismatch
checksum divergent              -> MigrationMismatch
version/trou inattendu connu     -> MigrationMismatch
version > runtime courant        -> SchemaNewer
metadata existante sans V000     -> MigrationMismatch

Un préfixe exact n'est donc plus confondu avec une divergence : il représente précisément le cas normal d'upgrade V000 -> V001 attendu en pre.003.

6. Application des migrations pending

Sous la transaction PostgreSQL et l'advisory lock déjà acquis :

load/validate history
-> déterminer next_index
-> refuser si pending && auto_migrate=false
-> appliquer chaque migration dans l'ordre
-> vérifier metadata shape
-> exécuter migration hook
-> insérer checksum/name/version dans history
-> migration suivante
-> commit unique

Une erreur à n'importe quelle étape provoque le rollback transactionnel normal ; aucune migration partiellement enregistrée n'est considérée appliquée.

7. Hook atomique de binding réseau

bootstrap reçoit désormais le RawNetworkId du backend et le transmet jusqu'à chaque migration.

Le moteur distingue deux contextes privés :

Existing   migration déjà présente dans history à la réouverture
AppliedNow migration exécutée pendant le bootstrap courant

Pour les migrations déjà appliquées, le hook est rejoué sous la transaction/advisory lock avant que le backend puisse être déclaré prêt. Pour une migration nouvellement appliquée, l'ordre est :

batch_execute(migration.sql)
-> metadata shape check
-> migration hook AppliedNow
-> INSERT history
-> commit final

V000 utilise :

MigrationHook::None

pre.003 pourra donc ajouter le hook V001 ksp_store_identity avec deux comportements sûrs : création/validation en AppliedNow, validation stricte sans recréation en Existing. La frontière reste transactionnelle et ne crée aucune seconde phase de bootstrap race-prone.

Aucune identité réseau n'est écrite dans cette tranche.

8. Compatibilité V000

Le fichier reste inchangé :

crates/ksp-store-postgres-lib/migrations/V000__bootstrap.sql

Checksum conservé :

d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450

La metadata historique reste :

ksp_store_schema_migrations
version BIGINT PRIMARY KEY
name TEXT NOT NULL
checksum TEXT NOT NULL
applied_at TIMESTAMPTZ NOT NULL

9. Tests du moteur

Les unit tests migration.rs couvrent maintenant :

registre réel V000 immutable
checksum V000 stable
current version dérivée du registre
registre synthétique V000/V001 ordonné
historique V000 comme préfixe pending valide
historique synthétique V000/V001 complet
registre vide/non-zero/gap/name vide/SQL vide rejeté
nom/checksum/history missing/gap rejetés
version future -> SchemaNewer

Un canari d'intégration source vérifie aussi :

registre embedded présent
hook de migration + contextes `AppliedNow`/`Existing` présents
RawNetworkId transmis au hook
validation préfixe utilisée
application pending utilisée
aucun V001__raw_transaction.sql
aucun ksp_store_identity

10. Fichiers modifiés

Cargo.toml
crates/ksp-store-postgres-lib/src/migration.rs
crates/ksp-store-postgres-lib/src/runtime.rs
crates/ksp-store-postgres-lib/unit_tests/migration.rs
crates/ksp-store-postgres-lib/tests/dependency_boundary.rs
docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md
docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md

11. Fichier ajouté

deltas/0.3.3/pre.002.md

12. Fichiers supprimés

Aucun.

13. Hors scope confirmé

Aucun changement n'est apporté à :

V001 physique
ksp_store_identity
tables/indexes RawTransaction
mapping Row/SQL métier
six capabilities RawTransaction
ksp-store-lib dispatch
RawAccountState
Config std.store
workers/jobs/apps
codecs wire

14. Validations exécutées dans l'environnement de génération

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

cargo, rustc et rustfmt ne sont pas disponibles dans l'environnement d'assemblage. Les validations Cargo ci-dessous restent donc opérateur et ne sont jamais déclarées PASS ici.

15. Gate opérateur demandé

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

Aucun test PostgreSQL live n'est requis : le SQL physique reste strictement V000 et aucun schéma métier n'est introduit.

16. Suite

Après gate vert, 0.3.3-pre.003 créera la vraie migration V001, les tables/constraints/indexes décidés en pre.001 et le binding atomique ksp_store_identity via le hook préparé ici.