v0.3.8-pre.008

This commit is contained in:
2026-09-03 19:53:25 +02:00
parent 10515d1562
commit 489d686023
16 changed files with 1050 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-store-desk/tests/desktop_security.rs
// version: 8
// version: 9
//! Security boundary tests for the Store Desk scaffold.
@@ -162,3 +162,71 @@ fn pre_007_fix_002_payload_preview_copy_never_logs_preview_material() {
assert!(!frontend.contains(r#"frontendDebug("main", "Store Desk long text copy completed", { fieldId, value })"#));
assert!(!frontend.contains(r#"frontendError("main", "Store Desk long text copy failed", { fieldId, value })"#));
}
#[test]
fn pre_008_account_rows_are_data_free_detail_is_bounded_and_filter_values_are_not_logged() {
let dto = include_str!("../src/dto_account.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 StoreAccountRowDto");
let response_start = dto.find("pub(crate) struct StoreAccountQueryResponseDto");
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("data_preview_hex"));
assert!(!row_source.contains("pub(crate) data:"));
}
assert!(dto.contains("data_preview_hex"));
assert!(dto.contains("data_preview_truncated"));
assert!(runtime.contains("ACCOUNT_DETAIL_PREVIEW_BYTES: usize = 512"));
assert!(runtime.contains("std::cmp::min(data.len(), ACCOUNT_DETAIL_PREVIEW_BYTES)"));
for required in [
"account DataTables page changed",
"account DataTables page length changed",
"account DataTables redraw completed",
"account detail opened",
"account detail closed",
] {
assert!(frontend.contains(required), "missing account tracing event: {required}");
}
for forbidden in [
r#"frontendDebug("main", "Store Desk account Store filter changed", { pubkey"#,
r#"frontendDebug("main", "Store Desk account Store filter changed", { slotMin"#,
r#"frontendDebug("main", "Store Desk account Store filter changed", { slotMax"#,
r#"frontendDebug("main", "Store Desk account detail opened", { pubkey"#,
"dataPreviewHex:",
] {
assert!(!frontend.contains(forbidden), "account business/filter value leaked into frontend tracing: {forbidden}");
}
}
#[test]
fn pre_008_account_request_rejects_datatables_search_order_draw_network_and_physical_material() {
let dto = include_str!("../src/dto_account.rs");
let runtime = include_str!("../src/store_runtime.rs");
for forbidden in ["draw:", "columns:", "search:", "order:", "cursor:", "network:", "connection_uri", "postgresql://", "endpoint"] {
assert!(!dto.contains(forbidden), "forbidden DataTables/physical account request material present: {forbidden}");
}
assert!(runtime.contains("25 | 50 | 100"));
assert!(runtime.contains("request.offset.parse::<u64>()"));
assert!(runtime.contains("parse_optional_pubkey(request.pubkey.as_deref())"));
assert!(runtime.contains("RawSlotRange::new"));
assert!(runtime.contains("request.pubkey.parse::<ksp_store_lib::Pubkey>()"));
assert!(runtime.contains("decode_hex_32(request.state_hash.as_str())"));
}
#[test]
fn pre_008_account_copy_tracing_never_logs_identity_or_data_material() {
let frontend = include_str!("../frontend/ts/main.ts");
for required in ["account-pubkey", "account-state-hash", "account-owner", "account-data-preview"] {
assert!(frontend.contains(required), "missing account copy field id: {required}");
}
for forbidden in [
r#"frontendDebug("main", "Store Desk long text copy requested", { fieldId, value })"#,
r#"frontendDebug("main", "Store Desk long text copy completed", { fieldId, value })"#,
r#"frontendError("main", "Store Desk long text copy failed", { fieldId, value })"#,
] {
assert!(!frontend.contains(forbidden), "account copy tracing leaked copied value material: {forbidden}");
}
}