Files
khadhroony-solana-project/docs/plans/020-V0_2_13_INTERFACE_PLAN.md
2026-08-28 04:31:32 +02:00

28 KiB
Raw Blame History

Plan 0.2.13 — Interface / wire foundation

1. Base, autorité et nature de pre.001

La release est ouverte exclusivement depuis l'archive opérateur khadhroony-solana-project-v0.2.12.zip, annoncée comme issue du tag stable v0.2.12. L'archive fournie ne contient pas de metadata .git; git describe n'est donc pas vérifiable dans le sandbox. Les marqueurs internes sont cohérents :

workspace.package.version = 0.2.12
prompts/018-V0_2_13_START_PROMPT.md présent
deltas/0.2.12/rel.001.md présent
crates/ksp-interface-lib absent
crates/ksp-program-api absent

Le log opérateur joint à la reprise établit sur la base stable :

cargo fmt --all                                      PASS
python3 scripts/audit_rust_workspace_rules.py        PASS
python3 scripts/audit_markdown_tables.py ...         PASS
cargo check --workspace                              PASS
cargo clippy --workspace --all-targets               PASS
cargo test --workspace                               PASS

Dans le sandbox de préparation, cargo n'est pas installé. Les audits Python de la base ont été rejoués et sont propres ; aucune commande Cargo non exécutée localement n'est déclarée PASS.

0.2.13-pre.001 reste un gate de lecture/audit/sizing. Il ne crée pas encore ksp-interface-lib et ne porte aucun code de l'ancien dépôt.

2. Décision de scope

Le minimum retenu pour 0.2.13 est une foundation Program-facing passive :

ProgramAccountMeta
ProgramInstruction
bornes locales explicites sur account metas et data
façade crate-root explicite
Error/Result communs via ksp-core-lib
aucun serde/codec générique ajouté sans protocole réel
aucun comportement Program

Cette surface correspond à la forme fondamentale d'une invocation Solana : identité du programme, comptes ordonnés avec flags signer/writable, puis octets opaques. Elle prépare directement la future construction d'instructions de ksp-program-api sans absorber le modèle d'acquisition/replay qui appartient à 0.3.2+.

Le scope est volontairement réduit par rapport au forecast initial : 0.2.13 ne crée ni modèle canonique de transaction, ni replay input, ni logs/return-data génériques, ni CPI path, ni discriminant spécifique d'un programme tant qu'aucun vertical slice officiel ne le justifie.

3. Règles et architecture confrontées à la base réelle

Sources internes relues avant décision :

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
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
ROADMAP.md

Les contraintes structurantes sont confirmées :

Core possède Pubkey, Error/Result et les Program IDs fondamentaux
Interface possède/reexporte de manière contrôlée les contrats wire officiels
Program API pourra dépendre de Core + Interface, jamais l'inverse
Transport reste propriétaire des DTOs RPC/WS/gRPC et ne dépend pas d'Interface
RAW/CORE n'exige aucun decoder Program
0.3.2 étendra Interface pour les wires génériques d'acquisition/CORE
pas de pub mod ; exports explicites depuis crate root
pas de dépendance externe sans usage réel

4. Inventaire interne stable pertinent

4.1 Core

Surface stable Owner actuel Visibilité/consumer Décision 0.2.13
Pubkey ksp-core-lib public crate-root; consommé dans le workspace réutiliser directement; aucun wrapper Interface
Error / ErrorCode / Result ksp-core-lib public crate-root; contrat commun réutiliser pour les erreurs de bornes Interface
18 Program IDs + registry/filter ksp-core-lib public crate-root laisser Core; Interface ne duplique pas les identités fondamentales

Les anciens wrappers textuels MdProgramId / MdPubkey de kbot3 n'apportent donc aucune valeur à la frontière KSP actuelle : un Pubkey typé existe déjà et doit rester l'identité fondamentale.

4.2 Transport

Type/famille observée Owner actuel Sémantique réelle Décision
SolanaEncodedTransaction On-chain Transport HTTP projection JSON-RPC encodée laisser Transport
SolanaConfirmedTransaction / SolanaBlockTransaction On-chain Transport HTTP réponse RPC avec états wire/metadata provider laisser Transport
SolanaWireField<T> On-chain Transport HTTP distinction omitted/null/value propre aux réponses RPC laisser Transport
YellowstoneCompiledInstruction On-chain Transport gRPC projection protobuf Yellowstone laisser Transport
YellowstoneInnerInstructions / YellowstoneReturnData On-chain Transport gRPC metadata d'update Geyser laisser Transport
YellowstoneTransactionError / ...Meta On-chain Transport gRPC sémantique provider/protobuf laisser Transport

Ces DTOs peuvent ressembler à de futurs objets génériques, mais ils représentent aujourd'hui des formes de transport concrètes. 0.2.13 ne les déplace pas et ne force aucune dépendance Transport -> Interface.

4.3 Dépendances workspace

La base possède déjà notamment :

solana-pubkey = ^4.3, default-features = false
serde = ^1.0
serde_json = ^1.0

Aucun solana-instruction, borsh, wincode ou crate d'interface Program n'est actuellement nécessaire au nouveau lot. Le graphe cible initial reste donc Interface -> Core uniquement.

5. Audit d'héritage khadhroony-bot3

Archive auditée : khadhroony-bot3_v0.5.3-pre.005-fix010.zip.

Familles inspectées :

ks-lib/src/model/solana.rs
ks-lib/src/model/canonical_transaction.rs
ks-lib/src/model/replay.rs
ks-lib/src/decoder/api/contracts.rs
ks-lib/src/executor/api/execution.rs
familles decoder/* wire pertinentes comme points de comparaison uniquement

La matrice suivante porte sur les concepts, pas sur un portage de code :

Concept kbot3 Verdict Cible KSP Raison
account { pubkey, is_signer, is_writable } ordonné REPRENDRE Interface 0.2.13 forme passive fondamentale d'une instruction; retirer le naming execution
instruction { program_id, accounts, data } REPRENDRE Interface 0.2.13 forme officielle minimale; retirer operation_code et toute policy
MdPubkey / MdProgramId en String REDESSINER Core remplacer par ksp_core_lib::Pubkey déjà possédé par Core
payload Vec<u8> non borné REDESSINER Interface 0.2.13 ajouter admission bornée et Debug résumé
DcApiInstructionDecoder + recognition/outcomes/proofs REPORTER Program API 0.2.14 comportement de reconnaissance/decode, interdit dans Interface
MdInstructionPath / parent / stack height REPORTER Interface/CORE 0.3.2+ contexte d'acquisition/replay, pas nécessaire au builder Program minimal
logs / return data / tx failure / balance changes génériques REPORTER Interface/CORE 0.3.2+ faits d'exécution/acquisition; ne pas préfigurer CORE
MdCanonicalTransaction + canonical JSON/hash REPORTER CORE series après 0.3.2 modèle source-neutral large à redéfinir avec Store/CORE réels
MdCoreInstructionReplayInput REPORTER CORE/replay après RAW contrat transversal trop large, dépend de données encore non possédées
Prepared plan, signers, fee payer, policies REPORTER Program API/Execution ultérieurs responsabilité d'orchestration/exécution, pas wire passif
monolithe ks-lib + générations d'API coexistantes REJETER aucune ownership flou et couplage vertical/horizontal à ne pas reproduire
version/hash/JSON génériques par réflexe REJETER aucune dans 0.2.13 aucun contrat sérialisé ne justifie une enveloppe/version générique maintenant

Anti-patterns à ne pas reproduire :

wrappers Pubkey/ProgramId textuels alors qu'une primitive typée existe
serde dérivé sur tous les contrats sans frontière de sérialisation réelle
JSON Value comme échappatoire pour des formes structurelles futures
contrat replay géant utilisé comme point de rencontre de toutes les couches
operation_code/policy/signers mêlés à l'instruction passive
traits decoder dans la même crate que les wires

6. Audit externe actuel — 27 août 2026

L'audit externe est limité aux candidates réellement proches du lot retenu.

Candidate Version actuelle observée Contrat / graphe Décision
solana-instruction 3.5.0 Instruction { program_id: Pubkey, accounts: Vec<AccountMeta>, data: Vec<u8> }; solana-pubkey ^4.3.0; codecs optionnels référence normative; pas de dépendance runtime 0.2.13
solana-program syscalls 4.1.0 MAX_CPI_INSTRUCTION_ACCOUNTS = 255; data 10 KiB; account infos uniques 128 source normative des plafonds d'admission initiaux; pas de dépendance
solana-loader-v3-interface 8.1.1 interface officielle; dépend solana-instruction ^3.5.0 + solana-pubkey ^4.3.0; wincode optionnel compatible en apparence mais hors premier lot; réauditer au vertical loader-v3

Sources primaires/current utilisées :

https://docs.rs/solana-instruction/3.5.0/solana_instruction/struct.Instruction.html
https://docs.rs/solana-program/4.1.0/solana_program/syscalls/index.html
https://docs.rs/solana-loader-v3-interface/8.1.1/solana_loader_v3_interface/
https://github.com/anza-xyz/solana-sdk

solana-instruction 3.5.0 est Apache-2.0 via le workspace Anza. Ses features serde, borsh, bincode et wincode sont optionnelles. La génération solana-pubkey ^4.3.0 est cohérente avec la base KSP.

La dépendance directe n'est néanmoins pas retenue maintenant : ses champs Vec publics ne permettent pas à KSP de garantir les bornes d'admission sur sa propre API, et aucun interop runtime ne requiert encore de convertir vers ce type. DEP-KSP-005 impose de ne pas ajouter une dépendance seulement pour refléter une forme triviale que KSP doit de toute façon borner.

7. Matrice de frontières

Concept/type Owner cible 0.2.13 ? 0.2.14 ? 0.3.2+ ? Autorité / raison
Pubkey Core reuse reuse reuse primitive fondamentale KSP déjà stable
Program IDs fondamentaux Core reuse reuse reuse registry Core déjà stable
account meta d'instruction Interface OUI consume reuse forme Solana officielle passive
instruction Program passive Interface OUI consume reuse minimum nécessaire au futur preparer
codec/discriminant Program spécifique Interface NON si vertical réel selon besoin aucun protocole concret dans foundation
instruction path / CPI ancestry Interface/CORE NON NON requis OUI fait structurel d'acquisition/normalisation
logs / return data / tx failure / balance deltas génériques Interface/CORE NON NON requis OUI surface RAW/CORE future
DTOs RPC/WS/Yellowstone existants Transport laisser laisser adapter plus tard projection transport concrète
decoder identity/recognition/decode Program API NON OUI audit consume CORE plus tard comportement extensible Program
implémentations officielles de programmes Program Lib NON NON plus tard vertical slices distincts
RAW persistence Store NON NON 0.3.1 architecture RAW
transaction/replay canonique générique CORE NON NON après 0.3.2 doit être défini avec acquisition/Store réels

8. Surface API proposée

Les noms restent ajustables jusqu'à implémentation, mais le contrat conceptuel est fermé :

pub use ksp_core_lib::Pubkey;

pub const MAX_PROGRAM_INSTRUCTION_ACCOUNTS: usize = 255;
pub const MAX_PROGRAM_INSTRUCTION_DATA_LEN: usize = 10 * 1024;

pub struct ProgramAccountMeta { /* private */ }
pub struct ProgramInstruction { /* private */ }

Façade visée :

ProgramAccountMeta::writable(pubkey, is_signer)
ProgramAccountMeta::readonly(pubkey, is_signer)
ProgramAccountMeta::{pubkey,is_signer,is_writable}

ProgramInstruction::try_new(program_id, accounts, data) -> ksp_core_lib::Result<Self>
ProgramInstruction::{program_id,accounts,data}

Décisions de contrat :

  • Pubkey est consommé via Core ; aucun ProgramId wrapper supplémentaire ;
  • les comptes gardent exactement leur ordre et les doublons restent permis ;
  • comptes vides et data vide restent valides ;
  • aucune validation sémantique de Program ID, signer ou writable au-delà de la forme passive ;
  • les champs restent privés afin d'empêcher la construction d'un état hors bornes ;
  • la construction valide les longueurs sans cloner les vecteurs fournis ;
  • Debug de ProgramInstruction doit résumer program_id, account_count et data_len, sans imprimer tout le payload ;
  • pas de serde::{Serialize, Deserialize} dans la foundation : aucune persistence/IPC/wire sérialisée générique ne l'exige, et une dérive Deserialize naïve affaiblirait le gate de taille avant allocation ;
  • aucun borsh, bincode ou wincode générique : les codecs arrivent avec un vrai protocole Program dans Interface ;
  • pas de format_version artificiel tant qu'aucun format sérialisé KSP n'est défini.

8.1 Bornes

Les bornes initiales suivent les plafonds runtime Solana actuels :

account metas d'une instruction <= 255
data d'une instruction          <= 10_240 octets

Elles sont des bornes d'admission Interface, pas la promesse qu'une instruction seule rentrera dans toute transaction top-level. Les contraintes de message/transaction, comptes uniques, fee payer, blockhash et assembly appartiennent aux couches d'exécution ultérieures.

8.2 Erreurs

Le crate n'introduit pas un second type d'erreur. Les violations de borne utilisent ksp_core_lib::Error/Result avec codes Interface stables et contexte sûr limité aux longueurs/plafonds. Aucun octet du payload, compte arbitraire ou valeur externe n'est copié dans les diagnostics.

Les codes exacts seront matérialisés avec la première primitive ; deux catégories suffisent conceptuellement :

invalid_program_instruction
program_instruction_limit_exceeded

Si la première implémentation démontre qu'une seule catégorie bornée suffit, ne pas créer la seconde par symétrie.

9. Threat / robustness model

Risque Décision Canari prévu
data surdimensionnée refus avant stockage/copie supplémentaire 10_240 accepté; 10_241 refusé
collection accounts surdimensionnée refus déterministe 255 accepté; 256 refusé
conversion/index overflow aucun cast étroit en foundation; comparer en usize borne 255 + absence de casts unchecked
ordre/doublons accounts préserver exactement; ne pas dédupliquer ordre et doublon round-trip structurel via accessors
wire malformé N/A : aucun decoder/codec dans le lot aucun faux test; réouvrir au premier codec réel
enum/discriminant inconnu N/A : aucun discriminant dans le lot réouvrir au vertical Program
structures imbriquées pathologiques N/A au-delà des deux Vec plates bornes accounts/data suffisent pour ce lot
Debug volumineux Debug résumé payload sentinelle absent du rendu Debug
allocation/copie excessive try_new consomme les Vec; pas de clone interne canari structure/API + revue source
serde hostile serde absent dependency/public API canary
panic/unwrap/expect/? interdits par règles/lints audit Rust + Clippy workspace
Program ID inconnu accepté : Pubkey opaque typé canari avec Pubkey non registry

10. Dependency graph cible et firewall

Cible de 0.2.13 :

ksp-interface-lib
    -> ksp-core-lib
        -> solana-pubkey ^4.3

Interdictions :

ksp-interface-lib -X-> ksp-program-api
ksp-interface-lib -X-> ksp-program-lib
ksp-interface-lib -X-> ksp-onchain-transport-lib
ksp-interface-lib -X-> ksp-offchain-transport-lib
ksp-interface-lib -X-> ksp-config-lib
ksp-interface-lib -X-> ksp-store-*
ksp-interface-lib -X-> ksp-wallet-lib
ksp-interface-lib -X-> Tauri
ksp-interface-lib -X-> reqwest/tonic/tokio/network

Aucun logging runtime n'est attendu dans une crate de contrats passifs. ksp-logging-lib reste absent sauf comportement futur démontré.

Validation Cargo prévue dès le scaffold :

cargo tree -p ksp-interface-lib --edges normal
cargo tree --duplicates

Comme aucune nouvelle dépendance externe n'est retenue au gate, aucun doublon codec/Solana ne doit être créé par pre.002.

11. Stratégie de tests

Tests unitaires privés

Sous unit_tests/ rattachés aux modules privés :

constructeurs account meta writable/readonly
bornes comptes 255/256
bornes data 10_240/10_241
empty accounts/data acceptés
ordre et doublons préservés
Pubkey inconnu accepté
Debug borné et payload absent
erreurs sans bytes ni valeur hostile

Tests d'intégration tests/

public_api.rs             consommation uniquement via crate-root
external_consumer.rs      petit consumer/crate canary si le pattern workspace le permet
dependency_boundary.rs    manifest/source firewall et absence de serde/codecs/network
release_completeness.rs   inventaire exact de la surface 0.2.13 retenue

Aucun smoke réseau n'est requis. Aucun round-trip binaire/JSON n'est inventé sans codec réel.

12. Hors scope explicite

ksp-program-api et tout trait decoder/preparer
ksp-program-lib
codec Program spécifique sans vertical réel
system/token/loader/metaplex instruction families
PDA seeds sans protocole concret
transaction/message/compiled instruction génériques d'acquisition
replay input / instruction path / CPI tree
logs / return data / transaction errors / balances génériques
Store/persistence
Transport refactor ou dépendance vers Interface
Wallet/Tauri/Config
serde/JSON canonical/hash
execution policy, signer selection, blockhash, simulation, send

13. Prévision souple recalibrée

Le scope réduit permet de supprimer le second lot wire optionnel du forecast initial et de garder des tranches compatibles avec le budget KSP de 1520 minutes de travail effectif.

pre.001 — audit + héritage + frontières + sizing

Statut : réalisé ; gate opérateur pre.001 intégralement PASS.

Relire les règles/architectures, auditer Core/Transport, classer kbot3, auditer les candidates externes, retenir la surface instruction passive, fixer bornes/firewall/threat model/tests et créer plan/validation.

pre.002 — scaffold ksp-interface-lib + façade + firewall

Statut : réalisé ; gate opérateur à confirmer.

Créer la crate, l'ajouter au workspace, poser lib.rs avec exports explicites, lints, README/USAGE initiaux et canaris manifest/firewall. Dépendance normale unique : ksp-core-lib.

pre.003 — ProgramAccountMeta + bornes communes

Statut : prévu

Matérialiser la primitive de compte ordonné, les constantes de borne, le modèle d'erreur Interface minimal et les unit/public canaries associés. Ne pas avancer ProgramInstruction si la tranche dépasse le budget.

pre.004 — ProgramInstruction passif borné

Statut : prévu

Ajouter l'instruction { program_id, accounts, data }, constructeur validé, accessors, Debug résumé et canaris d'ordre/doublons/limites. Aucun serde/codec ou comportement Program.

pre.005 — adversarial + consumer externe + API/dependency hardening

Statut : prévu

Fermer les cas limites, surface crate-root, consumer externe, firewall source/manifest et graphes Cargo. Ne pas ajouter un second domaine wire opportuniste.

pre.006 — gate technique final

Statut : prévu

Exécuter workspace complet, canaris de complétude/public API/dependencies, cargo tree et audit final du scope exact. Aucun README/USAGE final ni préparation de publication.

pre.007 — réconciliation documentaire finale

Statut : prévu

Finaliser README/USAGE de la crate, plan, validation et références durables réellement affectées. Ne pas modifier CHANGELOG.md, ROADMAP.md ni le prompt suivant.

pre.008 — préparation de publication minimale

Statut : prévu

Préparer uniquement prompts/019-V0_2_14_START_PROMPT.md, CHANGELOG.md, ROADMAP.md, le bump prerelease mécanique et le delta. Aucun code/test/README/USAGE/plan/validation/architecture ne doit être rouvert.

rel.001 — publication stable

Statut : prévu

Passer workspace.package.version à 0.2.13, rejouer le gate stable requis, publier le commit v0.2.13-rel.001 puis le tag stable v0.2.13.

14. Sizing et critère session

Tranche Charge relative Motif du découpage
pre.002 petite scaffold + firewall uniquement
pre.003 petite une primitive + bornes/erreurs
pre.004 petite à moyenne instruction + hardening local
pre.005 moyenne consumer + adversarial + graphes
pre.006 gate aucun développement fonctionnel
pre.007 documentation réconciliation séparée
pre.008 publication prep payload minimal séparé

Le scope paraît clôturable dans une release/session sans sacrifier les lanes de sortie. Si pre.003 ou pre.004 révèle qu'une dépendance/codec spécifique est indispensable, le gate doit être rouvert avant d'étendre le scope ; il ne faut pas réactiver automatiquement pre.005 comme second lot wire.

15. Gate 0.2.13-pre.001

À la sortie préparée :

base stable / prompt / rel                                 confirmé
règles et architecture obligatoires                        relues
Core / Transport                                            inventoriés
archive kbot3                                               auditée
matrice REPRENDRE/REDESSINER/REPORTER/REJETER              produite
0.2.13 / 0.2.14 / 0.3.2                                    séparés
premier lot                                                 ProgramAccountMeta + ProgramInstruction
nouvelle dépendance externe                                 aucune
threat model / tests / dependency graph                     définis
plan + validation                                           créés
implementation Program                                      absente

16. Gate attendu pour pre.003

pre.002 matérialise le scaffold strict décidé par le gate précédent :

nouvelle crate membre ksp-interface-lib
Cargo dépend uniquement de ksp-core-lib
lints workspace hérités
crate root explicite sans pub mod
Pubkey réexporté depuis Core
README/USAGE initiaux
canari public API minimal
canari dependency firewall
aucun ProgramAccountMeta/ProgramInstruction fonctionnel
aucun ksp-logging-lib / constants.rs / TRACING_TARGET

pre.003 peut commencer après application du delta et gate opérateur vert. Sa responsabilité reste limitée à ProgramAccountMeta, aux bornes communes et au modèle d'erreur Interface minimal ; ProgramInstruction reste réservé à pre.004.