v0.3.14-pre.007

This commit is contained in:
2026-09-12 07:47:16 +02:00
parent ae712eae64
commit 887664f3c0
9 changed files with 619 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
// version: 6
// version: 7
/// Maximum number of slots admitted by one private continuity HTTP discovery window outside this module.
pub(crate) const MAX_RAW_TRANSACTION_INGEST_CONTINUITY_DISCOVERY_WINDOW_SLOTS: u64 = MAX_RAW_TRANSACTION_INGEST_REPAIR_DISCOVERY_WINDOW_SLOTS;
@@ -174,6 +174,43 @@ impl RawTransactionIngestGapRange {
}
}
/// Private run-local obligation for one transaction reference already observed by a live source.
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct RawTransactionIngestKnownReferenceObligation {
commitment: ksp_onchain_transport_lib::SolanaCommitment,
reference: ksp_store_lib::RawTransactionReference,
slot: u64,
}
impl crate::RawTransactionIngestKnownReferenceObligation {
/// Creates one known-reference obligation without inventing any absence or coverage proof.
pub(crate) fn new(
reference: ksp_store_lib::RawTransactionReference,
slot: u64,
commitment: ksp_onchain_transport_lib::SolanaCommitment,
) -> ksp_core_lib::Result<Self> {
if commitment == ksp_onchain_transport_lib::SolanaCommitment::Processed {
return std::result::Result::Err(crate::runtime_error("continuity.known_reference_processed_unsupported"));
}
return std::result::Result::Ok(Self { commitment, reference, slot });
}
/// Returns the exact commitment under which this reference must be resolved.
pub(crate) const fn commitment(&self) -> ksp_onchain_transport_lib::SolanaCommitment {
return self.commitment;
}
/// Returns the already-known canonical transaction reference.
pub(crate) const fn reference(&self) -> &ksp_store_lib::RawTransactionReference {
return &self.reference;
}
/// Returns the already-observed slot associated with the reference.
pub(crate) const fn slot(&self) -> u64 {
return self.slot;
}
}
/// Private run-local anchor for one WebSocket continuity incident.
///
/// The anchor never derives slots from wall-clock time. Its inclusive start is the latest slot actually observed by that source before Transport reported a

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
// version: 30
// version: 31
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -119,6 +119,8 @@ pub(crate) use self::continuity::RawTransactionIngestContinuityCapabilityDescrip
pub(crate) use self::continuity::RawTransactionIngestContinuityContracts;
/// Private provider-neutral coverage scope used by run-local continuity proof contracts.
pub(crate) use self::continuity::RawTransactionIngestCoverageScope;
/// Private run-local obligation for one transaction reference already observed by a live source.
pub(crate) use self::continuity::RawTransactionIngestKnownReferenceObligation;
/// Private run-local WebSocket incident anchor built only from observed source slots and safe Transport counters.
pub(crate) use self::continuity::RawTransactionIngestWebSocketIncidentAnchor;
/// Creates one terminal content-conflict error without copying conflicting material into diagnostics.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
// version: 32
// version: 33
use sha2::Digest; // rust-rules: trait-import
@@ -4026,6 +4026,20 @@ struct RawTransactionIngestHydrationFetch {
observed: RawTransactionIngestObservedTransaction,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RawTransactionIngestKnownReferenceMissingDisposition {
AwaitCoverage,
PreferBlockSlot,
}
enum RawTransactionIngestKnownReferenceHydrationResolution {
Available(crate::RawTransactionIngress),
Missing {
disposition: RawTransactionIngestKnownReferenceMissingDisposition,
obligation: crate::RawTransactionIngestKnownReferenceObligation,
},
}
#[derive(Clone)]
enum RawTransactionIngestSharedHydrationResult {
Available(RawTransactionIngestObservedTransaction),
@@ -4219,14 +4233,24 @@ impl RawTransactionIngestHydrationCoordinator {
self.pending_signal_count -= pending.signals.len();
for pending_signal in pending.signals {
let signal_slot = pending_signal.signal.slot;
let ingress = finalize_hydration(hydration, settings, pending_signal.signal, pending_signal.received_at, &fetched.observed);
let ingress = match ingress {
let resolution = resolve_known_reference_hydration(hydration, settings, pending_signal.signal, pending_signal.received_at, &fetched.observed);
let resolution = match resolution {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let ingress = match ingress {
std::option::Option::Some(value) => value,
std::option::Option::None => {
let ingress = match resolution {
RawTransactionIngestKnownReferenceHydrationResolution::Available(value) => value,
RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation } => {
if obligation.commitment() != hydration.commitment
|| obligation.reference().network() != &hydration.network
|| obligation.slot() != signal_slot
{
return std::result::Result::Err(crate::runtime_error("source.known_reference_obligation_mismatch"));
}
match disposition {
RawTransactionIngestKnownReferenceMissingDisposition::AwaitCoverage
| RawTransactionIngestKnownReferenceMissingDisposition::PreferBlockSlot => {},
}
if let std::result::Result::Err(error) = processing_frontier.settle_pending(signal_slot) {
return std::result::Result::Err(error);
}
@@ -4389,6 +4413,38 @@ fn shared_hydration_result(
};
}
fn resolve_known_reference_hydration(
hydration: &RawTransactionIngestHydrationContext,
settings: &crate::RawTransactionIngestSettings,
signal: RawTransactionIngestSourceSignal,
received_at: ksp_store_lib::RawTimestamp,
observed: &RawTransactionIngestObservedTransaction,
) -> ksp_core_lib::Result<RawTransactionIngestKnownReferenceHydrationResolution> {
let reference = ksp_store_lib::RawTransactionReference::new(signal.network.clone(), signal.signature);
let obligation = match crate::RawTransactionIngestKnownReferenceObligation::new(reference, signal.slot, hydration.commitment) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let ingress = finalize_hydration(hydration, settings, signal, received_at, observed);
let ingress = match ingress {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
if let std::option::Option::Some(value) = ingress {
return std::result::Result::Ok(RawTransactionIngestKnownReferenceHydrationResolution::Available(value));
}
let block_slot_supported = match http_role_supports_rpc_method(&hydration.http_pool, &hydration.hydration_role, "getBlock", hydration.network.as_str()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let disposition = if block_slot_supported {
RawTransactionIngestKnownReferenceMissingDisposition::PreferBlockSlot
} else {
RawTransactionIngestKnownReferenceMissingDisposition::AwaitCoverage
};
return std::result::Result::Ok(RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation });
}
fn finalize_hydration(
hydration: &RawTransactionIngestHydrationContext,
settings: &crate::RawTransactionIngestSettings,

View File

@@ -1,7 +1,7 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
// version: 30
// version: 31
//! External public, security, redaction and release-boundary hardening canaries through `v0.3.14-pre.006`.
//! External public, security, redaction and release-boundary hardening canaries through `v0.3.14-pre.007`.
fn network(value: &'static str) -> std::option::Option<ksp_store_lib::RawNetworkId> {
let result = ksp_store_lib::RawNetworkId::new(value);
@@ -1116,3 +1116,30 @@ fn v0_3_14_pre_006_http_discovery_is_bounded_prefers_closed_range_and_never_uses
assert!(!root.contains("repair"), "pre.006 leaked lower-case repair responsibility through crate root");
return;
}
#[test]
fn v0_3_14_pre_007_known_reference_hydration_reuses_one_registry_and_preserves_missing_obligation() {
let continuity = include_str!("../src/continuity.rs");
let resources = include_str!("../src/runtime_resources.rs");
let root = include_str!("../src/lib.rs");
for required in [
"RawTransactionIngestKnownReferenceObligation",
"known_reference_processed_unsupported",
"RawTransactionIngestKnownReferenceHydrationResolution",
"RawTransactionIngestKnownReferenceMissingDisposition",
"fetch_hydration_shared",
"resolve_known_reference_hydration",
"PreferBlockSlot",
"AwaitCoverage",
"get_transaction_observed",
"http_role_supports_rpc_method",
] {
assert!(continuity.contains(required) || resources.contains(required), "required pre.007 known-reference guard missing: {required}");
}
assert_eq!(resources.matches("struct RawTransactionIngestGlobalHydrationRegistry").count(), 1);
assert!(!resources.contains("KnownReferenceHydrationRegistry"));
assert!(!resources.contains("known_reference_retry"));
assert!(!root.contains("pub use self::continuity::RawTransactionIngestKnownReferenceObligation"));
assert!(!root.contains("repair"), "pre.007 leaked lower-case repair responsibility through crate root");
return;
}

View File

@@ -1,7 +1,7 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
// version: 25
// version: 26
//! Release-completeness canaries through the `v0.3.14-pre.006` bounded HTTP continuity-discovery tranche.
//! Release-completeness canaries through the `v0.3.14-pre.007` known-reference hydration tranche.
#[test]
fn pre_010_production_module_inventory_is_exact() -> std::io::Result<()> {
@@ -302,3 +302,23 @@ fn v0_3_14_pre_006_bounded_http_discovery_canaries_are_present_without_backfill_
assert!(!root.contains("backfill"));
return;
}
#[test]
fn v0_3_14_pre_007_known_reference_hydration_canaries_are_present_without_second_registry_or_public_surface_growth() {
let continuity_tests = include_str!("../unit_tests/continuity.rs");
let hardening = include_str!("hardening.rs");
let resource_tests = include_str!("../unit_tests/runtime_resources.rs");
let root = include_str!("../src/lib.rs");
for required in [
"pre_007_known_reference_obligation_preserves_exact_reference_slot_and_commitment",
"v0_3_14_pre_007_known_reference_hydration_reuses_global_registry_and_available_material",
"v0_3_14_pre_007_missing_known_reference_remains_open_without_block_capability",
"v0_3_14_pre_007_missing_known_reference_prefers_same_role_block_slot_when_supported",
] {
assert!(continuity_tests.contains(required) || resource_tests.contains(required), "required pre.007 canary missing: {required}");
}
assert!(hardening.contains("v0_3_14_pre_007_known_reference_hydration_reuses_one_registry_and_preserves_missing_obligation"));
assert!(!root.contains("pub use self::continuity::RawTransactionIngestKnownReferenceObligation"));
assert!(!root.contains("pub use self::runtime_resources::RawTransactionIngestKnownReference"));
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
// version: 4
// version: 5
fn network() -> std::option::Option<ksp_store_lib::RawNetworkId> {
return match ksp_store_lib::RawNetworkId::new("mainnet") {
@@ -453,3 +453,23 @@ fn pre_005_coverage_epoch_ledger_is_bounded_monotone_and_capability_bound() {
assert!(overflow.validate_invariants(std::slice::from_ref(&matching)).is_err());
return;
}
#[test]
fn pre_007_known_reference_obligation_preserves_exact_reference_slot_and_commitment() {
let network = match network() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let reference = ksp_store_lib::RawTransactionReference::new(network, ksp_store_lib::RawTransactionSignature::new([9_u8; 64]));
let obligation =
match crate::RawTransactionIngestKnownReferenceObligation::new(reference.clone(), 4242, ksp_onchain_transport_lib::SolanaCommitment::Confirmed) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("unexpected known-reference obligation failure: {error}"),
};
assert_eq!(obligation.reference(), &reference);
assert_eq!(obligation.slot(), 4242);
assert_eq!(obligation.commitment(), ksp_onchain_transport_lib::SolanaCommitment::Confirmed);
let processed = crate::RawTransactionIngestKnownReferenceObligation::new(reference, 4242, ksp_onchain_transport_lib::SolanaCommitment::Processed);
assert!(processed.is_err());
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
// version: 26
// version: 27
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
@@ -450,6 +450,16 @@ const PRE_004_ZERO_SIGNATURE_TEXT: &str = "1111111111111111111111111111111111111
const PRE_004_ZERO_TRANSACTION_BASE64: &str = "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
fn http_pool_for_url(url: &str, cluster: &str, endpoint_name: &str, provider: &str) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
return http_pool_for_url_with_request_kinds(url, cluster, endpoint_name, provider, &["get_transaction"]);
}
fn http_pool_for_url_with_request_kinds(
url: &str,
cluster: &str,
endpoint_name: &str,
provider: &str,
request_kinds: &[&str],
) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
let url = match ksp_onchain_transport_lib::HttpEndpointUrl::parse(url) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
@@ -457,7 +467,7 @@ fn http_pool_for_url(url: &str, cluster: &str, endpoint_name: &str, provider: &s
let role = ksp_onchain_transport_lib::HttpEndpointRoleSettings::new(
ksp_onchain_transport_lib::HttpRoleName::new("hydration"),
true,
std::vec![ksp_onchain_transport_lib::HttpRequestKind::new("get_transaction")],
request_kinds.iter().map(|value| return ksp_onchain_transport_lib::HttpRequestKind::new(*value)).collect(),
10,
ksp_onchain_transport_lib::HttpRoleLimits::new(
std::option::Option::None,
@@ -517,6 +527,29 @@ fn signal_source_for_http_url_with_commitment(
};
}
fn signal_source_for_http_url_with_request_kinds(url: &str, request_kinds: &[&str]) -> std::option::Option<crate::RawTransactionIngestYellowstoneSource> {
let endpoint = match grpc_endpoint("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let channel = match ksp_onchain_transport_lib::YellowstoneGrpcChannel::prepare(&endpoint) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let request = match transaction_request(std::option::Option::Some(ksp_onchain_transport_lib::SolanaCommitment::Confirmed)) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let pool = match http_pool_for_url_with_request_kinds(url, "devnet", "http-hydration-fixture", "fixture-http-provider", request_kinds) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
return match crate::RawTransactionIngestYellowstoneSource::new(channel, request, pool, ksp_onchain_transport_lib::HttpRoleName::new("hydration")) {
std::result::Result::Ok(value) => std::option::Option::Some(value),
std::result::Result::Err(_) => std::option::Option::None,
};
}
fn standard_logs_source_for_http_url(
url: &str,
filter: ksp_onchain_transport_lib::SolanaLogsSubscribeFilter,
@@ -3140,6 +3173,196 @@ fn v0_3_14_pre_006_with_limit_discovery_never_uses_tip_alone_as_tail_coverage_pr
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_14_pre_007_known_reference_hydration_reuses_global_registry_and_available_material() {
let body = std::format!(
"{{\"jsonrpc\":\"2.0\",\"result\":{{\"slot\":42,\"blockTime\":1760000120,\"transaction\":[\"{}\",\"base64\"],\"meta\":null,\"version\":0,\"transactionIndex\":7}},\"id\":1}}",
PRE_004_ZERO_TRANSACTION_BASE64,
);
let (url, server) = match serve_http_once(body) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let source = match signal_source_for_http_url(url.as_str()) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let settings = match pre_004_settings() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let signal = match pre_004_signal(&source, super::RawTransactionIngestSourceFamily::Transaction, 42, 7, &["tx-fixture"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let hydration = source.hydration_context();
let key = match super::hydration_key(&hydration, &signal) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(4, 1));
let first = super::fetch_hydration_shared(
std::sync::Arc::clone(&registry),
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key.clone(),
hydration.commitment,
);
let second = super::fetch_hydration_shared(
std::sync::Arc::clone(&registry),
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key,
hydration.commitment,
);
let (first, second) = tokio::join!(first, second);
let first = match first {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert!(second.is_ok());
let request = match server.join() {
std::result::Result::Ok(std::result::Result::Ok(value)) => value,
_ => return,
};
assert!(request.contains("\"method\":\"getTransaction\""));
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_200_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let resolved = super::resolve_known_reference_hydration(&hydration, &settings, signal, received_at, &first.observed);
let ingress = match resolved {
std::result::Result::Ok(super::RawTransactionIngestKnownReferenceHydrationResolution::Available(value)) => value,
_ => return,
};
let (mut admission, sender) = crate::RawTransactionAdmission::new(1);
if sender.send(ingress).await.is_err() {
return;
}
std::mem::drop(sender);
let acquisition = match admission.receive(settings.network()).await {
std::result::Result::Ok(std::option::Option::Some(value)) => value,
_ => return,
};
assert_eq!(acquisition.transaction().slot(), 42);
assert_eq!(acquisition.transaction().reference().signature().as_bytes(), &[0_u8; 64]);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_14_pre_007_missing_known_reference_remains_open_without_block_capability() {
let (url, server) = match serve_http_once("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}".to_owned()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let source = match signal_source_for_http_url(url.as_str()) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let settings = match pre_004_settings() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let signal = match pre_004_signal(&source, super::RawTransactionIngestSourceFamily::TransactionStatus, 77, 0, &["status-fixture"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let hydration = source.hydration_context();
let key = match super::hydration_key(&hydration, &signal) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(2, 1));
let fetched = super::fetch_hydration_shared(
registry,
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key,
hydration.commitment,
)
.await;
let fetched = match fetched {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let _request = match server.join() {
std::result::Result::Ok(std::result::Result::Ok(value)) => value,
_ => return,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_200_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let resolved = super::resolve_known_reference_hydration(&hydration, &settings, signal, received_at, &fetched.observed);
let (disposition, obligation) = match resolved {
std::result::Result::Ok(super::RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation }) => (disposition, obligation),
_ => return,
};
assert_eq!(disposition, super::RawTransactionIngestKnownReferenceMissingDisposition::AwaitCoverage);
assert_eq!(obligation.slot(), 77);
assert_eq!(obligation.commitment(), ksp_onchain_transport_lib::SolanaCommitment::Confirmed);
assert_eq!(obligation.reference().signature().as_bytes(), &[0_u8; 64]);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_14_pre_007_missing_known_reference_prefers_same_role_block_slot_when_supported() {
let (url, server) = match serve_http_once("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}".to_owned()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let source = match signal_source_for_http_url_with_request_kinds(url.as_str(), &["get_transaction", "get_block"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let settings = match pre_004_settings() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let signal = match pre_004_signal(&source, super::RawTransactionIngestSourceFamily::Transaction, 88, 0, &["tx-fixture"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let hydration = source.hydration_context();
let key = match super::hydration_key(&hydration, &signal) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(2, 1));
let fetched = super::fetch_hydration_shared(
registry,
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key,
hydration.commitment,
)
.await;
let fetched = match fetched {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let _request = match server.join() {
std::result::Result::Ok(std::result::Result::Ok(value)) => value,
_ => return,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_200_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let resolved = super::resolve_known_reference_hydration(&hydration, &settings, signal, received_at, &fetched.observed);
let (disposition, obligation) = match resolved {
std::result::Result::Ok(super::RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation }) => (disposition, obligation),
_ => return,
};
assert_eq!(disposition, super::RawTransactionIngestKnownReferenceMissingDisposition::PreferBlockSlot);
assert_eq!(obligation.slot(), 88);
return;
}
#[test]
fn v0_3_13_pre_006_http_block_polling_qualifies_legacy_v0_v1_and_rejects_ambiguous_or_future_versions() {
let cases = [