v0.3.8-pre.007

This commit is contained in:
2026-09-03 17:54:50 +02:00
parent 8130e01b70
commit d5b4aef194
16 changed files with 1139 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-store-desk/tests/dependency_boundary.rs
// version: 4
// version: 5
//! Dependency-boundary tests for the Store Desk application.
@@ -75,3 +75,32 @@ fn pre_006_fix_001_shared_visible_items_use_the_crate_root_facade_inside_owner_m
assert!(tw_splash.contains("const WINDOW_LABEL_SPLASH: &str = \"splash\";"));
assert!(!tw_splash.contains("pub(crate) const WINDOW_LABEL_SPLASH"));
}
#[test]
fn pre_007_transaction_inspection_uses_store_facade_and_new_visible_items_use_crate_root_exports() {
let lib = include_str!("../src/lib.rs");
let runtime = include_str!("../src/store_runtime.rs");
let app_state = include_str!("../src/app_state.rs");
let tauri = include_str!("../src/tauri.rs");
for expected in [
"pub(crate) use self::dto_transaction::StoreTransactionDetailRequestDto;",
"pub(crate) use self::dto_transaction::StoreTransactionDetailDto;",
"pub(crate) use self::dto_transaction::StoreTransactionQueryRequestDto;",
"pub(crate) use self::dto_transaction::StoreTransactionQueryResponseDto;",
"pub(crate) use self::dto_transaction::StoreTransactionRowDto;",
] {
assert!(lib.contains(expected), "missing pre.007 crate-root DTO re-export: {expected}");
}
assert!(runtime.contains("ksp_store_lib::RawTransactionInspectionRead::inspect_raw_transactions"));
assert!(runtime.contains("ksp_store_lib::RawTransactionRead::get_raw_transaction"));
assert!(runtime.contains("ksp_store_lib::RawTransactionRetentionRead::get_raw_transaction_retention_state"));
assert!(runtime.contains("ksp_store_lib::RawTransactionRetentionRead::get_raw_transaction_tombstone"));
assert!(app_state.contains("request: crate::StoreTransactionQueryRequestDto"));
assert!(app_state.contains("request: crate::StoreTransactionDetailRequestDto"));
assert!(tauri.contains("request: crate::StoreTransactionQueryRequestDto"));
assert!(tauri.contains("request: crate::StoreTransactionDetailRequestDto"));
let sources = [runtime, app_state, tauri].join("\n");
for forbidden in ["ksp_store_api", "ksp_store_postgres", "tokio_postgres", "deadpool_postgres", "SELECT ", "OFFSET "] {
assert!(!sources.contains(forbidden), "Store Desk transaction inspection crossed physical/backend-neutral boundary: {forbidden}");
}
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-store-desk/tests/desktop_contract.rs
// version: 3
// version: 4
//! Desktop template and frontend contract tests for the Store Desk scaffold.
@@ -80,7 +80,7 @@ fn pre_002_binary_assets_reuse_the_ksp_desktop_template_byte_exact() {
}
#[test]
fn pre_006_shell_exposes_planned_views_store_overview_and_unconnected_raw_table_skeletons() {
fn pre_007_shell_exposes_transaction_filters_detail_and_keeps_account_skeleton_unconnected() {
let html = include_str!("../frontend/main.html");
for view in ["overview", "transactions", "accounts", "diagnostics"] {
assert!(html.contains(&format!("data-view=\"{view}\"")));
@@ -92,18 +92,26 @@ fn pre_006_shell_exposes_planned_views_store_overview_and_unconnected_raw_table_
{
assert!(html.contains(&format!("id=\"{overview_id}\"")), "missing Store Overview field: {overview_id}");
}
assert!(html.contains("jusqu'à pre.007"));
for transaction_id in ["refreshTransactions", "transactionSlotMin", "transactionSlotMax", "transactionDirection", "transactionDetailModal"] {
assert!(html.contains(&format!("id=\"{transaction_id}\"")), "missing pre.007 transaction control: {transaction_id}");
}
assert!(html.contains("jusqu'à pre.008"));
}
#[test]
fn pre_006_datatables_remain_unconnected_with_one_pager_owner_and_no_store_pager() {
fn pre_007_transaction_datatable_is_server_side_while_account_remains_unconnected_and_no_second_pager_exists() {
let source = include_str!("../frontend/ts/main.ts");
assert!(source.contains("datatables.net-bs5"));
assert!(source.contains("paging: true"));
assert!(source.contains("pageLength: 25"));
assert!(source.contains("lengthMenu: [25, 50, 100]"));
assert!(source.contains("store_query_transactions"));
assert!(source.contains("serverSide: true"));
assert!(source.contains("Store Desk transaction DataTable initialized"));
assert!(source.contains("Store Desk account DataTable skeleton initialized"));
assert!(source.contains("serverSide: false"));
assert!(source.contains("searching: false"));
assert!(source.contains("ordering: false"));
let html = include_str!("../frontend/main.html");
for forbidden in ["Premier", "Précédent", "Suivant", "storePager", "store-pagination"] {
assert!(!html.contains(forbidden), "second Store pager marker present: {forbidden}");
@@ -167,3 +175,25 @@ fn pre_006_store_lifecycle_is_composite_managed_health_visible_and_bounded_on_wi
assert!(tauri.contains("app_handle.exit(0)"));
assert!(tauri.contains("store_runtime_status"));
}
#[test]
fn pre_007_transaction_ipc_maps_datatables_offset_limit_counts_and_detail_without_cursor_contract() {
let dto = include_str!("../src/dto_transaction.rs");
let runtime = include_str!("../src/store_runtime.rs");
let tauri = include_str!("../src/tauri.rs");
let frontend = include_str!("../frontend/ts/main.ts");
assert!(dto.contains("records_total_decimal"));
assert!(dto.contains("records_filtered_decimal"));
assert!(runtime.contains("RawInspectionPageRequest::new(offset, limit)"));
assert!(runtime.contains("RawTransactionInspectionQuery::new"));
assert!(tauri.contains("store_query_transactions"));
assert!(tauri.contains("store_get_transaction_detail"));
assert!(frontend.contains("offset: page.start.toString()"));
assert!(frontend.contains("limit: page.length"));
assert!(frontend.contains("decimalCountToSafeNumber"));
assert!(frontend.contains("recordsTotalDecimal"));
assert!(frontend.contains("recordsFilteredDecimal"));
assert!(frontend.contains("data-transaction-detail"));
assert!(!dto.contains("RawPageCursor"));
assert!(!frontend.contains("storePager"));
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-store-desk/tests/desktop_security.rs
// version: 4
// version: 5
//! Security boundary tests for the Store Desk scaffold.
@@ -80,3 +80,51 @@ fn pre_006_store_status_ipc_is_backend_neutral_and_secret_free() {
assert!(!dto.contains(forbidden), "Store status DTO source contains forbidden field/material: {forbidden}");
}
}
#[test]
fn pre_007_transaction_rows_are_payload_free_detail_is_bounded_and_filter_values_are_not_logged() {
let dto = include_str!("../src/dto_transaction.rs");
let runtime = include_str!("../src/store_runtime.rs");
let frontend = include_str!("../frontend/ts/main.ts");
let row_start = dto.find("pub(crate) struct StoreTransactionRowDto");
let response_start = dto.find("pub(crate) struct StoreTransactionQueryResponseDto");
assert!(row_start.is_some());
assert!(response_start.is_some());
if let (std::option::Option::Some(row_start), std::option::Option::Some(response_start)) = (row_start, response_start) {
let row_source = &dto[row_start..response_start];
assert!(!row_source.contains("payload_preview_hex"));
assert!(!row_source.contains("payload: "));
}
assert!(dto.contains("payload_preview_hex"));
assert!(dto.contains("payload_preview_truncated"));
assert!(runtime.contains("TRANSACTION_DETAIL_PREVIEW_BYTES: usize = 512"));
assert!(runtime.contains("std::cmp::min(payload_bytes.len(), TRANSACTION_DETAIL_PREVIEW_BYTES)"));
assert!(frontend.contains("transaction DataTables server-side query started"));
assert!(frontend.contains("transaction DataTables page changed"));
assert!(frontend.contains("transaction DataTables page length changed"));
assert!(frontend.contains("transaction DataTables redraw completed"));
assert!(frontend.contains("transaction detail opened"));
assert!(frontend.contains("transaction detail closed"));
for forbidden in [
"frontendDebug(\"main\", \"Store Desk transaction Store filter changed\", { slotMin",
"frontendDebug(\"main\", \"Store Desk transaction Store filter changed\", { slotMax",
"frontendDebug(\"main\", \"Store Desk transaction detail opened\", { signature",
"payloadPreviewHex:",
] {
assert!(!frontend.contains(forbidden), "transaction business/filter value leaked into frontend tracing: {forbidden}");
}
}
#[test]
fn pre_007_transaction_request_rejects_datatables_search_order_draw_and_physical_material() {
let dto = include_str!("../src/dto_transaction.rs");
let runtime = include_str!("../src/store_runtime.rs");
for forbidden in ["draw:", "columns:", "search:", "order:", "cursor:", "connection_uri", "postgresql://", "endpoint"] {
assert!(!dto.contains(forbidden), "forbidden DataTables/physical request material present: {forbidden}");
}
assert!(runtime.contains("25 | 50 | 100"));
assert!(runtime.contains("request.offset.parse::<u64>()"));
assert!(runtime.contains("RawSlotRange::new"));
assert!(runtime.contains("\"ascending\" =>"));
assert!(runtime.contains("\"descending\" =>"));
}