diff --git a/ROADMAP.md b/ROADMAP.md index 0103454..a7ef7b2 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,5 +1,5 @@ - + # Roadmap KSP @@ -92,11 +92,12 @@ RAW -> CORE -> DECODE -> SPECIALIZED ## 0.3.x — RAW / acquisition persistée -- [ ] `0.3.1` — Introduire `ksp-store-api` + `ksp-store-lib` avec PostgreSQL de référence et **modèles/persistence RAW uniquement**. -- [ ] `0.3.2` — Étendre `ksp-interface-lib` avec les wires génériques nécessaires aux acquisitions et à la future normalisation CORE. -- [ ] `0.3.3` — Introduire `ksp-job-api` et un job de backfill historique concret. -- [ ] `0.3.4` — Introduire une application spécialisée de backfill/inspection RAW. -- [ ] Compléter ensuite la couche RAW avec le worker/service live, son contrôle et les outils d'exploitation réellement nécessaires avant de passer à CORE. +- [/] `0.3.1` — Introduire `ksp-store-api` uniquement avec le **modèle objet commun et les contrats N1 RAW/observations** : transactions et logs dans la première surface, provenance, identités, outcomes, queries/pagination et contrats backend, sans persistence concrète ni configuration backend. +- [ ] `0.3.2` — Introduire ensemble `ksp-store-lib` et `ksp-store-postgres-lib` : façade/runtime Store commune, feature `postgres` activée par défaut, implémentation PostgreSQL de référence via `tokio-postgres`, Config `std.store`/secrets et migrations privées au backend. Un backend connu demandé par Config mais absent des features compilées est rejeté explicitement. +- [ ] `0.3.3` — Étendre `ksp-interface-lib` avec les wires génériques nécessaires aux acquisitions et à la future normalisation de la couche suivant RAW. +- [ ] `0.3.4` — Introduire `ksp-job-api` et un job de backfill historique concret consommant uniquement `ksp-store-lib` côté Store. +- [ ] `0.3.5` — Introduire une application spécialisée de backfill/inspection RAW. +- [ ] Compléter ensuite la couche RAW avec le worker/service live, son contrôle et les outils d'exploitation réellement nécessaires avant de passer à la couche de normalisation générique suivante. ## Série CORE suivante diff --git a/deltas/0.3.1/pre.001-fix.001.md b/deltas/0.3.1/pre.001-fix.001.md new file mode 100644 index 0000000..54b6dca --- /dev/null +++ b/deltas/0.3.1/pre.001-fix.001.md @@ -0,0 +1,190 @@ + + + +# Delta `0.3.1-pre.001-fix.001` — split façade Store / backend PostgreSQL et roadmap + +## 1. Base + +```text +livraison : 0.3.1-pre.001 +Cargo : 0.3.1-pre.1 +``` + +Ce correctif reste dans le couloir de conception/audit de `pre.001`. Il ne crée aucune crate Store, aucun code runtime, aucune Config exécutable, aucune migration et aucune dependency PostgreSQL. + +## 2. Motif opérateur + +Le brainstorming postérieur à `pre.001` affine le split Store : + +```text +0.3.1 + ksp-store-api uniquement + +0.3.2 + ksp-store-lib + ksp-store-postgres-lib +``` + +`ksp-store-api` reste propriétaire du modèle objet/struct commun RAW/observations et des contrats/capabilities backend. `ksp-store-lib` devient la façade/runtime commune consommée par les jobs/workers/apps. Les backends sont des crates séparées importées optionnellement par `ksp-store-lib` selon les features compilées. + +## 3. Graphe corrigé + +Cible durable : + +```text +ksp-store-api + ^ ^ + | | +ksp-store-lib ksp-store-postgres-lib + | ^ + | feature postgres| + +-----------------+ + +futur ksp-store-mysql-lib -> ksp-store-api +ksp-store-lib[mysql] -> futur ksp-store-mysql-lib +``` + +Règles : + +```text +ksp-store-postgres-lib -X-> ksp-store-lib +backend alternatif -X-> ksp-store-lib +consumer métier -X-> crate backend directe +consumer métier -> ksp-store-lib uniquement côté Store +``` + +`ksp-store-lib` réexportera la surface commune de `ksp-store-api` nécessaire aux consumers afin qu'un worker/job n'ait pas à dépendre séparément de l'API et du backend. + +## 4. Features et sélection runtime + +`0.3.2` introduira : + +```text +default = [postgres] +postgres -> dep:ksp-store-postgres-lib +``` + +Les futures features backend pourront être compilées simultanément. La feature contrôle la **disponibilité dans le binaire** ; Config contrôle le **backend actif**. + +Un appel avec une Config demandant un backend KSP connu mais non présent dans les features compilées doit être rejeté explicitement, avec un code stable de type : + +```text +STORE_BACKEND_NOT_COMPILED +``` + +Aucun fallback silencieux vers PostgreSQL n'est permis. + +## 5. Config, URI, secrets et `.env` + +La responsabilité reste conforme aux règles Config KSP : + +```text +ksp-config-lib + = documents + schemas + placeholders + .env + provenance/sensitivity + +ksp-store-lib + = settings runtime + backend dispatch + +ksp-store-*-lib + = connexion/persistence backend +``` + +Pour un backend disposant d'une URI/DSN naturelle, la Config utilisera une URI plutôt qu'une décomposition artificielle, sauf besoin backend réellement justifié. Des options backend-specific peuvent être ajoutées sous forme typée lorsque nécessaire. + +Invariants : + +- une URI pouvant contenir user/password/token est `Secret` dans son ensemble ; +- les credentials proviennent de placeholders `KSP_SECRET_*` résolus par `ksp-config-lib` ; +- toute nouvelle variable apparaît commentée dans `.env.example` lors de sa première utilisation réelle ; +- le vrai `.env` et les vrais URI/credentials ne sont jamais versionnés ; +- Store et backend ne lisent jamais directement `.env` ni les variables KSP/KSPB ; +- URI/DSN/password/token restent absents des `Debug`, logs, erreurs et health ; +- l'absence de feature backend est détectée avant toute connexion ou fallback driver implicite. + +La forme exacte de `std.store`, du nom des variables et des settings runtime est reportée à `0.3.2`. + +## 6. ROADMAP corrigé + +La séquence devient : + +```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 aux acquisitions/normalisation future +0.3.4 ksp-job-api + premier backfill historique +0.3.5 application backfill/inspection RAW +``` + +La ligne `0.3.1` passe en cours et n'annonce plus de persistence PostgreSQL dans cette release. + +## 7. Version Cargo + +Ce correctif est strictement documentaire. Conformément à `VER-ID-008`, `workspace.package.version` reste : + +```text +0.3.1-pre.1 +``` + +## 8. Fichiers modifiés + +```text +ROADMAP.md +docs/plans/022-V0_3_1_STORE_RAW_PLAN.md +docs/validation/018-V0_3_1_STORE_RAW.md +``` + +## 9. Fichier ajouté + +```text +deltas/0.3.1/pre.001-fix.001.md +``` + +## 10. Fichiers supprimés + +```text +aucun +``` + +## 11. Validations exécutées + +Dans l'environnement de génération du fix : + +```text +python3 scripts/audit_rust_workspace_rules.py + General Rust rule audit: clean + Rust export completeness audit: 0 candidate(s) + KSP workspace Rust rule audit: clean + +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.1 + Markdown table audit: clean (184 table(s), 122 file(s)) +``` + +`cargo` n'est pas disponible dans cet environnement. Comme le fix ne modifie aucun fichier de code/build/runtime/config exécutable, aucune version Cargo n'est changée ; le gate opérateur reste néanmoins : + +```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.1 +cargo check --workspace +cargo clippy --workspace --all-targets +``` + +Aucun test Store ciblé n'existe encore et aucun gate PostgreSQL n'est requis dans ce fix documentaire. + +## 12. Questions ouvertes + +Aucune question ne bloque `0.3.1-pre.002`. + +Restent volontairement reportés à `0.3.2` : + +```text +forme exacte de StoreSettings +shape du document std.store +nom exact des variables KSP_SECRET_* Store +URI/DSN PostgreSQL exact accepté +pool/TLS/timeouts +migrations/schema/indexes +mapping PostgreSQL des modèles API +``` + +Ces détails ne changent pas les frontières déjà fixées par le présent correctif. diff --git a/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md b/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md index 3e23be7..d116544 100644 --- a/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md +++ b/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md @@ -1,5 +1,5 @@ - + # 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 +future ksp-store-lib::Store possède Arc ``` 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 compilé 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 ``` diff --git a/docs/validation/018-V0_3_1_STORE_RAW.md b/docs/validation/018-V0_3_1_STORE_RAW.md index cb57fe5..4647af6 100644 --- a/docs/validation/018-V0_3_1_STORE_RAW.md +++ b/docs/validation/018-V0_3_1_STORE_RAW.md @@ -1,11 +1,11 @@ - + # 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 |