v0.3.2-pre.004-fix.001

This commit is contained in:
2026-08-29 19:04:47 +02:00
parent 6d2b1401aa
commit 0a4cddafc4
17 changed files with 509 additions and 99 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md -->
<!-- version: 5 -->
<!-- version: 6 -->
# Plan `0.3.2` — Store/PostgreSQL runtime foundation
@@ -349,6 +349,7 @@ Lorsque la feature est active, `ksp-store-lib` convertit en privé ces settings
Les groupes de settings sont :
```text
network RawNetworkId explicite, un seul réseau logique par instance Store
connection_uri String possédée, Debug redacted, aucun getter de diagnostic
pool bornes de section 6
tls Disabled ou VerifyFull
@@ -381,7 +382,7 @@ StoreSettings
Store
```
`PostgresPoolSettings::default()` et `PostgresBootstrapSettings::default()` portent exactement les bornes décidées par le gate `pre.001`. `StoreSettings::with_default_shutdown(...)` fournit uniquement la borne commune de shutdown à 5 s. Il n'existe toujours aucun `Default` pour `PostgresStoreSettings` ou `StoreSettings`, afin de ne jamais inventer une URI ou un backend de production.
`PostgresPoolSettings::default()` et `PostgresBootstrapSettings::default()` portent exactement les bornes décidées par le gate `pre.001`. À partir de `pre.004-fix.001`, `StoreSettings` exige aussi un `RawNetworkId` explicite et `StoreSettings::with_default_shutdown(network, ...)` fournit uniquement la borne commune de shutdown à 5 s. Il n'existe toujours aucun `Default` pour `PostgresStoreSettings` ou `StoreSettings`, afin de ne jamais inventer une URI ou un backend de production.
Les validations `pre.003` restent backend-neutral et sans parsing PostgreSQL : URI non vide, pool 1..64, timeouts pool/connect 100..60 000 ms, migration 1 000..300 000 ms, lock 100..120 000 ms et shutdown 100..30 000 ms. Le parsing/normalisation de l'URI et les options réellement honorées restent propriétaires de `pre.005`.
@@ -611,28 +612,41 @@ Le document V1 est profilé comme les autres documents standards :
```json
{
"format_version": 1,
"default_profile": "postgres_default",
"default_profile": "devnet",
"profiles": [
{
"profile_id": "postgres_default",
"profile_id": "devnet",
"network": "devnet",
"backend": "postgres",
"postgres": {
"connection_uri": "${KSP_SECRET_STORE_POSTGRES_URI:-postgresql://localhost/ksp}",
"pool": {
"max_connections": 8,
"connect_timeout_ms": 10000,
"wait_timeout_ms": 5000,
"create_timeout_ms": 10000,
"recycle_timeout_ms": 5000
},
"tls": {
"mode": "verify_full"
},
"bootstrap": {
"auto_migrate": true,
"migration_timeout_ms": 30000,
"migration_lock_timeout_ms": 10000
},
"connection_uri": "${KSP_SECRET_STORE_DEVNET_POSTGRES_URI:-postgresql://localhost/ksp_devnet}",
"pool": { "max_connections": 8, "connect_timeout_ms": 10000, "wait_timeout_ms": 5000, "create_timeout_ms": 10000, "recycle_timeout_ms": 5000 },
"tls": { "mode": "verify_full" },
"bootstrap": { "auto_migrate": true, "migration_timeout_ms": 30000, "migration_lock_timeout_ms": 10000 },
"shutdown_timeout_ms": 5000
}
},
{
"profile_id": "mainnet",
"network": "mainnet-beta",
"backend": "postgres",
"postgres": {
"connection_uri": "${KSP_SECRET_STORE_MAINNET_POSTGRES_URI:-postgresql://localhost/ksp_mainnet}",
"pool": { "max_connections": 8, "connect_timeout_ms": 10000, "wait_timeout_ms": 5000, "create_timeout_ms": 10000, "recycle_timeout_ms": 5000 },
"tls": { "mode": "verify_full" },
"bootstrap": { "auto_migrate": true, "migration_timeout_ms": 30000, "migration_lock_timeout_ms": 10000 },
"shutdown_timeout_ms": 5000
}
},
{
"profile_id": "testnet",
"network": "testnet",
"backend": "postgres",
"postgres": {
"connection_uri": "${KSP_SECRET_STORE_TESTNET_POSTGRES_URI:-postgresql://localhost/ksp_testnet}",
"pool": { "max_connections": 8, "connect_timeout_ms": 10000, "wait_timeout_ms": 5000, "create_timeout_ms": 10000, "recycle_timeout_ms": 5000 },
"tls": { "mode": "verify_full" },
"bootstrap": { "auto_migrate": true, "migration_timeout_ms": 30000, "migration_lock_timeout_ms": 10000 },
"shutdown_timeout_ms": 5000
}
}
@@ -640,13 +654,17 @@ Le document V1 est profilé comme les autres documents standards :
}
```
Le fallback localhost est classé `Secret` car il appartient à un placeholder `KSP_SECRET_*`; sa safe projection reste redacted. Il ne provoque aucune connexion automatique.
Chaque profile `std.store` est un **target Store nommé** : son `profile_id` est l'identifiant de target, son champ `network` fixe exactement un réseau logique et son backend désigne exactement une base/configuration physique. `default_profile` choisit le target autonome ; un job, worker ou app peut imposer un autre `profile_id` via le mécanisme Config existant. `ksp-store-lib` ne route jamais entre plusieurs targets.
Le target par défaut committed est `devnet`, cohérent avec le défaut Transport et plus sûr pour les workflows de développement. Les targets `mainnet` et `testnet` utilisent des URI distinctes. Le fallback localhost de chaque target est classé `Secret` car il appartient à un placeholder `KSP_SECRET_*`; sa safe projection reste redacted. Il ne provoque aucune connexion automatique.
`.env.example` ajoutera dans la même tranche :
```text
# PostgreSQL connection URI used by Config std.store profiles.
# KSP_SECRET_STORE_POSTGRES_URI=postgresql://user:password@localhost/ksp
# PostgreSQL connection URIs used by named Config std.store targets.
# KSP_SECRET_STORE_DEVNET_POSTGRES_URI=postgresql://user:password@localhost/ksp_devnet
# KSP_SECRET_STORE_MAINNET_POSTGRES_URI=postgresql://user:password@localhost/ksp_mainnet
# KSP_SECRET_STORE_TESTNET_POSTGRES_URI=postgresql://user:password@localhost/ksp_testnet
```
La valeur d'exemple commentée n'est jamais un vrai credential.
@@ -657,6 +675,10 @@ Config reconnaît `backend = "postgres"` indépendamment de la feature du consum
Ainsi Config ne doit pas connaître les `cfg(feature = "postgres")` de chaque consumer.
### 12.4 Invariant target/réseau
Une instance `Store` ouverte reçoit exactement un `StoreSettings.network`. Ce réseau provient du target Config sélectionné, mais reste un contrat Store backend-neutral. Les futures opérations RAW doivent comparer ce réseau à celui de l'identité/query avant I/O : une transaction/account/query `devnet` soumise à un Store `mainnet-beta` doit être rejetée, jamais routée vers un autre Store. La sélection d'un autre réseau se fait en résolvant un autre profile/target puis en ouvrant une autre instance `Store`.
## 13. Logging et redaction
Les deux crates runtime auront un `constants.rs` privé avec un target explicite :
@@ -937,7 +959,7 @@ Le dernier comportement est volontairement transitoire : `pre.003` ne retourne j
### `pre.004` — Config `std.store`
Document/schema/example/registry/adaptor, `.env.example`, provenance/sensitivity/redaction, packaging resources strictement nécessaires. Aucun env dans Store/backend. `pre.004` matérialise les noms canoniques `std.store.json`, `std.store.schema.json` et `std.store.example.json`, conformément au prompt de démarrage et aux conventions Config existantes.
Document/schema/example/registry/adaptor, `.env.example`, provenance/sensitivity/redaction, targets nommés réseau-spécifiques, packaging resources strictement nécessaires. Aucun env dans Store/backend. `pre.004` matérialise les noms canoniques `std.store.json`, `std.store.schema.json` et `std.store.example.json`, conformément au prompt de démarrage et aux conventions Config existantes.
### `pre.005` — PostgreSQL connection + deadpool + Rustls