71 KiB
Validation 0.2.9 — moteur Yellowstone + standard Solana + PublicNode
Statut :
pre.009-fix.001est fermé : fmt/audit/check/Clippy sans warning, Transport 379 unit + 48 public API + 42 completeness + 4 doctests, dependency canary et workspace PASS.pre.010est candidate reconnect/replay avec observabilité prudente des gaps/duplicates.
1. Autorités du gate
Base interne :
v0.2.8 / archive Gitea stable fournie
workspace.package.version initial = 0.2.8
deltas/0.2.8/rel.001.md
prompts/014-V0_2_9_START_PROMPT.md
Sources upstream auditées le 2026-08-23 :
https://github.com/rpcpool/yellowstone-grpc/releases
https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md
https://github.com/rpcpool/yellowstone-grpc/blob/master/LICENSING.md
https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto
https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/solana-storage.proto
https://docs.rs/crate/yellowstone-grpc-client/latest
https://docs.rs/crate/yellowstone-grpc-proto/latest
Divergence enregistrée :
snapshot du prompt : GitHub release v14.2.2+solana.4.1.0
réaudit courant : GitHub release v15.1.2+solana.4.2.0 (2026-08-18)
crate client : 13.3.0
crate proto : 12.6.0
2. Baseline stable
| Gate | Preuve | État |
|---|---|---|
cargo fmt --all |
log opérateur v0.2.8 |
DONE |
| audit Rust workspace | clean | DONE |
cargo check --workspace |
log opérateur | DONE |
cargo clippy --workspace --all-targets |
log opérateur | DONE |
cargo test --workspace |
log opérateur | DONE |
| Transport unit | 335 passed | DONE |
| Transport public API | 41 passed | DONE |
| Transport release completeness | 34 passed | DONE |
| Transport doctests | 4 passed | DONE |
cargo tree -p ksp-onchain-transport-lib |
log opérateur | DONE |
cargo tree --duplicates |
log opérateur | DONE |
3. Matrice service Geyser
| RPC | Forme | Classification | Scope | Preuve cible | État |
|---|---|---|---|---|---|
Subscribe |
bidi | standard | IN | fixture locale + live | CANDIDATE pre.009 runtime bidi |
SubscribeDeshred |
bidi | Triton extension/pré-exécution malgré présence proto | OUT | canari d'absence/API | OUT |
SubscribeReplayInfo |
unary | standard | IN | fixture unary | DONE pre.003 |
Ping |
unary | standard | IN | fixture unary | DONE pre.003 |
GetLatestBlockhash |
unary | standard | IN | fixture unary | DONE pre.003 |
GetBlockHeight |
unary | standard | IN | fixture unary | DONE pre.003 |
GetSlot |
unary | standard | IN | fixture unary | DONE pre.003 |
IsBlockhashValid |
unary | standard | IN | fixture unary | DONE pre.003 |
GetVersion |
unary | standard | IN | fixture unary | DONE pre.003 |
4. SubscribeRequest — coverage normative
4.1 Top-level
| Champ | Sémantique | Scope | Preuve |
|---|---|---|---|
accounts |
map filter-name -> account filter | IN | exact wire + bounds |
slots |
map -> slot filter | IN | exact wire |
transactions |
map -> transaction filter | IN | exact wire + bounds |
transactions_status |
map -> transaction filter | IN | exact wire + bounds |
blocks |
map -> block filter | IN | exact wire + bounds |
blocks_meta |
map -> empty filter | IN | presence/empty semantics |
entry |
map -> empty filter | IN | presence/empty semantics |
commitment |
optional Processed/Confirmed/Finalized | IN | omitted/value exact |
accounts_data_slice |
repeated offset/length | IN | order + bounds |
ping |
optional id | IN | Ping/Pong lifecycle |
from_slot |
optional u64 | IN | reconnect/replay tests |
4.2 Accounts
| Capacité | Scope | Preuve |
|---|---|---|
account[] |
IN | order/cardinality/address validation |
owner[] |
IN | order/cardinality/address validation |
filters[] |
IN | AND semantics preserved structurally |
nonempty_txn_signature? |
IN | omitted/false/true |
cuckoo_accounts_filter? |
IN | exact wire + dimension/data bounds |
| memcmp bytes | IN | exact bytes + bounds |
| memcmp base58 | IN | exact string + validation |
| memcmp base64 | IN | exact string + validation |
datasize |
IN | exact u64 |
token_account_state |
IN | bool |
lamports eq/ne/lt/gt |
IN | oneof exact |
4.3 Slots
| Capacité | Scope | Preuve |
|---|---|---|
filter_by_commitment? |
IN | optional semantics |
interslot_updates? |
IN | optional semantics |
| processed/confirmed/finalized | IN | enum decode |
| first_shred_received/completed/created_bank/dead | IN | enum decode + dead_error |
4.4 Transactions / transaction_status
| Capacité | Scope | Preuve |
|---|---|---|
vote? |
IN | optional semantics |
failed? |
IN | optional semantics |
signature? |
IN | exact/validated |
account_include[] |
IN | order/bounds |
account_exclude[] |
IN | order/bounds |
account_required[] |
IN | order/bounds |
cuckoo_account_include? |
IN | exact wire + bounds |
token_accounts? = ALL |
IN | optional enum |
token_accounts? = BALANCE_CHANGED |
IN | optional enum |
4.5 Blocks
| Capacité | Scope | Preuve |
|---|---|---|
account_include[] |
IN | order/bounds |
include_transactions? |
IN | optional semantics |
include_accounts? |
IN | optional semantics |
include_entries? |
IN | optional semantics |
cuckoo_account_include? |
IN | exact wire + bounds |
5. SubscribeUpdate — coverage normative
| Variante | Champs structurants | Scope | Preuve |
|---|---|---|---|
account |
account info, slot, is_startup | IN | exact decode |
slot |
slot, parent?, status, dead_error? | IN | exact decode |
transaction |
signature, vote, transaction, meta, index, slot | IN | exact decode |
transaction_status |
slot, signature, vote, index, err | IN | exact decode |
block |
hash/rewards/time/height/parents/counts + tx/accounts/entries | IN | exact decode + bounds |
ping |
marker | IN | lifecycle |
pong |
id | IN | lifecycle |
block_meta |
metadata/counts | IN | exact decode |
entry |
slot/index/hash/counts | IN | exact decode |
Top-level à préserver :
filters[]
created_at
oneof absent/inconnu -> comportement explicitement testé
6. solana-storage.proto — nested wire utile
Le backend doit préserver les champs nécessaires des structures imbriquées actuelles, sans exposer les types upstream comme contrat public :
ConfirmedBlock
ConfirmedTransaction
Transaction
Message
MessageHeader
MessageAddressTableLookup
TransactionConfig
TransactionStatusMeta
TransactionError
InnerInstructions / InnerInstruction
CompiledInstruction
TokenBalance / UiTokenAmount
ReturnData
Reward / Rewards
UnixTimestamp
BlockHeight
NumPartitions
États optionnels/legacy particulièrement sensibles :
compute_units_consumed?
cost_units?
inner_instructions_none
log_messages_none
return_data_none
loaded writable/readonly addresses
commission / commission_bps
Preuve cible : fixtures issues du wire Protobuf + cas old/current + malformed/oversized, sans conversion JSON arbitraire.
7. Unary RPC matrix
| RPC | Request exact | Response exact | État |
|---|---|---|---|
| ReplayInfo | empty | first_available? |
CANDIDATE |
| Ping | count |
count |
CANDIDATE |
| LatestBlockhash | commitment? |
slot/hash/last_valid_height | CANDIDATE |
| BlockHeight | commitment? |
block_height | CANDIDATE |
| Slot | commitment? |
slot | CANDIDATE |
| IsBlockhashValid | blockhash + commitment? |
slot + bool | CANDIDATE |
| Version | empty | version | CANDIDATE |
8. Dépendances / licence
| Gate | Décision / matérialisation pre.003 |
Preuve / état |
|---|---|---|
| repository default | AGPL-3.0-only | LICENSING.md |
| client subtree | Apache-2.0 | LICENSING.md |
| proto subtree | Apache-2.0 | LICENSING.md |
| strategy A client+proto | rejetée comme default | documenté |
| strategy B proto+Tonic KSP | retenue ; TLS/unary matérialisés | source PASS / Cargo pending |
yellowstone-grpc-proto |
^12.6, default-features = false, aucune feature KSP |
Cargo tree pending |
tonic |
runtime channel+tls-aws-lc+tls-webpki-roots; dev codegen+server |
Cargo tree pending |
yellowstone-grpc-client |
absent | manifest canary ajouté |
prost/prost-types direct KSP |
absent | manifest / Cargo tree pending |
http / tonic-prost direct |
^1.5 / ^0.14, runtime minimal pour PathAndQuery/ProstCodec |
Cargo tree pending |
| strategy C vendored proto | fallback seulement | aucun vendoring |
| system protoc | aucun outil système KSP ajouté | proto publié/build vendored |
| raw upstream types public | interdit ; aucun reexport Tonic/Yellowstone | public API canary ajouté |
| executable Yellowstone deps | interdit | dependency firewall à revalider |
Versions observées :
yellowstone-grpc-client 13.3.0
yellowstone-grpc-proto 12.6.0
tonic 0.14.x (0.14.6 latest observé)
prost/prost-types 0.14.x (0.14.4 latest observé)
9. Architecture / ownership
| Invariant | Preuve cible | État pre.003 |
|---|---|---|
| backend gRPC distinct HTTP/WS | source/API canary | IMPLEMENTED / Cargo pending |
aucun WsProtocolKind gRPC |
source scan | SOURCE PASS |
| Transport owns gRPC | dependency graph | IMPLEMENTED / tree pending |
| Config -> Transport seulement | ownership test | hérité / final TODO |
| Transport -X-> Config | ownership test | SOURCE PASS / Cargo pending |
| Transport -X-> std::env KSP_* | ownership test | SOURCE PASS |
| Logging façade KSP only | logging ownership | SOURCE PASS |
| no raw Tonic client escape hatch | public API canary | IMPLEMENTED / Cargo pending |
| moteur Yellowstone partagé sans duplication provider | source/API canary | N1 FOUNDATION IMPLEMENTED |
| façade Solana Yellowstone standard distincte du moteur | public API canary | PARTIAL : 7 unary N2 / Subscribe TODO |
| PublicNode représenté comme provider/capabilities, pas comme nouveau protocole | public API/config canary | TODO pre.011/012 |
| provider peut réutiliser, restreindre ou étendre N2 sans dupliquer N1 | capability/completeness review | architecture conservée |
| aucune équivalence provider/standard présumée sans preuve | provider matrix/tests | architecture conservée |
| façade provider spécialisée seulement si delta réel | completeness review | TODO provider integration |
10. Settings, bounds et redaction
État après pre.003 :
DONE/source+tests ajoutés endpoint schemes http/https validés ; TLS réel matérialisé en pre.003
DONE/source+tests ajoutés endpoint URL, descripteurs et nombre d’endpoints plafonnés
DONE/source+tests ajoutés connect timeout > 0 et plafonné
DONE/source+tests ajoutés unary timeout > 0 et plafonné
DONE/source+tests ajoutés close timeout > 0 et plafonné
DONE/source+tests ajoutés max inbound/outbound > 0 et plafonnés
DONE/source+tests ajoutés request/update queue capacities > 0 et plafonnées
DONE/source+tests ajoutés reconnect attempt/backoff bornés
CANDIDATE pre.004 filter-group count <= 1024 total sur les sept maps
CANDIDATE pre.004 filter-name non vide/trim/control-free <= 128 octets + unicité globale
DONE/source+tests ajoutés metadata ASCII key/value count/size + reserved/bin bounds
TODO pre.005+ account/owner/include/exclude/required counts
CANDIDATE pre.004 data slice count <= 128, length <= 64 MiB, offset+length sans overflow ; memcmp TODO pre.005
TODO pre.005+ Cuckoo dimensions/data bounds
Security canaries :
DONE/source+tests ajoutés endpoint URL Debug redacted
DONE/source+tests ajoutés metadata publique/secrète redacted ; secret marqué sensitive
DONE/source+fixture Status message/details/metadata distants exclus des KspError
DONE pre.003/fix.001 connect réel + TLS WebPKI configuré ; erreur connect/TLS safe, gate Cargo PASS
CANDIDATE pre.004 SubscribeRequest Debug sans filter names/payload arbitraire ; update Debug TODO pre.005+
DONE pre.003 source/tests channel/client Debug sans URL, metadata value ni raw Tonic ; lifecycle stream ultérieur
11. Lifecycle / backpressure / replay
| Cas | Attendu | État |
|---|---|---|
| stream open | session bornée | DONE pre.009 / gate fix.001 PASS |
| request mutation | ordre déterministe | DONE pre.009 |
| server Ping -> client request ping -> Pong | explicite | DONE pre.009 |
| server half-close | reconnect si budget > 0 ; terminal normal sinon | CANDIDATE pre.010 |
| client close | half-close + cleanup borné | DONE pre.009 |
| receiver drop | Drop session => cleanup best-effort | DONE pre.009 |
| slow subscription | pas de queue infinie | DONE pre.009 |
| inbound oversized | limite Tonic avant payload KSP | DONE pre.009 |
| outbound oversized | encoded_len avant queue/write | DONE pre.009 |
| reconnect budget | borné | CANDIDATE pre.010 |
| resubscribe order | dernier request complet accepté | CANDIDATE pre.010 |
from_slot |
max(explicite, highest observed), sans promesse lossless | CANDIDATE pre.010 |
| ReplayInfo | informatif ; clamp seulement si gap de couverture replay prouvé | DONE unary + CANDIDATE usage reconnect |
| duplicates | identités bornées observables, jamais supprimées | CANDIDATE pre.010 |
| gaps | seulement si first_available > requested_from_slot |
CANDIDATE pre.010 |
| divergent node history | Block/BlockMeta hash-aware ; pas de claim global | CANDIDATE couverture documentée |
| shutdown during reconnect | aucune nouvelle connexion après shutdown | CANDIDATE pre.010 |
Claims interdits sans nouvelle preuve :
exactly-once
lossless
historical replay complet
ordre global sans gap
12. Config V3
Décision de gate :
V1 HTTP reste lisible
V2 HTTP+WS reste lisible
V3 ajoute gRPC explicitement
Shape conceptuelle à matérialiser :
globals.grpc_defaults
profiles[].grpc_endpoints[]
endpoint.metadata[] # public/non-secret
endpoint.secret_metadata[] # Config-owned secret provenance
Canaries :
| Gate | État |
|---|---|
| V1 backward readable | TODO |
| V2 backward readable | TODO |
| V3 schema strict | TODO |
| gRPC endpoint mapping | TODO |
| secret provenance enforced | TODO |
| safe projection redacted | TODO |
| no Transport -> Config | TODO |
.env.example inventory if new env vars |
TODO |
13. Providers — validation et séquence
| Provider | Accès gratuit/durable observé | Rôle architectural | Release cible | Verdict |
|---|---|---|---|---|
| PublicNode / Allnodes-backed | Mainnet + Testnet Yellowstone gRPC | première intégration concrète | 0.2.9 | IN provider |
| OrbitFlare | Devnet Free | provider dédié ; compat/restrictions/extensions à auditer | 0.2.10 | PLANNED |
| Helius LaserStream gRPC | accès dépendant du plan | provider dédié ; compat/replay/auth/extensions à auditer | 0.2.11 | PLANNED |
| eRPC | à réauditer | waitlist provider | non réservé | TODO |
| Triton | à réauditer | upstream + extensions provider possibles | non réservé | TODO |
| Alchemy | à réauditer | waitlist provider | non réservé | TODO |
| QuickNode | à réauditer | waitlist provider | non réservé | TODO |
| Chainstack | à réauditer | waitlist provider | non réservé | TODO |
| Tatum / Shyft / Solinfra / NodeFlare / autres | selon accès/capabilities | attente exploratoire | non réservé | IDEAS |
PublicNode 0.2.9
Cible principale officiellement affichée :
solana-yellowstone-grpc.publicnode.com:443
Gates :
utilise le moteur Yellowstone partagé
utilise la façade standard Solana
provider/capabilities/profile explicitement identifiables
aucune duplication actor/channel/stream
wire N2 réutilisé seulement pour les capacités réellement compatibles ; divergence N3 explicite
Mainnet smoke opt-in
Testnet smoke opt-in si endpoint exact confirmé
Providers suivants
OrbitFlare (0.2.10) et Helius LaserStream gRPC (0.2.11) sont les seules intégrations provider actuellement planifiées après PublicNode. Pour chacune, le gate doit comparer le provider au Yellowstone upstream courant : capacités supportées, restrictions, extensions wire, auth/metadata, compression, keepalive, replay/from_slot, limites et lifecycle.
Les autres providers restent en TODO/IDEAS sans release dédiée. Aucune façade, dépendance, Config profile ou smoke n'est préparé pour eux tant qu'une décision explicite ne les fait pas entrer dans la séquence active.
14. Non-régressions obligatoires
| Surface héritée | Attendu final | État |
|---|---|---|
| HTTP current | 52 typed | TODO final |
| HTTP historical | 14 Deprecated/Removed | TODO final |
| Standard WS | 18 opérations / 9 familles | TODO final |
| Helius WS | 7 standard + transaction | TODO final |
| Helius heartbeat | Ping 60 s | TODO final |
| Config V1/V2 | backward read | TODO final |
| Wallet/Wallet Desk | aucune dépendance protocolaire Yellowstone directe | TODO final |
15. Forecast / preuve par tranche — 15–20 min max ; release <= une session
pre.001 DONE audit/sizing/architecture 15–20 min nominal
pre.002 DONE moteur: deps/settings/errors/channel 15–20 min ; gate final fix.002 PASS
pre.003 DONE TLS/metadata + fixture + 7 unary standard 15–20 min ; gate final fix.001 PASS
pre.004 DONE standard: Subscribe common/from_slot/bounds 15–20 min ; gate final fix.001 PASS
pre.005 DONE standard: accounts + slots 15–20 min ; gate final fix.001 PASS
pre.006 DONE structure: namespace privé HTTP `http_*` 15–20 min ; gate PASS
pre.007 DONE standard: transactions + transaction_status 15–20 min ; gate PASS
pre.008 DONE standard: blocks + block_meta + entry 15–20 min ; gate final fix.001 PASS sans warning
pre.009 DONE moteur: bidi/backpressure/half-close/shutdown 15–20 min ; gate final fix.001 PASS sans warning, 379/48/42/4
pre.010 CANDIDATE moteur: reconnect/replay/gap/duplicate 15–20 min ; source/fixture candidate, gate opérateur à exécuter
pre.011 TODO Config V3 + protocol/provider + profils PublicNode 15–20 min
pre.012 TODO PublicNode live + compliance + docs/prompt 0.2.10 15–20 min
rel.001 TODO stable
Gate de sizing : une prerelease estimée à plus de 20 minutes est scindée ; si 0.2.9 ne paraît plus clôturable dans la session courante, la release est scindée avant implémentation supplémentaire.
16. Gate pre.001
| Critère du prompt | Verdict |
|---|---|
base stable v0.2.8 confirmée |
PASS |
| baseline opérateur enregistrée | PASS |
| upstream courant relu | PASS |
| divergence snapshot/latest enregistrée | PASS |
| service/proto exhaustif inventorié | PASS |
| standard vs provider extension classifié | PASS |
SubscribeDeshred classifié |
PASS / OUT |
| unary RPCs classifiés | PASS / 7 IN |
| replay/from_slot audités | PASS |
| strategy dependency choisie | PASS / B |
| licence auditée avant ajout | PASS |
| features/build/transitifs audit initial | PASS / matérialisation pre.002 |
| architecture distincte WS | PASS |
| metadata/auth neutral | PASS |
| Config shape décidée | PASS / V3 |
| resource/backpressure policy décidée | PASS |
| smoke ownership décidé | PASS |
| providers gratuits audités | PASS |
| release dimensionnée | PASS |
| forecast recalibré | PASS |
| split criteria écrits | PASS |
| aucune implémentation lourde prématurée | PASS |
Verdict pre.001 : gate positif ; pre.002 peut matérialiser la stratégie B sous validation Cargo.
17. Gate pre.002 / pre.002-fix.001
Premier passage opérateur sur pre.002 :
| Gate / observation | Résultat avant fix | État après fix.001 |
|---|---|---|
| workspace version | 0.2.9-pre.2 |
0.2.9-pre.2.fix.1 |
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | PASS local / clean |
cargo check --workspace |
PASS, avec warning channel jamais lu |
warning supprimé par état privé _channel |
cargo clippy --workspace --all-targets |
FAIL : implicit_return dans unit_tests/grpc_settings.rs |
corrigé ; à réexécuter |
cargo test -p ksp-onchain-transport-lib |
FAIL : connect_lazy() appelé hors reactor Tokio, 344/345 avant fix |
test/runtime corrigés ; à réexécuter |
| dependency canary Core | PASS / 3 passed | inchangé |
cargo tree -p ksp-onchain-transport-lib |
obtenu et inspecté | PASS graphe |
cargo tree -p ... --duplicates / workspace duplicates |
obtenu et inspecté | PASS avec doublons build/runtime documentés |
Correction fix.001 :
le champ Tonic reste présent en production ; il n'est pas placé sous cfg(test)
le champ privé devient `_channel` tant qu'aucune opération pre.003 ne le consomme
prepare() vérifie tokio::runtime::Handle::try_current() avant connect_lazy()
absence de runtime -> KspError grpc_channel_failed sûr, jamais panic Tonic
le test positif s'exécute sous #[tokio::test]
un test sync couvre explicitement l'absence de runtime et la redaction
la closure de cardinalité settings utilise un return explicite conforme à Clippy
Le choix de ne pas mettre le channel sous #[cfg(test)] est intentionnel : pre.002 matérialise une ressource N1 réelle de production qui sera consommée par pre.003; une compilation normale sans ce champ rendrait le contrat de tranche artificiellement différent entre production et tests.
Inspection du graphe opérateur :
tonic 0.14.6
yellowstone-grpc-proto 12.6.0
prost/prost-types 0.14.4
solana-pubkey 4.3.0 unifié
http/hyper/hyper-util 1.5.0 / 1.11.0 / 0.1.20
tower 0.5.3
bytes 1.12.1
Aucune version concurrente Tonic/Prost/Solana n'a été introduite dans le graphe Transport. Les répétitions Prost de même version proviennent des unités build/runtime de la crate proto publiée.
Verdict pre.002-fix.001 : correctif source prêt ; pre.002 reste ouverte jusqu'à réexécution verte de fmt/audit/check/clippy/tests/workspace et confirmation finale du graphe.
Second passage opérateur après fix.001
| Gate / observation | Résultat fix.001 |
État fix.002 |
|---|---|---|
| workspace version | 0.2.9-pre.2.fix.1 |
0.2.9-pre.2.fix.2 |
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | PASS local / clean |
cargo check --workspace |
PASS | inchangé |
cargo clippy --workspace --all-targets |
PASS | inchangé |
| Transport unit | PASS / 346 passed | inchangé |
Transport public_api |
FAIL / 41 passed, 1 failed : prepare() appelé hors runtime Tokio |
canari placé sous #[tokio::test] |
| dependency canary Core | PASS / 3 passed | inchangé |
| graphes Cargo | déjà fournis et inspectés | inchangés |
Le second échec ne révèle aucune nouvelle faiblesse du moteur N1 : il confirme au contraire le contrat introduit par fix.001. Le canari public API doit être exécuté dans le même contexte Tokio que le test unitaire positif ; aucune modification supplémentaire de YellowstoneGrpcChannel n'est nécessaire.
Verdict pre.002-fix.002 : correctif de test d'intégration prêt ; pre.002 reste ouverte jusqu'à réexécution verte de cargo test -p ksp-onchain-transport-lib, cargo test --workspace et des gates habituels.
Gate final opérateur pre.002-fix.002
| Gate | Résultat final |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS / clean |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS |
| Transport unit | 346/346 PASS |
Transport public_api |
42/42 PASS |
Transport release_completeness |
35/35 PASS |
| Transport doctests | 4/4 PASS |
| Core dependency canary | 3/3 PASS |
cargo test --workspace |
PASS |
Verdict : pre.002 fermée.
18. Gate pre.003 — candidate
| Gate / surface | État candidate |
|---|---|
| workspace version | 0.2.9-pre.3 |
runtime proto sans feature tonic |
SOURCE PASS |
| Tonic runtime channel + AWS-LC + WebPKI TLS | SOURCE PASS |
| Tonic server/codegen uniquement dev/test | SOURCE PASS |
| metadata ASCII publique/secrète redacted | SOURCE PASS |
| connexion réelle bornée | SOURCE PASS |
| 7 unary standard exacts | SOURCE PASS |
| fixture Geyser locale | SOURCE PASS |
| commitment mapping | SOURCE PASS |
| Status hostile sans payload distant | SOURCE PASS |
| timeout unary borné | SOURCE PASS |
| Subscribe / SubscribeDeshred | OUT pre.003 |
| PublicNode / Config V3 | OUT pre.003 |
| audit Rust workspace local | PASS / clean |
| fmt/check/Clippy/tests/Cargo trees | opérateur TODO |
La fixture active yellowstone-grpc-proto/tonic et Tonic codegen+server uniquement dans le graphe dev/test. Le runtime utilise les messages Protobuf publiés, tonic::client::Grpc et tonic-prost::ProstCodec derrière une façade KSP sans raw escape hatch.
Verdict pre.003 : candidate source prête ; fermeture seulement après gate Cargo opérateur complet et réinspection des graphes.
18.1 Premier gate opérateur pre.003 et pre.003-fix.001
| Gate / observation | Résultat pre.003 |
État fix.001 |
|---|---|---|
| workspace version | 0.2.9-pre.3 |
0.2.9-pre.3.fix.1 |
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | audit local PASS / clean |
cargo check --workspace |
PASS | inchangé |
cargo clippy --workspace --all-targets |
FAIL : 11 implicit_return dans unit_tests/grpc_unary.rs |
corrigé ; à réexécuter |
| Transport unit | 354/354 PASS | inchangé |
Transport public_api |
43/43 PASS | inchangé |
Transport release_completeness |
36/36 PASS | inchangé |
| Transport doctests | 4/4 PASS | inchangé |
| Core dependency canary | 3/3 PASS | inchangé |
cargo test --workspace |
PASS | inchangé fonctionnellement |
Correction :
9 diagnostics proviennent de l'expansion #[tonic::async_trait] sur la fixture serveur,
alors que les corps source ont déjà des return explicites.
=> allow(clippy::implicit_return) strictement local à cette implémentation de test, avec justification.
2 diagnostics concernent les closures metadata and_then.
=> return explicite dans les closures.
aucun changement N1/N2 runtime
aucune dépendance/feature modifiée
aucun Subscribe/PublicNode/Config V3 anticipé
Verdict pre.003-fix.001 : correctif Clippy minimal prêt ; fermeture de pre.003 après réexécution verte des gates habituels et inspection des graphes Cargo demandée par la tranche.
18.2 Gate final opérateur pre.003-fix.001
| Gate | Résultat final |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS / clean |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS |
| Transport unit | 354/354 PASS |
Transport public_api |
43/43 PASS |
Transport release_completeness |
36/36 PASS |
| Transport doctests | 4/4 PASS |
cargo test --workspace |
PASS |
cargo tree -p ... |
fourni/relu |
cargo tree -p ... -e features |
fourni/relu |
cargo tree -p ... --duplicates |
fourni/relu |
cargo tree --duplicates |
fourni/relu |
Graphe pertinent confirmé : tonic 0.14.6, tonic-prost 0.14.6, prost/prost-types 0.14.4, yellowstone-grpc-proto 12.6.0, solana-pubkey 4.3.0. Les features serveur/codegen et yellowstone-grpc-proto/tonic restent liées à la fixture dev/test ; aucune seconde version Tonic/Prost/Solana n'est introduite par la tranche.
Verdict : pre.003 fermée.
19. Gate pre.004 — candidate
| Surface | État candidate |
|---|---|
| workspace version | 0.2.9-pre.4 |
sept maps SubscribeRequest |
SOURCE PASS |
| map vide / entrée nommée vide | SOURCE+TEST |
| commitment optional exact | SOURCE+TEST |
| account-data slices ordonnées | SOURCE+TEST |
| ping optional exact | SOURCE+TEST |
from_slot optional exact |
SOURCE+TEST |
| filter names <=128 octets / unicité globale | SOURCE+TEST |
| filter groups <=1024 total | SOURCE+TEST |
| slices <=128 / length <=64 MiB / overflow rejeté | SOURCE+TEST |
| request Debug sans noms/payloads de filtres | SOURCE+TEST |
| filtres Accounts/Slots détaillés | OUT pre.004 |
| filtres Transactions/Blocks détaillés | OUT pre.004 |
| stream bidi / lifecycle / updates | OUT pre.004 |
| PublicNode / Config V3 | OUT pre.004 |
| audit Rust workspace local | PASS / clean |
| fmt/check/Clippy/tests | opérateur TODO |
Le proto publié yellowstone-grpc-proto 12.6.0 a été recontrôlé avant implémentation : les onze champs top-level retenus restent accounts, slots, transactions, transactions_status, blocks, blocks_meta, entry, commitment, accounts_data_slice, ping, from_slot. Aucun SubscribeDeshred n'entre dans la surface KSP.
Verdict pre.004 : candidate source prête ; fermeture après gate Cargo opérateur.
19.1 Premier gate opérateur pre.004 et pre.004-fix.001
| Gate / observation | Résultat pre.004 |
État fix.001 |
|---|---|---|
| workspace version | 0.2.9-pre.4 |
0.2.9-pre.4.fix.1 |
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | audit local PASS / clean |
cargo check --workspace |
PASS + 10 warnings dead_code |
helpers wire test-only sous #[cfg(test)] |
cargo clippy --workspace --all-targets |
PASS + mêmes 10 warnings | idem |
| Transport unit | 359/359 PASS | inchangé |
Transport public_api |
44/44 PASS | inchangé |
Transport release_completeness |
37/37 PASS | inchangé |
| Transport doctests | 4/4 PASS | inchangé |
| Core dependency canary | 3/3 PASS | inchangé |
cargo test --workspace |
PASS + mêmes warnings à la compilation | à réexécuter sans warning |
Les dix symboles concernés (to_wire et commitment_to_wire) servent uniquement aux tests de projection protobuf de pre.004. Le stream bidi n'étant pas ouvert avant pre.009, ils ne font pas encore partie du runtime. #[cfg(test)] évite donc un faux code mort de production sans créer une seconde implémentation ni modifier le contrat public. Lors de l'intégration runtime du stream, ces helpers seront naturellement retirés du cfg(test) au moment où ils auront un consommateur de production.
Verdict pre.004-fix.001 : fermé.
19.2 Gate opérateur final pre.004-fix.001
| Gate / observation | Résultat final |
|---|---|
| workspace version | 0.2.9-pre.4.fix.1 |
cargo fmt --all |
PASS |
| audit Rust workspace | PASS / clean |
cargo check --workspace |
PASS sans warnings pre.004 |
cargo clippy --workspace --all-targets |
PASS sans warnings pre.004 |
| Transport unit | 359/359 PASS |
Transport public_api |
44/44 PASS |
Transport release_completeness |
37/37 PASS |
| Transport doctests | 4/4 PASS |
cargo test --workspace |
PASS |
pre.004 est donc fermée.
20. Gate pre.005 — Accounts + Slots candidate
| Surface | État candidate |
|---|---|
| workspace version | 0.2.9-pre.5 |
account selectors account[] / owner[] |
SOURCE+TEST |
| account predicates memcmp bytes/base58/base64 | SOURCE+TEST |
| account predicates datasize/token-state/lamports | SOURCE+TEST |
nonempty_txn_signature? |
SOURCE+TEST |
cuckoo_accounts_filter? + SipHash |
SOURCE+TEST |
Slots filter_by_commitment? / interslot_updates? |
SOURCE+TEST |
| Account update DTO/decode | SOURCE+TEST |
Slot update DTO/decode + 7 statuts + dead_error? |
SOURCE+TEST |
| fixed-width pubkey/signature malformed | SOURCE+TEST |
| payload/timestamp/update-filter/dead-error bounds | SOURCE+TEST |
| Debug sans sélecteurs/payloads arbitraires | SOURCE+TEST |
| Transactions / transaction_status | OUT pre.005 |
| Blocks / block_meta / entry | OUT pre.005 |
| stream bidi / lifecycle | OUT pre.005 |
| PublicNode / Config V3 | OUT pre.005 |
| audit Rust workspace local | PASS / clean |
| fmt/check/Clippy/tests | opérateur TODO |
Les conversions request protobuf et les décodeurs Account/Slot sont test-only jusqu'à pre.009, faute de consommateur runtime avant l'ouverture du stream. Le contrat public reste entièrement KSP-owned.
Verdict pre.005 : candidate source prête ; fermeture après gate Cargo opérateur.
20.1 Premier gate opérateur pre.005 et pre.005-fix.001
| Gate / observation | Résultat pre.005 |
État fix.001 |
|---|---|---|
| workspace version | 0.2.9-pre.5 |
0.2.9-pre.5.fix.1 |
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | audit local à revalider |
cargo check --workspace |
PASS + 4 warnings dead_code |
constantes test-only sous #[cfg(test)] |
cargo clippy --workspace --all-targets |
FAIL : 1 implicit_return + 1 wrong_self_convention ; mêmes 4 warnings |
corrigé |
| Transport unit | 364/364 PASS | inchangé |
Transport public_api |
45/45 PASS | inchangé |
Transport release_completeness |
38/38 PASS | inchangé |
| Transport doctests | 4/4 PASS | inchangé |
| Core dependency canary | 3/3 PASS | inchangé |
cargo test --workspace |
PASS + 4 warnings à la compilation | à réexécuter sans warning |
Les quatre constantes concernées sont exclusivement consommées par les décodeurs Account/Slot eux-mêmes sous #[cfg(test)] jusqu'à l'ouverture du stream en pre.009. Elles passent donc sous le même cfg(test) plutôt que d'introduire un allow(dead_code). Le receiver du helper Slot devient self car le type est Copy; la closure is_some_and reçoit un return explicite conformément à la politique Clippy KSP.
Le même fix réaligne tous les tableaux Markdown de 016 et 012 sans modifier leur contenu sémantique.
Verdict pre.005-fix.001 : correctif source/documentaire prêt ; fermeture de pre.005 après gate opérateur sans warning.
20.2 Gate final opérateur pre.005-fix.001
| Gate | Résultat final |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS / clean |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS |
| Transport unit | 364/364 PASS |
Transport public_api |
45/45 PASS |
Transport release_completeness |
38/38 PASS |
| Transport doctests | 4/4 PASS |
| Core dependency canary | 3/3 PASS |
cargo test --workspace |
PASS |
Verdict : pre.005 fermée.
21. Gate pre.006 — namespace privé HTTP
| Surface / invariant | État candidate |
|---|---|
client.rs -> http_client.rs |
SOURCE PASS |
executor.rs -> http_executor.rs |
SOURCE PASS |
pool.rs -> http_pool.rs |
SOURCE PASS |
resilience.rs -> http_resilience.rs |
SOURCE PASS |
settings.rs -> http_settings.rs |
SOURCE PASS |
unit tests miroirs http_* |
SOURCE PASS |
| types/fonctions publics HTTP | INCHANGÉS |
rpc_common/accounts/blocks/transactions restent partagés |
SOURCE PASS |
json_rpc, constants, error non artificiellement préfixés |
SOURCE PASS |
| anciens fichiers supprimés après application overlay | opérateur TODO |
| release-completeness canary namespace | SOURCE PASS |
| audit Rust workspace local | PASS / clean |
| fmt/check/Clippy/tests/workspace | opérateur TODO |
Le renommage est limité aux cinq modules dont l'ownership HTTP est sans ambiguïté. Il ne modifie aucune signature publique et n'introduit aucune dépendance. L'overlay ZIP ajoute les nouveaux chemins ; les cinq anciens fichiers source et leurs cinq unit tests miroirs doivent être supprimés explicitement par l'opérateur après extraction.
Verdict pre.006 : candidate structurelle prête ; fermeture après suppressions opérateur et gate Cargo complet.
22. Gate final pre.006
| Gate | Résultat final |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS / clean |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS |
| Transport unit | 364/364 PASS |
Transport public_api |
45/45 PASS |
Transport release_completeness |
39/39 PASS |
| Transport doctests | 4/4 PASS |
| Core dependency canary | 3/3 PASS |
cargo test --workspace |
PASS |
Verdict : pre.006 fermée.
23. Gate pre.007 — Transactions + transaction_status candidate
| Surface | État candidate |
|---|---|
| workspace version | 0.2.9-pre.7 |
vote? / failed? |
SOURCE+TEST |
| signature Base58 décodée exactement 64 octets | SOURCE+TEST |
| include/exclude/required ordonnés et bornés | SOURCE+TEST |
| Cuckoo transaction include | SOURCE+TEST |
| token expansion ALL/BALANCE_CHANGED | SOURCE+TEST |
SubscribeUpdateTransaction |
SOURCE+TEST |
SubscribeUpdateTransactionStatus |
SOURCE+TEST |
| Transaction/Message/Header | SOURCE+TEST |
| compiled instructions / ALT lookups | SOURCE+TEST |
Transaction V1 TransactionConfig |
SOURCE+TEST |
| TransactionStatusMeta complet | SOURCE+TEST |
| inner instructions + legacy none marker | SOURCE+TEST |
| logs + legacy none marker | SOURCE+TEST |
| token balances / UiTokenAmount | SOURCE+TEST |
| loaded addresses | SOURCE+TEST |
| ReturnData + legacy none marker | SOURCE+TEST |
| rewards | SOURCE+TEST |
| compute_units_consumed / cost_units | SOURCE+TEST |
| opaque TransactionError borné | SOURCE+TEST |
| Debug sans signatures/token-balance text/payloads/logs/error bytes | SOURCE+TEST |
| Blocks / block_meta / entry | OUT pre.007 |
| stream bidi / lifecycle | OUT pre.007 |
| PublicNode / Config V3 | OUT pre.007 |
| audit Rust workspace local | PASS / clean |
| fmt/check/Clippy/tests | opérateur TODO |
Le proto 12.6.0 ajoute à la représentation de transaction le Message.config optionnel pour Transaction V1 / SIMD-0385 ; la candidate le conserve explicitement. Les marqueurs legacy inner_instructions_none, log_messages_none et return_data_none ne sont pas fusionnés avec leurs collections/messages.
Verdict pre.007 : candidate source prête ; fermeture après gate Cargo opérateur.
24. Gate final pre.007
| Gate | Résultat final |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS / clean |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS |
| Transport unit | 367/367 PASS |
Transport public_api |
46/46 PASS |
Transport release_completeness |
40/40 PASS |
| Transport doctests | 4/4 PASS |
| Core dependency canary | 3/3 PASS |
cargo test --workspace |
PASS |
Verdict : pre.007 fermée.
25. Gate pre.008 — Blocks + block_meta + entry candidate
| Surface / invariant | État candidate |
|---|---|
| workspace version | 0.2.9-pre.8 |
Blocks account_include[] |
SOURCE+TEST |
include_transactions? / include_accounts? |
SOURCE+TEST |
include_entries? |
SOURCE+TEST |
| Cuckoo block account include | SOURCE+TEST |
SubscribeUpdateBlock |
SOURCE+TEST |
rewards + num_partitions? |
SOURCE+TEST |
| block time / block height optionnels | SOURCE+TEST |
transactions réutilisent YellowstoneTransactionInfo |
SOURCE+TEST |
accounts réutilisent YellowstoneAccountInfo |
SOURCE+TEST |
| compteurs serveur indépendants des payload vectors | SOURCE+TEST |
SubscribeUpdateBlockMeta |
SOURCE+TEST |
SubscribeUpdateEntry + starting_transaction_index |
SOURCE+TEST |
| blockhash/parent blockhash Base58 -> 32 octets | SOURCE+TEST |
| entry hash exactement 32 octets | SOURCE+TEST |
| Debug sans hashes/sélecteurs/payloads imbriqués | SOURCE+TEST |
| stream bidi / Ping-Pong / lifecycle | OUT pre.008 |
| reconnect / replay | OUT pre.008 |
| PublicNode / Config V3 | OUT pre.008 |
| audit Rust workspace local | PASS / clean |
| fmt/audit/check/tests/workspace | PASS |
| Clippy | PASS + 1 warning fixture |
Les executed_transaction_count, updated_account_count et entries_count sont conservés tels que fournis par le serveur ; ils ne sont pas forcés à égaler les tailles de transactions[], accounts[] ou entries[], car les trois flags include_* peuvent omettre ces payloads. Les messages imbriqués Transaction et Account réutilisent strictement les DTOs déjà introduits ; aucune seconde projection n’est créée.
Les helpers wire/decode restent test-only jusqu’au premier consommateur runtime en pre.009.
Verdict pre.008 : contrat fonctionnel validé ; fix warning-only requis avant fermeture.
26. Gate pre.008-fix.001 — warning Clippy fixture
| Gate / observation | Résultat pre.008 |
Correctif fix.001 |
|---|---|---|
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | PASS local / clean |
cargo check --workspace |
PASS | inchangé |
cargo clippy --workspace --all-targets |
PASS + field_reassign_with_default |
initialiseur struct, warning supprimé |
| Transport unit | 370/370 PASS | contrat inchangé |
Transport public_api |
47/47 PASS | contrat inchangé |
Transport release_completeness |
41/41 PASS | contrat inchangé |
| Transport doctests | 4/4 PASS | contrat inchangé |
| Core dependency canary | 3/3 PASS | dépendances inchangées |
cargo test --workspace |
PASS | contrat inchangé |
Le warning provient uniquement de minimal_transaction_info() dans unit_tests/grpc_subscribe.rs. fix.001 initialise TransactionStatusMeta.fee directement dans le literal struct et conserve ..Default::default(). Aucun allow, aucun changement runtime, aucune dépendance et aucun élargissement vers le bidi.
Verdict fix.001 : PASS sans warning ; pre.008 fermée.
27. Gate pre.009 — bidi standard + backpressure + half-close + shutdown candidate
| Surface / invariant | État candidate |
|---|---|
| workspace version | 0.2.9-pre.9 |
/geyser.Geyser/Subscribe bidi |
SOURCE+TEST |
| request initial dans queue bornée | SOURCE+TEST |
mutation try_update() ordonnée/non bloquante |
SOURCE+TEST |
aucune unbounded_channel |
CANARY |
| decode des 9 variantes standard | SOURCE+TEST |
| server Ping -> ping-only id=1 | SOURCE+TEST |
| Pong observable | SOURCE+TEST |
server half-close => Ok(None) |
SOURCE+TEST |
| client close => request half-close | SOURCE+TEST |
shutdown hostile borné par close_timeout |
SOURCE+TEST |
| Drop session => half-close best-effort | SOURCE+TEST |
| slow receiver => terminal backpressure overflow | SOURCE+TEST |
| Status distant sans message/details secrets | SOURCE+TEST |
| update malformed => invalid response | SOURCE+TEST |
| max inbound Tonic | SOURCE+TEST |
| outbound encoded_len avant dispatch | SOURCE+TEST |
| reconnect/resubscribe/replay | OUT pre.009 |
SubscribeDeshred |
OUT 0.2.9 |
| PublicNode / Config V3 | OUT pre.009 |
| audit Rust workspace local | PASS / clean |
| fmt/check/tests/workspace | PASS |
| Clippy | PASS + 2 warnings |
Les helpers protobuf qui étaient test-only jusqu'à pre.008 sont maintenant compilés en runtime parce que grpc_stream les consomme effectivement. Aucun helper raw n'est public : les frontières restent YellowstoneSubscribeRequest et YellowstoneSubscribeUpdate.
Le flux sortant utilise la même mpsc bornée que celle fournie à tonic::client::Grpc::streaming; aucune queue cachée non bornée n'est interposée. Le Ping de keepalive serveur provoque une mutation ping-only actor-owned avec id=1, puis le Pong reste visible dans la file d'updates KSP.
pre.009 ne tente aucun reconnect. Un half-close serveur est terminal normal ; Status, decode invalide et overflow sont terminaux en erreur. Le budget de reconnect, l'ordre de resubscribe, from_slot/ReplayInfo, gaps, duplicates et node divergence restent exclusivement pre.010.
Verdict pre.009 : fermé après pre.009-fix.001, gate opérateur final intégralement vert et sans warning.
28. Gate pre.009-fix.001 — taille de l’enum update + canari Send
| Gate / observation | Résultat pre.009 |
Correctif fix.001 |
|---|---|---|
cargo fmt --all |
PASS | à réexécuter |
| audit Rust workspace | PASS / clean | PASS local / clean |
cargo check --workspace |
PASS | contrat inchangé |
cargo clippy --workspace --all-targets |
PASS + 2 warnings | boxing Transaction + usage réel de T |
| Transport unit | 379/379 PASS | contrat attendu inchangé |
Transport public_api |
48/48 PASS | contrat attendu inchangé |
Transport release_completeness |
42/42 PASS | contrat attendu inchangé |
| Transport doctests | 4/4 PASS | contrat attendu inchangé |
| Core dependency canary | 3/3 PASS | dépendances inchangées |
cargo test --workspace |
PASS | contrat attendu inchangé |
large_enum_variant |
Transaction ~664 B, Block ~280 B | Transaction(Box<YellowstoneTransactionUpdate>) |
extra_unused_type_parameters |
helper assert_send<T>() n’utilise pas T |
PhantomData<T> matérialise l’usage compile-time |
Le boxing ne modifie ni le protobuf ni YellowstoneTransactionUpdate : il réduit uniquement la taille du discriminant public transporté dans la queue bidi. Le canari Send conserve la même contrainte et ne construit aucune session réseau. Aucun allow Clippy n’est ajouté. Le gate opérateur final du 2026-08-24 repasse intégralement vert, Clippy sans warning, avec les compteurs 379/48/42/4 inchangés.
Verdict fix candidate : correction minimale prête ; fermeture de pre.009 après gate opérateur sans warning.
29. Candidate pre.010 — reconnect/replay et continuité observable
Réaduit upstream au 2026-08-24 :
SubscribeRequest.from_slot toujours présent
SubscribeReplayInfoResponse.first_available? toujours présent
changelog 2026-07-22 fix replay Blocks/state gap
changelog 2026-06-15 upstream autoreconnect traite l'equivocation par quarantaine/blockhash
KSP conserve sa stratégie B : aucune importation de la sémantique yellowstone-grpc-client autoreconnect. Le stream KSP rouvre lui-même /geyser.Geyser/Subscribe sur le channel N1 existant.
Preuve source pre.010 |
État |
|---|---|
état public Reconnecting |
SOURCE |
| snapshot reconnect/replay/gap/duplicate | SOURCE |
budget max_retries |
SOURCE |
| backoff exponentiel initial/max | SOURCE |
| dernier request complet resoumis | SOURCE |
resume max(explicit, last_observed) |
SOURCE |
| ReplayInfo consulté avant replay | SOURCE |
first_available > requested => replay non couvert + clamp |
SOURCE+TEST |
| duplicate identité bornée, update livrée | SOURCE+TEST |
mutation refusée pendant Reconnecting |
SOURCE+TEST |
| shutdown interrompt le backoff | SOURCE+TEST |
| épuisement budget => terminal sûr | SOURCE+TEST |
| cache identité borné à 512 | SOURCE |
| exactement-once/lossless | EXPLICIT NON-CLAIM |
| Config V3 / PublicNode | OUT pre.010 |
SubscribeDeshred |
OUT 0.2.9 |
La détection de gap n'utilise pas les sauts entre slots d'updates filtrés : un filtre peut légitimement ne produire aucun message pendant plusieurs slots. Le seul gap compté par cette tranche est une plage de replay objectivement devenue indisponible d'après SubscribeReplayInfo.first_available ; cela ne prouve pas qu'un update correspondant aux filtres existait ou a été perdu.
Le cache de duplicates retient des identités minimales Account/Slot/Transaction/TransactionStatus/Block/BlockMeta/Entry. Il ne retient pas les payloads complets et ne supprime jamais un update. Pour Block/BlockMeta, le blockhash fait partie de l'identité afin de ne pas classer deux histoires divergentes de même slot comme un simple duplicate ; aucune détection globale d'equivocation n'est prétendue.
Gate candidate attendu : audit statique clean ; après exécution opérateur, Transport attendu autour de 383 unit / 49 public API / 43 release-completeness / 4 doctests. Aucune dépendance/feature changée, donc pas de cargo tree supplémentaire.