32 KiB
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 :
Pubkeyest consommé via Core ; aucunProgramIdwrapper 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 ;
DebugdeProgramInstructiondoit résumerprogram_id,account_countetdata_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ériveDeserializenaïve affaiblirait le gate de taille avant allocation ; - aucun
borsh,bincodeouwincodegénérique : les codecs arrivent avec un vrai protocole Program dans Interface ; - pas de
format_versionartificiel 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 15–20 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 intégralement PASS.
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 : réalisé ; fmt/audits/check/Clippy/tests Interface PASS, cargo test --workspace non fourni dans la preuve opérateur.
Matérialiser la primitive de compte ordonné, la borne accounts, le modèle d'erreur Interface minimal et les unit/public canaries associés. ProgramInstruction et la borne data restent réservés à pre.004.
pre.004 — ProgramInstruction passif borné
Statut : réalisé ; gate opérateur à confirmer.
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.
17. État préparé pre.003
pre.003 matérialise uniquement la primitive de compte et les contrats nécessaires à la future admission de ProgramInstruction :
ProgramAccountMeta présent
fields privés
constructeurs readonly / writable
accessors pubkey / is_signer / is_writable
Pubkey Core réutilisé
MAX_PROGRAM_INSTRUCTION_ACCOUNTS 255
ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED interface.program_instruction_limit_exceeded
ProgramInstruction absent par contrat
MAX_PROGRAM_INSTRUCTION_DATA_LEN absent jusqu'à pre.004
serde / borsh / bincode / wincode absents
ksp-logging-lib / constants.rs / TRACING_TARGET absents
La constante 255 ferme le contrat public de borne accounts mais son enforcement 255/256 appartient au constructeur de ProgramInstruction de pre.004; ProgramAccountMeta représente un seul compte et n'invente donc pas une collection artificielle uniquement pour tester cette limite.
Une seule catégorie d'erreur Interface est introduite. invalid_program_instruction reste absent : aucun invariant de forme distinct des limites n'est encore matérialisé et le créer par symétrie serait prématuré. Les futures erreurs de borne doivent utiliser ksp_core_lib::Error/Result et ne projeter que des longueurs/plafonds sûrs.
La preuve opérateur fournie pour pre.003 confirme fmt, audits, cargo check, Clippy, tests ciblés Interface et graphes Cargo. cargo test --workspace n'apparaît pas dans cette preuve ; il doit donc être rejoué au gate de pre.004 avant de déclarer la continuité workspace complète.
18. État préparé pre.004
pre.004 matérialise le second et dernier type du premier lot wire générique retenu :
ProgramInstruction présent
fields privés
program_id Pubkey Core
accounts Vec<ProgramAccountMeta> consommé
data Vec<u8> opaque consommé
MAX_PROGRAM_INSTRUCTION_ACCOUNTS 255
MAX_PROGRAM_INSTRUCTION_DATA_LEN 10_240
try_new bornes accounts puis data
accounts 255 / 256 accepté / refusé
data 10_240 / 10_241 accepté / refusé
accounts/data vides acceptés
ordre/doublons préservés
Program Pubkey non registry accepté
Debug program_id/account_count/data_len uniquement
serde / borsh / bincode / wincode absents
solana-instruction absent
ksp-logging-lib / constants.rs / TRACING_TARGET absents
ProgramInstruction::try_new consomme les deux Vec fournis et compare leurs longueurs en usize avant stockage dans l'objet. La foundation n'ajoute aucun clone, cast étroit ou allocation de conversion. Une allocation éventuellement déjà réalisée par l'appelant pour construire le Vec reste naturellement hors du contrôle de l'API.
Les deux limites utilisent le code commun interface.program_instruction_limit_exceeded. Le contexte d'erreur est volontairement réduit à field, actual_len et maximum_len; aucune donnée du payload ni aucun account arbitraire n'est recopié dans le diagnostic.
Le Debug manuel n'imprime ni la collection accounts ni les octets data. Il expose uniquement l'identité publique du programme et les deux longueurs structurelles utiles au diagnostic.
Le passage à pre.005 doit désormais se concentrer sur les canaris adversariaux/consumer externe/API/dependency hardening, sans ajouter un second domaine wire.