From 29a888d1dc71fcd8cf92b76760e834ef9dc623d5 Mon Sep 17 00:00:00 2001 From: SinuS Von SifriduS Date: Fri, 28 Aug 2026 21:31:08 +0200 Subject: [PATCH] v0.3.1-pre.001 --- Cargo.toml | 4 +- deltas/0.3.1/pre.001.md | 296 +++++++ docs/plans/022-V0_3_1_STORE_RAW_PLAN.md | 1015 +++++++++++++++++++++++ docs/validation/018-V0_3_1_STORE_RAW.md | 268 ++++++ 4 files changed, 1581 insertions(+), 2 deletions(-) create mode 100644 deltas/0.3.1/pre.001.md create mode 100644 docs/plans/022-V0_3_1_STORE_RAW_PLAN.md create mode 100644 docs/validation/018-V0_3_1_STORE_RAW.md diff --git a/Cargo.toml b/Cargo.toml index d35e313..b0d564d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 322 +# version: 323 [workspace] 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-wallet-lib"] [workspace.package] -version = "0.2.14" +version = "0.3.1-pre.1" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/deltas/0.3.1/pre.001.md b/deltas/0.3.1/pre.001.md new file mode 100644 index 0000000..faca949 --- /dev/null +++ b/deltas/0.3.1/pre.001.md @@ -0,0 +1,296 @@ + + + +# Delta `0.3.1-pre.001` — audit Store API, N1 RAW et split PostgreSQL + +## 1. Base requise + +Base directe attendue : + +```text +v0.2.14 +workspace.package.version = 0.2.14 +``` + +Sources obligatoires réellement disponibles à l'ouverture : + +```text +archive opérateur khadhroony-solana-project-v0.2.14.zip +archive historique khadhroony-bot3_v0.5.3-pre.005-fix010.zip +``` + +La metadata Git n'est pas incluse dans l'archive opérateur ; le tag `v0.2.14` ne peut donc pas être interrogé localement. La version Cargo, `deltas/0.2.14/rel.001.md`, le prompt 020 et la surface Program API publiée concordent avec la base stable attendue. + +Commit attendu : + +```text +v0.3.1-pre.001 +``` + +Archive overlay attendue : + +```text +ksp-general-0.3.1-pre.001.zip +``` + +## 2. Objectif + +Ouvrir `0.3.1` uniquement par le gate prévu : + +```text +lecture règles + architecture +audit base KSP stable +audit historique kbot3 +audit PostgreSQL/driver actuel +brainstorming N1 RAW +split ksp-store-api / ksp-store-lib +ownership +API candidate +backend extension model +threat model +stratégie de tests +sizing et prévision souple recalibrée +``` + +Aucune crate Store fonctionnelle n'est ajoutée dans cette livraison. + +## 3. Décision de scope majeure + +Le scope du prompt initial est volontairement réduit et scindé : + +```text +0.3.1 = ksp-store-api uniquement +0.3.2 = ksp-store-lib PostgreSQL via tokio-postgres +``` + +`ksp-store-api` possédera le modèle objet/struct commun et les opérations backend-agnostic. Les représentations internes, rows, requêtes, migrations, pools et transactions SQL seront invisibles aux consumers. + +Une future implémentation alternative, par exemple `ksp-store-mysql-lib`, dépendra directement de `ksp-store-api` et non de `ksp-store-lib`. + +La composition/configuration choisira l'implémentation liée au host puis fournira la même façade `Store` aux consumers. + +Le `ROADMAP.md` stable contient encore l'ancienne prévision combinée. Il n'est pas modifié dans cette tranche et sera réconcilié dans la lane de préparation de publication conformément au workflow KSP. + +## 4. N1 RAW retenu + +Le niveau N1/D1 est défini comme acquisition persistée/replayable. + +Surface initiale `0.3.1` : + +```text +RawTransaction +RawTransactionObservation +RawLog +RawLogObservation +RawPayload/provenance/reference/outcome/page communs +``` + +Familles prévues mais reportées : + +```text +RawAccount +RawBlock +RawSlot/updates si besoin durable distinct +autres acquisitions justifiées ultérieurement +``` + +HTTP, WebSocket et gRPC sont des moyens d'acquisition/provenance, pas des familles RAW séparées. + +Le RAW transaction devra pouvoir être transformé ultérieurement en normalisation Solana générique (actuellement nommée CORE/D2), puis décomposé en instructions top-level et CPI indépendantes afin qu'un decoder absent/Unsupported n'empêche pas le traitement du reste. + +## 5. API/backend model + +Décisions candidates : + +```text +Store = façade consumer commune +StoreBackend = contrat d'implémentation externe object-safe +capabilities = StoreHealth + RawTransactionStore + RawLogStore +async = StoreFuture<'a, T> boxed KSP-owned par défaut +atomicité = opérations métier persist_*_acquisition +transaction SQL handle public = interdit +page = 100 défaut / 500 max / cursor opaque borné +``` + +Sémantique d'idempotence : + +```text +nouvelle clé -> Inserted +même clé + même contenu -> AlreadyPresent +même clé + contenu divergent -> Error Conflict +``` + +Aucun `has_*` n'est requis avant write. + +## 6. Héritage kbot3 + +L'archive historique a été extraite et les surfaces Store prioritaires réellement relues. + +Le Store historique comporte 16 tables N1-N3, 240 ressources SQL atomiques et 79 index attendus. La séparation façade/PostgreSQL, les observations, la pagination bornée et l'idempotence sont réutilisables conceptuellement, mais les contrats N2/N3 et la représentation physique ne sont pas repris. + +Résumé : + +```text +REPRENDRE séparation façade/backend, health portable, repository capabilities, pagination bornée, observations, idempotence +REDESSINER StoreOpenOptions, raw DTO/entities, write semantics, diagnostics, Config Store +REPORTER schema/migrations/indexes, raw table physique, replay processing, CORE, DECODE, materialization, processing ledger +REJETER maintenance destructive publique, JSON backend options opaque, PK SQL comme identité API, monolithe N1/N2/N3 +``` + +La matrice détaillée est dans `docs/plans/022-V0_3_1_STORE_RAW_PLAN.md`. + +## 7. Audit externe + +Audit actuel au 28 août 2026 : + +```text +PostgreSQL 18.6 — stable courant, 13 août 2026 +tokio-postgres 0.7.18 — stable courant, 12 juin 2026 +Rust 2024, MSRV 1.85 +prepared statements / transactions / COPY / async pipelined supportés +``` + +Décision opérateur : `tokio-postgres` sera le driver interne du backend PostgreSQL de référence dans `0.3.2`. + +Aucune dependency PostgreSQL n'est ajoutée dans `0.3.1`. + +## 8. Dependency graph `0.3.1` + +Cible : + +```text +ksp-store-api +└── ksp-core-lib +``` + +`ksp-interface-lib`, serde, chrono, tokio et toute crate DB restent absents tant qu'un usage public réel ne les justifie pas. + +## 9. Sizing recalibré + +Prévision active : + +```text +pre.001 audit/design/split +pre.002 scaffold ksp-store-api +pre.003 primitives RAW + transaction +pre.004 raw logs + extensibilité N1 +pre.005 backend contract + Store facade + external canary +pre.006 queries/pagination/outcomes/notification reference +pre.007 adversarial/API hardening + completeness +pre.008 gate technique final +pre.009 réconciliation documentaire +pre.010 préparation de publication minimale +rel.001 publication stable +``` + +Le futur `0.3.2` ouvre `ksp-store-lib` PostgreSQL/`tokio-postgres`. + +## 10. Fichiers ajoutés + +```text +docs/plans/022-V0_3_1_STORE_RAW_PLAN.md +docs/validation/018-V0_3_1_STORE_RAW.md +deltas/0.3.1/pre.001.md +``` + +## 11. Fichiers modifiés + +```text +Cargo.toml +``` + +## 12. Fichiers supprimés + +```text +aucun +``` + +## 13. Version Cargo + +La prerelease non-fix synchronise : + +```text +workspace.package.version = 0.3.1-pre.1 +``` + +Aucune crate Store n'existe encore ; le changement Cargo identifie uniquement le gate `pre.001` conformément au workflow. + +## 14. Validations de baseline + +Le journal opérateur fourni à l'ouverture sur `v0.2.14` montre : + +```text +cargo fmt --all PASS +audit Rust général / exports / workspace PASS +audit Markdown PASS — 175 tables / 128 fichiers +cargo check --workspace PASS +cargo clippy --workspace --all-targets PASS +cargo test --workspace PASS +``` + +Les smokes live opt-in restent ignorés comme prévu par leurs contrats. + +Cette preuve de base ne remplace pas le gate après application de `pre.001`. + +## 15. Validations après application + +Dans l'environnement de génération du présent overlay, les contrôles statiques suivants ont été réellement exécutés après modification : + +```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 tables, 121 files) +``` + +`cargo` n'est pas installé dans l'environnement de génération utilisé pour préparer l'archive. `cargo fmt --all`, `cargo check --workspace` et `cargo clippy --workspace --all-targets` n'ont donc pas été rejoués ici et ne sont pas déclarés PASS. Le baseline opérateur `v0.2.14` fourni reste vert, mais ne remplace pas le gate opérateur après application. + +## 16. Validations non requises dans cette tranche + +```text +cargo test -p ksp-store-api crate encore absente +cargo tree -p ksp-store-api crate encore absente +PostgreSQL live backend reporté à 0.3.2 +migration/schema tests backend reporté à 0.3.2 +``` + +## 17. Questions ouvertes + +Aucune question architecturale ne bloque `pre.002`. + +Restent volontairement à stabiliser par les tranches de code : + +```text +nom exact des wrappers d'identité RAW +format_id/version concret du premier RawPayload transaction +bornes finales payload/provenance +identité déterministe exacte d'un RawLog +forme finale StoreFuture/backend traits +référence notification introduite en pre.006 ou reportée si insuffisamment stable +``` + +Ces questions ne remettent pas en cause : + +```text +Store API seule en 0.3.1 +PostgreSQL/tokio-postgres en 0.3.2 +modèle public commun backend-agnostic +transaction + logs comme premières familles N1 +``` + +## 18. Application et validation opérateur + +Après application de l'overlay : + +```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 scaffold Store, SQL, migration ou changement Config ne doit être ajouté à ce delta. diff --git a/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md b/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md new file mode 100644 index 0000000..3e23be7 --- /dev/null +++ b/docs/plans/022-V0_3_1_STORE_RAW_PLAN.md @@ -0,0 +1,1015 @@ + + + +# Plan `0.3.1` — Store API RAW foundation + +## 1. Statut et base + +Ce plan est établi par `0.3.1-pre.001` à partir de la release stable `v0.2.14` et de l'archive historique obligatoire `khadhroony-bot3_v0.5.3-pre.005-fix010.zip`. + +La base KSP vérifiée à l'ouverture est : + +```text +workspace.package.version = 0.2.14 +deltas/0.2.14/rel.001.md présent +prompts/020-V0_3_1_START_PROMPT.md présent +ksp-program-api présent +ksp-store-api absent +ksp-store-lib absent +``` + +L'archive opérateur ne contient pas de metadata Git exploitable ; le tag `v0.2.14` ne peut donc pas être revérifié localement. La version Cargo, le delta `rel.001`, le prompt 020 et la surface Program API publiée concordent avec la base stable attendue. + +Le journal opérateur fourni avec l'archive montre un baseline stable intégralement vert avant ouverture de `0.3.1` : audits Rust/Markdown, `cargo check --workspace`, Clippy et `cargo test --workspace` passent. + +Après application de `pre.001`, la version Cargo cible est : + +```text +0.3.1-pre.1 +``` + +## 2. Décision opérateur qui recalibre le prompt initial + +Le brainstorming de `pre.001` a séparé la création de l'API Store de son implémentation PostgreSQL. + +La trajectoire devient : + +```text +0.3.1 = ksp-store-api uniquement +0.3.2 = ksp-store-lib, backend PostgreSQL officiel 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`. + +Conséquences immédiates : + +```text +aucune dépendance PostgreSQL en 0.3.1 +aucun tokio-postgres dans Cargo en 0.3.1 +aucun pool +aucune table +aucun SQL +aucune migration +aucun std.store +aucun ksp-store-lib +``` + +`0.3.1` doit stabiliser le contrat logique suffisamment pour que `0.3.2` puisse ensuite demander : + +> quelle représentation PostgreSQL satisfait le mieux ce contrat ? + +et non : + +> comment exposer les tables déjà créées ? + +## 3. Mission recalibrée + +`0.3.1` introduit `ksp-store-api` comme **modèle logique commun et API fonctionnelle backend-agnostic du niveau N1 / D1 RAW**. + +La crate doit posséder : + +```text +modèles objet/struct persistants communs +références durables +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 +format canonique de notification de disponibilité si la référence RAW est stabilisée +``` + +Elle ne possède pas : + +```text +schéma physique +rows backend +SQL +migrations +pool/connection +transactions SQL +backend selection par lecture Config +tokio-postgres +PostgreSQL/MySQL/SQLite/RocksDB/ClickHouse types +Transport +Program decoder +Materializer +``` + +Le modèle public `ksp-store-api` est volontairement réutilisable par toute implémentation future. Un backend peut choisir une représentation physique radicalement différente sans modifier les DTO/entités et opérations logiques consommés par l'extérieur. + +## 4. Modèle d'extensibilité backend + +### 4.1 Graphe durable + +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-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 : + +```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 +``` + +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. + +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.3 Modèle public et modèle interne + +Deux modèles restent strictement distincts : + +```text +ksp-store-api + RawTransaction / RawLog / provenance / queries / outcomes + = public et commun + +backend + PostgresRawTransactionRow / SQL columns / statements / indexes + = privés à l'implémentation +``` + +Aucun type de row backend, handle de pool, statement préparé ou nom d'objet SQL ne traverse la façade publique. + +## 5. Sources KSP relues + +Le gate `pre.001` a relu les sources prescrites par le prompt : + +```text +RULES.md +docs/000-README.md +docs/rules/RULES_GENERAL.md +docs/rules/RULES_KSP.md +docs/rules/RULES_RUST.md +docs/rules/RULES_DEPENDENCIES.md +docs/rules/RULES_DOCUMENTATION.md +docs/rules/FILE_CONTRACTS.md +docs/rules/VERSION_WORKFLOW.md +docs/rules/PROMPT_STRUCTURE.md + +docs/architecture/000-README.md +docs/architecture/001-PROJECT_OBJECTIVES.md +docs/architecture/002-LAYERS_AND_DEPENDENCIES.md +docs/architecture/003-COMPONENT_CONTRACTS.md +docs/architecture/004-COMPONENT_INVENTORY.md +docs/architecture/005-DEPENDENCY_GRAPH.md +docs/architecture/006-WIRE_AND_PROGRAM.md +docs/architecture/007-EXECUTION_AND_POLICY.md +docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md +docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md +docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md +``` + +Les règles directement structurantes sont : + +```text +KSP-API-001..007 +KSP-CONFIG-001..018 +KSP-NOTIFY-001..006 +KSP-STORE-001..002 +KSP-DATA-001..004 +KSP-PIPE-001..007 +DEP-KSP-001..005 +DEP-CARGO-001..007 +DEP-STORE-001..008 +DEP-TRANSPORT-001..005 +DEP-PIPE-001..008 +DEP-WORKER-001..003 +DEP-JOB-001..003 +``` + +Le résultat normatif principal est : + +```text +Store API possède les contrats persistants +Store API -X-> Transport/Program/Materializer +Transport -X-> Store API +conversion explicite à la composition +persist -> commit -> notification +notification != backlog +at-least-once + persistence idempotente +``` + +## 6. N1 / D1 RAW : définition retenue + +### 6.1 Rôle + +N1 est la couche **acquisition persistée / RAW replayable**. + +Elle ne se limite pas à une table `raw_transactions`. Elle regroupe les faits d'acquisition nécessaires pour rejouer ultérieurement la normalisation générique Solana sans redemander arbitrairement la donnée au provider. + +La première surface concrète `0.3.1` retient : + +```text +RawTransaction +RawTransactionObservation +RawLog +RawLogObservation +provenance commune +références durables communes +``` + +Les familles suivantes sont explicitement prévues mais reportées tant que leur acquisition/replay exact n'est pas suffisamment auditée : + +```text +RawAccount / account observation +RawBlock +RawSlot / slot update si un besoin durable distinct existe +autres familles d'acquisition réellement nécessaires +``` + +Aucun enum fermé ne doit empêcher leur ajout. + +### 6.2 Transport n'est pas une famille RAW + +Les mécanismes suivants sont des **origines d'acquisition**, pas des modèles persistants distincts : + +```text +HTTP JSON-RPC +WebSocket JSON-RPC +Yellowstone gRPC +provider extension +import +backfill +``` + +Interdit : + +```text +RawHttpTransaction +RawWsTransaction +RawGrpcTransaction +``` + +La même transaction logique acquise par HTTP, WS et gRPC doit converger vers un `RawTransaction` commun, avec plusieurs observations/provenances si nécessaire. + +### 6.3 Transaction canonique et observation + +Le contrat sépare : + +```text +RawTransaction + = fait RAW canonique source-independent et replayable + +RawTransactionObservation + = fait qu'une source donnée a observé/acquis cette transaction +``` + +Exemple : + +```text + RawTransaction T + ^ + | + +---------------+---------------+ + | | | + HTTP/Helius obs WS/Helius obs gRPC/PublicNode obs +``` + +La duplication d'observation ne duplique pas automatiquement la transaction canonique. + +### 6.4 Raw logs + +`RawLog` est une famille N1 distincte et n'est pas confondue avec la future décomposition CORE des logs. + +Elle doit préserver l'observation de logs suffisamment fidèlement pour : + +```text +conserver l'ordre des lignes +conserver slot/signature/identité applicable +conserver le statut source nécessaire +permettre replay/inspection +permettre de relier un log à une transaction lorsqu'elle est connue +``` + +Une observation `logsSubscribe` peut également servir de déclencheur pour acquérir ensuite la transaction complète. Le modèle de provenance ne doit pas empêcher une lineage future : + +```text +RawLogObservation + -> déclenche acquisition transaction +RawTransactionObservation + -> RawTransaction +``` + +Cette relation causale n'est pas un orchestrateur et n'est pas obligatoirement implémentée dans `0.3.1`. + +### 6.5 Autres RAW + +Le design doit permettre d'ajouter plus tard des familles distinctes sans créer un `RawAnything { kind, json }` universel. + +Le partage se fait par composition de primitives communes : + +```text +RawAcquisitionProvenance +RawPayload +RawContentHash / idempotence key +RawDataReference +PageRequest / Page +``` + +et non par effacement des sémantiques propres à chaque famille. + +## 7. Payload replayable + +### 7.1 Décision de niveau API + +`ksp-store-api` possède un **payload de persistence RAW KSP**, pas un payload réseau provider. + +Le contrat candidat est un conteneur borné et versionné : + +```text +RawPayload + format_id + format_version + bytes + content_hash +``` + +`format_id` identifie un format de persistence KSP source-independent. Il ne vaut pas `helius_json`, `yellowstone_proto` ou un autre wire provider. + +La conversion : + +```text +transport model + -> conversion explicite + -> RawPayload KSP +``` + +reste hors de `ksp-store-api`. + +### 7.2 Pas de codec improvisé + +`0.3.1` ne choisit pas un codec réseau ou Solana concurrent. `bincode` reste interdit pour les codecs wire KSP. + +Le premier format concret de transaction canonique doit pouvoir être produit par la future couche de conversion à partir des wires génériques KSP. Sa définition détaillée peut évoluer pendant `0.3.1` tant que les invariants publics restent : + +```text +source-independent +versionné +borné +lossless pour la normalisation générique couverte +Debug sans bytes +hashable/idempotent +``` + +Le Store ne prétend pas que des bytes arbitraires sans format connu sont replayables. + +## 8. Future décomposition N1 -> niveau générique Solana + +La frontière architecturale actuelle reste nommée : + +```text +RAW -> CORE -> DECODE -> SPECIALIZED +``` + +Le nom `CORE` n'est pas considéré comme irréversible. Une revue de nomenclature pourra être faite avant l'ouverture effective de D2 sans modifier les responsabilités déjà fixées. + +Le rôle de D2 reste en revanche clair : décomposer/normaliser une transaction RAW en faits Solana génériques indépendants des decoders Program. + +Le futur flux doit permettre notamment : + +```text +RawTransaction + -> transaction/message générique + -> account keys + -> instruction top-level #0 + -> instruction top-level #1 + -> CPI/inner instruction #1.0 + -> CPI/inner instruction #1.1 + -> logs/meta/balances/return data applicables +``` + +Chaque instruction/CPI doit ensuite pouvoir être traitée indépendamment : + +```text +instruction générique + -> decoder disponible ? + oui -> decode + non -> Unsupported/NotApplicable durable sans bloquer le reste +``` + +`0.3.1` ne crée aucun type D2/CORE et ne dépend pas de `ksp-program-api`. + +## 9. Provenance commune + +La provenance candidate doit pouvoir représenter sans secret : + +```text +network/cluster +provider code +endpoint logical id optionnel +transport/protocol code +acquisition method +origin live/backfill/import/replay/repair +commitment optionnel +capture/session/filter logical ids optionnels +observed/received timestamp +source payload size/hash optionnels +``` + +Interdits : + +```text +endpoint URL +DSN +API key +token/password +payload source complet par simple diagnostic +``` + +Les codes provider/protocol/method restent ouverts et bornés ; aucun enum provider fermé n'est introduit dans Store API. + +## 10. Identité et idempotence + +### 10.1 Principes + +L'API ne fournit pas de méthode `has_*` à appeler avant un write idempotent. + +Le backend doit recevoir une opération unique avec ces sémantiques : + +```text +clé déjà absente + -> Inserted + +même clé + même contenu canonique + -> AlreadyPresent + +même clé + contenu différent + -> Conflict +``` + +Cela évite un check-then-insert race. + +### 10.2 Transactions + +La clé logique d'un `RawTransaction` est dérivée au minimum du réseau et de la signature canonique. Un hash du contenu canonique protège contre une collision logique avec contenu divergent. + +La signature ne doit pas être représentée comme un identifiant SQL `i64` dans l'API. + +### 10.3 Observations + +Chaque observation possède une clé d'idempotence déterministe fournie par le producer/composition selon un contrat documenté. Deux acquisitions légitimes distinctes peuvent donc être conservées même si elles pointent vers le même RAW. + +### 10.4 Logs + +L'identité exacte d'un `RawLog` sera stabilisée avec son modèle concret ; elle doit être déterministe et ne doit pas dépendre d'un primary key backend. + +Aucune promesse exactly-once distribuée n'est faite. + +## 11. API candidate + +### 11.1 Façade commune + +Le consumer normal doit recevoir une façade commune : + +```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é. + +### 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 stratégie candidate est : + +```text +StoreBackend: Send + Sync +méthodes object-safe +futures boxed KSP-owned via un alias StoreFuture<'a, T> +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. + +### 11.3 Capabilities + +Éviter un trait de 150 méthodes. La candidate est une composition de capabilities N1 : + +```text +StoreHealth +RawTransactionStore +RawLogStore +``` + +Un contrat composite `StoreBackend` peut agréger les capabilities exigées par la façade `Store` de cette release. + +Les futures couches D2/D3/D4 ne sont pas ajoutées par anticipation. + +### 11.4 Opérations atomiques métier + +Aucun handle de transaction SQL/public n'est exposé. + +Les invariants multi-écritures sont exprimés par des opérations logiques communes. Candidate : + +```text +persist_transaction_acquisition(transaction, observation) +record_transaction_observation(observation) +get_raw_transaction(reference) +list_raw_transactions(query, page) +list_transaction_observations(query, page) + +persist_log_acquisition(raw_log, observation) +record_log_observation(observation) +get_raw_log(reference) +list_raw_logs(query, page) +list_log_observations(query, page) + +health() +``` + +`persist_*_acquisition` signifie au contrat que le RAW et son observation réussissent atomiquement ou échouent ensemble. PostgreSQL réalisera cela avec une transaction privée en `0.3.2`; un autre backend utilisera son mécanisme natif. + +### 11.5 Outcomes + +Le vocabulaire candidat : + +```text +RawWriteOutcome + Inserted + AlreadyPresent + +Conflict + = Error KSP stable, pas un succès silencieux +``` + +Pour une acquisition combinée, l'outcome doit distinguer au minimum l'état du RAW et de l'observation sans révéler de clé backend. + +### 11.6 Pagination + +Le concept historique `PageRequest/PageSlice` est repris avec : + +```text +default = 100 +maximum = 500 +cursor opaque et borné +ordre déterministe par query +``` + +Le cursor est un token d'implémentation retourné par la façade et réinjecté tel quel par le consumer. Son contenu ne devient pas API et ne doit pas être utilisé comme transport d'un SQL fragment. + +## 12. Références durables et notifications + +L'ownership `KSP-NOTIFY-001..006` reste à `ksp-store-api`. + +Le candidat est une référence compacte : + +```text +RawDataReference + Transaction(RawTransactionReference) + Log(RawLogReference) + futures variantes non exhaustives +``` + +Puis un signal logique : + +```text +RawDataAvailable { + reference, +} +``` + +Le mécanisme de diffusion est hors scope. + +Ordre obligatoire : + +```text +persist +commit +notify +``` + +La notification ne transporte pas le payload RAW et ne remplace jamais `list_*`/backlog Store. + +Si les références concrètes ne sont pas assez stabilisées lors de leur tranche, le type de notification peut être reporté sans déplacer son ownership. + +## 13. Health et diagnostics + +La façade peut exposer un health commun minimal : + +```text +Unknown +Healthy +Degraded +Unhealthy +``` + +avec un backend code sûr et un code diagnostic borné si nécessaire. + +Ne pas exposer dans l'API commune : + +```text +migration SQL state +pool handles +connection count détaillé par driver +server error brut +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. + +## 14. Dependency graph `0.3.1` + +Graphe maximal par défaut : + +```text +ksp-store-api +└── ksp-core-lib +``` + +Aucune dépendance externe n'est nécessaire pour la foundation candidate : + +```text +pas de serde +pas de chrono +pas de tokio +pas de async-trait +pas de futures-util +pas de ksp-interface-lib tant qu'un type Interface réel n'est pas requis +``` + +Les timestamps persistants peuvent être représentés par un newtype KSP en unités Unix explicites plutôt que d'ajouter `chrono` par réflexe. Le choix exact est prouvé dans la tranche de modèle. + +## 15. Audit historique kbot3 + +### 15.1 Surface auditée + +L'archive historique a été extraite et les surfaces prescrites ont été relues, notamment : + +```text +ks-store/Cargo.toml +ks-store/README.md +ks-store/USAGE.md +ks-store/TODO.md +ks-store/src/lib.rs +ks-store/src/store.rs +ks-store/src/contracts/** +ks-store/src/postgres/** +ks-store/migrations/postgres/** +config/store.config.json +config/schemas/store.config.schema.json +ks-config/src/store.rs +docs/architecture/STORAGE_ARCHITECTURE.md +docs/guides/POSTGRES_STORAGE.md +docs/plans/V0_5_3_KS_STORE_NORMALIZATION_PLAN.md +``` + +Le Store historique couvre 16 tables N1-N3, 240 ressources SQL atomiques et 79 index attendus. Cette surface confirme l'intérêt de la séparation façade/backend, de l'idempotence et des observations, mais elle est beaucoup trop large pour `0.3.1`. + +### 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 | + +## 16. Audit PostgreSQL et driver de référence futur + +### 16.1 Décision + +Le choix opérateur est fixé pour la version suivante : + +```text +ksp-store-lib + backend officiel = PostgreSQL + driver interne = tokio-postgres +``` + +Ce choix n'ajoute aucune dependency à `0.3.1`. + +### 16.2 État externe audité au 28 août 2026 + +Sources primaires actuelles consultées : documentation PostgreSQL et documentation/package `tokio-postgres`. + +Résultats : + +```text +PostgreSQL stable courant : 18.6, publié le 13 août 2026 +tokio-postgres courant : 0.7.18, publié le 12 juin 2026 +edition tokio-postgres : Rust 2024 +MSRV tokio-postgres : Rust 1.85 +runtime async : Tokio +prepared statements : supportés +transactions / isolation : supportées +COPY in/out : supporté +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. + +### 16.3 SQLx + +SQLx `0.9.0` a été réaudité comme alternative mais n'est plus retenu après décision opérateur. + +La comparaison a néanmoins confirmé l'intérêt d'éviter dans KSP les defaults de connexion influencés par `PG*`/`.pgpass` lorsque le backend peut être construit explicitement depuis Config. + +La performance ne constitue pas à elle seule la raison du choix : `0.3.2` devra optimiser les vrais chemins KSP avec prepared statements, batching/COPY lorsque justifié, transactions et indexes adaptés. + +## 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`. + +Il pourra créer librement : + +```text +PostgresStoreBackend +Postgres*Row privés +migrations +schema version +prepared statements +indexes +pool +transaction handles privés +mapping Rust API <-> PostgreSQL +``` + +mais aucun de ces éléments ne devient une dépendance des consumers. + +La compatibilité backend devra être testée par round-trip des modèles API et par introspection/validation du schema PostgreSQL réel. + +## 18. Sorties PostgreSQL du prompt initial explicitement déplacées + +Le prompt de démarrage demandait encore à `pre.001` un schéma PostgreSQL candidat, une migration policy et un gate PostgreSQL live parce que `0.3.1` devait initialement contenir API **et** implémentation. La décision de split rend ces sorties prématurées. + +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` | + +Les invariants API qui contraignent déjà ce futur schéma restent fixés maintenant : + +```text +identités logiques non dépendantes d'une PK SQL +idempotence Inserted/AlreadyPresent/Conflict +atomicité RAW + observation +pagination bornée +payload versionné et borné +provenance sans secret +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. + +## 19. Threat model `0.3.1` + +| Menace | Réponse de design | +|------------------------------|-----------------------------------------------------------------------| +| payload hostile trop grand | bornes à la construction des contrats RAW avant persistence | +| raw payload leak via `Debug` | implémentations Debug manuelles/redacted pour conteneurs sensibles | +| secret provider/endpoint | provenance ne contient que des ids/codes sûrs, jamais URL/credential | +| duplicate race | write idempotent atomique, jamais `has_*` comme précondition | +| même clé / contenu divergent | conflit explicite, pas d'overwrite silencieux | +| partial RAW + observation | opération `persist_*_acquisition` atomique au contrat | +| cursor hostile | taille/limit bornées; cursor opaque non interprété par consumer | +| query non bornée | aucune liste publique sans `PageRequest` borné | +| backend leak | aucun type driver/row/table/SQL dans la façade | +| backend error leak | mapping vers erreurs KSP sûres; source externe auditée avant chaînage | +| closed-world backend | contrat implémentable hors `ksp-store-lib` | +| closed-world RAW family | types/familles extensibles sans JSON fourre-tout | +| cross-backend mismatch | conformance suite commune sur chaque implémentation | +| scope creep D2/D3/D4 | aucun type CORE/DECODE/SPECIALIZED dans `0.3.1` | + +Les menaces DSN/SQL injection/schema drift/migrations restent documentées pour `0.3.2`, où elles deviennent exécutables. Elles ne justifient pas des types SQL dans l'API. + +## 20. Stratégie de tests `0.3.1` + +Prévoir : + +```text +unit tests module-local +public API canaries crate-root +external backend canary +object-safe facade/backend composition canary +manifest/dependency firewall +exact public export inventory +exact production module inventory +bounds payload/provenance/cursor +Debug/redaction tests +idempotence outcome semantics +transaction/log identity validation +atomic-operation contract fake backend +pagination bounds +notification reference contract si introduit +release completeness +cargo tree -p ksp-store-api --edges normal +cargo tree --duplicates +``` + +Le **backend externe canary** doit implémenter le contrat avec une petite implémentation mémoire de test située hors des modules de production. Il prouve : + +```text +aucune dépendance à ksp-store-lib +aucune connaissance PostgreSQL +construction de Store depuis l'implémentation +mêmes appels consumer +``` + +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 | + +## 22. Hors scope strict `0.3.1` + +```text +ksp-store-lib +PostgreSQL runtime +tokio-postgres dependency +pool/TLS PostgreSQL +SQL/tables/indexes/migrations +std.store Config +backend MySQL/SQLite/Oracle/RocksDB/ClickHouse +Transport acquisition runtime +conversion Transport -> RAW fonctionnelle +D2/CORE structs et persistence +RAW -> D2 normalizer +Program decode +Materializer +processing ledger +worker/job/backfill +application Store/RAW +notification transport concret +retention/archive/purge lifecycle +truncate/drop/maintenance API +``` + +## 23. Prévision souple recalibrée `0.3.1` + +Chaque tranche vise environ 15–20 minutes de travail effectif. + +### `pre.001` — Audit, modèle N1 et split API/backend + +Base, règles, architecture, audit kbot3, audit PostgreSQL/driver futur, RAW transactions/logs, ownership, API candidate, threat model, tests et sizing. + +### `pre.002` — Scaffold `ksp-store-api` + +Créer uniquement la crate API, manifest Core-only, façade crate-root et documentation initiale. Aucun modèle fonctionnel lourd. + +### `pre.003` — Primitives RAW communes + transaction + +Introduire payload/reference/provenance/idempotence/timestamps bornés puis `RawTransaction` et son observation. + +### `pre.004` — RAW logs + extensibilité N1 + +Introduire `RawLog`/observation, vérifier ordering/identity/bounds et verrouiller l'absence de type RAW fourre-tout. + +### `pre.005` — Capabilities backend + façade `Store` + +Implémenter les contracts object-safe, la façade commune et l'external backend canary, sans runtime DB. + +### `pre.006` — Queries, pagination, outcomes et notification reference + +Finaliser reads/list/backlog bornés, atomic acquisition contract et référence de notification si suffisamment stable. + +### `pre.007` — Adversarial/API hardening + completeness + +Payload/cursor/provenance hostile, Debug, external backend, exact exports/modules, dependency firewall et scope négatif D2/D3/D4. + +### `pre.008` — Gate technique final + +Workspace complet, tests Store API, graphes Cargo. Aucun développement fonctionnel nouveau. + +### `pre.009` — Réconciliation documentaire finale + +README/USAGE, plan, validation et références durables réellement concernées. Aucun `CHANGELOG.md`, `ROADMAP.md` ni prompt suivant. + +### `pre.010` — Préparation de publication minimale + +Uniquement : + +```text +Cargo.toml +CHANGELOG.md +ROADMAP.md +prompts/021-V0_3_2_START_PROMPT.md +delta pre.010 +``` + +Le prompt `0.3.2` ouvre `ksp-store-lib` PostgreSQL/`tokio-postgres`. + +### `rel.001` — Publication stable + +Mécanique de publication uniquement. + +La release reste estimée clôturable dans une session si les tranches conservent cette granularité et si aucun codec/normalizer D2 n'est tiré dans le scope. + +## 24. Trajectoire `0.3.x` résultante + +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.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. + +## 25. Critères de fermeture de `0.3.1` + +La stable `0.3.1` est prête seulement si : + +```text +ksp-store-api existe seule dans le domaine Store +modèle objet RAW commun stable +RawTransaction + observations stables +RawLog + observations stables +future extension N1 non bloquée +façade Store commune stable +backend externe implémentable sans ksp-store-lib +aucun type backend/SQL public +queries/pagination bornées +idempotence/conflict semantics explicites +atomic acquisition contract explicite +références durables stables +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 +``` diff --git a/docs/validation/018-V0_3_1_STORE_RAW.md b/docs/validation/018-V0_3_1_STORE_RAW.md new file mode 100644 index 0000000..cb57fe5 --- /dev/null +++ b/docs/validation/018-V0_3_1_STORE_RAW.md @@ -0,0 +1,268 @@ + + + +# 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. + +Le scope concret N1 initial est : + +```text +RawTransaction + observation +RawLog + observation +provenance/références/outcomes/queries communs +façade Store + contrat backend externe +``` + +Les autres familles RAW restent extensibles et reportées jusqu'à audit réel de leur besoin. + +## 2. Gate `pre.001` + +| Critère | Statut | Preuve | +|----------------------------|---------|-------------------------------------------------------------------------------| +| base stable `0.2.14` | PASS | Cargo `0.2.14`, `rel.001` et prompt 020 présents | +| metadata Git/tag | N/A | archive opérateur sans metadata Git exploitable | +| baseline opérateur | PASS | audits, check, Clippy et workspace tests fournis verts sur `v0.2.14` | +| `ksp-program-api` stable | PASS | façade instruction-only relue | +| `ksp-store-api` absent | PASS | aucun répertoire Store API sur la base | +| `ksp-store-lib` absent | PASS | aucun répertoire Store lib sur la base | +| archive kbot3 disponible | PASS | archive historique extraite et auditée | +| règles Store/API relues | PASS | règles KSP/Dependencies/Workflow prescrites relues | +| architecture durable relue | PASS | graph/store/acquisition relus, D1/D2 séparés | +| matrice héritage kbot3 | PASS | `REPRENDRE / REDESSINER / REPORTER / REJETER` dans le plan 022 | +| audit externe PostgreSQL | PASS | PostgreSQL 18.6 courant au 28 août 2026 | +| audit driver futur | PASS | `tokio-postgres 0.7.18`, Rust 2024/MSRV 1.85, async/transactions/COPY audités | +| split version | PASS | `0.3.1 = Store API`, `0.3.2 = Store lib PostgreSQL` | +| dependency graph `0.3.1` | PASS | cible Core-only | +| modèle backend commun | PASS | API object/struct commune, rows backend privées | +| inventaire RAW initial | PASS | transaction + logs + observations | +| 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 | +| 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` | +| 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 | +| sizing | PASS | dix prereleases courtes + lanes fermeture séparées | + +## 3. Décisions structurelles à prouver par le code + +| Contrat | Décision `pre.001` | Gate futur | +|-----------------------------|-------------------------------------------------------------------|-------------------------------| +| crate `ksp-store-api` | seule crate Store créée en `0.3.1` | `pre.002` | +| dépendance normale | `ksp-core-lib` uniquement par défaut | `pre.002` | +| backend PostgreSQL | absent de `0.3.1` | completeness `pre.007` | +| `RawPayload` | KSP-owned, source-independent, versionné, borné, Debug sans bytes | `pre.003` | +| transaction identity | réseau + signature logique, jamais PK SQL | `pre.003` | +| `RawTransaction` | objet persistant commun replayable | `pre.003` | +| `RawTransactionObservation` | acquisition/provenance séparée du RAW | `pre.003` | +| `RawLog` | famille N1 distincte avec ordering préservé | `pre.004` | +| `RawLogObservation` | provenance séparée du log canonique | `pre.004` | +| 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` | +| 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` | +| `PageRequest` | borné, default 100, max 500 | `pre.006` | +| cursor | opaque, borné, aucun SQL/backend contract visible | `pre.006` | +| notification reference | compacte, durable, payload non dupliqué | `pre.006` ou report explicite | +| health | portable et sanitisé | `pre.005` / `pre.006` | + +## 4. Dependency firewall final attendu + +Le graphe final `0.3.1` doit rester : + +```text +ksp-store-api +└── ksp-core-lib + └── solana-pubkey +``` + +Interdits par défaut dans Store API : + +```text +ksp-store-lib +ksp-onchain-transport-lib +ksp-offchain-transport-lib +ksp-interface-lib sans usage de type réel +ksp-program-api +ksp-program-lib +ksp-materializer-api +ksp-config-lib +ksp-logging-lib +ksp-wallet-lib +tokio-postgres +sqlx +serde / serde_json +chrono +tokio +async-trait +Tauri +``` + +Toute divergence exige un usage public réel et une révision du plan. + +## 5. Matrice N1 initiale + +| Famille | `0.3.1` | Identité logique candidate | Replay couvert | Provenance | +|-------------|---------|-----------------------------------------------------------|---------------------------------------------------------------------------|-------------------------------| +| transaction | IN | network + signature | future décomposition générique Solana complète couverte par le format RAW | observations séparées | +| logs | IN | identité transaction/slot + clé déterministe à stabiliser | ordre et contenu log nécessaires à replay/inspection | observations séparées | +| account | REPORTÉ | pubkey + context/slot/version à auditer | futur compte RAW replayable | prévu par primitives communes | +| block | REPORTÉ | network + slot/block identity | futur backfill/block replay | prévu par primitives communes | +| slot/update | REPORTÉ | sémantique exacte à auditer | seulement si un fait durable distinct est utile | prévu par primitives communes | + +## 6. Frontière N1 -> D2 + +`0.3.1` doit préserver sans implémenter : + +```text +RawTransaction + -> generic Solana normalization + -> transaction/message + -> account keys + -> top-level instructions + -> CPI/inner instructions + -> logs/meta/balances/return data + -> traitement individuel ultérieur +``` + +Canari négatif durable : + +```text +ksp-store-api -X-> ksp-program-api +``` + +Le terme `CORE` reste le nom architectural actuel de D2 mais peut être renommé avant ouverture de cette couche sans modifier la séparation fonctionnelle. + +## 7. Extensibilité backend + +Le canari externe doit démontrer : + +```text +crate/test consumer 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 + -X-> ksp-store-lib + -X-> PostgreSQL +``` + +L'implémentation PostgreSQL officielle de `0.3.2` devra satisfaire la même suite de conformance. + +## 8. Threat/API gates futurs + +| Gate | Attendu | Statut initial | +|---------------------------------|-----------------------------------------------------|-----------------------| +| oversized RAW payload | rejet avant stockage/copied allocation pathologique | `pre.003` | +| payload Debug | aucun bytes brut | `pre.003` | +| hostile provenance text | borné/trim/control policy explicite | `pre.003` | +| duplicate same content | outcome `AlreadyPresent` | `pre.006` | +| duplicate divergent content | erreur Conflict stable | `pre.006` | +| check-then-insert | absent de l'API publique | `pre.005` | +| partial transaction+observation | interdit par atomic acquisition contract | `pre.005` | +| page limit 0/>500 | rejet | `pre.006` | +| cursor oversize | rejet | `pre.006` | +| SQL/backend cursor leak | absent | `pre.006` / `pre.007` | +| 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` | +| closed RAW enum | future family ajoutable | `pre.004` / `pre.007` | +| D2/D3/D4 creep | aucune surface | `pre.007` | + +## 9. Gates de fermeture prévus + +### Gate technique final `pre.008` + +Commandes de référence : + +```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 +cargo test -p ksp-store-api +cargo test -p ksp-logging-lib --test ownership +cargo test --workspace +cargo tree -p ksp-store-api --edges normal +cargo tree --duplicates +``` + +### Réconciliation documentaire `pre.009` + +Doit fermer : + +```text +crates/ksp-store-api/README.md +crates/ksp-store-api/USAGE.md +plan 022 +validation 018 +indexes/références durables concernées +``` + +Sans `CHANGELOG.md`, `ROADMAP.md` ni prompt suivant. + +### Préparation de publication `pre.010` + +Doit rester limitée à : + +```text +Cargo.toml +CHANGELOG.md +ROADMAP.md +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`. + +## 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 : + +```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 +``` + +## 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 |