Files
khadhroony-solana-project/crates/ksp-app-wallet-desk/tests/desktop_security.rs
2026-08-21 10:01:11 +02:00

103 lines
4.6 KiB
Rust

// file: crates/ksp-app-wallet-desk/tests/desktop_security.rs
// version: 5
//! Static desktop security contracts for the Wallet Desk pre.002 shell.
fn app_root() -> std::path::PathBuf {
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
}
fn read_text(path: &std::path::Path) -> String {
let source = std::fs::read_to_string(path);
assert!(source.is_ok(), "unable to read {}", path.display());
return match source {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => String::new(),
};
}
#[test]
fn initial_capability_surface_is_core_plus_tracing_only() {
let root = app_root();
let capability = read_text(root.join("capabilities/default.json").as_path());
assert!(capability.contains("\"core:default\""));
assert!(capability.contains("\"tracing:default\""));
assert!(!capability.contains("dialog:"));
assert!(!capability.contains("fs:"));
}
#[test]
fn frontend_shell_uses_no_browser_native_dialog_or_secret_storage() {
let root = app_root();
let main = read_text(root.join("frontend/ts/main.ts").as_path());
let html = read_text(root.join("frontend/main.html").as_path());
for forbidden in ["window.alert", "window.confirm", "window.prompt", "localStorage", "sessionStorage"] {
assert!(!main.contains(forbidden), "forbidden frontend primitive {forbidden}");
assert!(!html.contains(forbidden), "forbidden frontend primitive {forbidden}");
}
}
#[test]
fn locked_inventory_frontend_never_receives_protected_wallet_identity_fields() {
let root = app_root();
let inventory = read_text(root.join("src/wallet_inventory.rs").as_path());
assert!(!inventory.contains("pubkey:"));
assert!(!inventory.contains("alias:"));
assert!(!inventory.contains("notes:"));
assert!(!inventory.contains("password:"));
}
#[test]
fn create_passwords_are_request_only_and_protected_projection_is_purged() {
let root = app_root();
let session = read_text(root.join("src/wallet_session.rs").as_path());
let main = read_text(root.join("frontend/ts/main.ts").as_path());
let authorized = session.split("pub(crate) struct WalletAuthorizedDto").nth(1);
assert!(authorized.is_some());
let authorized = authorized.unwrap_or_default().split("}\n\n/// Create request").next().unwrap_or_default();
assert!(!authorized.contains("password"));
let request_start = session.find("pub(crate) struct WalletCreateRequestDto");
assert!(request_start.is_some());
let request_start = request_start.unwrap_or_default();
assert!(session[request_start..].contains("owner_password"));
assert!(session[request_start..].contains("view_password"));
assert!(main.contains("clearAuthorizedProjection"));
assert!(main.contains("clearCreateFormSensitiveInputs"));
assert!(!main.contains("frontendDebug(\"main\", request.ownerPassword"));
assert!(!main.contains("frontendTrace(\"main\", request.viewPassword"));
}
#[test]
fn unlock_passwords_and_config_secret_names_never_cross_rust_to_frontend() {
let root = app_root();
let session = read_text(root.join("src/wallet_session.rs").as_path());
let main = read_text(root.join("frontend/ts/main.ts").as_path());
let html = read_text(root.join("frontend/main.html").as_path());
let authorized = session.split("pub(crate) struct WalletAuthorizedDto").nth(1);
assert!(authorized.is_some());
let authorized = authorized.unwrap_or_default().split("}\n\n/// Create request").next().unwrap_or_default();
assert!(!authorized.contains("password"));
let unlock_request = session.find("pub(crate) struct WalletUnlockRequestDto");
assert!(unlock_request.is_some());
assert!(session[unlock_request.unwrap_or_default()..].contains("password: String"));
assert!(main.contains("clearUnlockSensitiveInputs"));
assert!(!main.contains("KSP_SECRET_WALLET_PASS_"));
assert!(!html.contains("KSP_SECRET_WALLET_PASS_"));
assert!(!main.contains("variableName"));
assert!(!main.contains("effectiveSource"));
}
#[test]
fn wallet_selection_does_not_auto_unlock_configured_secrets() {
let root = app_root();
let main = read_text(root.join("frontend/ts/main.ts").as_path());
let selection_start = main.find("async function selectWallet");
let selection_end = main.find("function bindWalletTableSelection");
assert!(selection_start.is_some());
assert!(selection_end.is_some());
let selection = &main[selection_start.unwrap_or_default()..selection_end.unwrap_or(main.len())];
assert!(selection.contains("select_wallet"));
assert!(!selection.contains("unlock_wallet_view_configured"));
assert!(!selection.contains("unlock_wallet_owner_configured"));
}