Files
khadhroony-solana-project/crates/ksp-store-postgres-lib
2026-08-30 17:02:44 +02:00
..
2026-08-30 10:21:48 +02:00
2026-08-30 15:53:07 +02:00
2026-08-30 16:07:51 +02:00
2026-08-30 16:06:20 +02:00
2026-08-29 19:53:00 +02:00
2026-08-30 17:02:44 +02:00
2026-08-30 17:02:44 +02:00

ksp-store-postgres-lib

ksp-store-postgres-lib est le backend PostgreSQL physique officiel du Store KSP.

La crate implémente la fondation connexion/pool/TLS/migrations/health derrière ksp-store-lib. Elle dépend directement de ksp-store-api mais ne dépend jamais de la façade ksp-store-lib.

Responsabilités

La crate possède seule pour PostgreSQL :

  • le parsing et la normalisation de la configuration physique tokio-postgres ;
  • le pool borné deadpool-postgres ;
  • la policy TLS physique avec Rustls ;
  • les roots système et le provider cryptographique AWS-LC ;
  • le bootstrap/moteur de migrations privé KSP ;
  • la table metadata ksp_store_schema_migrations ;
  • la migration logique V000 relocalisée sous migrations/v000_bootstrap/ et son checksum SHA-256 historique ;
  • l'advisory transaction lock borné des migrations ;
  • les snapshots runtime/health sûrs destinés au bridge de façade ;
  • la fermeture explicite du pool et son fallback Drop best-effort ;
  • la classification d'erreurs backend sans conserver le texte d'erreur PostgreSQL.

Frontière d'utilisation

Les applications, jobs et workers KSP ne dépendent normalement pas de cette crate :

consumer -> ksp-store-lib -> [feature postgres] ksp-store-postgres-lib

La surface publique de cette crate existe pour le bridge inter-crates et les tests d'intégration backend. Elle ne constitue pas une seconde façade Store.

ksp-store-postgres-lib ne réexporte pas tokio-postgres, Deadpool ou Rustls.

Connexion et pool

PostgresBackend::open :

  1. valide et normalise l'URI fournie explicitement ;
  2. impose la policy TLS typée ;
  3. construit un pool borné ;
  4. prouve une connexion physique ;
  5. vérifie/applique le bootstrap selon les settings ;
  6. ne retourne qu'après succès de cette fondation.

Le backend ne lit aucun environnement, .env, PG*, .pgpass ou fichier TLS implicite libpq.

TLS

Les modes sont exactement :

Disabled
VerifyFull

VerifyFull exige :

  • TLS ;
  • roots système ;
  • certificat valide ;
  • vérification de l'identité serveur ;
  • aucune dégradation automatique en plaintext.

Les configurations ne permettant pas de vérifier une identité serveur, comme hostaddr seul, sont rejetées.

Migrations

La fondation historique V000 est embarquée sous :

migrations/v000_bootstrap/tables/001_ksp_store_schema_migrations.sql

La vertical slice V001 est ensuite répartie sous migrations/v001_raw_transaction/{tables,constraints,indexes}/ tout en restant une migration logique unique. V000 crée la metadata privée :

ksp_store_schema_migrations

Le moteur vérifie version, nom et checksum SHA-256, sérialise les runners par advisory transaction lock et refuse une history divergente ou plus récente que le runtime.

V001 possède désormais le schéma physique RawTransaction et son contrat de compatibilité. Les lectures exactes sont acquises depuis pre.004; pre.005 ajoute les écritures atomiques transaction + observation, l'idempotence réelle et la classification de conflit. pre.006 ajoute la navigation keyset déterministe sur l'index (slot, signature) et son cursor opaque lié à la requête. pre.007 ajoute les transitions de rétention atomiques Full -> Archived -> Purged et le rejet explicite de Compacted. pre.008 ferme la conformance backend en implémentant les six traits RawTransaction* directement sur PostgresBackend.

Health et erreurs

PostgresBackendRuntimeSnapshot et PostgresBackendHealthSnapshot ne contiennent que des compteurs et états sûrs destinés à la façade.

PostgresBackendError ne conserve que :

PostgresBackendErrorKind
phase statique

Le texte d'erreur PostgreSQL, l'URI, SQL et les valeurs bind ne traversent pas cette frontière.

Support PostgreSQL

La politique de support de 0.3.2 fixe PostgreSQL 15 comme major minimal. Le test live de fondation refuse explicitement un serveur plus ancien ; le backend ne fixe aucun plafond arbitraire de major PostgreSQL. La compatibilité de migration reste basée sur le schéma KSP.

La preuve opérateur réelle et le major effectivement exercé sont conservés dans la matrice de validation, pas dans cette documentation durable.

Lectures RAW 0.3.3-pre.004

Le backend expose désormais quatre lectures étroites qui retournent uniquement des modèles ksp-store-api :

get_raw_transaction
get_raw_transaction_observation
get_raw_transaction_retention_state
get_raw_transaction_tombstone

Le SQL et les rows restent privés au backend. Le mapping PostgreSQL est fallible et couvre notamment NUMERIC(20,0) -> u64, BIGINT -> u32/u64, timestamps bornés, bytes de taille fixe et codes de provenance. Une ligne stockée incompatible produit uniquement PostgresBackendErrorKind::DataInvalid; un échec de SELECT produit ReadFailed. Les lectures portant un RawTransactionReference rejettent un réseau différent avant toute acquisition de pool.

Full lit le payload chaud, Archived le reconstruit depuis la relation archive et Purged retourne None; le tombstone reste accessible séparément pour Purged.

Écritures RAW 0.3.3-pre.005

Le backend expose deux écritures étroites :

persist_raw_transaction_acquisition
record_raw_transaction_observation

L'acquisition canonique et son observation sont commises dans une seule transaction PostgreSQL. L'insertion utilise les clés uniques physiques sans prélecture has_*; après un conflit unique, le backend verrouille la ligne gagnante et compare le contenu réel avant de conclure AlreadyPresent ou Conflict. Les octets du payload sont comparés lorsqu'ils existent encore : le hash seul ne constitue jamais une preuve d'idempotence.

Un tombstone Purged compatible produit SkippedPurged/NotRecorded en mode normal. ForceRehydrate restaure Full et l'observation dans la même transaction. Une observation supplémentaire ne crée jamais implicitement son canonique ; une référence absente est classée ReferenceNotFound et un canonical purgé retourne NotRecorded.

Les erreurs physiques d'écriture sont réduites à WriteFailed; aucune erreur serveur, SQLSTATE, query ou valeur de bind n'est conservée.

Pagination RAW 0.3.3-pre.006

list_raw_transactions parcourt uniquement les références canoniques récupérables, en excluant les tombstones Purged. L'ordre total est :

Ascending  = (slot ASC, signature ASC)
Descending = (slot DESC, signature DESC)

La continuation est une keyset stricte > / <, jamais un OFFSET. Le cursor backend V1 fait exactement 109 octets et transporte KSPT, version 1, le dernier slot, la dernière signature et un digest SHA-256 lié au réseau, à la direction et aux bornes de slots. Un cursor rejoué sous une autre query est QueryInvalid.

RawPageLimit n'est pas réduit par une policy KSP : PostgreSQL utilise LIMIT requested + 1, avec comme seule borne physique requested <= i64::MAX - 1. Une valeur supérieure produit PageLimitUnsupported sans clamp. La pagination ne promet aucun snapshot inter-pages.

Rétention RAW 0.3.3-pre.007

transition_raw_transaction_retention applique uniquement les transitions physiques supportées :

Full -> Archived -> Purged

Le backend verrouille la ligne canonique avec FOR UPDATE, valide la forme physique courante, compare current avec expected et n'effectue la mutation qu'en cas de correspondance. current == target retourne AlreadyAtTarget; une race ayant déplacé l'état ailleurs retourne ExpectedStateMismatch. Une référence absente est ReferenceNotFound.

Full -> Archived copie d'abord les octets exacts dans ksp_raw_transaction_archive_payloads, puis retire le payload chaud et passe l'état à archived dans la même transaction. Archived -> Purged supprime l'archive, efface block_time, conserve les cinq champs de tombstone et passe l'état à purged atomiquement. Les écritures d'acquisition/rehydration et les transitions utilisent le même verrou canonique, ce qui sérialise les races purge/ForceRehydrate.

Toute transition dont expected ou target vaut Compacted est rejetée avant pool.get() avec RetentionCompactionUnsupported et le code stable store.postgres_retention_compaction_unsupported. PostgreSQL n'utilise pas TOAST comme faux contrat de compaction.

Preuve PostgreSQL live 0.3.3

La vertical slice RawTransaction possède un test PostgreSQL réel opt-in dédié :

postgres_raw_transaction_live

Il refuse une base où une table KSP gérée existe déjà, lit lURI dédiée uniquement sur stdin, ne laffiche jamais et nettoie seulement le schéma quil a lui-même créé. La preuve couvre bootstrap V000/V001, binding réseau, réparation additive contrôlée, écritures atomiques, concurrence réelle, observations, pagination/cursor, rétention/ForceRehydrate, races et rollback par annulation dune tâche bloquée sur un verrou PostgreSQL.

Le test reste #[ignore] dans les gates ordinaires. Après les corrections de compatibilité catalogue/drift de pre.009-fix.001..006, il passe sur PostgreSQL 17 et a été rejoué une seconde fois avec succès au gate technique final pre.011. Son exécution réelle et le major exercé sont enregistrés dans la matrice de validation de la release.

Hors périmètre actuel

La crate ne contient encore :

  • aucune capability RawAccount* ;
  • aucune implémentation PostgreSQL des capabilities RawAccount* ;
  • aucune orchestration worker/job ;
  • aucun transport d'acquisition ou decoder Program.

Documentation