v0.3.1-pre.001-fix-002

This commit is contained in:
2026-08-29 07:28:45 +02:00
parent 1a07574bae
commit 62ed72f2b5
4 changed files with 798 additions and 348 deletions

View File

@@ -1,83 +1,82 @@
<!-- file: docs/validation/018-V0_3_1_STORE_RAW.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# Validation `0.3.1` — Store API RAW foundation
## 1. Objet
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`.
Cette matrice est ouverte par `0.3.1-pre.001`, corrigée par `pre.001-fix.001` puis recalibrée par `pre.001-fix.002`. 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 :
Le scope concret N1 certain est :
```text
RawTransaction + observation
RawLog + observation
provenance/références/outcomes/queries communs
contrats/capabilities backend externes
cycle de rétention logique + tombstone
```
Les autres familles RAW restent extensibles et reportées jusqu'à audit réel de leur besoin.
`RawAccountState`/observation et `TransactionStatusObservation` doivent être audités cross-source et prévus dans l'API lorsque leur sémantique commune est prouvée. Les notifications de logs/slot/vote sont classées séparément comme candidats event-only, avec ownership Interface préféré lorsqu'elles ne sont pas persistées.
## 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 | 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-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 |
| sizing | PASS | dix prereleases courtes + lanes fermeture séparées |
| Critère | Statut | Preuve / décision |
|----------------------------------|---------|-----------------------------------------------------------------------------------|
| base stable `0.2.14` | PASS | Cargo `0.2.14`, `rel.001` et prompt 020 présents |
| baseline opérateur | PASS | audits/check/Clippy fournis verts ; validation tests déclarée OK |
| archive kbot3 + kbot2 historique | PASS | kbot3 extraite ; `olddocs/archivekbot2` audité pour lifecycle/replay |
| règles Store/API relues | PASS | règles KSP/Dependencies/Workflow prescrites relues |
| split version | PASS | `0.3.1 = Store API`, `0.3.2 = Store lib + PostgreSQL lib` |
| dependency graph `0.3.1` | PASS | cible Core-only |
| modèle backend commun | PASS | API object/struct commune, rows backend privées |
| admission multi-source | PASS | même modèle seulement si HTTP/WS/gRPC satisfont intégralement la même sémantique |
| `RawTransaction` | PASS | premier modèle persistant certain |
| logs dans transaction | PASS | restent dans `RawTransaction`, extraction seulement en N2 STRUCTURAL |
| logsSubscribe | REPORTÉ | event-only candidat ; pas de `RawLog` Store persistant par défaut |
| account state | PRÉVU | modèle/observation à figer après matrice de compatibilité |
| transaction status | PRÉVU | observation/event à figer si sémantique commune prouvée |
| slot/vote | TODO | event-only candidats ; ownership Interface à auditer |
| RawBlock | IDEA | non persisté par défaut ; `getBlock` sert de conteneur d'acquisition |
| Yellowstone Entry | REJETÉ | aucun replay/decomposition/event métier justifiant un modèle Store |
| frontière Interface/Store | PASS | persistent/replay -> Store API ; event-only partagé -> Interface préférentiel |
| N2 nomenclature | PASS | `CORE` remplacé par nom de travail `STRUCTURAL` |
| pipeline non linéaire | PASS | toutes les familles N1 ne sont pas forcées N1->N2->N3->N4 |
| processing proof | PASS | futur ledger stage+processor/version+input hash ; `processed: bool` insuffisant |
| retention lifecycle | PASS | `Full/Compacted/Archived/Purged` redessiné backend-agnostic |
| tombstone anti-rebackfill | PASS | identité/hash/slot minimal conservé après purge ; backfill forcé distinct |
| notification ownership runtime | PASS | Store ne possède aucun event bus/scheduler/DB notify |
| schema/migrations PostgreSQL | REPORTÉ | responsabilité `ksp-store-postgres-lib` `0.3.2` |
| D2/N3/N4 persistence | ABSENT | hors `0.3.1` |
| threat model | PASS | source mismatch, purge prématurée, stale processing, backend/event leaks couverts |
| 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 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` |
| `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` |
| Contrat | Décision `pre.001-fix.002` | 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` |
| `RawPayload` | KSP-owned, source-independent, versionné, borné, Debug sans bytes | `pre.003` |
| `RawTransaction` | objet persistant commun uniquement depuis une source complète | `pre.003` |
| `RawTransactionObservation` | acquisition/provenance séparée du RAW | `pre.003` |
| transaction `logMessages` | partie du RAW transactionnel | `pre.003` |
| logs structuraux | extraction N2 STRUCTURAL future, jamais `RawLog` N1 distinct | canari négatif `pre.003/007` |
| `RawAccountState`/observation | modèle prévu si HTTP/WS/gRPC convergent sans perte | `pre.004` |
| `TransactionStatusObservation` | modèle prévu si surfaces status convergent | `pre.004` |
| logs/slot/vote event-only | ne créent aucune capability Store par défaut | `pre.004/007` |
| Interface vs Store | event-only partagé -> Interface ; persistent/replay -> Store API | `pre.004/007` |
| model vs capability | un modèle API n'oblige pas tous les backends à le persister | `pre.005` |
| capabilities | read/write fines et object-safe | `pre.005` |
| transaction handle | aucun handle SQL/backend public | `pre.005` |
| atomic acquisition | méthode métier RAW + observation all-or-nothing | `pre.005/006` |
| write outcome | `Inserted / AlreadyPresent`; divergence = `Err Conflict` | `pre.006` |
| page/cursor | default 100, max 500, cursor opaque borné | `pre.006` |
| `RawRetentionState` | logique `Full/Compacted/Archived/Purged`, sans détail physique | `pre.006` |
| tombstone | identité/hash/slot minimal durable après purge | `pre.006` |
| backfill normal après purge | skip distinct | `pre.006` |
| force rehydrate | chemin explicite distinct, jamais fallback automatique | `pre.006` |
| processing evidence | futur ledger version-aware, jamais un bool unique | boundary `pre.006/007` |
| façade runtime `Store` | reportée à `ksp-store-lib`, hors `0.3.1` | `0.3.2` |
## 4. Dependency firewall final attendu
@@ -115,22 +114,25 @@ 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 |
| Famille / fait | Classification actuelle | Persistence Store | N2 attendu | Action `0.3.1` |
|--------------------------------|--------------------------|-------------------|----------------|--------------------------------------------------------------------|
| transaction complète | N1 RAW | oui | STRUCTURAL oui | implémenter modèle + observation |
| logs contenus dans transaction | partie de RawTransaction | via transaction | STRUCTURAL oui | préserver lossless, ne pas dupliquer en `RawLog` |
| account state complet | N1 RAW candidat | futur oui | à déterminer | audit HTTP/WS/gRPC puis prévoir modèle/observation |
| transaction status | observation candidat | optionnelle | non | audit signature/status sources |
| `logsSubscribe` notification | event-only candidat | non par défaut | non | ownership Interface/worker à figer |
| slot/root/slotsUpdates | event-only candidat | non | non | TODO use-case + compatibilité |
| vote | event-only candidat | non | non | TODO seulement si forme commune utile |
| block complet | acquisition container | non par défaut | — | IDEA uniquement ; extraire transactions plutôt que stocker le bloc |
| Yellowstone Entry | transport-only | non | — | explicitement non retenu |
## 6. Frontière N1 -> D2
## 6. Frontière N1 -> N2 STRUCTURAL
`0.3.1` doit préserver sans implémenter :
```text
RawTransaction
-> generic Solana normalization
-> transaction/message
-> StructuralTransaction/message
-> account keys
-> top-level instructions
-> CPI/inner instructions
@@ -138,13 +140,17 @@ RawTransaction
-> traitement individuel ultérieur
```
Canari négatif durable :
N2 est nommé **STRUCTURAL** parce qu'il décrit une décomposition générique Solana, pas un domaine métier « Core ».
Canaris :
```text
ksp-store-api -X-> ksp-program-api
RawTransaction logMessages -X-> entité RawLog persistante séparée
une erreur/absence future de decoder -X-> blocage des autres instructions
```
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.
Toutes les familles N1 ne sont pas obligées de posséder un N2. `RawAccountState` peut par exemple aller directement vers une future étape de decode si aucune décomposition structurelle utile n'est identifiée.
## 7. Extensibilité backend
@@ -163,24 +169,26 @@ crate/test backend externe
## 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 | 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` |
| Gate | Attendu | Statut initial |
|----------------------------------|-------------------------------------------------|----------------|
| oversized RAW payload | rejet avant allocation pathologique | `pre.003` |
| payload Debug | aucun bytes brut | `pre.003` |
| partial source -> RawTransaction | interdit ; contrat complet exigé | `pre.003/004` |
| HTTP/WS/gRPC semantic mismatch | détecté par admission matrix | `pre.004` |
| duplicate same content | `AlreadyPresent` | `pre.006` |
| duplicate divergent content | Conflict stable | `pre.006` |
| partial transaction+observation | interdit par atomic acquisition | `pre.005` |
| event-only -> Store capability | absent par défaut | `pre.004/007` |
| Interface/Store duplicate model | absent | `pre.007` |
| page limit 0/>500 | rejet | `pre.006` |
| SQL/backend cursor leak | absent | `pre.006/007` |
| external backend | implémente API sans Store lib | `pre.005` |
| processing `bool` comme vérité | absent ; future preuve version-aware documentée | `pre.006/007` |
| purge sans policy/evidence | impossible par contrat | `pre.006/007` |
| tombstone supprimé avec payload | interdit | `pre.006` |
| rebackfill normal après purge | skip | `pre.006` |
| force rehydrate implicite | interdit | `pre.006` |
| N2/N3/N4 creep | aucune surface | `pre.007` |
## 9. Gates de fermeture prévus
@@ -227,7 +235,7 @@ prompts/021-V0_3_2_START_PROMPT.md
delta pre.010
```
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`.
Le `ROADMAP.md` est réconcilié par `pre.001-fix.001` puis `pre.001-fix.002`; `pre.010` ne doit plus avoir à réparer la taxonomie N1/N2 ni le split backend.
## 10. PostgreSQL reporté à `0.3.2`
@@ -267,16 +275,16 @@ sécurité
## 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 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 |
| Tranche | Objet | État |
|-----------|------------------------------------------|-----------------------|
| `pre.001` | audit/design/taxonomie/split | PRÊT après gate local |
| `pre.002` | scaffold + taxonomie Store API | À FAIRE |
| `pre.003` | primitives + RawTransaction | À FAIRE |
| `pre.004` | admission matrix + account/status models | À FAIRE |
| `pre.005` | backend contracts/capabilities | À FAIRE |
| `pre.006` | queries/outcomes/retention/tombstone | À FAIRE |
| `pre.007` | boundary/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 |