Files
khadhroony-solana-project/docs/validation/018-V0_3_1_STORE_RAW.md
2026-08-29 11:39:50 +02:00

28 KiB
Raw Blame History

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 seront développées de pair sur trois slices : fondation 0.3.2, RawTransaction 0.3.3, puis RawAccountState + complétude 0.3.4.

Le scope concret N1 certain est :

RawTransaction + observation
RawAccountState + observation
provenance/références/outcomes/queries communs
contrats/capabilities backend externes
cycle de rétention logique + tombstone

pre.004 prouve la convergence de RawAccountState/observation entre HTTP/WS/gRPC sous admission stricte bytes complets + slot. TransactionStatusObservation reste différé : snapshot HTTP, transition WS et update Yellowstone ne sont pas encore un fait unique. Les notifications logs/slot/vote restent event-only candidates, 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..0.3.4 = Store lib + PostgreSQL lib par slices
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 PASS pre.004 matérialise modèle/observation sous bytes complets + slot
transaction status REPORTÉ HTTP snapshot, WS transition et Yellowstone update restent distincts
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É fondation 0.3.2, schémas RAW complétés en 0.3.3/0.3.4
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 admis si HTTP/WS/gRPC convergent sans perte, matérialisé en pre.004 pre.004
TransactionStatusObservation non matérialisé : surfaces status non équivalentes report explicite 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 limit caller > 0 ; sans max KSP ; cursor opaque <= 4 KiB 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 fondation 0.3.2

4. Dependency firewall final attendu

Le graphe final 0.3.1 doit rester :

ksp-store-api
└── ksp-core-lib
    └── solana-pubkey

Interdits par défaut dans Store API :

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 oui à terme pas démontré modèle + observation matérialisés en pre.004
transaction status familles distinctes non figée non différer : snapshot HTTP != transition WS != update Yellowstone
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 :

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 :

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 :

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 et la fondation ksp-store-postgres-lib. La conformance API du backend officiel sera matérialisée par famille : RawTransaction en 0.3.3, puis RawAccountState et la complétude cross-family en 0.3.4.

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 PASS
account bytes partiels/parsés refusés avant RawAccountState pre.004 PASS
account sans slot durable refusé comme état persistant pre.004 PASS
account data Debug aucun bytes brut pre.004 PASS
status surfaces artificiellement fusionnées aucun modèle commun prématuré pre.004 PASS
duplicate same content AlreadyPresent pre.006
duplicate divergent content Conflict stable pre.006
partial transaction+observation interdit par atomic acquisition pre.005 PASS
event-only -> Store capability absent par défaut pre.004/007
Interface/Store duplicate model absent pre.007
page limit 0 rejet ; aucun max KSP artificiel pre.006
SQL/backend cursor leak absent pre.006/007
external backend implémente API sans Store lib pre.005 PASS
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 :

RawNetworkId
RawTransactionSignature [u8; 64]
RawTransactionReference
RawFormatId
RawContentHash [u8; 32]
RawObservationKey [u8; 32]
RawTimestamp
RawAcquisitionOrigin
RawProvenanceCode
RawAcquisitionProvenance
RawPayload
RawTransaction
RawTransactionObservation

Gates matérialisés :

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é.

8.2 Matérialisation pre.004

La tranche ajoute :

MAX_RAW_ACCOUNT_DATA_BYTES
RawAccountStateReference
RawAccountState
RawAccountObservation

Invariants vérifiés par modèle/canaris :

référence = network + pubkey + slot + canonical state hash
account data complet <= 16 MiB
empty account data autorisé
Debug RawAccountState ne rend jamais les bytes
write_version/transaction_signature/is_startup restent observation-only optionnels
HTTP/WS/gRPC source details n'entrent pas dans RawAccountState
aucun TransactionStatusObservation artificiel
aucun RawLogNotification/RawSlotEvent/RawVoteEvent/RawBlock/YellowstoneEntry public

Matrice d'admission validée architecturalement :

getAccountInfo/getMultipleAccounts -> oui avec bytes complets
getProgramAccounts               -> contexte obligatoire
accountSubscribe                 -> oui avec bytes complets
programSubscribe                 -> contexte obligatoire
Yellowstone Account              -> aucun accounts_data_slice
jsonParsed/dataSlice/bare program -> non

La conversion source -> modèle reste hors ksp-store-api; la crate ne dépend toujours que de ksp-core-lib.

8.3 Matérialisation pre.005

La tranche ajoute uniquement des contracts de capability backend-agnostic :

StoreApiFuture<'a, T>

RawTransactionRead
RawTransactionWrite
RawTransactionObservationRead
RawTransactionObservationWrite

RawAccountStateRead
RawAccountStateWrite
RawAccountObservationRead
RawAccountObservationWrite

Gates matérialisés :

traits Send + Sync et dyn-compatible
aucune dépendance async-trait/tokio/futures-util ajoutée
backend externe implémentable avec std + ksp-store-api seulement
aucun trait StoreBackend monolithique
aucune façade runtime Store
aucun type Config/backend/SQL public
persist_raw_transaction_acquisition = transaction + observation atomiques
persist_raw_account_acquisition = account state + observation atomiques
record_*_observation = acquisition supplémentaire sans retransmettre le RAW
get_* = référence/observation key backend-independent
write success/failure seulement en pre.005
outcomes/idempotence/conflict détaillés réservés à pre.006

Le canari tests/external_backend.rs définit un backend mémoire externe qui implémente les huit traits sans dépendre de ksp-store-lib, PostgreSQL ou d'un runtime async. Il prouve également que chaque capability est utilisable derrière dyn Trait.

Aucune implémentation de persistence n'est fournie par ksp-store-api; les futures concrètes du canari ne servent qu'à vérifier le contrat d'extension.

8.4 Matérialisation pre.006

La tranche ajoute les contrats logiques suivants sans backend/runtime :

RawPageCursor / RawPageLimit / RawPageRequest / RawPage<T>
RawSlotRange / RawSortDirection
RawTransactionQuery / RawAccountStateQuery
RawEntityWriteOutcome / RawObservationWriteOutcome / RawAcquisitionWriteOutcome
RawRetentionState
RawTransactionAcquisitionMode
RawTransactionTombstone
RawTransactionRetentionTransition / RawRetentionWriteOutcome
RawTransactionRetentionRead / RawTransactionRetentionWrite

Gates matérialisés :

page limit 0 rejeté
u64::MAX admis comme demande représentable : aucun maximum métier KSP
cursor opaque borné à 4 KiB et Debug sans contenu
range de slots inversée rejetée
queries limitées aux critères de données, sans backlog/executor policy
Inserted / AlreadyPresent explicites
contenu divergent = ERROR_CODE_RAW_CONFLICT
RAW + observation gardent le contrat atomique
Full -> Compacted -> Archived -> Purged, avec Full -> Archived autorisé
aucun Full -> Purged direct
aucun Purged -> Full via transition générique
force rehydrate explicite via acquisition transactionnelle
tombstone minimal sans payload
retention policy choisie hors Store par worker/job/maintenance

8.5 Matérialisation pre.007

La tranche ferme le hardening de surface sans ajouter de nouvelle famille N1 :

security_hardening.rs
release_completeness.rs
RawRetentionWriteOutcome::ExpectedStateMismatch

Gates matérialisés :

erreurs model/query/provenance hostiles sans echo de valeur
Debug payload/hash/signature/account sans bytes sensibles
cursor exact 4 KiB accepté, dépassement rejeté
RawPageLimit u64::MAX reste représentable
compare-and-transition perdue distincte de Applied/AlreadyAtTarget
exports crate-root exacts
inventaire exact des modules production RAW
10 capabilities fines exactes, aucun StoreBackend/Store runtime
Interface ne réexporte pas les modèles persistants Store
Store API ne publie aucun event-only logs/slot/vote
aucune surface STRUCTURAL/DECODED/DOMAIN
aucune fuite PostgreSQL/MySQL/backend runtime

La course de rétention est un état normal de concurrence : si l'état durable ne correspond plus à expected et n'est pas déjà target, le backend doit retourner ExpectedStateMismatch. Cette sémantique évite d'utiliser une erreur de validation pour une course et impose une compare-and-transition atomique à l'implémentation future.

8.6 Gate technique pre.008

Le gate opérateur final a été exécuté après cargo clean, donc sans dépendre du cache incrémental précédent.

Résultat :

audits Rust/Markdown PASS
cargo check --workspace PASS
cargo clippy --workspace --all-targets PASS
tests ciblés Core/Logging/Config/Transport/Off-chain/Wallet/Interface/Store/Desks PASS
cargo test --workspace PASS
cargo tauri build SOL Prices Desk PASS
cargo tauri build Wallet Desk PASS
cargo tauri build Config Desk PASS
cargo tree -p ksp-store-api --edges normal inspecté
cargo tree --duplicates inspecté

Le seul incident de commande était le nom inexistant ksp-program-lib; il ne correspond à aucune crate publiée. Le test ciblé correct cargo test -p ksp-program-api a ensuite été exécuté séparément et passe : 3 unit, 2 dependency-boundary, 2 external-implementation, 4 public-api, 4 release-completeness et 3 security-hardening, plus doc-tests.

Le graphe normal Store API reste strictement ksp-store-api -> ksp-core-lib et aucune dépendance backend/runtime n'entre dans la crate.

8.7 Réconciliation pre.009

PASS opérateur ciblé. Après application de 0.3.1-pre.009, audits Rust/Markdown, cargo check --workspace, Clippy et cargo test -p ksp-store-api passent. Aucun re-gate Tauri/workspace complet n'était requis après le gate lourd propre de pre.008.

La surface finale réellement retenue pour 0.3.1 est :

RawTransaction / RawTransactionObservation
RawAccountState / RawAccountObservation
primitives de provenance/format/hash/timestamps
queries cursorisées sans plafond métier KSP arbitraire
outcomes idempotence/conflit
RawRetentionState + tombstone transactionnel
normal skip après purge + force rehydrate explicite
10 capabilities backend fines/object-safe

Sont explicitement reportés plutôt que simulés dans la foundation :

TransactionStatusObservation
logs/slot/vote event-only contracts
StoreHealth/readiness runtime
type canonique dédié de wake-up persisté-data
processing ledger / backlog métier / executor policy
compression/archive physique
backend PostgreSQL et std.store
N2 STRUCTURAL / N3 DECODED / N4 DOMAIN

README.md ne contient aucune surface Store détaillée devenue fausse et aucun document USAGE Store n'existe encore ; ils ne sont donc pas modifiés artificiellement par cette tranche.

9. Gates de fermeture

Gate technique final pre.008

PASS opérateur complet. Voir §8.6. Le gate a été reconstruit après cargo clean et couvre audits, workspace check/Clippy/tests, builds Tauri des trois Desk et graphes Cargo. Le test ciblé ksp-program-api a également été rejoué avec le bon nom de package.

Réconciliation documentaire pre.009

PASS opérateur ciblé. Voir §8.7. Le plan, la validation, les architectures Store réellement concernées et IDEAS.md sont réconciliés. Aucun README/USAGE Store n'existe à maintenir actuellement.

Redécoupage documentaire pre.010

La décision opérateur postérieure à pre.009 sépare l'ancien scope PostgreSQL unique en trois releases afin de préserver la qualité et la clôture par session, sans séparer ksp-store-lib de ksp-store-postgres-lib. Cette responsabilité documentaire doit être fermée avant la lane de publication.

Préparation de publication pre.011

La préparation de publication finale est décalée à pre.011 après le redécoupage documentaire pre.010. Elle doit rester limitée à :

Cargo.toml
CHANGELOG.md
ROADMAP.md
prompts/021-V0_3_2_START_PROMPT.md
delta pre.011

pre.011 ne doit plus réparer la taxonomie N1/N2 ni le découpage Store/PostgreSQL : ces décisions appartiennent aux tranches documentaires antérieures.

10. PostgreSQL reporté aux slices 0.3.20.3.4

Aucun gate PostgreSQL live n'est demandé à 0.3.1. Le développement de ksp-store-lib et ksp-store-postgres-lib reste conjoint, mais l'ancien scope unique 0.3.2 est redécoupé pour préserver la qualité et la clôture par session.

0.3.2 — fondation runtime/backend PostgreSQL

ksp-store-lib
  -> façade Store commune minimale
  -> réexports utiles de ksp-store-api
  -> feature postgres par défaut
  -> dispatch backend selon Config
  -> erreur backend connu mais non compilé
  -> health/readiness runtime si justifié par le gate pre.001

ksp-store-postgres-lib
  -> tokio-postgres
  -> connexion/pool/TLS audités
  -> bootstrap migrations KSP-owned
  -> transaction primitive privée si nécessaire à la suite

Config
  -> std.store
  -> URI/DSN backend lorsque naturel
  -> secrets ${KSP_SECRET_*} / .env owned par ksp-config-lib
  -> aucun vrai secret versionné

Aucune capability RawTransaction ou RawAccountState n'est implémentée artificiellement dans cette fondation uniquement pour gonfler le scope.

0.3.3 — vertical slice PostgreSQL RawTransaction

RawTransaction + observation
write/read/get/list cursorisé
atomic RAW + observation
idempotence / AlreadyPresent / conflict
retention / tombstone / force rehydrate
rollback et races réelles
conformance ksp-store-api

0.3.4 — vertical slice PostgreSQL RawAccountState + complétude

RawAccountState + observation
write/read/get/list cursorisé
idempotence / conflict / atomic observation
conformance cross-family
migration/index hardening
backend dispatch/health final
gate PostgreSQL réel final

Règles communes aux trois slices :

URI/DSN/credentials redacted
aucune lecture directe env/.env par Store ou backend
aucun plafond métier arbitraire de pagination imposé par Store
limitations physiques backend exposées sans devenir policy executor
PostgreSQL réel opt-in pendant développement puis gate final de la slice concernée

11. État des tranches

Tranche Objet État
pre.001 audit/design/taxonomie/split PASS
pre.002 scaffold + taxonomie Store API PASS
pre.003 primitives + RawTransaction PASS après fix.001
pre.004 admission matrix + account/status models PASS
pre.005 backend contracts/capabilities PASS
pre.006 queries/outcomes/retention/tombstone PASS après fix.001
pre.007 boundary/adversarial/completeness PASS après fix.001
pre.008 gate technique final PASS opérateur complet
pre.009 réconciliation documentaire PASS opérateur ciblé
pre.010 redécoupage documentaire futures slices PRÊT après audits documentaires
pre.011 préparation publication À FAIRE
rel.001 stable À FAIRE