v0.3.3-pre.010

This commit is contained in:
2026-08-30 16:06:20 +02:00
parent f28e4d87f0
commit 12eaf7a3de
8 changed files with 283 additions and 12 deletions

View File

@@ -6,7 +6,7 @@ resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"]
[workspace.package]
version = "0.3.3-pre.9.fix.6"
version = "0.3.3-pre.10"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-store-lib/tests/hardening_completeness.rs
// version: 3
// version: 4
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -261,3 +261,29 @@ fn pre_009_facade_production_sources_keep_config_env_physical_sql_and_backend_ha
}
return;
}
#[test]
fn pre_010_facade_raw_transaction_capability_inventory_is_exact_and_raw_account_scope_stays_closed() {
let store = include_str!("../src/store.rs");
let capability_impls = [
"impl ksp_store_api::RawTransactionRead for Store",
"impl ksp_store_api::RawTransactionWrite for Store",
"impl ksp_store_api::RawTransactionObservationRead for Store",
"impl ksp_store_api::RawTransactionObservationWrite for Store",
"impl ksp_store_api::RawTransactionRetentionRead for Store",
"impl ksp_store_api::RawTransactionRetentionWrite for Store",
];
for implementation in capability_impls {
assert_eq!(store.matches(implementation).count(), 1, "unexpected Store capability implementation inventory: {implementation}");
}
for forbidden in [
"impl ksp_store_api::RawAccountStateRead for Store",
"impl ksp_store_api::RawAccountStateWrite for Store",
"impl ksp_store_api::RawAccountObservationRead for Store",
"impl ksp_store_api::RawAccountObservationWrite for Store",
] {
assert!(!store.contains(forbidden), "RawAccountState scope opened in Store during RawTransaction hardening: {forbidden}");
}
assert_eq!(store.matches("validate_operation_network(").count(), 9);
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-store-lib/unit_tests/store.rs
// version: 5
// version: 6
fn poll_ready<T>(future: impl std::future::Future<Output = T>) -> T {
let mut future = std::boxed::Box::pin(future);
@@ -72,3 +72,36 @@ fn pre_008_operation_network_guard_rejects_mismatch_without_echoing_requested_ne
assert!(!std::format!("{error:?}").contains("other-network"));
return;
}
#[cfg(feature = "postgres")]
#[test]
fn pre_010_postgres_error_code_mapping_covers_every_current_backend_kind() {
let cases = [
(ksp_store_postgres_lib::PostgresBackendErrorKind::ConfigInvalid, crate::ERROR_CODE_POSTGRES_CONFIG_INVALID),
(ksp_store_postgres_lib::PostgresBackendErrorKind::ConnectFailed, crate::ERROR_CODE_POSTGRES_CONNECT_FAILED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::PoolTimeout, crate::ERROR_CODE_POSTGRES_POOL_TIMEOUT),
(ksp_store_postgres_lib::PostgresBackendErrorKind::HealthFailed, crate::ERROR_CODE_POSTGRES_HEALTH_FAILED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::Conflict, ksp_store_api::ERROR_CODE_RAW_CONFLICT),
(ksp_store_postgres_lib::PostgresBackendErrorKind::DataInvalid, crate::ERROR_CODE_POSTGRES_DATA_INVALID),
(ksp_store_postgres_lib::PostgresBackendErrorKind::MigrationFailed, crate::ERROR_CODE_POSTGRES_MIGRATION_FAILED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::PageLimitUnsupported, crate::ERROR_CODE_POSTGRES_PAGE_LIMIT_UNSUPPORTED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::MigrationMismatch, crate::ERROR_CODE_POSTGRES_MIGRATION_MISMATCH),
(ksp_store_postgres_lib::PostgresBackendErrorKind::QueryInvalid, ksp_store_api::ERROR_CODE_RAW_QUERY_INVALID),
(ksp_store_postgres_lib::PostgresBackendErrorKind::ReadFailed, crate::ERROR_CODE_POSTGRES_READ_FAILED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::ReferenceNotFound, crate::ERROR_CODE_RAW_REFERENCE_NOT_FOUND),
(
ksp_store_postgres_lib::PostgresBackendErrorKind::RetentionCompactionUnsupported,
crate::ERROR_CODE_POSTGRES_RETENTION_COMPACTION_UNSUPPORTED,
),
(ksp_store_postgres_lib::PostgresBackendErrorKind::SchemaNewer, crate::ERROR_CODE_POSTGRES_SCHEMA_NEWER),
(ksp_store_postgres_lib::PostgresBackendErrorKind::ShutdownTimeout, crate::ERROR_CODE_SHUTDOWN_TIMEOUT),
(ksp_store_postgres_lib::PostgresBackendErrorKind::TlsFailed, crate::ERROR_CODE_POSTGRES_TLS_FAILED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::WriteFailed, crate::ERROR_CODE_POSTGRES_WRITE_FAILED),
(ksp_store_postgres_lib::PostgresBackendErrorKind::WrongNetwork, crate::ERROR_CODE_WRONG_NETWORK),
];
assert_eq!(cases.len(), 18);
for (kind, expected) in cases {
assert_eq!(super::postgres_error_code(kind), expected);
}
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
// version: 9
// version: 10
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -255,3 +255,49 @@ fn pre_009_live_raw_transaction_proof_is_opt_in_isolated_and_secret_safe() {
}
return;
}
#[test]
fn pre_010_raw_transaction_capability_implementation_inventory_is_exact_and_raw_account_scope_stays_closed() {
let runtime = include_str!("../src/runtime.rs");
let capability_impls = [
"impl ksp_store_api::RawTransactionRead for PostgresBackend",
"impl ksp_store_api::RawTransactionWrite for PostgresBackend",
"impl ksp_store_api::RawTransactionObservationRead for PostgresBackend",
"impl ksp_store_api::RawTransactionObservationWrite for PostgresBackend",
"impl ksp_store_api::RawTransactionRetentionRead for PostgresBackend",
"impl ksp_store_api::RawTransactionRetentionWrite for PostgresBackend",
];
for implementation in capability_impls {
assert_eq!(runtime.matches(implementation).count(), 1, "unexpected PostgreSQL capability implementation inventory: {implementation}");
}
for forbidden in [
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
"impl ksp_store_api::RawAccountObservationWrite for PostgresBackend",
] {
assert!(!runtime.contains(forbidden), "RawAccountState scope opened during RawTransaction hardening: {forbidden}");
}
let migration = include_str!("../src/migration.rs");
assert!(!migration.contains("ksp_raw_account"));
return;
}
#[test]
fn pre_010_raw_transaction_private_sql_keeps_keyset_navigation_and_bounded_statement_surface() {
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 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"] {
assert!(!source.contains(forbidden), "forbidden RawTransaction scope/policy SQL detected: {forbidden}");
}
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-store-postgres-lib/unit_tests/runtime.rs
// version: 4
// version: 5
fn network() -> ksp_store_api::RawNetworkId {
return match ksp_store_api::RawNetworkId::new("devnet") {
@@ -124,3 +124,38 @@ fn pre_008_capability_error_mapping_uses_stable_store_and_store_api_codes() {
}
return;
}
#[test]
fn pre_010_capability_error_mapping_covers_every_current_backend_error_kind() {
let cases = [
(crate::PostgresBackendErrorKind::ConfigInvalid, ksp_store_api::ErrorCode::new("store", "postgres_config_invalid")),
(crate::PostgresBackendErrorKind::ConnectFailed, ksp_store_api::ErrorCode::new("store", "postgres_connect_failed")),
(crate::PostgresBackendErrorKind::PoolTimeout, ksp_store_api::ErrorCode::new("store", "postgres_pool_timeout")),
(crate::PostgresBackendErrorKind::HealthFailed, ksp_store_api::ErrorCode::new("store", "postgres_health_failed")),
(crate::PostgresBackendErrorKind::Conflict, ksp_store_api::ERROR_CODE_RAW_CONFLICT),
(crate::PostgresBackendErrorKind::DataInvalid, ksp_store_api::ErrorCode::new("store", "postgres_data_invalid")),
(crate::PostgresBackendErrorKind::MigrationFailed, ksp_store_api::ErrorCode::new("store", "postgres_migration_failed")),
(crate::PostgresBackendErrorKind::PageLimitUnsupported, ksp_store_api::ErrorCode::new("store", "postgres_page_limit_unsupported")),
(crate::PostgresBackendErrorKind::MigrationMismatch, ksp_store_api::ErrorCode::new("store", "postgres_migration_mismatch")),
(crate::PostgresBackendErrorKind::QueryInvalid, ksp_store_api::ERROR_CODE_RAW_QUERY_INVALID),
(crate::PostgresBackendErrorKind::ReadFailed, ksp_store_api::ErrorCode::new("store", "postgres_read_failed")),
(crate::PostgresBackendErrorKind::ReferenceNotFound, ksp_store_api::ErrorCode::new("store", "raw_reference_not_found")),
(crate::PostgresBackendErrorKind::RetentionCompactionUnsupported, crate::ERROR_CODE_POSTGRES_RETENTION_COMPACTION_UNSUPPORTED),
(crate::PostgresBackendErrorKind::SchemaNewer, ksp_store_api::ErrorCode::new("store", "postgres_schema_newer")),
(crate::PostgresBackendErrorKind::ShutdownTimeout, ksp_store_api::ErrorCode::new("store", "shutdown_timeout")),
(crate::PostgresBackendErrorKind::TlsFailed, ksp_store_api::ErrorCode::new("store", "postgres_tls_failed")),
(crate::PostgresBackendErrorKind::WriteFailed, ksp_store_api::ErrorCode::new("store", "postgres_write_failed")),
(crate::PostgresBackendErrorKind::WrongNetwork, ksp_store_api::ErrorCode::new("store", "wrong_network")),
];
assert_eq!(cases.len(), 18);
for (kind, expected) in cases {
let backend = crate::PostgresBackendError::new(kind, "pre_010_safe_phase");
let mapped = super::map_capability_error(backend);
assert_eq!(mapped.code(), expected);
let rendered = std::format!("{mapped:?}");
assert!(rendered.contains("pre_010_safe_phase"));
assert!(!rendered.contains("postgresql://"));
assert!(!rendered.contains("SELECT "));
}
return;
}

112
deltas/0.3.3/pre.010.md Normal file
View File

@@ -0,0 +1,112 @@
<!-- file: deltas/0.3.3/pre.010.md -->
<!-- version: 1 -->
# Delta `0.3.3-pre.010` — hardening/completeness RawTransaction
## 1. Base acquise
Base opérateur :
```text
0.3.3-pre.9.fix.6
```
Le gate standard est entièrement propre et la preuve opt-in `postgres_raw_transaction_live` passe sur PostgreSQL 17. `pre.009`, corrections incluses, est donc fermée.
## 2. Version
```text
workspace.package.version = 0.3.3-pre.10
```
## 3. Nature de la tranche
`pre.010` est une tranche de hardening uniquement. Aucun fichier de production, aucune ressource SQL et aucune migration ne sont modifiés.
Elle ajoute des canaris de complétude qui figent la vertical slice acquise avant le gate technique final.
## 4. Conformance des six capacités
Les tests exigent exactement une implémentation de chacun des traits suivants sur `PostgresBackend` puis sur `Store` :
```text
RawTransactionRead
RawTransactionWrite
RawTransactionObservationRead
RawTransactionObservationWrite
RawTransactionRetentionRead
RawTransactionRetentionWrite
```
Le hardening refuse simultanément toute ouverture prématurée des quatre capacités `RawAccountState`/observation et toute ressource de migration `ksp_raw_account*`.
## 5. Hardening SQL privé
Le canari backend fige les propriétés physiques utiles à la vertical slice :
- keyset ASC/DESC sur `(slot, signature)` ;
- `LIMIT` physique sans `OFFSET` ;
- `FOR UPDATE` pour les chemins concurrents ;
- `ON CONFLICT DO NOTHING` pour lidempotence canonique ;
- archive payload séparée ;
- absence de `SELECT *`, `ON CONFLICT DO UPDATE`, `processing_state`, `batch_size` ou `priority`.
Ce scan ne crée aucune policy worker dans Store.
## 6. Mapping derreurs exhaustif
Les 18 variantes actuelles de `PostgresBackendErrorKind` sont toutes exercées :
- dans `ksp-store-postgres-lib`, vers le contrat `ksp-store-api` ;
- dans `ksp-store-lib`, vers les codes stables possédés par la façade.
Le canari backend vérifie en plus que le rendu de lerreur mappée ne contient ni URI PostgreSQL ni SQL.
## 7. Migrations
Inchangées :
```text
V000 d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450
V001 31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51
```
V001 reste à 40 ressources.
## 8. Fichiers modifiés
```text
Cargo.toml
crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
crates/ksp-store-postgres-lib/unit_tests/runtime.rs
crates/ksp-store-lib/tests/hardening_completeness.rs
crates/ksp-store-lib/unit_tests/store.rs
docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md
docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md
deltas/0.3.3/pre.010.md
```
Aucune suppression.
## 9. Gate opérateur attendu
```bash
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.3
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-store-api
cargo test -p ksp-store-lib
cargo test -p ksp-store-postgres-lib
cargo test -p ksp-config-lib
cargo check -p ksp-store-lib --no-default-features
```
Aucun nouveau live PostgreSQL nest requis en `pre.010`, car le runtime et les migrations sont byte-identiques à la base live validée `pre.009-fix.006`.
## 10. Suite si le gate est vert
```text
0.3.3-pre.011 — gate technique final
```

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md -->
<!-- version: 10 -->
<!-- version: 11 -->
# Plan `0.3.3` — Store/PostgreSQL RawTransaction vertical slice
@@ -1190,11 +1190,12 @@ Tranche matérialisée :
### `0.3.3-pre.010` — hardening/completeness
- scans boundaries ;
- hostile rows/cursors/errors ;
- inventaires modules/exports/deps ;
- conformance des six capacités ;
- absence de scope creep.
- inventaire exact des six implémentations `RawTransaction` dans le backend et la façade ;
- mapping exhaustif des 18 classes derreur PostgreSQL actuelles vers les codes Store/API stables ;
- canaris SQL privés : keyset, `LIMIT`, verrouillage/idempotence/rétention, absence de `OFFSET`/upsert divergent/policy worker ;
- maintien des scans boundaries, hostile rows/cursors/errors, modules/exports/deps ;
- fermeture explicite du scope `RawAccountState` dans runtime, façade et migrations ;
- aucun changement de production, migration ou checksum attendu.
### `0.3.3-pre.011` — gate technique final

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md -->
<!-- version: 20 -->
<!-- version: 21 -->
# Validation `0.3.3` — Store/PostgreSQL RawTransaction vertical slice
@@ -808,3 +808,21 @@ cargo check -p ksp-store-lib --no-default-features
- [PASS statique] aucune ressource SQL V000/V001, ordre de ressource ou checksum de migration n'est modifié ;
- [À FAIRE] gate Cargo opérateur puis live PostgreSQL `postgres_raw_transaction_live`.
### `pre.009-fix.006` — clôture opérateur et live PostgreSQL 17
- [PASS] gate standard complet propre le 2026-08-30 ;
- [PASS] `ksp-store-postgres-lib` : 40 tests unitaires, 9 boundary, 5 hardening, 9 public API ;
- [PASS] preuve live `postgres_raw_transaction_live` sur PostgreSQL 17 : 1 test passé ;
- [PASS] bootstrap V000/V001, drift/repair, écritures concurrentes, pagination, rétention, cancellation et réouverture finale exercés ;
- [PASS] aucune migration SQL ni checksum V000/V001 modifié ;
- [PASS] `pre.009` est fermée et `pre.010` peut ouvrir le hardening final.
### `pre.010` — hardening/completeness
- [PASS statique] inventaire exact dune implémentation de chacun des six traits `RawTransaction` côté `PostgresBackend` et côté `Store` ;
- [PASS statique] absence dimplémentation `RawAccountState` et de ressource `ksp_raw_account*` ;
- [PASS statique] canari SQL conserve keyset ASC/DESC, `LIMIT`, `FOR UPDATE`, `ON CONFLICT DO NOTHING` et archive séparée, sans `OFFSET`, `SELECT *`, `ON CONFLICT DO UPDATE` ni policy worker ;
- [PASS statique] les 18 variantes actuelles de `PostgresBackendErrorKind` sont couvertes par le mapping capability backend et par le mapping façade ;
- [PASS statique] aucun fichier de production ou migration nest modifié ; checksums V000/V001 inchangés ;
- [À FAIRE] gate Cargo opérateur complet de `pre.010`.