Files
khadhroony-solana-project/docs/validation/018-V0_3_1_STORE_RAW.md
2026-08-29 07:51:09 +02:00

328 lines
18 KiB
Markdown

<!-- file: docs/validation/018-V0_3_1_STORE_RAW.md -->
<!-- version: 4 -->
# Validation `0.3.1` — Store API RAW foundation
## 1. Objet
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 certain est :
```text
RawTransaction + observation
provenance/références/outcomes/queries communs
contrats/capabilities backend externes
cycle de rétention logique + tombstone
```
`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 / 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-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
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 / 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 -> N2 STRUCTURAL
`0.3.1` doit préserver sans implémenter :
```text
RawTransaction
-> StructuralTransaction/message
-> account keys
-> top-level instructions
-> CPI/inner instructions
-> logs/meta/balances/return data
-> traitement individuel ultérieur
```
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
```
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
Le canari externe doit démontrer :
```text
crate/test backend externe
-> dépend de ksp-store-api
-> définit son propre backend mémoire
-> implémente les contrats/capabilities publics
-X-> ksp-store-lib
-X-> PostgreSQL
```
`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
| 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` |
### 8.1 Matérialisation `pre.003`
La tranche implémente et couvre localement par canaris source/audit :
```text
RawNetworkId
RawTransactionSignature [u8; 64]
RawTransactionReference
RawFormatId
RawContentHash [u8; 32]
RawObservationKey [u8; 32]
RawTimestamp
RawAcquisitionOrigin
RawProvenanceCode
RawAcquisitionProvenance
RawPayload
RawTransaction
RawTransactionObservation
```
Gates matérialisés :
```text
Core-only dependency firewall conservé
payload KSP source-independent, non vide, version > 0
payload maximum Store = 16 MiB
source payload metadata maximum = 64 MiB
Debug RawPayload ne rend jamais les bytes
signature/observation key/hash ne dépendent d'aucune PK backend
provenance sans URL/source payload
observed_at <= received_at
logs transactionnels restent dans le payload RawTransaction
aucun RawLog/N2 STRUCTURAL/backend/runtime ajouté
```
La complétude sémantique d'une source HTTP/WS/gRPC vers le format canonique n'est pas simulée dans Store API : elle reste le gate d'admission/conversion de `pre.004`. `pre.003` exige seulement qu'un `RawTransaction` reçoive un `RawPayload` déjà canonique complet selon son format KSP déclaré.
## 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` 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`
Aucun gate PostgreSQL live n'est demandé à `0.3.1`.
Le prochain prompt devra transformer les invariants API en façade commune + backend de référence et prévoir :
```text
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/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 |