99 lines
7.0 KiB
Markdown
99 lines
7.0 KiB
Markdown
<!-- file: ks-store/README.md -->
|
||
<!-- version: 10 -->
|
||
|
||
# ks-store
|
||
|
||
`ks-store` porte la frontière de persistance généraliste de Khadhroony Solana. Les consommateurs utilisent des contrats fonctionnels et une façade `Store` indépendante du moteur concret ; PostgreSQL reste l'implémentation opérationnelle de `0.5.3`, confinée à l'intérieur de la crate.
|
||
|
||
## Périmètre
|
||
|
||
La crate expose :
|
||
|
||
- `Store` et `StoreOpenOptions` comme façade d'ouverture et handle persistant backend-agnostique ;
|
||
- les DTO et entités N1 raw/acquisition, N2 Core, N3 decode/materialization et ledger ;
|
||
- les traits async `StoreHealthStore`, `RawTransactionStore`, `CoreTransactionStore`, `AccountStateStore`, `CoreExtractionStore` et `DecodePipelineStore` ;
|
||
- les filtres et résultats de replay sans préfixe backend ;
|
||
- des diagnostics et résumés runtime/init sanitisés ne révélant ni secret ni nom physique d'objet ;
|
||
- des transactions atomiques pour normalisation d’état de compte, extraction Core, décodage et matérialisation.
|
||
|
||
## Frontière backend
|
||
|
||
`PostgresStore`, `PostgresStoreOptions`, `sqlx::PgPool`, les requêtes SQL et les noms physiques de tables sont privés à `ks-store`. `ks-pipeline`, les scénarios et les applications ne doivent connaître que `Store`, les repositories et les DTO fonctionnels.
|
||
|
||
`ks-store` ne dépend pas de `ks-config`. Un consommateur lui fournit un backend sélectionné et un objet `backend_options` opaque ; seul `ks-store` interprète et valide les paramètres PostgreSQL puis crée la connexion.
|
||
|
||
## Configuration et sécurité
|
||
|
||
`StoreOpenOptions` ne dérive pas `Debug` et ne rend pas les options backend accessibles après construction. Les résumés publics exposent uniquement des informations explicitement sanitisées : code backend, présence d'une connexion, état d'initialisation, health, modèle logique et compteurs.
|
||
|
||
Le backend PostgreSQL masque le descripteur de connexion et utilise l'unique target de crate `ks-store`, complété par `backend="postgres"`, `domain="ks-store.pg"` et un champ `action` structuré. Aucun DSN, password ou valeur bindée n'est destiné aux diagnostics publics.
|
||
|
||
## Baseline PostgreSQL `0.5.3-pre.003`
|
||
|
||
`pre.003` reconstruit directement le schéma actif sous le namespace `k_sol_*`. Les quatre migrations historiques `0001` à `0004` et les deux scripts de maintenance monolithiques ne font plus partie de la chaîne active.
|
||
|
||
Le baseline candidat au gel comprend **16 tables N1-N3** :
|
||
|
||
- N1 : transactions raw, observations d'acquisition de transactions et observations génériques de comptes ;
|
||
- N2 : transaction Core, clés de comptes, instructions top-level, CPI, logs, variations de balances, return data et états canoniques de comptes ;
|
||
- N3/transverse : processing ledger, événements décodés, déclarations/observations de couverture et `k_sol_mat_outputs`.
|
||
|
||
Les ressources PostgreSQL sont rangées sous `migrations/postgres/` et suivent la règle **une instruction SQL par fichier**. À l’ouverture, `ks-store` valide toute ressource gérée déjà présente : une colonne, clé primaire/étrangère ou index existant mais incompatible provoque une erreur. Avec `auto_initialize_schema=true`, les ressources gérées absentes peuvent être complétées de manière **strictement additive** : création d’une table absente, ajout d’une colonne absente, ajout d’une contrainte/clé absente et création d’un index absent. L’auto-initialisation ne supprime, ne renomme et ne modifie jamais une colonne existante. Les tables étrangères et d’anciens objets `kb_sol_*` peuvent coexister sans blocage tant qu’ils ne font pas partie du contrat actif.
|
||
|
||
Le baseline conserve **16 tables** et comporte désormais **240 ressources SQL atomiques** et **79 index attendus** après la revue des chemins de replay `pre.004`, comptés sans exposer leurs noms dans l'API publique.
|
||
|
||
## Repositories et replay `0.5.3-pre.004`
|
||
|
||
`pre.004` ferme la symétrie opérationnelle des repositories sans ajouter de table :
|
||
|
||
- les instructions top-level et CPI restent séparées physiquement mais sont lues par une union logique commune pour le replay ;
|
||
- le lifecycle decode/materialization est recalculé pour les deux scopes et tient compte de l’identité/version du decoder courant ;
|
||
- le remplacement d’un graphe Core invalide ses descendants N3 dans la même transaction ; un remplacement decode invalide les sorties de matérialisation de ce decoder/input ;
|
||
- `k_sol_obs_account_observations` -> `k_sol_core_account_states` devient un replay N1 -> N2 opérationnel, versionné par processing ledger ;
|
||
- les pages interactives utilisent un curseur stable et sont bornées à 500 lignes ; les batches de processing Core/decode/account-state sont séparément bornés à 1 000 ;
|
||
- les opérations PostgreSQL réécrites émettent des traces `TRACE` sous `ks-store` avec durée/résultat/nombre de lignes, sans SQL brut ni valeur bindée.
|
||
|
||
Le gel formel N1/N2/N3 n’est pas encore déclaré : il reste conditionné au snapshot et aux validations de réconciliation prévus dans la tranche dédiée.
|
||
|
||
## Readiness des futurs décodeurs
|
||
|
||
Le canari future-decoder a conduit à trois corrections génériques avant gel :
|
||
|
||
- `block_time` devient une colonne de premier rang sur raw/Core transaction ;
|
||
- `returnData` est conservée explicitement dans le Core via `k_sol_core_return_data` ;
|
||
- un chemin générique d'observation/état de compte est réservé via `k_sol_obs_account_observations` et `k_sol_core_account_states`.
|
||
|
||
Les instructions top-level et CPI restent physiquement séparées. Les deux contrats portent `stack_height` lorsque disponible ; les CPI conservent un `parent_instruction_path` vers le parent immédiat reconstructible.
|
||
|
||
N3 réserve en outre une provenance de schéma nullable sur les observations décodées afin qu'un futur décodeur basé sur un schéma externe/IDL puisse tracer ce schéma sans remodeler le Core.
|
||
|
||
Aucune structure `anchor_*`, DEX ou projection metadata N4 n'est créée en `pre.003`.
|
||
|
||
## Responsabilités
|
||
|
||
- garantir les invariants des données persistées ;
|
||
- posséder la connexion et l'initialisation du backend actif ;
|
||
- fournir des frontières async typées au pipeline ;
|
||
- protéger les opérations multi-tables par transactions ;
|
||
- borner les diagnostics et replay exposés ;
|
||
- permettre le remplacement futur de PostgreSQL sans réécriture des consommateurs.
|
||
|
||
## Hors périmètre
|
||
|
||
La crate ne décode pas les instructions, n'acquiert pas elle-même les transactions/comptes et ne décide pas quelle matérialisation ou projection N4 exécuter. Elle persiste les faits produits par `ks-lib` et orchestrés par `ks-pipeline`.
|
||
|
||
## Relations
|
||
|
||
- dépend de `ks-core` pour les erreurs ;
|
||
- utilise les contrats de replay de `ks-lib` ;
|
||
- est consommée principalement par `ks-pipeline`, `ks-pipeline-demo-scenarios` et `kb-app-demo-desktop` ;
|
||
- ne dépend pas de `ks-config`.
|
||
|
||
## Documents
|
||
|
||
- [Utilisation](USAGE.md)
|
||
- [Travaux restants](TODO.md)
|
||
- [Historique](CHANGELOG.md)
|
||
- [Architecture du stockage](../docs/architecture/STORAGE_ARCHITECTURE.md)
|
||
- [Plan actif `0.5.3`](../docs/plans/V0_5_3_KS_STORE_NORMALIZATION_PLAN.md)
|