22 KiB
Validation 0.2.9 — Yellowstone gRPC standard + PublicNode
Statut courant : le gate déterministe de pre.012 est vert sans warning ; le smoke PublicNode live et les graphes Cargo finaux ne figurent pas comme exécutés dans le log opérateur fourni. pre.012-fix.001 ajoute la règle durable de séparation de fermeture et déplace les gates restants vers pre.013 technique/live, pre.014 réconciliation documentaire et pre.015 publication minimale.
1. Autorités et baseline courante
Autorités :
RULES.md + docs/rules/*
plan 016 courant
code réel Transport/Config
prompts/014-V0_2_9_START_PROMPT.md pour les contraintes non supersédées
deltas/0.2.9/* pour l'historique immuable et les décisions postérieures au prompt
upstream Yellowstone primaire
Baseline opérateur immédiatement avant pre.012 (0.2.9-pre.011) :
| Gate | Résultat |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS, 0 candidate export |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS sans warning |
| Config unit | 113/113 PASS |
| Config public API | 15/15 PASS |
| Config ownership | 5/5 PASS |
| Transport unit | 383/383 PASS |
| Transport public API | 49/49 PASS |
| Transport release completeness | 43/43 PASS |
| Transport doctests | 4/4 PASS |
| workspace dependency canary | 3/3 PASS |
cargo test --workspace |
PASS |
Cette baseline est le seuil de non-régression de pre.012.
2. Gate dépendances et licence
| Exigence | Décision / preuve | État |
|---|---|---|
| proto officiel sans vendoring | yellowstone-grpc-proto ^12.6 |
PASS |
| pas de client upstream runtime | yellowstone-grpc-client absent |
PASS |
| runtime Tonic KSP-owned | tonic ^0.14 + tonic-prost ^0.14 |
PASS |
| proto subtree compatible | Apache-2.0 selon LICENSING.md upstream |
PASS |
| source AGPL copiée | aucune | PASS |
| raw client Tonic public | aucun | PASS |
| graph final | réinspection pre.012 |
PENDING FINAL |
Le graphe de dépendances n'est pas modifié par pre.012; aucune nouvelle dépendance Cargo n'est introduite dans cette tranche.
3. Matrice service Geyser
| RPC | Classification | Cible | Preuve | Verdict |
|---|---|---|---|---|
Subscribe |
standard | oui | stream bidi local + lifecycle | PASS |
SubscribeDeshred |
extension/pré-exécution Triton | non | exclusion documentée | OUT |
SubscribeReplayInfo |
standard unary | oui | fixture unary + reconnect tests | PASS |
Ping |
standard unary | oui | fixture exact echo | PASS |
GetLatestBlockhash |
standard unary | oui | fixture typed | PASS |
GetBlockHeight |
standard unary | oui | fixture typed | PASS |
GetSlot |
standard unary | oui | fixture typed | PASS |
IsBlockhashValid |
standard unary | oui | fixture typed + invalid input | PASS |
GetVersion |
standard unary | oui | fixture typed | PASS |
4. SubscribeRequest — coverage normative
4.1 Top-level
| Champ | Verdict | Preuve minimale |
|---|---|---|
accounts |
PASS | maps typed + wire exact |
slots |
PASS | maps typed + wire exact |
transactions |
PASS | maps typed + wire exact |
transactions_status |
PASS | same filter family, separate map |
blocks |
PASS | maps typed + wire exact |
blocks_meta |
PASS | named empty marker preserved |
entry |
PASS | named empty marker preserved |
commitment |
PASS | optional wire semantics |
accounts_data_slice |
PASS | order + bounds |
ping |
PASS | optional id |
from_slot |
PASS | optional + replay mutation |
4.2 Accounts
account[]
owner[]
filters[]
nonempty_txn_signature?
cuckoo_accounts_filter?
memcmp bytes/base58/base64
datasize
token_account_state
lamports eq/ne/lt/gt
Verdict : PASS — wire complet retenu, bounds déterministes, payload Debug redacted, malformed fixed-width rejeté.
4.3 Slots
filter_by_commitment?
interslot_updates?
processed
confirmed
finalized
first_shred_received
completed
created_bank
dead + dead_error?
Verdict : PASS.
4.4 Transactions et transaction_status
vote?
failed?
signature?
account_include[]
account_exclude[]
account_required[]
cuckoo_account_include?
token_accounts? = ALL | BALANCE_CHANGED
Verdict : PASS — request wire, transaction storage/meta, status error et malformed signature couverts.
4.5 Blocks, block_meta, entry
account_include[]
include_transactions?
include_accounts?
include_entries?
cuckoo_account_include?
blocks_meta marker
entry marker
Verdict : PASS — block complet, metadata, entries et champs optional/legacy couverts.
5. SubscribeUpdate — coverage normative
| Variante | Verdict |
|---|---|
| account | PASS |
| slot | PASS |
| transaction | PASS |
| transaction_status | PASS |
| block | PASS |
| ping | PASS |
| pong | PASS |
| block_meta | PASS |
| entry | PASS |
top-level filters[] / created_at |
PASS |
Les raw protobufs ne sortent pas de la façade publique. Les décodeurs rejettent les formes structurellement invalides sans copier des payloads arbitraires dans les erreurs.
6. Settings, bounds et redaction
| Contrôle | État |
|---|---|
URL http/https seulement et longueur bornée |
PASS |
| URL Debug redacted | PASS |
| metadata key/value/count bornés | PASS |
| metadata secret/public distincte | PASS Transport |
| timeouts non nuls et bornés | PASS |
| reconnect bounds cohérents | PASS |
| inbound/outbound message sizes | PASS |
| request/update queue capacities | PASS |
| filter group/name bounds | PASS |
| account/owner/memcmp/data slice bounds | PASS |
| transaction/block selectors bounds | PASS |
remote Status message/details non recopiés |
PASS |
| Transport -> env/config | absent ou PASS |
7. Lifecycle, backpressure et replay
| Exigence | Verdict | Preuve |
|---|---|---|
| stream bidi unique | PASS | round-trip fixture |
| mutation request | PASS | same request channel |
| server Ping / client reply | PASS | actor test |
| Pong decode | PASS | update decode |
| server half-close | PASS | state terminal observable |
| explicit client close | PASS | half-close avant deadline |
| hostile server shutdown | PASS | close timeout borné |
| slow receiver | PASS | overflow terminal observable |
| oversized inbound | PASS | Tonic decoder bound |
| oversized outbound | PASS | reject avant queue dispatch |
| reconnect backoff | PASS | budget borné |
| shutdown pendant backoff | PASS | interruption sans nouvelle connexion |
| resubscribe déterministe | PASS | last accepted full request |
reprise from_slot |
PASS | dernier slot observé + demande explicite |
ReplayInfo first_available |
PASS | clamp/gap seulement si prouvé |
| duplicate observability | PASS | compteur borné, pas de suppression silencieuse |
| exactly-once/lossless | NON GARANTI | contrat explicite |
Snapshot public requis et présent :
reconnect_count
replay_attempt_count
continuity_gap_count
duplicate_update_count
last_requested_from_slot
last_observed_slot
state/error code safe
8. Gate Config V3 — pre.011
8.1 Schema et backward compatibility
Le gate opérateur pre.011 ferme les exigences suivantes :
| Exigence | Preuve | Verdict |
|---|---|---|
schema $id V3 |
urn:ksp:schema:std.transport:v3 |
PASS |
| branches V1/V2 conservées | fixtures V1, V2 et document committé | PASS |
| V1 HTTP-only | v1_transport_fixture... |
PASS |
| V2 HTTP+WS | fixture V2 + compatibilité constructeur | PASS |
| V3 HTTP+WS+gRPC | 113 tests Config | PASS |
grpc_endpoints optionnel par profil V3 |
profil devnet_public sans gRPC |
PASS |
| propriétés inconnues refusées | branches schema strictes | PASS |
8.2 Mapping runtime
V3 doit mapper :
grpc_defaults -> YellowstoneGrpcSessionSettings
grpc_endpoints[].url -> YellowstoneGrpcEndpointUrl
provider -> YellowstoneGrpcProviderName
cluster -> YellowstoneGrpcClusterName
protocol = solana_yellowstone -> gate Config explicite
metadata -> YellowstoneGrpcMetadataEntry::public
secret_metadata -> YellowstoneGrpcMetadataEntry::secret
session overrides -> merge avec grpc_defaults
API :
| Surface | Exigence | Statut source |
|---|---|---|
http_settings() |
inchangée | OK |
ws_settings() |
V1 None, V2/V3 selon profil | OK |
grpc_settings() |
V1/V2 None, V3 optionnel | PASS |
into_transport_settings() |
tuple historique HTTP + WS inchangé | PASS |
into_all_transport_settings() |
nouveau tuple HTTP + WS + gRPC | PASS |
8.3 Provenance et secrets
Règles validées :
metadata publique + provenance KSP_SECRET_* -> reject
secret_metadata sans provenance secret -> reject
secret_metadata + variable KSP_PUBLIC_/KSP_* -> reject
secret_metadata + KSP_SECRET_/KSPB_SECRET_ -> accept
segments littéraux autour du secret -> accept
safe_value -> secret segment ********
Transport Debug -> URL/metadata secret absents
Les tests V3 démontrent le cas valide et les deux croisements invalides sans exposer les canaris.
8.4 PublicNode Mainnet
Profil committé et validé :
profile_id = publicnode_mainnet
provider = publicnode
cluster = mainnet-beta
protocol = solana_yellowstone
url = https://solana-yellowstone-grpc.publicnode.com:443 # provider affiche host:port ; KSP ajoute le scheme TLS requis
metadata = aucune
Le mapping produit un endpoint TLS Yellowstone standard ; le test committed_v3_publicnode_mainnet_maps_provider_neutral_yellowstone_grpc passe et Debug ne doit pas exposer l'URL.
8.5 PublicNode Testnet
Verdict final documentaire : EXTERNAL BLOCK, NOT GUESSED.
Le réaudit officiel du 2026-08-24 confirme une capacité Solana Testnet gRPC chez PublicNode, mais l'hostname exact n'a pas été obtenu depuis une source PublicNode suffisamment autoritative. Aucun profil, aucun hostname déduit et aucun smoke Testnet ne sont versionnés.
capacité Testnet gRPC confirmée
hostname exact non confirmé
profil KSP absent
smoke KSP absent
raison interdiction d'inventer un endpoint provider
9. Provider-neutrality
| Point | Verdict |
|---|---|
type public PublicNodeGrpc* sans divergence |
absent, PASS |
| protocol standard encodé comme provider | non, PASS |
| provider descriptif séparé | oui, PASS |
| auth PublicNode hardcodée dans Transport | non, PASS |
Helius/OrbitFlare runtime gRPC dans 0.2.9 |
non, PASS |
| provider extensions dans N2 | aucune, PASS |
10. Non-régressions obligatoires
Le gate final doit préserver :
HTTP current typed 52/52
HTTP historical 14/14 Deprecated/Removed
KSP-TRANSPORT-007 vert
Standard WebSocket 9 familles / 18 opérations
Helius LaserStream WebSocket 7 familles standard + transaction + slotsUpdates, heartbeat provider-owned
Transport -> Config interdit
Transport -> std::env KSP_* interdit
tracing direct Transport interdit
pre.012 ne modifie pas le runtime Transport ; elle ajoute uniquement un smoke live ignoré par défaut et de la documentation/audit. Son seuil de non-régression est la baseline pre.011.
11. Historique des gates fermé
Les détails de commandes, warnings corrigés et fichiers exacts restent dans leurs deltas immuables.
| Tranche | Gate consolidé |
|---|---|
pre.001 + fix.001 + fix.002 |
audit/sizing/providers/licence fermé |
pre.002 + fix.001 + fix.002 |
moteur/settings/channel fermé |
pre.003 + fix.001 |
TLS/metadata/unary fermé |
pre.004 + fix.001 |
Subscribe common fermé |
pre.005 + fix.001 |
Accounts/Slots fermé |
pre.006 |
namespace HTTP fermé |
pre.007 |
Transactions fermé |
pre.008 + fix.001 |
Blocks fermé |
pre.009 + fix.001 |
bidi/backpressure fermé |
pre.010 + fix.001 |
reconnect/replay fermé sans warning |
pre.011 |
Config V3/PublicNode mapping fermé |
Cette table remplace les anciens appendices numérotés successivement 19.x, 20, 21, etc. qui rendaient le document ambigu.
12. Verdict opérateur pre.012
12.1 Gate déterministe reçu
| Exigence | Résultat opérateur |
|---|---|
cargo fmt --all |
PASS |
| audit Rust workspace | PASS, 0 candidate export |
| audit Markdown | PASS, 87 tableaux / 252 fichiers |
cargo check --workspace |
PASS |
cargo clippy --workspace --all-targets |
PASS sans warning |
| Config unit | 113/113 PASS |
| Config public API | 15/15 PASS |
| Config ownership | 5/5 PASS |
| Transport unit | 383/383 PASS |
| Transport public API | 49/49 PASS |
| Transport release completeness | 43/43 PASS |
| Transport doctests | 4/4 PASS |
| workspace dependencies | 3/3 PASS |
cargo test --workspace |
PASS |
| smoke Mainnet programmatique sans credential | NOT RUN, ignored |
| graphes Cargo finaux | NOT PROVIDED / NOT RUN |
Le test yellowstone_publicnode_smoke compile et apparaît correctement comme ignored dans les tests Transport et workspace, mais cela ne constitue pas une exécution live. Aucune preuve de cargo tree final n'est présente dans le log fourni.
12.2 Effet de pre.012-fix.001
Le fix ne change ni runtime, ni schema, ni Config, ni smoke. Il corrige le workflow de fermeture afin que les responsabilités restantes ne soient plus mélangées :
pre.013 technique/live : smoke PublicNode + graphes Cargo finaux
pre.014 réconciliation documentaire : plan/validation/README/USAGE/références
pre.015 publication minimale : prompt suivant + CHANGELOG + ROADMAP
rel.001 mécanique stable uniquement
Le contenu prompt/README/USAGE déjà préparé en pre.012 n'est pas supprimé rétroactivement. Le prompt reste un brouillon jusqu'à pre.015 ; README/USAGE seront réconciliés définitivement en pre.014.
13. Gate pre.013 — technique/live
Commandes minimales :
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo clippy --workspace --all-targets
cargo tree -p ksp-onchain-transport-lib
cargo tree -p ksp-onchain-transport-lib --duplicates
cargo tree --duplicates
cargo test -p ksp-onchain-transport-lib --test yellowstone_publicnode_smoke -- --ignored --nocapture
Verdicts attendus :
smoke Mainnet réellement exécuté
GetVersion + GetSlot via TLS sans credential ou incident externe précisément classifié
graphes Cargo inspectés
aucun changement README/USAGE/prompt/CHANGELOG/ROADMAP
Un défaut local découvert dans ce gate reste dans pre.013-fix.NNN. Un incident externe n'est jamais maquillé en PASS local.
14. Gate pre.014 — réconciliation documentaire
Cette tranche ferme les documents durables après le gate technique réel :
plan 016
validation 012
README/USAGE Transport
documents de référence 0.2.9 réellement concernés
audit Markdown des documents touchés
Elle n'introduit aucun nouveau runtime/smoke et ne finalise pas CHANGELOG.md, ROADMAP.md ni le prompt suivant.
Le verdict de la validation 012 devient définitif dans cette tranche, sur la base exclusive des preuves réellement exécutées en pre.013 et des gates antérieurs.
15. Gate pre.015 — préparation de publication
Payload fonctionnel autorisé :
prompts/015-V0_2_10_START_PROMPT.md
CHANGELOG.md
ROADMAP.md
Seuls les fichiers mécaniques de version et de traçabilité (Cargo.toml, delta pre.015) peuvent s'ajouter à ce payload. Aucun README, USAGE, plan, validation, règle, code, test, schema ou config ne doit être corrigé dans pre.015.
Si un tel défaut est découvert, une nouvelle prerelease dédiée est ouverte puis la préparation de publication est rejouée sous un nouveau numéro.
16. Verdict stable attendu avant rel.001
0.2.9 peut passer à rel.001 seulement après la séquence suivante :
pre.013 technique/live fermé
pre.014 réconciliation documentaire fermée
pre.015 prompt/CHANGELOG/ROADMAP fermé
Et si tous les invariants suivants sont vrais :
standard vs extension explicitement classifié
SubscribeDeshred OUT documenté
7 unary verts
Subscribe + 9 updates verts
resource/backpressure/lifecycle verts
reconnect/replay sans promesse lossless
Config V3 backward V1/V2
provider/protocol distincts
PublicNode Mainnet live exécuté avec résultat consigné
Testnet jamais inventé
HTTP/WS/Helius non régressés
dependency firewall vert
cargo graphs inspectés
README/USAGE réconciliés avant la dernière pre
validation 012 fermée avant la dernière pre
prompt/CHANGELOG/ROADMAP seuls dans la dernière pre
workspace final vert