v0.3.2-pre.011

This commit is contained in:
2026-08-30 05:55:29 +02:00
parent e1fe419028
commit b375f263dc
13 changed files with 1011 additions and 36 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 344 # version: 345
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"] members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"]
[workspace.package] [workspace.package]
version = "0.3.2-pre.10" version = "0.3.2-pre.11"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-config-lib/README.md --> <!-- file: crates/ksp-config-lib/README.md -->
<!-- version: 10 --> <!-- version: 11 -->
# ksp-config-lib # ksp-config-lib
@@ -25,6 +25,7 @@ La crate centralise les documents JSON, leurs schemas, les profils et compositio
- l'adapter du document Logging effectif vers `ksp_logging_lib::LoggingSettings` ; - l'adapter du document Logging effectif vers `ksp_logging_lib::LoggingSettings` ;
- l'adapter du document Transport V1/V2/V3 vers `HttpTransportSettings`, `WsTransportSettings` et, en V3, `YellowstoneGrpcTransportSettings`, y compris redaction/provenance des URLs `KSP_SECRET_*` ; - l'adapter du document Transport V1/V2/V3 vers `HttpTransportSettings`, `WsTransportSettings` et, en V3, `YellowstoneGrpcTransportSettings`, y compris redaction/provenance des URLs `KSP_SECRET_*` ;
- l'adapter de `cfg.std.offchain_transport` vers `ksp_offchain_transport_lib::MarketPriceService`, avec contrôle de provenance des credentials/public fields et sans rendre les limites provider configurables ; - l'adapter de `cfg.std.offchain_transport` vers `ksp_offchain_transport_lib::MarketPriceService`, avec contrôle de provenance des credentials/public fields et sans rendre les limites provider configurables ;
- l'adapter de `cfg.std.store` vers `ksp_store_lib::StoreSettings`, avec sélection d'un target nommé, réseau explicite et URI PostgreSQL à provenance `Secret` ;
- la surface de management pour inspecter et réparer les sources Config enregistrées, modifier `std.logging.json`, consulter les rapports d'environnement, révéler explicitement une valeur réelle et modifier `.env` ; - la surface de management pour inspecter et réparer les sources Config enregistrées, modifier `std.logging.json`, consulter les rapports d'environnement, révéler explicitement une valeur réelle et modifier `.env` ;
- les écritures atomiques JSON/`.env` et la protection des permissions `.env` ; - les écritures atomiques JSON/`.env` et la protection des permissions `.env` ;
- les audits workspace empêchant les bypass d'ownership Config et les oublis dans `.env.example`. - les audits workspace empêchant les bypass d'ownership Config et les oublis dans `.env.example`.
@@ -34,14 +35,17 @@ La crate centralise les documents JSON, leurs schemas, les profils et compositio
Le registre par défaut connaît : Le registre par défaut connaît :
```text ```text
cfg.composite.ksp-app-wallet-desk -> config/composite.ksp-app-wallet-desk.json cfg.composite.ksp-app-solprices-desk -> config/composite.ksp-app-solprices-desk.json
cfg.composite.ksp-app-wallet-desk -> config/composite.ksp-app-wallet-desk.json
cfg.std.logging -> config/std.logging.json cfg.std.logging -> config/std.logging.json
cfg.std.offchain_transport -> config/std.offchain_transport.json cfg.std.offchain_transport -> config/std.offchain_transport.json
cfg.std.store -> config/std.store.json
cfg.std.transport -> config/std.transport.json cfg.std.transport -> config/std.transport.json
cfg.std.wallet -> config/std.wallet.json cfg.std.wallet -> config/std.wallet.json
schema.composite -> config/schemas/composite.schema.json schema.composite -> config/schemas/composite.schema.json
schema.std.logging -> config/schemas/std.logging.schema.json schema.std.logging -> config/schemas/std.logging.schema.json
schema.std.offchain_transport -> config/schemas/std.offchain_transport.schema.json schema.std.offchain_transport -> config/schemas/std.offchain_transport.schema.json
schema.std.store -> config/schemas/std.store.schema.json
schema.std.transport -> config/schemas/std.transport.schema.json schema.std.transport -> config/schemas/std.transport.schema.json
schema.std.wallet -> config/schemas/std.wallet.schema.json schema.std.wallet -> config/schemas/std.wallet.schema.json
``` ```
@@ -50,7 +54,7 @@ schema.std.wallet -> config/schemas/std.wallet.schema.json
`ConfigManagement::read_source()` permet d'inspecter le texte brut d'un document Config enregistré même lorsque ce document est invalide. `save_source_candidate()` complète cette frontière : le candidat brut est parsé, validé contre son schema et les invariants sémantiques KSP, puis persisté atomiquement uniquement après validation complète. Le `file_id` doit appartenir au registre et désigner un document Config ; aucun path arbitraire n'est accepté. `ConfigManagement::read_source()` permet d'inspecter le texte brut d'un document Config enregistré même lorsque ce document est invalide. `save_source_candidate()` complète cette frontière : le candidat brut est parsé, validé contre son schema et les invariants sémantiques KSP, puis persisté atomiquement uniquement après validation complète. Le `file_id` doit appartenir au registre et désigner un document Config ; aucun path arbitraire n'est accepté.
`config/examples/composite.example.json` conserve lexemple générique. `config/composite.ksp-app-wallet-desk.json` est le premier composite runtime concret : il sélectionne Logging, Transport et Wallet par `file_id`, sans dépendre de leurs filenames physiques. `config/examples/composite.example.json` conserve lexemple générique. Les composites runtime committed restent possédés par Config : `config/composite.ksp-app-solprices-desk.json` sélectionne Logging + Off-chain Transport, tandis que `config/composite.ksp-app-wallet-desk.json` sélectionne Logging + Off-chain Transport + On-chain Transport + Wallet. Tous référencent leurs documents par `file_id`, sans dépendre de filenames physiques.
Le fichier local d'environnement est : Le fichier local d'environnement est :
@@ -68,11 +72,11 @@ Les autres crates et applications KSP ne doivent pas :
- parser ou écrire directement `.env` ; - parser ou écrire directement `.env` ;
- ouvrir directement les documents Config connus par leur filename physique ; - ouvrir directement les documents Config connus par leur filename physique ;
- réimplémenter la sélection de profils, les compositions ou les placeholders ; - réimplémenter la sélection de profils, les compositions ou les placeholders ;
- reconstruire elles-mêmes la configuration Logging, On-chain Transport, Off-chain Transport ou Wallet depuis le JSON. - reconstruire elles-mêmes la configuration Logging, On-chain Transport, Off-chain Transport, Store ou Wallet depuis le JSON.
`ksp-config-lib` dépend de `ksp-core-lib` pour `Error`/`Result`, de `ksp-logging-lib` pour les événements Config utiles et le contrat `LoggingSettings`, de `ksp-onchain-transport-lib` pour construire le contrat runtime On-chain Transport et de `ksp-offchain-transport-lib` pour construire le service market-price dans la direction Config -> Transport. Le document Wallet reste un contrat de chemins/profils Config et nintroduit aucune dépendance Config -> `ksp-wallet-lib`. `ksp-config-lib` dépend de `ksp-core-lib` pour `Error`/`Result`, de `ksp-logging-lib` pour les événements Config utiles et le contrat `LoggingSettings`, de `ksp-onchain-transport-lib` pour construire le contrat runtime On-chain Transport et de `ksp-offchain-transport-lib` pour construire le service market-price dans la direction Config -> Transport et de `ksp-store-lib` avec `default-features = false` pour construire les settings Store dans la direction Config -> Store sans forcer un backend physique. Le document Wallet reste un contrat de chemins/profils Config et nintroduit aucune dépendance Config -> `ksp-wallet-lib`.
La dépendance inverse est interdite : `ksp-core-lib`, `ksp-logging-lib`, `ksp-onchain-transport-lib` et `ksp-offchain-transport-lib` ne dépendent pas de Config. La dépendance inverse est interdite : `ksp-core-lib`, `ksp-logging-lib`, `ksp-onchain-transport-lib`, `ksp-offchain-transport-lib` et les crates Store ne dépendent pas de Config.
Config ne possède pas le `LoggingGuard`. L'application ou le service qui orchestre le runtime construit la configuration effective puis possède le lifecycle `ksp_logging_lib::initialize/reinitialize`. Config ne possède pas le `LoggingGuard`. L'application ou le service qui orchestre le runtime construit la configuration effective puis possède le lifecycle `ksp_logging_lib::initialize/reinitialize`.
@@ -84,7 +88,7 @@ Un secret reste accessible au runtime ou au management lorsqu'un consumer autori
Les méthodes `reveal_*` constituent un opt-in explicite au réel. L'authentification/autorisation de l'utilisateur humain appartient à l'application appelante et les valeurs retournées par ces méthodes ne doivent jamais être journalisées. Les méthodes `reveal_*` constituent un opt-in explicite au réel. L'authentification/autorisation de l'utilisateur humain appartient à l'application appelante et les valeurs retournées par ces méthodes ne doivent jamais être journalisées.
Le document Logging refuse les valeurs de sensibilité `Secret` dans sa configuration effective. Le document Transport accepte les valeurs secrètes pour les URLs HTTP/WebSocket et, en V3, pour `grpc_endpoints[].secret_metadata[]` : la valeur réelle est transmise au runtime légitime, tandis que la projection sûre et les `Debug` restent redacted. Les metadata gRPC publiques et secrètes sont séparées et leur provenance Config est contrôlée avant mapping. `std.offchain_transport` exige une provenance `Secret` pour les API keys effectives et une provenance `Public` pour la paire DexScreener lorsqu'elle vient de l'environnement ; il ne permet ni URL provider arbitraire ni override de rate limit. `std.wallet` refuse également toute sensibilité `Secret` pour `wallets_directory`/`wallets_subdirectory`; les passwords Wallet restent un autre flux Config et ne sont jamais stockés dans ce JSON. Le document Logging refuse les valeurs de sensibilité `Secret` dans sa configuration effective. Le document Transport accepte les valeurs secrètes pour les URLs HTTP/WebSocket et, en V3, pour `grpc_endpoints[].secret_metadata[]` : la valeur réelle est transmise au runtime légitime, tandis que la projection sûre et les `Debug` restent redacted. Les metadata gRPC publiques et secrètes sont séparées et leur provenance Config est contrôlée avant mapping. `std.offchain_transport` exige une provenance `Secret` pour les API keys effectives et une provenance `Public` pour la paire DexScreener lorsqu'elle vient de l'environnement ; il ne permet ni URL provider arbitraire ni override de rate limit. `std.store` exige une provenance `Secret` pour chaque URI PostgreSQL effective et conserve des targets réseau-spécifiques indépendants (`devnet`, `mainnet`, `testnet`) sans exposer l'URI dans les projections sûres. `std.wallet` refuse également toute sensibilité `Secret` pour `wallets_directory`/`wallets_subdirectory`; les passwords Wallet restent un autre flux Config et ne sont jamais stockés dans ce JSON.
## Documentation ## Documentation
@@ -94,6 +98,8 @@ Le document Logging refuse les valeurs de sensibilité `Secret` dans sa configur
- [`../../config/std.logging.json`](../../config/std.logging.json) — document standard Logging ; - [`../../config/std.logging.json`](../../config/std.logging.json) — document standard Logging ;
- [`../../config/std.transport.json`](../../config/std.transport.json) — document standard Transport V3 HTTP + WebSocket + Yellowstone gRPC, avec lecture backward des V1/V2 ; - [`../../config/std.transport.json`](../../config/std.transport.json) — document standard Transport V3 HTTP + WebSocket + Yellowstone gRPC, avec lecture backward des V1/V2 ;
- [`../../config/std.offchain_transport.json`](../../config/std.offchain_transport.json) — document standard Off-chain Transport V1, actuellement limité au domaine `market_price` SOL/USD ; - [`../../config/std.offchain_transport.json`](../../config/std.offchain_transport.json) — document standard Off-chain Transport V1, actuellement limité au domaine `market_price` SOL/USD ;
- [`../../config/std.store.json`](../../config/std.store.json) — targets Store PostgreSQL Devnet/Mainnet/Testnet et settings runtime bornés ;
- [`../../config/std.wallet.json`](../../config/std.wallet.json) — racine Wallet globale et sous-répertoire optionnel par profil ; - [`../../config/std.wallet.json`](../../config/std.wallet.json) — racine Wallet globale et sous-répertoire optionnel par profil ;
- [`../../config/composite.ksp-app-wallet-desk.json`](../../config/composite.ksp-app-wallet-desk.json) — composition Logging/Transport/Wallet de Wallet Desk ; - [`../../config/composite.ksp-app-solprices-desk.json`](../../config/composite.ksp-app-solprices-desk.json) — composition Logging/Off-chain Transport de SOL Prices Desk ;
- [`../../config/composite.ksp-app-wallet-desk.json`](../../config/composite.ksp-app-wallet-desk.json) — composition Logging/Off-chain Transport/On-chain Transport/Wallet de Wallet Desk ;
- [`../../.env.example`](../../.env.example) — inventaire versionné des variables d'environnement runtime. - [`../../.env.example`](../../.env.example) — inventaire versionné des variables d'environnement runtime.

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-config-lib/USAGE.md --> <!-- file: crates/ksp-config-lib/USAGE.md -->
<!-- version: 13 --> <!-- version: 14 -->
# Utilisation de ksp-config-lib # Utilisation de ksp-config-lib
@@ -28,8 +28,11 @@ Les arguments compris par Config sont :
```text ```text
--cfgpath=/path/to/config --cfgpath=/path/to/config
--schemapath=/path/to/schemas --schemapath=/path/to/schemas
--filemap=cfg.composite.ksp-app-solprices-desk=my-solprices-desk.json
--filemap=cfg.composite.ksp-app-wallet-desk=my-wallet-desk.json --filemap=cfg.composite.ksp-app-wallet-desk=my-wallet-desk.json
--filemap=cfg.std.logging=my-logging.json --filemap=cfg.std.logging=my-logging.json
--filemap=cfg.std.offchain_transport=my-offchain-transport.json
--filemap=cfg.std.store=my-store.json
--filemap=cfg.std.transport=my-transport.json --filemap=cfg.std.transport=my-transport.json
--filemap=cfg.std.wallet=my-wallet.json --filemap=cfg.std.wallet=my-wallet.json
``` ```
@@ -212,7 +215,56 @@ Config ne permet pas de fournir `base_url`, `endpoint_url`, `rate_limit` ou `req
ksp-config-lib -> ksp-offchain-transport-lib ksp-config-lib -> ksp-offchain-transport-lib
``` ```
Off-chain Transport ne lit ni `.env`, ni `KSP_*`, ni les documents Config. Une application telle que la future `ksp-app-solprices-desk` peut recevoir le service déjà composé puis utiliser uniquement `registry()`, `refresh`, `refresh_many` et `refresh_all`. Off-chain Transport ne lit ni `.env`, ni `KSP_*`, ni les documents Config. `ksp-app-solprices-desk` reçoit le service déjà composé puis utilise uniquement la surface provider-neutral `registry()`, `refresh`, `refresh_many` et `refresh_all`.
### 4.4 Construire le Store depuis Config
`cfg.std.store` définit des targets nommés. Chaque target sélectionne exactement un réseau logique, un backend et une URI PostgreSQL distincte. Config résout les secrets puis construit le contrat backend-neutral `ksp_store_lib::StoreSettings` sans activer la feature PostgreSQL du consumer :
```rust
let store_config = match engine.load_resolved_store_config(
std::option::Option::Some("devnet"),
&environment,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let target_id = store_config.target_id();
let network = store_config.settings().network();
let _ = (target_id, network);
let store_settings = store_config.into_settings();
let store = match ksp_store_lib::Store::open(store_settings).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let _health = store.health().await;
let closed = store.close().await;
if let std::result::Result::Err(error) = closed {
return std::result::Result::Err(error);
}
```
Targets committed :
```text
devnet -> network devnet -> KSP_SECRET_STORE_DEVNET_POSTGRES_URI
mainnet -> network mainnet-beta -> KSP_SECRET_STORE_MAINNET_POSTGRES_URI
testnet -> network testnet -> KSP_SECRET_STORE_TESTNET_POSTGRES_URI
```
`default_profile = "devnet"` choisit un seul target. La sélection d'un autre target se fait par le `profile_id` explicite ; `ksp-store-lib` ne multiplexe pas plusieurs bases ou réseaux dans une même instance.
Chaque `connection_uri` doit provenir d'un placeholder `KSP_SECRET_*`/`KSPB_SECRET_*`. Une URI littérale ou issue d'une variable non secrète est rejetée par l'adapter effectif. La valeur réelle est transmise au runtime Store, mais `ResolvedStoreConfig`, `StoreSettings` et les projections sûres ne l'affichent pas.
La direction de dépendance reste :
```text
ksp-config-lib -> ksp-store-lib (default-features = false)
ksp-store-lib -X-> ksp-config-lib
ksp-store-postgres-lib -X-> ksp-config-lib
```
## 5. Profils et composites ## 5. Profils et composites
@@ -237,7 +289,7 @@ let component = match composite.component("wallet") {
let wallet = engine.resolve_wallet_config_profile(component.resolved(), &environment); let wallet = engine.resolve_wallet_config_profile(component.resolved(), &environment);
``` ```
La même forme existe pour Logging via `resolve_logging_config_profile`. Le composite concret `cfg.composite.ksp-app-wallet-desk` référence actuellement `logging`, `transport` et `wallet`; Wallet Desk valide ces trois frontières au bootstrap. La même forme existe pour Logging via `resolve_logging_config_profile`. Le composite `cfg.composite.ksp-app-solprices-desk` référence `logging` et `offchain_transport`. Le composite `cfg.composite.ksp-app-wallet-desk` référence `logging`, `offchain_transport`, `transport` et `wallet`; chaque application valide ses frontières de composition au bootstrap.
## 6. Management de `std.logging.json` ## 6. Management de `std.logging.json`

View File

@@ -0,0 +1,95 @@
<!-- file: crates/ksp-store-lib/README.md -->
<!-- version: 1 -->
# ksp-store-lib
`ksp-store-lib` est la façade runtime Store commune de KSP.
Elle expose aux consumers une surface backend-neutral, réexporte les contrats RAW de `ksp-store-api`, sélectionne uniquement les backends compilés et masque leurs objets physiques. Le backend PostgreSQL officiel est activé par défaut via la feature `postgres` et reste implémenté dans `ksp-store-postgres-lib`.
## Responsabilités
`ksp-store-lib` possède :
- `StoreSettings`, avec un réseau logique unique, un backend sélectionné et un timeout de fermeture borné ;
- les settings PostgreSQL publics KSP-owned : pool, TLS, bootstrap/migrations et URI sensible ;
- la feature `postgres` par défaut et le comportement explicite `backend_not_compiled` lorsque PostgreSQL est sélectionné sans cette feature ;
- `Store::open`, qui ne retourne une instance qu'après validation, ouverture physique du backend compilé et bootstrap/history réussis ;
- `Store::runtime_snapshot()` pour les compteurs runtime sûrs sans I/O ;
- `Store::health().await` pour la readiness portable et bornée ;
- `Store::close(self).await` pour la fermeture explicite bornée ;
- le mapping des erreurs backend vers des codes Store stables sans exposer les erreurs physiques ;
- les réexports crate-root de `ksp-store-api` nécessaires aux consumers ordinaires.
## Une instance = un réseau
Une instance `Store` représente exactement :
```text
1 Store = 1 RawNetworkId + 1 backend physique sélectionné
```
Le runtime Store n'est pas un multiplexeur multi-database ou multi-réseau. La sélection d'un target nommé appartient à Config. Le document `std.store` peut donc définir plusieurs targets indépendants — par exemple Devnet, Mainnet et Testnet — mais un appel à `Store::open` reçoit les settings d'un seul target.
Cette séparation permet d'utiliser des bases PostgreSQL distinctes par réseau tout en conservant le réseau dans l'identité logique des données RAW.
## PostgreSQL
Avec la feature par défaut :
```text
ksp-store-lib
-> ksp-store-api
-> ksp-logging-lib
-> ksp-store-postgres-lib
```
`ksp-store-lib` ne réexporte aucun type `tokio-postgres`, Deadpool ou Rustls.
Les modes TLS publics sont volontairement limités à :
```text
Disabled
VerifyFull
```
`VerifyFull` impose TLS avec vérification de la chaîne et de l'identité serveur. La policy typée Store prime sur les paramètres TLS présents dans l'URI.
## Config et secrets
Store ne lit ni `.env`, ni variables `KSP_*` / `KSPB_*`, ni variables/fichiers implicites libpq (`PG*`, `.pgpass`, fichiers TLS PostgreSQL).
`ksp-config-lib` possède `std.store`, la résolution des secrets et la sélection du target. Il construit ensuite un `StoreSettings` backend-neutral. L'URI PostgreSQL reste nécessaire au runtime mais n'a aucun getter public dans `ksp-store-lib` et son `Debug` est redacted.
Les targets committed sont actuellement :
```text
devnet -> network devnet -> base indépendante
mainnet -> network mainnet-beta -> base indépendante
testnet -> network testnet -> base indépendante
```
Les credentials restent dans les variables `KSP_SECRET_STORE_*_POSTGRES_URI` ou le `.env` possédé par Config.
## Surface actuelle et hors périmètre
La fondation runtime ne fournit encore aucune implémentation PostgreSQL des capabilities métier RAW de `ksp-store-api`.
Sont volontairement hors de cette surface :
- persistence/query/rétention PostgreSQL de `RawTransaction` ;
- persistence/query/rétention PostgreSQL de `RawAccountState` ;
- batch-size, priorité, backlog ou policy de worker/job ;
- transport d'acquisition, Program decoding et materialization ;
- exposition publique de SQL, pool, client, row, statement ou transaction PostgreSQL.
Les premières vertical slices métier sont ajoutées séparément afin que la façade runtime reste stable et backend-neutral.
## Documentation
- [`USAGE.md`](USAGE.md) — construction des settings, ouverture, health et fermeture ;
- [`../ksp-store-postgres-lib/README.md`](../ksp-store-postgres-lib/README.md) — responsabilité du backend PostgreSQL physique ;
- [`../../config/std.store.json`](../../config/std.store.json) — targets Store committed ;
- [`../../docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md`](../../docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md) — architecture durable Store ;
- [`../../docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md`](../../docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md) — plan de fondation ;
- [`../../docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md`](../../docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md) — matrice de validation.

View File

@@ -0,0 +1,219 @@
<!-- file: crates/ksp-store-lib/USAGE.md -->
<!-- version: 1 -->
# Utilisation de ksp-store-lib
## 1. Dépendance et features
Le consumer runtime normal dépend uniquement de la façade :
```toml
[dependencies]
ksp-store-lib = { path = "../ksp-store-lib" }
```
La feature par défaut est :
```text
postgres
```
Pour construire un binaire sans backend physique :
```toml
ksp-store-lib = { path = "../ksp-store-lib", default-features = false }
```
Dans ce mode, le type PostgreSQL reste connu par la surface de settings mais `Store::open` retourne `ERROR_CODE_BACKEND_NOT_COMPILED` avant toute I/O si PostgreSQL est sélectionné.
Un consumer ordinaire ne dépend pas directement de `ksp-store-postgres-lib`.
## 2. Construire des settings PostgreSQL programmatiquement
La construction directe est utile pour les tests, outils internes ou compositions qui n'utilisent pas `ksp-config-lib`.
```rust
fn programmatic_store_settings(connection_uri: std::string::String) -> ksp_store_lib::Result<ksp_store_lib::StoreSettings> {
let network = ksp_store_lib::RawNetworkId::new("devnet");
let network = match network {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let postgres = ksp_store_lib::PostgresStoreSettings::new(
connection_uri,
ksp_store_lib::PostgresPoolSettings::default(),
ksp_store_lib::PostgresTlsMode::VerifyFull,
ksp_store_lib::PostgresBootstrapSettings::default(),
);
let settings = ksp_store_lib::StoreSettings::with_default_shutdown(
network,
ksp_store_lib::StoreBackendSettings::Postgres(postgres),
);
let validation = settings.validate();
if let std::result::Result::Err(error) = validation {
return std::result::Result::Err(error);
}
return std::result::Result::Ok(settings);
}
```
`PostgresStoreSettings` ne fournit volontairement aucun getter public de l'URI. Son `Debug` remplace cette valeur par `<redacted>`.
## 3. Ouvrir et fermer un Store
`Store::open` est async et ne retourne un succès qu'après que le backend compilé a prouvé sa fondation runtime.
```rust
async fn use_store(settings: ksp_store_lib::StoreSettings) -> ksp_store_lib::Result<()> {
let store = ksp_store_lib::Store::open(settings).await;
let store = match store {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let runtime = store.runtime_snapshot();
let _network = runtime.network();
let _capacity = runtime.pool_capacity();
let _size = runtime.pool_size();
let _available = runtime.pool_available();
let _waiting = runtime.pool_waiting();
let health = store.health().await;
match health.state() {
ksp_store_lib::StoreHealthState::Ready => {}
ksp_store_lib::StoreHealthState::NotReady => {
let _safe_error_code = health.last_error_code();
}
_ => {}
}
return store.close().await;
}
```
`Store::close(self)` consomme l'instance afin qu'une fermeture explicite ne puisse pas être suivie d'une nouvelle opération via la même valeur.
## 4. Construire les settings depuis Config
Le chemin applicatif recommandé utilise `ksp-config-lib`, propriétaire du document `std.store`, de `.env` et des secrets.
Après construction du `ConfigDocumentEngine` :
```rust
fn resolve_store_settings(
engine: &ksp_config_lib::ConfigDocumentEngine,
environment: &ksp_config_lib::ConfigEnvironment,
target: std::option::Option<&str>,
) -> ksp_core_lib::Result<ksp_store_lib::StoreSettings> {
let resolved = engine.load_resolved_store_config(target, environment);
let resolved = match resolved {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(resolved.into_settings());
}
```
Targets committed :
```text
devnet -> RawNetworkId("devnet")
mainnet -> RawNetworkId("mainnet-beta")
testnet -> RawNetworkId("testnet")
```
Chaque target peut utiliser une URI PostgreSQL distincte. `default_profile` sélectionne un seul target ; `Store` ne route pas automatiquement entre plusieurs targets.
## 5. Settings disponibles
### `PostgresPoolSettings`
Valeurs par défaut :
```text
max_connections 8
connect_timeout 10 s
wait_timeout 5 s
create_timeout 10 s
recycle_timeout 5 s
```
Les getters sont :
```text
max_connections()
connect_timeout()
wait_timeout()
create_timeout()
recycle_timeout()
```
`validate()` vérifie les bornes sans I/O.
### `PostgresBootstrapSettings`
Valeurs par défaut :
```text
auto_migrate true
migration_timeout 30 s
migration_lock_timeout 10 s
```
Getters :
```text
auto_migrate()
migration_timeout()
migration_lock_timeout()
```
### `StoreSettings`
La surface expose :
```text
backend()
backend_kind()
network()
shutdown_timeout()
validate()
```
`StoreSettings::new` permet de choisir explicitement le timeout de shutdown. `StoreSettings::with_default_shutdown` utilise la borne commune par défaut de 5 secondes.
## 6. Health et diagnostics
`StoreRuntimeSnapshot` est synchrone et ne déclenche aucune I/O. Il expose uniquement :
```text
backend_kind
network
pool_capacity
pool_size
pool_available
pool_waiting
```
`StoreHealthSnapshot` ajoute une probe async bornée :
```text
state = Ready | NotReady
migration_version
pending_migration_count
last_error_code
runtime snapshot
```
Aucun snapshot n'expose URI, host, user, database, SQL, handle backend ou texte d'erreur PostgreSQL.
## 7. Limite fonctionnelle actuelle
`ksp-store-lib` réexporte les modèles et traits RAW de `ksp-store-api`, mais le backend PostgreSQL de la fondation n'implémente encore aucune capability `RawTransaction*` ou `RawAccount*`.
Les consumers ne doivent donc pas interpréter la disponibilité du runtime PostgreSQL comme une persistence métier déjà présente.

View File

@@ -0,0 +1,124 @@
<!-- file: crates/ksp-store-postgres-lib/README.md -->
<!-- version: 1 -->
# 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` ;
- le sentinel `V000__bootstrap.sql` et son checksum SHA-256 ;
- 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 :
```text
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 :
```text
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 embarque uniquement :
```text
migrations/V000__bootstrap.sql
```
Elle crée la metadata privée :
```text
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.
Aucune migration métier RAW n'appartient à cette fondation.
## Health et erreurs
`PostgresBackendRuntimeSnapshot` et `PostgresBackendHealthSnapshot` ne contiennent que des compteurs et états sûrs destinés à la façade.
`PostgresBackendError` ne conserve que :
```text
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.
## Hors périmètre actuel
La crate ne contient encore :
- aucune implémentation PostgreSQL des capabilities `RawTransaction*` ;
- aucune implémentation PostgreSQL des capabilities `RawAccount*` ;
- aucun repository métier RAW ;
- aucune table/index métier ;
- aucune orchestration worker/job ;
- aucun transport d'acquisition ou decoder Program.
## Documentation
- [`USAGE.md`](USAGE.md) — bridge physique et lifecycle ;
- [`../ksp-store-lib/README.md`](../ksp-store-lib/README.md) — façade runtime destinée aux consumers ;
- [`../../docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md`](../../docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md) — architecture Store ;
- [`../../docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md`](../../docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md) — décisions pool/TLS/migrations ;
- [`../../docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md`](../../docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md) — preuves déterministes et PostgreSQL réel.

View File

@@ -0,0 +1,155 @@
<!-- file: crates/ksp-store-postgres-lib/USAGE.md -->
<!-- version: 1 -->
# Utilisation de ksp-store-postgres-lib
## 1. Quand utiliser cette crate directement
Le consumer applicatif normal utilise `ksp-store-lib`.
Une dépendance directe à `ksp-store-postgres-lib` est réservée aux composants qui implémentent ou testent le bridge physique PostgreSQL. La crate backend ne doit pas devenir une façade parallèle.
Un tel composant doit déclarer explicitement le backend et `ksp-store-api`, car `PostgresBackendSettings::new` reçoit le `RawNetworkId` backend-neutral sans le réexporter :
```toml
[dependencies]
ksp-store-api = { path = "../ksp-store-api" }
ksp-store-postgres-lib = { path = "../ksp-store-postgres-lib" }
```
## 2. Construire le bridge physique
`PostgresBackendSettings` reçoit des valeurs déjà possédées et validées par la couche appelante. L'URI est sensible et son `Debug` est redacted.
```rust
fn backend_settings(
network: ksp_store_api::RawNetworkId,
connection_uri: std::string::String,
) -> ksp_store_postgres_lib::PostgresBackendSettings {
return ksp_store_postgres_lib::PostgresBackendSettings::new(
network,
connection_uri,
8,
std::time::Duration::from_secs(10),
std::time::Duration::from_secs(5),
std::time::Duration::from_secs(10),
std::time::Duration::from_secs(5),
ksp_store_postgres_lib::PostgresBackendTlsMode::VerifyFull,
true,
std::time::Duration::from_secs(30),
std::time::Duration::from_secs(10),
);
}
```
Le backend reçoit un seul `RawNetworkId`. Une instance physique n'est pas un routeur multi-réseau.
## 3. Ouvrir, sonder et fermer
```rust
async fn use_backend(
settings: ksp_store_postgres_lib::PostgresBackendSettings,
) -> std::result::Result<(), ksp_store_postgres_lib::PostgresBackendError> {
let backend = ksp_store_postgres_lib::PostgresBackend::open(settings).await;
let backend = match backend {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let runtime = backend.runtime_snapshot();
let _capacity = runtime.pool_capacity();
let _size = runtime.pool_size();
let _available = runtime.pool_available();
let _waiting = runtime.pool_waiting();
let health = backend.health().await;
let _ready = health.ready();
let _migration_version = health.migration_version();
let _pending = health.pending_migration_count();
let _safe_error_kind = health.last_error_kind();
return backend.close(std::time::Duration::from_secs(5)).await;
}
```
`open` prouve la connexion et le bootstrap avant de retourner. `close` ferme le pool puis attend son drain dans la deadline fournie.
## 4. Choisir le mode TLS
### `VerifyFull`
À utiliser pour les connexions PostgreSQL protégées :
```rust
ksp_store_postgres_lib::PostgresBackendTlsMode::VerifyFull
```
Le backend charge les roots système et vérifie certificat + identité serveur. Il rejette une configuration ne fournissant pas d'identité vérifiable.
### `Disabled`
```rust
ksp_store_postgres_lib::PostgresBackendTlsMode::Disabled
```
Ce mode désactive explicitement TLS. Il ne doit être utilisé que lorsque la topologie de déploiement justifie clairement une connexion non chiffrée.
La valeur typée choisie par KSP prime sur les paramètres SSL de l'URI.
## 5. Bootstrap et migrations
Le backend embarque son propre moteur de migrations. Le seul artefact initial est :
```text
migrations/V000__bootstrap.sql
```
Le bootstrap maintient :
```text
ksp_store_schema_migrations
version
name
checksum SHA-256
```
Le runner est transactionnel et sérialisé par advisory transaction lock. Une divergence de checksum/nom/version ou une history plus récente est terminale ; aucun down migration automatique n'est exécuté.
`auto_migrate = false` permet de vérifier l'état sans appliquer de migration pending.
## 6. Classifier les erreurs sans fuite
```rust
match error.kind() {
ksp_store_postgres_lib::PostgresBackendErrorKind::ConfigInvalid => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::ConnectFailed => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::PoolTimeout => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::HealthFailed => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::MigrationFailed => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::MigrationMismatch => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::SchemaNewer => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::ShutdownTimeout => {}
ksp_store_postgres_lib::PostgresBackendErrorKind::TlsFailed => {}
_ => {}
}
let _safe_phase = error.phase();
```
Ne pas reconstruire un diagnostic utilisateur à partir de l'erreur brute PostgreSQL : cette erreur n'est volontairement pas conservée par le bridge.
## 7. Ce que cette crate ne permet pas encore
La fondation physique n'implémente pas les traits `RawTransaction*` ou `RawAccount*` de `ksp-store-api`.
Un backend ouvert et healthy prouve uniquement :
```text
connexion/pool
TLS selon policy
bootstrap/history
health/readiness
close borné
```
Il ne prouve aucune persistence métier RAW.

268
deltas/0.3.2/pre.011.md Normal file
View File

@@ -0,0 +1,268 @@
<!-- file: deltas/0.3.2/pre.011.md -->
<!-- version: 1 -->
# Delta `0.3.2-pre.011` — réconciliation documentaire finale Store/PostgreSQL
## 1. Base requise
Base directe attendue :
```text
0.3.2-pre.010
```
Commit attendu :
```text
v0.3.2-pre.011
```
Archive overlay attendue :
```text
ksp-general-0.3.2-pre.011.zip
```
Cette tranche suit le gate technique final `pre.010` et n'ajoute aucun comportement runtime.
## 2. Résultat du gate technique `pre.010`
Le gate opérateur `0.3.2-pre.010` a été rejoué après `cargo clean` et fournit les preuves suivantes :
```text
audits Rust PASS
cargo check --workspace PASS
cargo clippy --workspace --all-targets PASS
tests ciblés de toutes les crates PASS
ksp-store-lib default + --no-default-features PASS
cargo test --workspace PASS
graphes Cargo normal/features/duplicates exécutés
3 builds Tauri Linux PASS
PostgreSQL live foundation PASS — major 17
```
La ligne d'audit Markdown du journal opérateur `pre.010` a utilisé par erreur `deltas/0.3.1` au lieu de `deltas/0.3.2`. L'overlay `pre.010` avait été audité dans l'environnement de génération avec le chemin correct ; `pre.011` rejoue explicitement le scope complet `deltas/0.3.2`. Cette erreur de scope de commande ne constitue pas un défaut runtime et n'ouvre pas un `pre.010-fix`.
## 3. Objectif
Appliquer `VER-LIFECYCLE-006` et figer les documents durables de la fondation Store/PostgreSQL avant la préparation de publication minimale :
```text
README/USAGE ksp-store-lib
README/USAGE ksp-store-postgres-lib
README/USAGE ksp-config-lib pour std.store
index docs global
index plans
index validations
plan 023
validation 019
```
Cette tranche ne finalise pas `CHANGELOG.md`, `ROADMAP.md` ni le prompt `0.3.3`.
## 4. Documentation de `ksp-store-lib`
Le nouveau README fixe durablement :
```text
façade runtime backend-neutral
feature postgres par défaut
1 Store = 1 RawNetworkId + 1 backend physique
aucun multiplexage automatique de bases/réseaux
Config propriétaire des targets et secrets
aucun type PostgreSQL physique réexporté
aucune capability RAW PostgreSQL encore implémentée
```
Le nouveau USAGE documente :
```text
dépendance consumer normale uniquement vers ksp-store-lib
construction programmatique de StoreSettings
Store::open / runtime_snapshot / health / close
résolution recommandée via ksp-config-lib
settings pool/bootstrap/TLS
surface health sûre
limite fonctionnelle de la fondation
```
## 5. Documentation de `ksp-store-postgres-lib`
Le README et le USAGE fixent la crate comme backend physique, non comme seconde façade :
```text
consumer ordinaire -X-> ksp-store-postgres-lib
bridge façade/tests seulement
pool Deadpool borné
TLS Disabled / VerifyFull via Rustls
roots système + AWS-LC
moteur de migrations KSP privé
V000 bootstrap + ksp_store_schema_migrations
history version/name/SHA-256 + advisory transaction lock
health/runtime snapshots sûrs
PostgresBackendError = kind + phase statique
aucune table/repository/capability RAW métier
```
La politique durable reste PostgreSQL >= 15 pour la validation de fondation ; le major effectivement exercé reste enregistré dans la matrice et non figé comme dépendance runtime maximale.
## 6. Réconciliation Config
`ksp-config-lib/README.md` et `USAGE.md` documentent désormais :
```text
cfg.std.store / schema.std.store
Config -> Store avec default-features = false
sélection de target nommée
RawNetworkId explicite
provenance Secret obligatoire de l'URI PostgreSQL
variables KSP_SECRET_STORE_DEVNET_POSTGRES_URI
KSP_SECRET_STORE_MAINNET_POSTGRES_URI
KSP_SECRET_STORE_TESTNET_POSTGRES_URI
targets committed devnet/mainnet/testnet
bases PostgreSQL indépendantes par target
absence de routage multi-target dans Store
```
Aucune lecture d'environnement n'est déplacée vers Store/backend.
## 7. Indexes et documents de release
Les indexes durables référencent maintenant le plan `023` et la validation `019` ainsi que la documentation des deux crates runtime.
Le plan `023` enregistre le résultat réel de `pre.010`, la correction de scope Markdown à rejouer et la matérialisation documentaire de `pre.011`.
La matrice `019` est réconciliée avec les preuves réelles de `pre.002` à `pre.010`, y compris :
```text
ksp-store-api non régressé
pool/TLS/bootstrap/health/close
hardening/security
feature mismatch
no-env
PostgreSQL live major 17 en pre.008 et pre.010
3 builds Tauri au gate final
aucun TODO technique applicable à 0.3.2
```
Le seul statut restant avant fermeture de `pre.011` est son propre gate documentaire opérateur.
## 8. Documents relus et volontairement inchangés
Les architectures suivantes ont été relues sur la surface finale `pre.010` :
```text
docs/architecture/003-COMPONENT_CONTRACTS.md
docs/architecture/004-COMPONENT_INVENTORY.md
docs/architecture/005-DEPENDENCY_GRAPH.md
docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md
```
Elles sont déjà cohérentes avec le split façade/backend et ne sont pas modifiées artificiellement.
Le choix documentaire de `0.3.1-pre.009` de ne pas créer un README/USAGE propre à `ksp-store-api` n'est pas rouvert par cette release runtime/backend.
## 9. Hors scope préservé
Aucun élément suivant n'est introduit :
```text
RawTransaction PostgreSQL persistence/query/retention
RawAccountState PostgreSQL persistence/query/retention
SQL métier RAW
repository métier
batch/backlog/priority worker/job
Store Desk
nouvelle migration
nouvelle dépendance
nouveau test fonctionnel
modification src/**
```
## 10. Fichiers ajoutés
```text
crates/ksp-store-lib/README.md
crates/ksp-store-lib/USAGE.md
crates/ksp-store-postgres-lib/README.md
crates/ksp-store-postgres-lib/USAGE.md
deltas/0.3.2/pre.011.md
```
## 11. Fichiers modifiés
```text
Cargo.toml
crates/ksp-config-lib/README.md
crates/ksp-config-lib/USAGE.md
docs/000-README.md
docs/plans/000-README.md
docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md
docs/validation/000-README.md
docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md
```
## 12. Fichiers supprimés
```text
aucun
```
## 13. Version Cargo
La prerelease non-fix synchronise :
```text
workspace.package.version = 0.3.2-pre.11
```
Aucune dépendance, feature ou configuration Cargo n'est modifiée en dehors de cette version.
## 14. Validation de génération
L'environnement de génération ne fournit pas `cargo`/`rustc`; aucun résultat Cargo local n'est donc déclaré PASS par ce delta.
Les audits Python applicables ont été rejoués après matérialisation de l'overlay, avec le chemin Markdown exact `deltas/0.3.2` :
```text
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
Markdown table audit: clean (186 table(s), 142 file(s))
```
Cette preuve corrige explicitement le défaut de scope de la commande Markdown observé dans le journal opérateur `pre.010`.
## 15. Gate opérateur après application
```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.2
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-lib --no-default-features
cargo test -p ksp-store-postgres-lib
cargo test -p ksp-config-lib
cargo check -p ksp-store-lib --no-default-features
```
Le smoke PostgreSQL réel, les graphes Cargo complets, `cargo test --workspace` et les trois builds Tauri ne sont pas rejoués par nécessité dans cette tranche documentaire : ils sont déjà le gate technique vert de `pre.010` et `pre.011` ne modifie aucun code, dépendance, config runtime, resource Tauri ou migration.
## 16. Suite
Si le gate documentaire `pre.011` est vert, la seule prerelease restante est `pre.012`, strictement limitée à la préparation de publication :
```text
Cargo.toml
CHANGELOG.md
ROADMAP.md
prompts/022-V0_3_3_START_PROMPT.md
deltas/0.3.2/pre.012.md
```
Aucun README, USAGE, plan, validation, architecture, code, test, schema ou config ne devra être rouvert dans `pre.012`.

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md --> <!-- file: docs/plans/000-README.md -->
<!-- version: 68 --> <!-- version: 69 -->
# Plans KSP # Plans KSP
@@ -31,6 +31,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
- [`020-V0_2_13_INTERFACE_PLAN.md`](020-V0_2_13_INTERFACE_PLAN.md) — plan historique clôturé de la release stable `0.2.13 — Interface / wire foundation`; il fixe la surface finale `ProgramAccountMeta` + `ProgramInstruction`, les bornes `255` / `10_240`, le firewall Interface -> Core, les canaris de complétude/consumer externe et la frontière avec Program API/RAW/CORE. - [`020-V0_2_13_INTERFACE_PLAN.md`](020-V0_2_13_INTERFACE_PLAN.md) — plan historique clôturé de la release stable `0.2.13 — Interface / wire foundation`; il fixe la surface finale `ProgramAccountMeta` + `ProgramInstruction`, les bornes `255` / `10_240`, le firewall Interface -> Core, les canaris de complétude/consumer externe et la frontière avec Program API/RAW/CORE.
- [`021-V0_2_14_PROGRAM_API_PLAN.md`](021-V0_2_14_PROGRAM_API_PLAN.md) — plan historique clôturé de la release stable `0.2.14 — Program API foundation`; il fixe la façade instruction-only ouverte, les enums Recognition/Outcome, `ProgramInstructionDecoder`, l'output associé possédé par l'implémentation, le canari externe avec Program Pubkey non enregistré, le firewall Core/Interface et le report du payload canonique D3, du registry runtime et de `ProgramExecutionPreparer`. - [`021-V0_2_14_PROGRAM_API_PLAN.md`](021-V0_2_14_PROGRAM_API_PLAN.md) — plan historique clôturé de la release stable `0.2.14 — Program API foundation`; il fixe la façade instruction-only ouverte, les enums Recognition/Outcome, `ProgramInstructionDecoder`, l'output associé possédé par l'implémentation, le canari externe avec Program Pubkey non enregistré, le firewall Core/Interface et le report du payload canonique D3, du registry runtime et de `ProgramExecutionPreparer`.
- [`022-V0_3_1_STORE_RAW_PLAN.md`](022-V0_3_1_STORE_RAW_PLAN.md) — plan candidat réconcilié de `0.3.1 — Store API RAW foundation`; il fixe `ksp-store-api` seul, les modèles transaction/account + observations, queries/outcomes/capabilities, rétention/tombstone, la frontière event-only/Interface et le report de `ksp-store-lib` + PostgreSQL à `0.3.2`. - [`022-V0_3_1_STORE_RAW_PLAN.md`](022-V0_3_1_STORE_RAW_PLAN.md) — plan candidat réconcilié de `0.3.1 — Store API RAW foundation`; il fixe `ksp-store-api` seul, les modèles transaction/account + observations, queries/outcomes/capabilities, rétention/tombstone, la frontière event-only/Interface et le report de `ksp-store-lib` + PostgreSQL à `0.3.2`.
- [`023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md`](023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md) — plan candidat réconcilié de `0.3.2 — Store/PostgreSQL runtime foundation`; il fixe le split façade/backend, `std.store` multi-target réseau-spécifique, tokio-postgres/Deadpool/Rustls, migrations metadata-only, health/readiness, live PostgreSQL et les reports des vertical slices RAW vers `0.3.3`/`0.3.4`.
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre. Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md --> <!-- file: docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md -->
<!-- version: 12 --> <!-- version: 13 -->
# Plan `0.3.2` — Store/PostgreSQL runtime foundation # Plan `0.3.2` — Store/PostgreSQL runtime foundation
@@ -1117,11 +1117,26 @@ cargo tree --duplicates
### `pre.010` — Gate technique final ### `pre.010` — Gate technique final
Base requise : `0.3.2-pre.009` avec hardening/completeness entièrement vert. Le gate opérateur `pre.009` du 29 août 2026 confirme les audits Rust/Markdown, workspace check/Clippy, Store API, backend PostgreSQL, façade avec et sans feature, Config, graphes Cargo et `cargo test --workspace`. Statut : matérialisé et gate technique opérateur exécuté le 29 août 2026.
Cette tranche ne modifie aucun code de production, test fonctionnel, migration, Config ou dépendance runtime. Elle synchronise uniquement la version de prerelease et prépare le gate technique final. Le gate part de `0.3.2-pre.009` avec hardening/completeness entièrement vert. Il a été rejoué après `cargo clean` sur `0.3.2-pre.10` et confirme :
Gate final attendu : ```text
audits Rust clean
workspace check + Clippy PASS
toutes les crates ciblées PASS
ksp-store-lib default + no-default-features PASS
cargo test --workspace PASS
graphes normal/features/duplicates exécutés
3 builds Tauri Linux PASS
PostgreSQL live foundation PASS sur major 17
```
La commande opérateur d'audit Markdown a ciblé par erreur `deltas/0.3.1` au lieu de `deltas/0.3.2`. L'overlay `pre.010` avait été audité avec le bon chemin dans l'environnement de génération ; `pre.011` rejoue obligatoirement l'audit Markdown complet avec `deltas/0.3.2` avant de figer la documentation. Ce défaut de scope de commande ne révèle aucun échec runtime et n'ouvre pas de `pre.010-fix`.
Cette tranche ne modifie aucun code de production, test fonctionnel, migration, Config ou dépendance runtime. Elle synchronise uniquement la version de prerelease et porte le gate technique final.
Gate final exécuté :
```bash ```bash
cargo fmt --all cargo fmt --all
@@ -1162,7 +1177,24 @@ Aucun développement fonctionnel nouveau n'est autorisé dans `pre.010`. Tout d
### `pre.011` — Réconciliation documentaire finale ### `pre.011` — Réconciliation documentaire finale
README/USAGE des deux crates, plan/validation/indexes/architecture réellement impactés. Pas de CHANGELOG/ROADMAP/prompt suivant. Statut : matérialisé par `0.3.2-pre.011`; gate documentaire opérateur requis après application.
La tranche fige les références durables réellement concernées :
```text
ksp-store-lib/README.md + USAGE.md
ksp-store-postgres-lib/README.md + USAGE.md
ksp-config-lib README/USAGE complétés pour std.store
docs/000-README.md
docs/plans/000-README.md
docs/validation/000-README.md
plan 023
validation 019
```
Les architectures `003/004/005/008` ont été relues sur la base `pre.010` et restent cohérentes avec la surface réellement livrée ; elles ne sont pas modifiées artificiellement. Le choix historique de `0.3.1-pre.009` de ne pas créer un README/USAGE `ksp-store-api` n'est pas rouvert dans cette release backend/runtime.
`CHANGELOG.md`, `ROADMAP.md` et le prompt `0.3.3` restent strictement réservés à `pre.012`.
### `pre.012` — Préparation de publication minimale ### `pre.012` — Préparation de publication minimale
@@ -1221,9 +1253,9 @@ Store Desk
## 21. Questions restantes ## 21. Questions restantes
Aucune question architecturale ne bloque `pre.002`. Aucune question architecturale ou technique ne bloque la préparation de publication de `0.3.2`.
Les décisions foundation encore ouvertes après `pre.008` sont uniquement des preuves de hardening/completeness et de clôture ; le DDL metadata, le health/readiness et la stratégie du test PostgreSQL réel sont désormais matérialisés. La fondation runtime/backend est fermée fonctionnellement. Les seules surfaces volontairement reportées sont les vertical slices métier déjà réservées à `0.3.3+` : persistence/query/rétention `RawTransaction`, puis `RawAccountState` et conformance RAW.
Toute découverte qui exigerait : Toute découverte qui exigerait :

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/000-README.md --> <!-- file: docs/validation/000-README.md -->
<!-- version: 32 --> <!-- version: 33 -->
# Validations KSP # Validations KSP
@@ -27,3 +27,4 @@ Documents :
- [`016-V0_2_13_INTERFACE.md`](016-V0_2_13_INTERFACE.md) — matrice historique clôturée de la release stable `0.2.13` : ownership Interface/Core/Transport/Program, surface passive, bornes/adversarial, façade publique exacte, consumer externe, release completeness et dependency firewall. - [`016-V0_2_13_INTERFACE.md`](016-V0_2_13_INTERFACE.md) — matrice historique clôturée de la release stable `0.2.13` : ownership Interface/Core/Transport/Program, surface passive, bornes/adversarial, façade publique exacte, consumer externe, release completeness et dependency firewall.
- [`017-V0_2_14_PROGRAM_API.md`](017-V0_2_14_PROGRAM_API.md) — matrice historique clôturée de la release stable `0.2.14 — Program API foundation` : façade instruction-only ouverte, Recognition/Outcome, trait externe, Program Pubkey non enregistré, hardening adversarial, release completeness et firewall Core/Interface. - [`017-V0_2_14_PROGRAM_API.md`](017-V0_2_14_PROGRAM_API.md) — matrice historique clôturée de la release stable `0.2.14 — Program API foundation` : façade instruction-only ouverte, Recognition/Outcome, trait externe, Program Pubkey non enregistré, hardening adversarial, release completeness et firewall Core/Interface.
- [`018-V0_3_1_STORE_RAW.md`](018-V0_3_1_STORE_RAW.md) — matrice candidate finale de `0.3.1 — Store API RAW foundation` : modèles transaction/account, observations, capabilities backend, pagination sans policy executor, outcomes, rétention/tombstone, hardening, gate complet `pre.008` et reports explicites vers `0.3.2+`. - [`018-V0_3_1_STORE_RAW.md`](018-V0_3_1_STORE_RAW.md) — matrice candidate finale de `0.3.1 — Store API RAW foundation` : modèles transaction/account, observations, capabilities backend, pagination sans policy executor, outcomes, rétention/tombstone, hardening, gate complet `pre.008` et reports explicites vers `0.3.2+`.
- [`019-V0_3_2_STORE_POSTGRES_FOUNDATION.md`](019-V0_3_2_STORE_POSTGRES_FOUNDATION.md) — matrice candidate finale de `0.3.2 — Store/PostgreSQL runtime foundation` : feature graph, settings/Config, pool/TLS, migrations metadata-only, health, hardening, graphes, builds Tauri et preuve PostgreSQL réelle major 17.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md --> <!-- file: docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md -->
<!-- version: 12 --> <!-- version: 13 -->
# Validation `0.3.2` — Store/PostgreSQL runtime foundation # Validation `0.3.2` — Store/PostgreSQL runtime foundation
@@ -160,7 +160,7 @@ exports/capabilities existants conservés
aucun type backend ajouté pour PostgreSQL aucun type backend ajouté pour PostgreSQL
``` ```
Statut : `PASS pre.009 opérateur / TODO revalidation pre.010` — le canari backend externe de `ksp-store-api` est rejoué sans modification de la crate. Statut : `PASS pre.009 opérateur / PASS pre.010 opérateur` — le canari backend externe de `ksp-store-api` est rejoué sans modification de la crate.
## 4. Public API et settings ## 4. Public API et settings
@@ -266,7 +266,7 @@ future RAW mismatch Store.network != entity/query.network rejeté avant I/O
Matérialisé contractuellement par `pre.004-fix.001`; l'enforcement sur opérations RAW sera exercé dans `0.3.3`/`0.3.4`. Matérialisé contractuellement par `pre.004-fix.001`; l'enforcement sur opérations RAW sera exercé dans `0.3.3`/`0.3.4`.
Statut : `PASS pre.004-fix.001 opérateur` pour la sélection target/réseau / `TODO 0.3.3-0.3.4` pour le mismatch RAW. Statut : `PASS pre.004-fix.001 opérateur` pour la sélection target/réseau / `N/A 0.3.2` pour le mismatch d'opérations RAW, dont l'enforcement appartient aux vertical slices `0.3.3`-`0.3.4`.
### V32-CONFIG-003 — No-env Store/backend ### V32-CONFIG-003 — No-env Store/backend
@@ -458,7 +458,7 @@ Critères :
0 repository RAW métier 0 repository RAW métier
``` ```
Statut : `PASS pre.009 opérateur / TODO revalidation pre.010`. Statut : `PASS pre.009 opérateur / PASS pre.010 opérateur`.
## 9. Health/readiness ## 9. Health/readiness
@@ -536,7 +536,7 @@ cleanup metadata
La preuve rollback évite tout hook public de test : une transaction `tokio-postgres` de test exécute le V000 exact par `include_str!`, insère un sentinel transitoire, provoque ensuite une erreur SQL puis est droppée. Le test vérifie que la metadata n'existe pas après le rollback implicite et que le bootstrap KSP normal peut repartir proprement. La preuve rollback évite tout hook public de test : une transaction `tokio-postgres` de test exécute le V000 exact par `include_str!`, insère un sentinel transitoire, provoque ensuite une erreur SQL puis est droppée. Le test vérifie que la metadata n'existe pas après le rollback implicite et que le bootstrap KSP normal peut repartir proprement.
Statut : `PASS live pre.008 PostgreSQL 17 / TODO revalidation pre.010`. Statut : `PASS live pre.008 PostgreSQL 17 / PASS live pre.010 PostgreSQL 17`.
### V32-LIVE-004 — PostgreSQL support ### V32-LIVE-004 — PostgreSQL support
@@ -544,7 +544,7 @@ Critère : test refuse major < 15 et enregistre seulement le major safe réellem
Cible release : PostgreSQL 18.6. `pre.008` interroge uniquement `SHOW server_version_num`, dérive le major et n'imprime aucune identité de serveur. Le gate opérateur réel a été exécuté avec succès sur PostgreSQL 17. Cible release : PostgreSQL 18.6. `pre.008` interroge uniquement `SHOW server_version_num`, dérive le major et n'imprime aucune identité de serveur. Le gate opérateur réel a été exécuté avec succès sur PostgreSQL 17.
Statut : `PASS live pre.008 PostgreSQL 17 / TODO revalidation pre.010`. Statut : `PASS live pre.008 PostgreSQL 17 / PASS live pre.010 PostgreSQL 17`.
## 11. Security/adversarial ## 11. Security/adversarial
@@ -636,7 +636,9 @@ PostgreSQL live foundation
3 builds Tauri avec resources std.store packagées 3 builds Tauri avec resources std.store packagées
``` ```
Statut global `pre.010` : `MATÉRIALISÉ / TODO gate opérateur`. Statut global `pre.010` : `PASS technique opérateur`.
Le gate a été rejoué après `cargo clean` sur `0.3.2-pre.10` : audits Rust, workspace check/Clippy, tests ciblés, `cargo test --workspace`, graphes Cargo, trois builds Tauri et PostgreSQL live major 17 sont verts. La ligne d'audit Markdown opérateur a utilisé `deltas/0.3.1` par erreur ; l'overlay `pre.010` avait été audité avec `deltas/0.3.2` dans l'environnement de génération et `pre.011` rejoue le scope Markdown exact avant clôture documentaire.
## 14. Gates Rust/workspace ## 14. Gates Rust/workspace
@@ -686,9 +688,27 @@ cargo test --workspace
Les trois builds Tauri sont requis au gate final parce que `pre.004` a réellement ajouté les resources `std.store` au packaging desktop. Les trois builds Tauri sont requis au gate final parce que `pre.004` a réellement ajouté les resources `std.store` au packaging desktop.
Statut global : `TODO gate opérateur pre.010`. Statut global technique : `PASS pre.010 opérateur`; audit Markdown `deltas/0.3.2` à rejouer dans le gate documentaire `pre.011`.
## 15. Critères de fermeture ## 15. Réconciliation documentaire `pre.011`
Critères :
```text
README/USAGE ksp-store-lib présents et alignés sur la façade publique
README/USAGE ksp-store-postgres-lib présents et explicitement backend-only
ksp-config-lib README/USAGE documentent cfg.std.store et les targets réseau
indexes docs/plans/validation référencent 0.3.2
plan 023 reflète le gate technique réel
matrice 019 ne conserve aucun TODO applicable à 0.3.2
CHANGELOG/ROADMAP/prompt suivant inchangés
```
Les architectures générales Store ont été relues et restent cohérentes ; aucune modification artificielle n'est nécessaire.
Statut : `MATÉRIALISÉ pre.011 / TODO gate documentaire opérateur`.
## 16. Critères de fermeture
La matrice ne peut passer en finale que si tous les critères applicables sont `PASS` et que : La matrice ne peut passer en finale que si tous les critères applicables sont `PASS` et que :
@@ -703,4 +723,4 @@ PostgreSQL live vert
workspace/clippy/tests verts workspace/clippy/tests verts
``` ```
La réconciliation finale de cette matrice appartient à la prerelease documentaire précédant la lane de publication. La réconciliation finale de cette matrice est matérialisée par `pre.011`. Après son gate documentaire vert, la seule étape restante est la préparation de publication minimale `pre.012`.