v0.3.1-pre.001-fix-001

This commit is contained in:
2026-08-29 06:39:25 +02:00
parent 29a888d1dc
commit 1a07574bae
4 changed files with 468 additions and 169 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/022-V0_3_1_STORE_RAW_PLAN.md -->
<!-- version: 1 -->
<!-- version: 2 -->
# Plan `0.3.1` — Store API RAW foundation
@@ -36,12 +36,12 @@ La trajectoire devient :
```text
0.3.1 = ksp-store-api uniquement
0.3.2 = ksp-store-lib, backend PostgreSQL officiel via tokio-postgres
0.3.2 = ksp-store-lib + ksp-store-postgres-lib
feature postgres par défaut
PostgreSQL de référence via tokio-postgres
```
Cette décision remplace pour `0.3.1` la mission combinée `ksp-store-api + ksp-store-lib` décrite dans le prompt de démarrage et encore visible dans le `ROADMAP.md` stable `v0.2.14`.
Le `ROADMAP.md` n'est pas modifié dans `pre.001` conformément aux lanes documentaires KSP. Il devra être réconcilié dans la lane de préparation de publication de `0.3.1`, avec le prompt de démarrage `0.3.2`.
Cette décision remplace pour `0.3.1` la mission combinée `ksp-store-api + ksp-store-lib` décrite dans le prompt de démarrage. `pre.001-fix.001` réconcilie immédiatement le `ROADMAP.md` afin que la trajectoire globale ne conserve pas une séquence désormais fausse.
Conséquences immédiates :
@@ -77,11 +77,12 @@ provenance d'acquisition
outcomes d'écriture/idempotence
queries et pagination bornées
health/readiness communs utiles
contrats backend extensibles
façade Store commune consommée par workers/jobs/apps
contrats/capabilities backend extensibles
format canonique de notification de disponibilité si la référence RAW est stabilisée
```
La façade runtime concrète `Store`, la sélection d'un backend compilé et l'orchestration commune appartiendront à `ksp-store-lib` en `0.3.2`. Les consumers ordinaires jobs/workers/apps dépendront alors uniquement de `ksp-store-lib`, qui réexportera la surface commune nécessaire de `ksp-store-api`.
Elle ne possède pas :
```text
@@ -108,56 +109,119 @@ Le modèle public `ksp-store-api` est volontairement réutilisable par toute imp
Le graphe cible devient :
```text
ksp-store-api
|
modèles + opérations
|
+-----------+-----------+
| |
ksp-store-lib ksp-store-mysql-lib
PostgreSQL officiel exemple futur
tokio-postgres impl indépendante
ksp-store-api
modèles + contrats communs
|
+------------------+------------------+
| |
v v
ksp-store-lib ksp-store-postgres-lib
façade/runtime commun impl PostgreSQL
backend dispatch tokio-postgres
| ^
| feature postgres (default) ----------+
|
+-- feature mysql ------> futur ksp-store-mysql-lib
+-- autres features ----> futurs backends
```
`ksp-store-mysql-lib` est uniquement un exemple de future implémentation. `0.3.1` et `0.3.2` n'implémentent aucun autre backend que PostgreSQL.
Une future implémentation alternative doit dépendre de `ksp-store-api`, pas de `ksp-store-lib`.
### 4.2 Sélection par Config et composition
`ksp-store-api` ne lit pas Config. `ksp-store-lib` ne lit pas Config non plus.
La composition future suit :
Règles de dépendances :
```text
ksp-config-lib
-> settings backend typés
composition/application
-> choisit l'implémentation disponible
-> construit ksp_store_api::Store
consumer
-> appelle toujours la même façade Store
ksp-store-lib -> ksp-store-api
ksp-store-lib[postgres] -> ksp-store-postgres-lib
ksp-store-postgres-lib -> ksp-store-api
futur ksp-store-mysql-lib -> ksp-store-api
ksp-store-postgres-lib -X-> ksp-store-lib
backend alternatif -X-> ksp-store-lib
```
Lorsque plusieurs implémentations seront effectivement liées à un même host, changer de backend doit pouvoir se limiter au choix Config/composition. Un consumer logique ne branche pas sur `postgres`, `mysql`, `rocksdb` ou un autre moteur.
`ksp-store-lib` est donc le point de consommation normal du workspace, tandis que `ksp-store-api` reste le contrat d'implémentation partagé entre la façade et les backends.
La Config ne peut évidemment sélectionner qu'une implémentation réellement liée au binaire concerné ; `0.3.2` n'en fournira qu'une, PostgreSQL.
### 4.2 Features de `ksp-store-lib`
### 4.3 Modèle public et modèle interne
`0.3.2` introduira au minimum :
Deux modèles restent strictement distincts :
```text
default = [postgres]
postgres -> dépendance optionnelle ksp-store-postgres-lib
```
Les futures features peuvent ajouter `mysql`, `sqlite`, `rocksdb`, `clickhouse` ou tout autre backend réellement implémenté. Plusieurs features backend peuvent être compilées simultanément ; la feature décide **quels backends sont disponibles dans le binaire**, jamais lequel est sélectionné au runtime.
La Config décide le backend actif parmi ceux compilés. Un backend KSP connu mais absent des features du binaire doit produire une erreur distincte et stable de type `STORE_BACKEND_NOT_COMPILED`, sans fallback silencieux vers PostgreSQL ou un autre backend.
### 4.3 Config, URI et secrets
`ksp-store-api`, `ksp-store-lib` et les crates backend ne lisent jamais directement `.env` ni les variables KSP/KSPB. `ksp-config-lib` reste propriétaire des documents, placeholders, `.env`, provenance et sensibilité.
La configuration future suit :
```text
std.store / profil composite
|
v
ksp-config-lib
résolution ${KSP_SECRET_*}
+ validation schema/sémantique
|
v
settings runtime ksp-store-lib
|
v
backend compilé sélectionné
|
v
crate backend privée
```
Règles fixées pour `0.3.2` et les futurs backends :
- utiliser une URI/DSN lorsque le moteur possède une forme URI naturelle (`postgresql://...`, futur `mysql://...`, etc.) ;
- permettre des options typées backend-specific uniquement lorsqu'elles sont réellement nécessaires et sans `serde_json::Value` opaque comme contrat runtime ;
- considérer l'URI entière comme `Secret` dès qu'elle peut embarquer user/password/token ou autre credential ;
- obtenir les secrets via des placeholders `KSP_SECRET_*` résolus par Config, avec inventaire dans `.env.example` au même delta que leur première utilisation ;
- ne jamais versionner un vrai `.env` ni un URI/credential réel ;
- ne jamais exposer URI, password, token, query secret ou chemin sensible dans `Debug`, logs, erreurs ou health ;
- distinguer `backend inconnu` de `backend KSP connu mais non compilé` avant tentative de connexion ;
- éviter tout fallback implicite vers `PG*`, `.pgpass` ou autre source d'environnement lue directement par le driver/backend lorsque Config a déjà fourni les settings effectifs.
La forme exacte de `StoreSettings` et du document `std.store` appartient au design de `0.3.2`; `0.3.1` fixe seulement ces responsabilités et invariants.
### 4.4 Surface consumer
Les jobs/workers/apps ne dépendent pas directement de `ksp-store-postgres-lib` ni des futurs backends. Le chemin normal est :
```text
ksp-job-* / ksp-worker-* / app
-> ksp-store-lib
-> réexporte les types API communs nécessaires
-> expose Store/open/read/write/query communs
-> dispatch vers le backend choisi par Config
```
Le consumer ne contient aucun `#[cfg(feature = "postgres")]` métier et ne branche pas sur `postgres`, `mysql` ou un nom de moteur pour lire/écrire les données.
### 4.5 Modèle public et modèle interne
Trois surfaces restent strictement distinctes :
```text
ksp-store-api
RawTransaction / RawLog / provenance / queries / outcomes
= public et commun
= modèle objet et contrats communs à toutes les implémentations
backend
PostgresRawTransactionRow / SQL columns / statements / indexes
= privés à l'implémentation
ksp-store-lib
Store / lifecycle / dispatch / settings runtime publics communs
= façade de consommation normale
ksp-store-postgres-lib
Postgres*Row / SQL / schema / migrations / pool / statements
= implémentation privée au backend
```
Aucun type de row backend, handle de pool, statement préparé ou nom d'objet SQL ne traverse la façade publique.
Aucun type de row backend, handle de pool, statement préparé, migration ou nom d'objet SQL ne traverse `ksp-store-lib` vers ses consumers.
## 5. Sources KSP relues
@@ -486,21 +550,15 @@ Aucune promesse exactly-once distribuée n'est faite.
## 11. API candidate
### 11.1 Façade commune
### 11.1 Contrats communs
Le consumer normal doit recevoir une façade commune :
`ksp-store-api` définit le modèle et les opérations backend-agnostic qu'une implémentation doit satisfaire. `0.3.1` ne construit pas de backend, ne sélectionne aucun moteur et n'introduit pas encore la façade runtime concrète `Store`.
```text
Store
```
et appeler des opérations backend-agnostic.
Le backend concret implémente un contrat public d'extension, mais son modèle interne reste privé.
Le backend concret implémente un contrat public d'extension, mais son modèle interne reste privé. En `0.3.2`, `ksp-store-lib::Store` enveloppera ce contrat et deviendra la seule façade de consommation normale des jobs/workers/apps.
### 11.2 Object-safety et async
La sélection de backend par Config/composition est un besoin runtime réel. L'API doit donc permettre de construire une même façade `Store` à partir d'une implémentation externe différente.
La future sélection runtime impose que le contrat backend puisse être stocké derrière une abstraction dynamique sans connaître le moteur concret.
La stratégie candidate est :
@@ -508,7 +566,7 @@ La stratégie candidate est :
StoreBackend: Send + Sync
méthodes object-safe
futures boxed KSP-owned via un alias StoreFuture<'a, T>
Store possède Arc<dyn StoreBackend>
future ksp-store-lib::Store possède Arc<dyn StoreBackend>
```
Cette stratégie évite une dépendance `async-trait` uniquement pour masquer la transformation. Le coût d'une box de future est accepté au niveau Store, dominé par l'I/O de persistence, et doit rester mesurable si un chemin futur démontre le contraire.
@@ -523,7 +581,7 @@ RawTransactionStore
RawLogStore
```
Un contrat composite `StoreBackend` peut agréger les capabilities exigées par la façade `Store` de cette release.
Un contrat composite `StoreBackend` peut agréger les capabilities N1 nécessaires à la future façade `ksp-store-lib::Store`.
Les futures couches D2/D3/D4 ne sont pas ajoutées par anticipation.
@@ -638,7 +696,7 @@ DSN
SQLSTATE arbitraire présenté comme contrat portable
```
Les diagnostics spécifiques à PostgreSQL appartiennent à `ksp-store-lib` et sont projetés vers le contrat commun seulement lorsque cela a un sens portable.
Les diagnostics spécifiques à PostgreSQL appartiennent à `ksp-store-postgres-lib`. `ksp-store-lib` ne projette vers le contrat commun que les états réellement portables et sanitised.
## 14. Dependency graph `0.3.1`
@@ -690,31 +748,31 @@ Le Store historique couvre 16 tables N1-N3, 240 ressources SQL atomiques et 79 i
### 15.2 Matrice d'héritage
| Concept historique | Observation kbot3 | Décision | Application KSP |
|-----------------------------------------|-------------------------------------------------------------------|------------|---------------------------------------------------------------------------------|
| séparation façade Store / PostgreSQL | PostgreSQL et `sqlx::PgPool` privés | REPRENDRE | API commune séparée; backend PostgreSQL reporté à `0.3.2` |
| `StoreOpenOptions` / backend selection | backend + `serde_json::Value` opaque dans Store | REDESSINER | Config/composition sélectionne une implémentation typée puis construit `Store` |
| health/readiness | contrat backend-neutral présent | REPRENDRE | health minimal portable dans `ksp-store-api` |
| `contracts/dto/raw.rs` | transaction canonique + observations transaction/account | REDESSINER | transaction + logs + provenance commune, sans JSON universel ni lifecycle D2/D3 |
| `contracts/entity/raw.rs` | rows exposant `i64`, JSON et timestamps backend-shaped | REDESSINER | entités logiques sans PK SQL ni type physique |
| `RawTransactionStore` | `has_*` puis inserts séparés | REDESSINER | write idempotent atomique sans check-then-insert |
| repository traits | capabilities async séparées | REPRENDRE | capabilities N1 séparées + façade commune |
| pagination | 100 par défaut, 500 max, cursor opaque | REPRENDRE | mêmes bornes candidates, cursor toujours opaque |
| replay contracts | filtres mêlés au processing N2/N3 | REPORTER | `0.3.1` fournit seulement lectures RAW nécessaires au futur replay |
| error contracts | erreurs Store historiques | REDESSINER | `ksp_core_lib::Error/Result` + codes Store stables |
| schema validation / migration bootstrap | validation stricte des objets PostgreSQL | REPORTER | responsabilité `ksp-store-lib` en `0.3.2` |
| migrations atomiques | ressources SQL actives nombreuses | REPORTER | aucune migration dans Store API |
| constraints/indexes | 79 index attendus | REPORTER | design physique seulement après stabilisation API |
| idempotence / uniqueness | observation keys + canonical identity | REPRENDRE | sémantique publique déterministe; mécanisme backend privé |
| raw transaction table | table physique `k_sol_raw_transactions` | REPORTER | `RawTransaction` commun maintenant; table seulement en `0.3.2` |
| acquisition observations | transaction + account observations | REPRENDRE | concept N1 central; transaction + log initialement |
| processing ledger | couvre N2/N3 processing | REPORTER | appartient aux futures couches de processing, pas N1 foundation |
| CORE tables | transaction, keys, instructions, CPI, logs, balances, return data | REPORTER | future couche D2, aucune surface en `0.3.1` |
| DECODE coverage/events | contrats decoder/materializer | REPORTER | future D3 |
| materialization journal | `k_sol_mat_outputs` | REPORTER | future D3 |
| maintenance truncate/drop | scripts destructifs dédiés | REJETER | aucune API runtime générique destructive Store |
| Config Store | backend + options JSON historiques | REDESSINER | Config reste owner; settings PostgreSQL typés en `0.3.2` |
| runtime diagnostics | résumés sanitised mais backend riches | REDESSINER | health portable dans API; détails backend privés |
| Concept historique | Observation kbot3 | Décision | Application KSP |
|-----------------------------------------|-------------------------------------------------------------------|------------|----------------------------------------------------------------------------------------------------------|
| séparation façade Store / PostgreSQL | PostgreSQL et `sqlx::PgPool` privés | REPRENDRE | API commune séparée; façade + backend PostgreSQL reportés à `0.3.2` |
| `StoreOpenOptions` / backend selection | backend + `serde_json::Value` opaque dans Store | REDESSINER | Config produit les settings communs; `ksp-store-lib` sélectionne un backend compi et construit `Store` |
| health/readiness | contrat backend-neutral présent | REPRENDRE | health minimal portable dans `ksp-store-api` |
| `contracts/dto/raw.rs` | transaction canonique + observations transaction/account | REDESSINER | transaction + logs + provenance commune, sans JSON universel ni lifecycle D2/D3 |
| `contracts/entity/raw.rs` | rows exposant `i64`, JSON et timestamps backend-shaped | REDESSINER | entités logiques sans PK SQL ni type physique |
| `RawTransactionStore` | `has_*` puis inserts séparés | REDESSINER | write idempotent atomique sans check-then-insert |
| repository traits | capabilities async séparées | REPRENDRE | capabilities N1 séparées + façade commune |
| pagination | 100 par défaut, 500 max, cursor opaque | REPRENDRE | mêmes bornes candidates, cursor toujours opaque |
| replay contracts | filtres mêlés au processing N2/N3 | REPORTER | `0.3.1` fournit seulement lectures RAW nécessaires au futur replay |
| error contracts | erreurs Store historiques | REDESSINER | `ksp_core_lib::Error/Result` + codes Store stables |
| schema validation / migration bootstrap | validation stricte des objets PostgreSQL | REPORTER | responsabilité `ksp-store-postgres-lib` en `0.3.2` |
| migrations atomiques | ressources SQL actives nombreuses | REPORTER | aucune migration dans Store API |
| constraints/indexes | 79 index attendus | REPORTER | design physique seulement après stabilisation API |
| idempotence / uniqueness | observation keys + canonical identity | REPRENDRE | sémantique publique déterministe; mécanisme backend privé |
| raw transaction table | table physique `k_sol_raw_transactions` | REPORTER | `RawTransaction` commun maintenant; table privée à `ksp-store-postgres-lib` en `0.3.2` |
| acquisition observations | transaction + account observations | REPRENDRE | concept N1 central; transaction + log initialement |
| processing ledger | couvre N2/N3 processing | REPORTER | appartient aux futures couches de processing, pas N1 foundation |
| CORE tables | transaction, keys, instructions, CPI, logs, balances, return data | REPORTER | future couche D2, aucune surface en `0.3.1` |
| DECODE coverage/events | contrats decoder/materializer | REPORTER | future D3 |
| materialization journal | `k_sol_mat_outputs` | REPORTER | future D3 |
| maintenance truncate/drop | scripts destructifs dédiés | REJETER | aucune API runtime générique destructive Store |
| Config Store | backend + options JSON historiques | REDESSINER | Config reste owner; settings Store/URI secrets adaptés vers `ksp-store-lib` en `0.3.2` |
| runtime diagnostics | résumés sanitised mais backend riches | REDESSINER | health portable dans API; détails backend privés |
## 16. Audit PostgreSQL et driver de référence futur
@@ -724,7 +782,12 @@ Le choix opérateur est fixé pour la version suivante :
```text
ksp-store-lib
backend officiel = PostgreSQL
façade/runtime commun
feature postgres = feature par défaut
feature postgres -> ksp-store-postgres-lib
ksp-store-postgres-lib
backend officiel de référence = PostgreSQL
driver interne = tokio-postgres
```
@@ -749,7 +812,7 @@ pipelining : supporté
TLS : connector externe, à choisir explicitement en 0.3.2
```
`tokio-postgres::Config` peut être construit et renseigné programmaticalement. `0.3.2` devra éviter les chemins de configuration implicites et remplir explicitement user/host/port/database/TLS/options depuis les settings fournis par Config/composition.
`tokio-postgres::Config` peut être construit et renseigné programmaticalement. `0.3.2` devra éviter les chemins de configuration implicites : l'URI/les options effectives viennent de `ksp-config-lib` via les settings publics de `ksp-store-lib`, puis sont converties vers le backend PostgreSQL sans lecture directe de `.env`, `PG*` ou `.pgpass`.
### 16.3 SQLx
@@ -761,9 +824,28 @@ La performance ne constitue pas à elle seule la raison du choix : `0.3.2` devra
## 17. Contrat attendu de `0.3.2` sans le concevoir physiquement ici
`0.3.2` devra implémenter **le même modèle objet et les mêmes opérations** de `ksp-store-api`.
`0.3.2` introduira **deux crates dans la même release** :
Il pourra créer librement :
```text
ksp-store-lib
ksp-store-postgres-lib
```
`ksp-store-lib` devra :
```text
dépendre de ksp-store-api
réexporter la surface API commune nécessaire aux consumers
exposer la façade Store et son lifecycle
posséder la sélection/dispatch des backends compilés
activer postgres par défaut
importer ksp-store-postgres-lib seulement sous feature postgres
accepter les settings effectifs fournis par Config
rejeter distinctement un backend connu mais non compilé
ne jamais exposer les types internes d'un backend
```
`ksp-store-postgres-lib` devra implémenter **le même modèle objet et les mêmes contrats** de `ksp-store-api` et pourra créer librement :
```text
PostgresStoreBackend
@@ -775,11 +857,12 @@ indexes
pool
transaction handles privés
mapping Rust API <-> PostgreSQL
tokio-postgres
```
mais aucun de ces éléments ne devient une dépendance des consumers.
Les consumers jobs/workers/apps dépendront uniquement de `ksp-store-lib`, avec la feature par défaut ou une sélection explicite de features. Les crates backend alternatives dépendront de `ksp-store-api`, pas de `ksp-store-lib`.
La compatibilité backend devra être testée par round-trip des modèles API et par introspection/validation du schema PostgreSQL réel.
La compatibilité PostgreSQL devra être testée par round-trip des modèles API et par introspection/validation du schema réel.
## 18. Sorties PostgreSQL du prompt initial explicitement déplacées
@@ -787,15 +870,15 @@ Le prompt de démarrage demandait encore à `pre.001` un schéma PostgreSQL cand
Elles sont donc classées ainsi :
| Sortie initialement demandée | Décision `pre.001` | Release propriétaire |
|------------------------------------------------|--------------------|-----------------------|
| tables/colonnes/PK/FK/indexes RAW | REPORTER | `0.3.2 ksp-store-lib` |
| mapping `u64`/bytes/timestamps vers PostgreSQL | REPORTER | `0.3.2` |
| migration layout/version/checksum | REPORTER | `0.3.2` |
| schema introspection/conformance | REPORTER | `0.3.2` |
| pool/TLS/timeouts | REPORTER | `0.3.2` |
| PostgreSQL live gate | REPORTER | `0.3.2` |
| SQL injection/statement policy exécutable | REPORTER | `0.3.2` |
| Sortie initialement demandée | Décision `pre.001` | Release propriétaire |
|------------------------------------------------|--------------------|--------------------------------|
| tables/colonnes/PK/FK/indexes RAW | REPORTER | `0.3.2 ksp-store-postgres-lib` |
| mapping `u64`/bytes/timestamps vers PostgreSQL | REPORTER | `0.3.2` |
| migration layout/version/checksum | REPORTER | `0.3.2` |
| schema introspection/conformance | REPORTER | `0.3.2` |
| pool/TLS/timeouts | REPORTER | `0.3.2` |
| PostgreSQL live gate | REPORTER | `0.3.2` |
| SQL injection/statement policy exécutable | REPORTER | `0.3.2` |
Les invariants API qui contraignent déjà ce futur schéma restent fixés maintenant :
@@ -811,6 +894,16 @@ round-trip exact du modèle objet commun
Aucun nom de table candidat n'est donc produit par `0.3.1-pre.001`. C'est une conséquence volontaire du split, pas une omission du gate.
La trajectoire roadmap corrigée est :
```text
0.3.1 ksp-store-api RAW/observations
0.3.2 ksp-store-lib + ksp-store-postgres-lib
0.3.3 wires Interface nécessaires à l'acquisition/normalisation future
0.3.4 ksp-job-api + premier backfill
0.3.5 application backfill/inspection RAW
```
## 19. Threat model `0.3.1`
| Menace | Réponse de design |
@@ -840,7 +933,7 @@ Prévoir :
unit tests module-local
public API canaries crate-root
external backend canary
object-safe facade/backend composition canary
object-safe backend contract canary
manifest/dependency firewall
exact public export inventory
exact production module inventory
@@ -861,35 +954,36 @@ Le **backend externe canary** doit implémenter le contrat avec une petite impl
```text
aucune dépendance à ksp-store-lib
aucune connaissance PostgreSQL
construction de Store depuis l'implémentation
mêmes appels consumer
implémentation des mêmes capabilities API
round-trip via le contrat backend commun
```
Aucun PostgreSQL live test n'appartient à `0.3.1` puisque le backend PostgreSQL n'existe pas encore.
## 21. Ownership
| Concept | Owner | Visibilité | Introduction | Raison |
|-----------------------------|----------------------------|---------------------------------|---------------------|-------------------------------------------|
| `RawTransaction` | `ksp-store-api` | public | `0.3.1` | modèle persistant commun |
| `RawTransactionObservation` | `ksp-store-api` | public | `0.3.1` | provenance/acquisition distincte du RAW |
| `RawLog` | `ksp-store-api` | public | `0.3.1` | seconde famille N1 explicitement demandée |
| `RawLogObservation` | `ksp-store-api` | public | `0.3.1` | provenance logs |
| `RawPayload` | `ksp-store-api` | public | `0.3.1` | contrat persistant replayable versionné |
| RAW references | `ksp-store-api` | public | `0.3.1` | reads, notification, lineage |
| write outcomes | `ksp-store-api` | public | `0.3.1` | sémantique idempotente commune |
| query/page | `ksp-store-api` | public | `0.3.1` | backlog/replay backend-agnostic |
| health portable | `ksp-store-api` | public | `0.3.1` | consumer commun |
| backend extension trait | `ksp-store-api` | public | `0.3.1` | implémentation externe réelle |
| `Store` facade | `ksp-store-api` | public | `0.3.1` | appels communs indépendants du backend |
| PostgreSQL settings | `ksp-store-lib` | public ou adapter-boundary | `0.3.2` | construction du backend de référence |
| PostgreSQL rows | `ksp-store-lib` | privé | `0.3.2` | mapping physique |
| pool/connection | `ksp-store-lib` | privé | `0.3.2` | détail runtime |
| SQL/statements | `ksp-store-lib` | privé | `0.3.2` | détail backend |
| migrations/schema | `ksp-store-lib` | privé/opérateur | `0.3.2` | détail backend |
| transport -> RAW conversion | composition/pipeline futur | privé/réutilisable selon besoin | release acquisition | `DEP-KSP-003` |
| RAW -> D2 normalization | future pipeline générique | hors `0.3.1` | série suivante | aucune dépendance Program |
| notification mechanism | futur host/runtime | hors API de diffusion | ultérieur | Store API possède seulement le format |
| Concept | Owner | Visibilité | Introduction | Raison |
|------------------------------|----------------------------|---------------------------------|---------------------|-------------------------------------------|
| `RawTransaction` | `ksp-store-api` | public | `0.3.1` | modèle persistant commun |
| `RawTransactionObservation` | `ksp-store-api` | public | `0.3.1` | provenance/acquisition distincte du RAW |
| `RawLog` | `ksp-store-api` | public | `0.3.1` | seconde famille N1 explicitement demandée |
| `RawLogObservation` | `ksp-store-api` | public | `0.3.1` | provenance logs |
| `RawPayload` | `ksp-store-api` | public | `0.3.1` | contrat persistant replayable versionné |
| RAW references | `ksp-store-api` | public | `0.3.1` | reads, notification, lineage |
| write outcomes | `ksp-store-api` | public | `0.3.1` | sémantique idempotente commune |
| query/page | `ksp-store-api` | public | `0.3.1` | backlog/replay backend-agnostic |
| health portable | `ksp-store-api` | public | `0.3.1` | consumer commun |
| backend extension trait | `ksp-store-api` | public | `0.3.1` | implémentation externe réelle |
| `Store` facade | `ksp-store-lib` | public | `0.3.2` | point de consommation commun |
| backend dispatch/settings | `ksp-store-lib` | public/privé selon contrat | `0.3.2` | features disponibles + sélection Config |
| PostgreSQL settings internes | `ksp-store-postgres-lib` | privé ou constructor-boundary | `0.3.2` | construction du backend de référence |
| PostgreSQL rows | `ksp-store-postgres-lib` | privé | `0.3.2` | mapping physique |
| pool/connection | `ksp-store-postgres-lib` | privé | `0.3.2` | détail runtime |
| SQL/statements | `ksp-store-postgres-lib` | privé | `0.3.2` | détail backend |
| migrations/schema | `ksp-store-postgres-lib` | privé/opérateur | `0.3.2` | détail backend |
| transport -> RAW conversion | composition/pipeline futur | privé/réutilisable selon besoin | release acquisition | `DEP-KSP-003` |
| RAW -> D2 normalization | future pipeline générique | hors `0.3.1` | série suivante | aucune dépendance Program |
| notification mechanism | futur host/runtime | hors API de diffusion | ultérieur | Store API possède seulement le format |
## 22. Hors scope strict `0.3.1`
@@ -935,9 +1029,9 @@ Introduire payload/reference/provenance/idempotence/timestamps bornés puis `Raw
Introduire `RawLog`/observation, vérifier ordering/identity/bounds et verrouiller l'absence de type RAW fourre-tout.
### `pre.005` — Capabilities backend + façade `Store`
### `pre.005` — Capabilities backend extensibles
Implémenter les contracts object-safe, la façade commune et l'external backend canary, sans runtime DB.
Implémenter les contrats object-safe et l'external backend canary, sans façade runtime `Store` et sans runtime DB. La façade commune appartient à `ksp-store-lib` en `0.3.2`.
### `pre.006` — Queries, pagination, outcomes et notification reference
@@ -967,7 +1061,7 @@ prompts/021-V0_3_2_START_PROMPT.md
delta pre.010
```
Le prompt `0.3.2` ouvre `ksp-store-lib` PostgreSQL/`tokio-postgres`.
Le prompt `0.3.2` ouvre ensemble `ksp-store-lib` et `ksp-store-postgres-lib`, avec feature `postgres` par défaut et `tokio-postgres` strictement dans la crate backend.
### `rel.001` — Publication stable
@@ -981,14 +1075,14 @@ La prévision durable devient, sous réserve des gates de chaque release :
```text
0.3.1 ksp-store-api / N1 RAW contract
0.3.2 ksp-store-lib / PostgreSQL reference via tokio-postgres
0.3.2 ksp-store-lib + ksp-store-postgres-lib / PostgreSQL reference via tokio-postgres
0.3.3 generic Interface/wire additions nécessaires à acquisition/normalisation
0.3.4 ksp-job-api + premier backfill RAW concret
0.3.5 application backfill/inspection RAW
ensuite worker/service live RAW avant ouverture D2
```
Cette renumérotation remplace la prévision `0.3.1..0.3.4` de la base `v0.2.14`; elle sera écrite dans le `ROADMAP.md` au moment prévu par le workflow documentaire.
Cette renumérotation remplace la prévision `0.3.1..0.3.4` de la base `v0.2.14`; `pre.001-fix.001` l'écrit immédiatement dans le `ROADMAP.md` pour éviter de poursuivre avec une trajectoire fausse.
## 25. Critères de fermeture de `0.3.1`
@@ -1000,7 +1094,7 @@ modèle objet RAW commun stable
RawTransaction + observations stables
RawLog + observations stables
future extension N1 non bloquée
façade Store commune stable
contrats backend communs stables
backend externe implémentable sans ksp-store-lib
aucun type backend/SQL public
queries/pagination bornées
@@ -1011,5 +1105,5 @@ notification format introduit ou reporté explicitement
aucune dépendance PostgreSQL
aucune surface D2/D3/D4
workspace et graphes entièrement verts
prompt `0.3.2` cohérent avec PostgreSQL/tokio-postgres
prompt `0.3.2` cohérent avec ksp-store-lib + ksp-store-postgres-lib + tokio-postgres
```

View File

@@ -1,11 +1,11 @@
<!-- file: docs/validation/018-V0_3_1_STORE_RAW.md -->
<!-- version: 1 -->
<!-- version: 2 -->
# Validation `0.3.1` — Store API RAW foundation
## 1. Objet
Cette matrice est ouverte par `0.3.1-pre.001`. Elle valide désormais **`ksp-store-api` uniquement** ; l'implémentation PostgreSQL `ksp-store-lib` a été déplacée vers `0.3.2` par décision opérateur pendant le gate de brainstorming.
Cette matrice est ouverte par `0.3.1-pre.001` et corrigée par `pre.001-fix.001`. Elle valide **`ksp-store-api` uniquement**. La façade/runtime commune `ksp-store-lib` et l'implémentation PostgreSQL séparée `ksp-store-postgres-lib` sont réunies dans `0.3.2`.
Le scope concret N1 initial est :
@@ -13,7 +13,7 @@ Le scope concret N1 initial est :
RawTransaction + observation
RawLog + observation
provenance/références/outcomes/queries communs
façade Store + contrat backend externe
contrats/capabilities backend externes
```
Les autres familles RAW restent extensibles et reportées jusqu'à audit réel de leur besoin.
@@ -41,14 +41,14 @@ Les autres familles RAW restent extensibles et reportées jusqu'à audit réel d
| autres RAW | REPORTÉ | account/block/slot ajoutés seulement sur besoin audité |
| provenance | PASS | provider/protocol/origin/timing sûrs, aucun secret |
| idempotence | PASS | atomic put, `Inserted/AlreadyPresent`, divergence = conflict |
| API candidate | PASS | façade Store + capabilities object-safe + external backend |
| API candidate | PASS | capabilities object-safe + external backend; façade runtime reportée à 0.3.2 |
| public SQL transaction | ABSENT | invariants atomiques exprimés par opérations métier |
| pagination | PASS | 100 par défaut / 500 max / cursor opaque borné |
| notification ownership | PASS | référence RAW KSP-owned, mécanisme hors scope |
| D2/CORE persistence | ABSENT | explicitement hors `0.3.1` |
| DECODE/SPECIALIZED | ABSENT | explicitement hors `0.3.1` |
| schema PostgreSQL candidat | REPORTÉ | déplacé intégralement à `0.3.2` par split API/backend |
| migration policy | REPORTÉ | responsabilité `ksp-store-lib` `0.3.2` |
| migration policy | REPORTÉ | responsabilité `ksp-store-postgres-lib` `0.3.2` |
| PostgreSQL live gate | REPORTÉ | aucun backend DB dans `0.3.1`; gate obligatoire à définir en `0.3.2` |
| threat model | PASS | modèle hostile/API/backend couvert dans plan 022 |
| stratégie de tests | PASS | unit/public/external/firewall/completeness, aucun PostgreSQL live |
@@ -70,7 +70,7 @@ Les autres familles RAW restent extensibles et reportées jusqu'à audit réel d
| future RAW families | extensibles sans JSON universel | `pre.004` / `pre.007` |
| `StoreFuture<'a, T>` | future object-safe KSP-owned, sans `async-trait` par défaut | `pre.005` |
| backend trait | implémentable hors workspace, `Send + Sync` | `pre.005` |
| façade `Store` | même consumer surface quel que soit backend injecté | `pre.005` |
| façade runtime `Store` | reportée à `ksp-store-lib`, hors `0.3.1` | `0.3.2` |
| transaction handle | aucun handle SQL/backend public | `pre.005` |
| atomic acquisition | méthode métier RAW + observation all-or-nothing | `pre.005` / `pre.006` |
| write outcome | `Inserted / AlreadyPresent`; divergence = `Err Conflict` | `pre.006` |
@@ -151,17 +151,15 @@ Le terme `CORE` reste le nom architectural actuel de D2 mais peut être renommé
Le canari externe doit démontrer :
```text
crate/test consumer externe
crate/test backend externe
-> dépend de ksp-store-api
-> définit son propre backend mémoire
-> implémente le contrat public
-> construit la façade Store
-> écrit et relit transaction/log via les mêmes fonctions
-> implémente les contrats/capabilities publics
-X-> ksp-store-lib
-X-> PostgreSQL
```
L'implémentation PostgreSQL officielle de `0.3.2` devra satisfaire la même suite de conformance.
`0.3.2` ajoutera ensuite la façade de consommation `ksp-store-lib`. Le backend officiel `ksp-store-postgres-lib` devra satisfaire la même suite de conformance API.
## 8. Threat/API gates futurs
@@ -180,7 +178,7 @@ L'implémentation PostgreSQL officielle de `0.3.2` devra satisfaire la même sui
| provider secret leak | absent du modèle public | `pre.003` / `pre.007` |
| backend row/public type | absent | `pre.007` |
| async runtime dependency | aucune dependency Tokio dans API par défaut | `pre.005` / `pre.007` |
| external backend | compile et fonctionne sans Store lib | `pre.005` |
| external backend | implémente API sans dépendre de Store lib | `pre.005` |
| closed RAW enum | future family ajoutable | `pre.004` / `pre.007` |
| D2/D3/D4 creep | aucune surface | `pre.007` |
@@ -229,40 +227,56 @@ prompts/021-V0_3_2_START_PROMPT.md
delta pre.010
```
Le `ROADMAP.md` y réconcilie la nouvelle séquence `0.3.1 API -> 0.3.2 PostgreSQL`.
Le `ROADMAP.md` est déjà réconcilié par `pre.001-fix.001`; `pre.010` ne doit plus avoir à réparer ce split, seulement refléter l'état final et préparer le prompt `0.3.2`.
## 10. PostgreSQL reporté à `0.3.2`
Aucun gate PostgreSQL live n'est demandé à `0.3.1`.
Le prochain prompt devra transformer les invariants API en backend de référence et prévoir :
Le prochain prompt devra transformer les invariants API en façade commune + backend de référence et prévoir :
```text
tokio-postgres
settings programmatiques issus de Config/composition
pool/TLS audités
migrations KSP-owned
schema conformance
write/read round-trip des modèles API
idempotence/race
atomic rollback
pagination
error/DSN redaction
PostgreSQL réel opt-in puis gate final obligatoire
ksp-store-lib
-> façade Store commune
-> réexports utiles de ksp-store-api
-> feature postgres par défaut
-> dispatch backend selon Config
-> erreur backend connu mais non compilé
ksp-store-postgres-lib
-> tokio-postgres
-> pool/TLS audités
-> migrations KSP-owned
-> schema conformance
-> write/read round-trip des modèles API
-> idempotence/race
-> atomic rollback
-> pagination
Config
-> std.store
-> URI/DSN backend lorsque naturel
-> secrets ${KSP_SECRET_*} / .env owned par ksp-config-lib
-> aucun vrai secret versionné
sécurité
-> URI/DSN/credentials redacted
-> aucune lecture directe env/.env par Store ou backend
-> PostgreSQL réel opt-in puis gate final obligatoire
```
## 11. État initial des tranches
| Tranche | Objet | État |
|-----------|---------------------------------|-----------------------|
| `pre.001` | audit/design/split API/backend | PRÊT après gate local |
| `pre.002` | scaffold Store API | À FAIRE |
| `pre.003` | primitives + RawTransaction | À FAIRE |
| `pre.004` | RawLog + extensibilité N1 | À FAIRE |
| `pre.005` | backend contract + façade Store | À FAIRE |
| `pre.006` | queries/outcomes/notification | À FAIRE |
| `pre.007` | adversarial/completeness | À FAIRE |
| `pre.008` | gate technique final | À FAIRE |
| `pre.009` | réconciliation documentaire | À FAIRE |
| `pre.010` | préparation publication | À FAIRE |
| `rel.001` | stable | À FAIRE |
| Tranche | Objet | État |
|-----------|--------------------------------|-----------------------|
| `pre.001` | audit/design/split API/backend | PRÊT après gate local |
| `pre.002` | scaffold Store API | À FAIRE |
| `pre.003` | primitives + RawTransaction | À FAIRE |
| `pre.004` | RawLog + extensibilité N1 | À FAIRE |
| `pre.005` | backend contracts/capabilities | À FAIRE |
| `pre.006` | queries/outcomes/notification | À FAIRE |
| `pre.007` | adversarial/completeness | À FAIRE |
| `pre.008` | gate technique final | À FAIRE |
| `pre.009` | réconciliation documentaire | À FAIRE |
| `pre.010` | préparation publication | À FAIRE |
| `rel.001` | stable | À FAIRE |