v0.3.8-pre.004

This commit is contained in:
2026-09-03 12:32:53 +02:00
parent 009b957523
commit c4198ac656
17 changed files with 902 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
// version: 17
// version: 18
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -281,6 +281,7 @@ fn pre_009_live_raw_transaction_proof_is_opt_in_isolated_and_secret_safe() {
"prove_concurrent_identical_insert",
"prove_concurrent_divergent_insert",
"prove_pagination",
"prove_inspection",
"prove_retention_and_rehydrate",
"prove_retention_races",
"prove_cancellation_rollback",
@@ -298,13 +299,14 @@ fn pre_009_live_raw_transaction_proof_is_opt_in_isolated_and_secret_safe() {
}
#[test]
fn pre_010_raw_capability_implementation_inventory_is_exactly_ten() {
fn v0_3_8_pre_004_raw_capability_implementation_inventory_is_exactly_eleven() {
let runtime = include_str!("../src/runtime.rs");
let capability_impls = [
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
"impl ksp_store_api::RawAccountObservationWrite for PostgresBackend",
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
"impl ksp_store_api::RawTransactionInspectionRead for PostgresBackend",
"impl ksp_store_api::RawTransactionObservationRead for PostgresBackend",
"impl ksp_store_api::RawTransactionObservationWrite for PostgresBackend",
"impl ksp_store_api::RawTransactionRead for PostgresBackend",
@@ -315,7 +317,7 @@ fn pre_010_raw_capability_implementation_inventory_is_exactly_ten() {
for implementation in capability_impls {
assert_eq!(runtime.matches(implementation).count(), 1, "unexpected PostgreSQL capability implementation inventory: {implementation}");
}
assert_eq!(runtime.matches("impl ksp_store_api::Raw").count(), 10);
assert_eq!(runtime.matches("impl ksp_store_api::Raw").count(), 11);
let migration = include_str!("../src/migration.rs");
assert!(migration.contains("raw_account_state"));
assert!(migration.contains("crate::V002_RESOURCES"));
@@ -324,25 +326,77 @@ fn pre_010_raw_capability_implementation_inventory_is_exactly_ten() {
}
#[test]
fn pre_010_raw_transaction_private_sql_keeps_keyset_navigation_and_bounded_statement_surface() {
fn v0_3_8_pre_004_raw_transaction_keyset_sql_remains_offset_free_and_unchanged_in_role() {
let source = include_str!("../src/raw_transaction.rs");
for required in [
"ORDER BY slot ASC, signature ASC",
"ORDER BY slot DESC, signature DESC",
"LIMIT $5",
"FOR UPDATE",
"ON CONFLICT (signature) DO NOTHING",
"ON CONFLICT (observation_key) DO NOTHING",
"ksp_raw_transaction_archive_payloads",
] {
let ascending = source.lines().find(|line| line.starts_with("const LIST_TRANSACTIONS_ASC_SQL"));
let ascending = match ascending {
std::option::Option::Some(value) => value,
std::option::Option::None => panic!("missing canonical ascending keyset SQL"),
};
let descending = source.lines().find(|line| line.starts_with("const LIST_TRANSACTIONS_DESC_SQL"));
let descending = match descending {
std::option::Option::Some(value) => value,
std::option::Option::None => panic!("missing canonical descending keyset SQL"),
};
for statement in [ascending, descending] {
assert!(statement.contains("retention_state <> 'purged'"));
assert!(statement.contains("LIMIT $5"));
assert!(!statement.contains(" OFFSET "));
}
assert!(ascending.contains("(slot, signature) >"));
assert!(ascending.contains("ORDER BY slot ASC, signature ASC"));
assert!(descending.contains("(slot, signature) <"));
assert!(descending.contains("ORDER BY slot DESC, signature DESC"));
for required in ["FOR UPDATE", "ON CONFLICT (signature) DO NOTHING", "ON CONFLICT (observation_key) DO NOTHING", "ksp_raw_transaction_archive_payloads"] {
assert!(source.contains(required), "required hardened RawTransaction SQL contract missing: {required}");
}
for forbidden in [" OFFSET ", "SELECT *", "ON CONFLICT DO UPDATE", "processing_state", "batch_size", "priority"] {
for forbidden in ["SELECT *", "ON CONFLICT DO UPDATE", "processing_state", "batch_size", "priority"] {
assert!(!source.contains(forbidden), "forbidden RawTransaction scope/policy SQL detected: {forbidden}");
}
return;
}
#[test]
fn v0_3_8_pre_004_transaction_inspection_sql_is_single_statement_payload_free_counted_and_random_access() {
let source = include_str!("../src/raw_transaction.rs");
let ascending = source.lines().find(|line| line.starts_with("const INSPECT_TRANSACTIONS_ASC_SQL"));
let ascending = match ascending {
std::option::Option::Some(value) => value,
std::option::Option::None => panic!("missing ascending inspection SQL"),
};
let descending = source.lines().find(|line| line.starts_with("const INSPECT_TRANSACTIONS_DESC_SQL"));
let descending = match descending {
std::option::Option::Some(value) => value,
std::option::Option::None => panic!("missing descending inspection SQL"),
};
for statement in [ascending, descending] {
for required in [
"COUNT(*)::TEXT AS filtered_count_text",
"COUNT(*)::TEXT FROM ksp_raw_transactions",
"LEFT JOIN LATERAL",
"LEFT JOIN ksp_raw_transaction_archive_payloads",
"OCTET_LENGTH(transaction_row.payload)::BIGINT",
"OCTET_LENGTH(archive_row.payload)::BIGINT",
"LIMIT $3 OFFSET $4",
"payload_size_bytes",
"hot_payload_present",
"archive_payload_present",
] {
assert!(statement.contains(required), "missing transaction inspection SQL contract: {required}");
}
assert!(!statement.contains("transaction_row.payload, transaction_row.retention_state"));
assert!(!statement.contains("archive_row.payload AS"));
assert!(!statement.contains("retention_state <> 'purged'"));
}
assert!(ascending.contains("ORDER BY transaction_row.slot ASC, transaction_row.signature ASC"));
assert!(descending.contains("ORDER BY transaction_row.slot DESC, transaction_row.signature DESC"));
assert_eq!(source.matches(" OFFSET ").count(), 2);
assert!(source.contains("raw_transaction_inspection_sql_window(query.page())"));
assert!(source.contains("raw_transaction_inspection_offset"));
assert!(source.contains("raw_transaction_inspection_limit"));
return;
}
#[test]
fn pre_010_raw_account_private_sql_is_non_destructive_keyset_and_family_local() {
let source = include_str!("../src/raw_account.rs");