Files
khadhroony-bot3/docs/guides/POSTGRES_STORAGE.md
2026-08-12 11:00:59 +02:00

152 lines
6.3 KiB
Markdown

<!-- file: docs/guides/POSTGRES_STORAGE.md -->
<!-- version: 6 -->
# Guide PostgreSQL et contrats de stockage
## Objectif
`ks-store` porte la frontière de stockage généraliste. PostgreSQL reste le backend opérationnel actif, mais il est encapsulé derrière la façade publique backend-agnostique `Store`.
## Connexion
Les consommateurs ne construisent plus `PostgresStore`, `PostgresStoreOptions` ni un pool SQLx. Ils transmettent le backend sélectionné et ses options résolues à `StoreOpenOptions`; `ks-store` valide et interprète ensuite les paramètres PostgreSQL.
```rust
let options = match ks_store::StoreOpenOptions::new(
true,
"postgres",
serde_json::json!({
"url": database_url,
"max_connections": 10,
"connect_timeout_ms": 10_000,
"auto_initialize_schema": true
}),
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match ks_store::Store::open(options).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
```
Le descripteur public éventuellement affiché provient du résumé runtime et est déjà masqué par `ks-store`. Le DSN brut et les options backend ne doivent jamais être propagés dans les DTO, erreurs applicatives ou logs normaux.
## Domaines
- N1 raw/acquisition : transactions canoniques, observations de transactions et observations génériques de comptes ;
- N2 Core : transactions, clés, top-level, CPI, logs, variations de balances, return data et états de comptes ;
- N3/transverse : ledger, observations décodées, couverture et `k_sol_mat_outputs` ;
- replay/diagnostic : sélections et résumés bornés au-dessus de ces contrats.
## Baseline `0.5.3-pre.003`
`pre.003` reconstruit directement le schéma sous `k_sol_*`. Les bases Devnet/Mainnet/test historiques sont considérées reconstructibles ; aucune migration in-place depuis `kb_sol_*` n'est fournie.
Le comportement attendu à l'ouverture est :
1. base vide + auto-init : création du baseline complet ;
2. base `k_sol_*` déjà conforme : vérification/idempotence ;
3. base contenant encore des objets `kb_sol_*` : refus non destructif et demande de reconstruction explicite ;
4. `DROP`/`TRUNCATE` : opérations de maintenance distinctes, jamais déclenchées implicitement par `Store::open()`.
Le baseline candidat au gel comprend 16 tables N1-N3.
## Ressources SQL
Les ressources actives sont sous :
```text
ks-store/migrations/postgres/
schema/
tables/
constraints/
indexes/
maintenance/
truncate/
drop/
```
Chaque fichier contient une instruction SQL. Le code PostgreSQL privé utilise `include_str!` et l'orchestrateur global exécute le schéma dans une transaction unique avec advisory lock.
Il n'existe plus trois initialiseurs raw/Core/decode indépendants : **l'initialisation du schéma est globale**.
Le corpus `pre.003` contient actuellement :
- 16 créations de tables ;
- 129 ressources de contraintes ;
- 59 créations d'index explicites ;
- 16 ressources `TRUNCATE` ;
- 16 ressources `DROP` ;
- soit **236 ressources SQL**.
PostgreSQL attend **75 index** au total dans son diagnostic : 59 index explicites plus les 16 index de clé primaire créés par PostgreSQL.
Les index non uniques restent des optimisations physiques et ne font pas partie du gel logique N1-N3.
## Statut du schéma
La façade n'utilise plus `_sqlx_migrations` comme preuve du baseline actuel. Le statut est dérivé du contrat réellement observé :
- aucune ressource connue : non initialisé ;
- toutes les ressources attendues : contrat courant ;
- présence partielle : drift/partial.
Le résumé d'initialisation expose des compteurs de modèles, tables et index sans publier leurs noms physiques.
## Compatibilité des identités de processeurs
Depuis `0.5.1-pre.003`, les identités techniques produites par `ks-lib` utilisent `ks-lib-decoder.*`, `ks-lib-executor.*` et `ks-lib-materializer.*`.
Comme les bases `0.5.2` doivent être reconstruites pour le nouveau baseline `0.5.3`, les anciennes identités `kb-lib.*` ne sont pas migrées automatiquement dans ce chantier.
## Core readiness
`pre.003` ajoute les éléments génériques nécessaires au futur redécodage :
- `block_time` sur raw/Core transaction ;
- `stack_height` sur top-level/CPI ;
- parent CPI immédiat reconstructible ;
- `k_sol_core_return_data` ;
- `k_sol_obs_account_observations` ;
- `k_sol_core_account_states` ;
- provenance de schéma optionnelle sur les observations décodées.
Ces contrats sont indépendants d'Anchor/IDL. Aucun parser Anchor ni table `anchor_*` n'appartient à `0.5.3`.
## Repositories
Les traits publics et la façade `Store` décrivent des opérations fonctionnelles indépendantes du moteur. PostgreSQL implémente ces contrats à l'intérieur de `ks-store`; aucune crate consommatrice ne reçoit `PgPool`, un type SQLx ou une requête concrète.
Le schéma des observations/états de comptes est introduit avant gel en `pre.003`; son ingestion/replay fonctionnel est raccordé dans la tranche repositories/replay suivante.
## Diagnostics
La surface publique expose :
- health snapshot ;
- schema/migration snapshot générique ;
- backend descriptor masqué ;
- résumé de configuration sanitisé ;
- résumé d'initialisation/vérification par modèle logique ;
- diagnostics de ressources sans nom physique d'objet.
Les noms de tables, index, contraintes et le SQL restent des détails backend-internes. Les traces PostgreSQL utilisent l'unique `target: crate::TRACING_TARGET` (`ks-store`) avec les champs structurés `backend="postgres"`, `domain="ks-store.pg"` et un `action` précis.
## Invariants
- aucune donnée canonique ne doit être dupliquée sans justification ;
- les écritures rejouables doivent être idempotentes ;
- la progression de campagne doit rester cohérente avec les lignes effectivement traitées ;
- les requêtes dynamiques n'acceptent que des identifiants validés ;
- les détails PostgreSQL utiles au diagnostic restent backend-internes ;
- les erreurs traversant la façade publique ne doivent jamais divulguer DSN, password ou options sensibles ;
- un nouveau décodeur doit pouvoir exploiter N1/N2/N3 sans remodelage normal de ces niveaux.
## Références
- `docs/architecture/STORAGE_ARCHITECTURE.md` ;
- `ks-store/USAGE.md` ;
- `ks-store/README.md`.