Files
khadhroony-solana-project/crates/ksp-interface-lib/README.md
2026-08-31 13:07:56 +02:00

194 lines
6.6 KiB
Markdown

<!-- file: crates/ksp-interface-lib/README.md -->
<!-- version: 3 -->
# ksp-interface-lib
`ksp-interface-lib` possède les contrats passifs KSP qui doivent être partagés entre plusieurs composants sans imposer leur runtime d'origine. Sa surface couvre actuellement deux familles distinctes : les contrats wire Program génériques et un petit ensemble de faits d'acquisition provider-neutral dont la sémantique commune a été démontrée.
La crate reste une façade de représentation. Elle ne possède ni transport réseau, ni event bus, ni worker/job, ni persistence, ni exécution, ni comportement métier Program.
## Ownership
La crate réutilise les primitives fondamentales déjà possédées par `ksp-core-lib` :
```text
Pubkey
Error / ErrorCode / Result
Program IDs fondamentaux
```
`Pubkey` est réexporté depuis le crate-root Interface afin qu'un consumer n'introduise aucun wrapper d'identité parallèle. Les Program IDs restent possédés et répertoriés par Core.
Le graphe normal reste strictement :
```text
ksp-interface-lib
└── ksp-core-lib
└── solana-pubkey
```
La crate ne possède aucune feature Cargo, aucune `dev-dependency` et aucune `build-dependency` runtime propre.
## Surface publique
La façade crate-root expose :
```text
Pubkey
ProgramAccountMeta
MAX_PROGRAM_INSTRUCTION_ACCOUNTS
ProgramInstruction
MAX_PROGRAM_INSTRUCTION_DATA_LEN
ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED
SlotLifecycleStage
SlotLifecycleEvent
TransactionSignature
TransactionExecutionOutcome
TransactionExecutionEvent
```
Aucun module interne n'est public.
## Contrats Program passifs
### `ProgramAccountMeta`
`ProgramAccountMeta` représente un compte ordonné d'une instruction avec :
```text
pubkey
is_signer
is_writable
```
Les champs restent privés. Les constructeurs publics sont `readonly(pubkey, is_signer)` et `writable(pubkey, is_signer)`, complétés par les accessors `pubkey()`, `is_signer()` et `is_writable()`.
La structure n'applique aucune sémantique spécifique à un programme et n'exige pas que la `Pubkey` appartienne au registry des Program IDs Core.
### `ProgramInstruction`
`ProgramInstruction` représente un contrat passif borné :
```text
program_id
accounts: Vec<ProgramAccountMeta>
data: Vec<u8>
```
`ProgramInstruction::try_new` consomme directement les deux `Vec`, conserve l'ordre et les doublons des accounts et préserve les octets opaques de `data` sans décodage.
Les cas vides sont valides et une `program_id` inconnue du registry KSP reste admissible.
### Bornes d'admission
| Limite | Valeur |
|------------------------------------|----------|
| `MAX_PROGRAM_INSTRUCTION_ACCOUNTS` | `255` |
| `MAX_PROGRAM_INSTRUCTION_DATA_LEN` | `10_240` |
Ces valeurs sont des **bornes d'admission Interface**. Elles ne constituent pas une garantie qu'une instruction donnée respecte à elle seule toutes les contraintes d'une transaction Solana complète.
Un dépassement utilise le code commun :
```text
interface.program_instruction_limit_exceeded
```
Le contexte d'erreur est limité aux métadonnées sûres `field`, `actual_len` et `maximum_len`. Aucun payload arbitraire ni account meta hostile n'est recopié dans l'erreur.
Le `Debug` de `ProgramInstruction` est volontairement borné : il affiche `program_id`, `account_count` et `data_len`, jamais les accounts complets ni les octets du payload.
## Faits passifs d'acquisition
Les événements Interface sont des **projections provider-neutral supplémentaires**. Ils ne remplacent jamais les DTOs riches de `ksp-onchain-transport-lib` et ne deviennent jamais la source de vérité durable d'un backlog.
La conversion depuis un DTO HTTP/WS/gRPC/provider appartient à la composition ou au consumer qui connaît les deux contrats. `ksp-interface-lib` ne dépend donc pas de Transport.
### `SlotLifecycleEvent`
`SlotLifecycleEvent` conserve exactement :
```text
slot: u64
stage: SlotLifecycleStage
```
Les stages actuellement représentés sont :
```text
Processed
FirstShredReceived
Completed
CreatedBank
Dead
OptimisticallyConfirmed
Rooted
```
`SlotLifecycleStage` est `#[non_exhaustive]` afin qu'un consumer externe traite explicitement l'évolution future de l'enum.
Parent, timestamp, diagnostics de slot mort, source/provider, filter/session metadata et autres détails Transport ne sont pas copiés dans ce contrat minimal.
### `TransactionExecutionEvent`
`TransactionExecutionEvent` conserve exactement :
```text
slot: u64
signature: TransactionSignature
outcome: TransactionExecutionOutcome
```
`TransactionSignature` contient exactement les 64 bytes canoniques déjà décodés d'une signature Solana. Son `Debug` ne rend pas les bytes.
`TransactionExecutionOutcome` distingue uniquement :
```text
Succeeded
Failed
```
L'enum est `#[non_exhaustive]`. Le contrat ne contient aucun log, payload RAW, erreur provider, commitment, provenance, network id, source metadata ni détail d'exécution arbitraire. Une source ambiguë ou insuffisante doit rester dans son owner Transport au lieu de forcer un événement Interface.
## Codecs et runtime
La crate n'ajoute aucun codec ou runtime par réflexe :
```text
serde / serde_json absents
borsh absent tant qu'aucun wire réel ne le requiert
wincode absent tant qu'aucun wire réel ne le requiert
bincode interdit pour les codecs wire KSP
transport/runtime réseau absent
logging runtime absent
```
Des codecs/layouts/discriminants spécifiques peuvent être ajoutés uniquement lorsqu'un protocole réel en démontre le besoin et que leur ownership wire appartient bien à Interface.
Les événements passifs ne constituent pas un comportement runtime. La crate ne dépend donc pas de `ksp-logging-lib` et ne possède ni `constants.rs` ni `TRACING_TARGET`.
## Frontières
`ksp-interface-lib` ne possède pas :
```text
RPC / WebSocket / gRPC
provider DTOs Transport
sessions / reconnect / backpressure
Config / environnement
persistence / Store / cursor / retention
notifications post-commit Store
worker / job / scheduler / event bus
Program decoding / recognition / proofs
execution policy / signers
RawTransaction / RawAccountState
```
Les données persistantes/replayables restent dans `ksp-store-api`. Les notifications post-commit de données persistées restent un contrat Store API lorsqu'un publisher/consumer réel les justifie. Les faits réseau riches restent Transport-owned.
## Références
- [Usage public](USAGE.md)
- [Architecture Wire + Program](../../docs/architecture/006-WIRE_AND_PROGRAM.md)
- [Architecture Acquisition/Workers/Jobs](../../docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md)