v0.2.6-pre.011
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/src/app_state.rs
|
||||
// version: 14
|
||||
// version: 15
|
||||
|
||||
//! Shared backend state owned by the Wallet Desk Tauri application.
|
||||
|
||||
@@ -722,6 +722,46 @@ impl AppState {
|
||||
return self.finish_owner_operation(context, result).await;
|
||||
}
|
||||
|
||||
/// Strongly disables VIEW from the current OWNER session while preserving OWNER authorization.
|
||||
pub(crate) async fn disable_wallet_view(&self) -> ksp_core_lib::Result<crate::WalletViewSecurityStatusDto> {
|
||||
let context = self.begin_owner_operation("view_disable");
|
||||
let mut context = match context {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let result = context.owner.disable_view(context.path.as_path()).await;
|
||||
if result.is_ok() {
|
||||
context.result_view_enabled = false;
|
||||
}
|
||||
let wallet = self.finish_owner_operation(context, result).await;
|
||||
return match wallet {
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(crate::view_security_status_from_authorized(&value)),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(error),
|
||||
};
|
||||
}
|
||||
|
||||
/// Strongly recreates VIEW from the current OWNER session with a fresh metadata key, slot and password.
|
||||
pub(crate) async fn recreate_wallet_view(
|
||||
&self,
|
||||
request: crate::WalletPasswordRotationRequestDto,
|
||||
) -> ksp_core_lib::Result<crate::WalletViewSecurityStatusDto> {
|
||||
let context = self.begin_owner_operation("view_recreate");
|
||||
let mut context = match context {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let password = ksp_wallet_lib::ViewPassword::new(request.password);
|
||||
let result = context.owner.recreate_view(context.path.as_path(), password).await;
|
||||
if result.is_ok() {
|
||||
context.result_view_enabled = true;
|
||||
}
|
||||
let wallet = self.finish_owner_operation(context, result).await;
|
||||
return match wallet {
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(crate::view_security_status_from_authorized(&value)),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(error),
|
||||
};
|
||||
}
|
||||
|
||||
/// Rotates the OWNER password while preserving the current authorized identity and metadata projection.
|
||||
pub(crate) async fn rotate_owner_password(&self, request: crate::WalletPasswordRotationRequestDto) -> ksp_core_lib::Result<crate::WalletAuthorizedDto> {
|
||||
let context = self.begin_owner_operation("owner_password_rotate");
|
||||
@@ -894,7 +934,15 @@ impl AppState {
|
||||
},
|
||||
};
|
||||
let pubkey = owner.pubkey().to_owned();
|
||||
let context = OwnerOperationContext { operation, owner, path: path.clone(), pubkey, view_enabled, wallet_id: wallet_id.clone() };
|
||||
let context = OwnerOperationContext {
|
||||
operation,
|
||||
owner,
|
||||
path: path.clone(),
|
||||
pubkey,
|
||||
result_view_enabled: view_enabled,
|
||||
view_enabled,
|
||||
wallet_id: wallet_id.clone(),
|
||||
};
|
||||
*session = crate::WalletSession::OwnerOperation { wallet_id, path, pubkey, view_enabled };
|
||||
ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WALLET_SESSION, wallet_id = context.wallet_id.as_str(), operation, "Wallet OWNER privileged operation started");
|
||||
return std::result::Result::Ok(context);
|
||||
@@ -917,9 +965,9 @@ impl AppState {
|
||||
}
|
||||
|
||||
fn install_owner_after_operation_success(&self, context: OwnerOperationContext) -> ksp_core_lib::Result<crate::WalletAuthorizedDto> {
|
||||
let OwnerOperationContext { operation, owner, path, pubkey, view_enabled, wallet_id } = context;
|
||||
let OwnerOperationContext { operation, owner, path, pubkey, result_view_enabled, view_enabled, wallet_id } = context;
|
||||
let configured_secret_candidate_count = self.secret_candidate_count_or_zero(wallet_id.as_str());
|
||||
let dto = crate::owner_projection(wallet_id.as_str(), view_enabled, configured_secret_candidate_count, &owner);
|
||||
let dto = crate::owner_projection(wallet_id.as_str(), result_view_enabled, configured_secret_candidate_count, &owner);
|
||||
let session = self.wallet_session.lock();
|
||||
let mut session = match session {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -933,7 +981,7 @@ impl AppState {
|
||||
pubkey: reserved_pubkey,
|
||||
view_enabled: reserved_view_enabled,
|
||||
} if reserved_wallet_id == wallet_id && reserved_path == path && reserved_pubkey == pubkey && reserved_view_enabled == view_enabled => {
|
||||
*session = crate::WalletSession::Owner { wallet_id: wallet_id.clone(), path, view_enabled, wallet: owner };
|
||||
*session = crate::WalletSession::Owner { wallet_id: wallet_id.clone(), path, view_enabled: result_view_enabled, wallet: owner };
|
||||
ksp_logging_lib::info!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WALLET_SESSION, wallet_id = wallet_id.as_str(), operation, "Wallet OWNER privileged operation completed");
|
||||
return std::result::Result::Ok(dto);
|
||||
},
|
||||
@@ -949,7 +997,7 @@ impl AppState {
|
||||
}
|
||||
|
||||
fn restore_owner_after_operation_failure(&self, context: OwnerOperationContext) {
|
||||
let OwnerOperationContext { operation, owner, path, pubkey, view_enabled, wallet_id } = context;
|
||||
let OwnerOperationContext { operation, owner, path, pubkey, result_view_enabled: _, view_enabled, wallet_id } = context;
|
||||
let session = self.wallet_session.lock();
|
||||
let mut session = match session {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -974,7 +1022,7 @@ impl AppState {
|
||||
}
|
||||
|
||||
async fn recover_owner_state_conflict(&self, context: OwnerOperationContext) {
|
||||
let OwnerOperationContext { operation, owner, path, pubkey, view_enabled, wallet_id } = context;
|
||||
let OwnerOperationContext { operation, owner, path, pubkey, result_view_enabled: _, view_enabled, wallet_id } = context;
|
||||
drop(owner);
|
||||
let inspected = ksp_wallet_lib::inspect_locked_wallet_file_v1(path.as_path()).await;
|
||||
let session = self.wallet_session.lock();
|
||||
@@ -1144,6 +1192,7 @@ struct OwnerOperationContext {
|
||||
owner: std::boxed::Box<ksp_wallet_lib::WalletOwner>,
|
||||
path: std::path::PathBuf,
|
||||
pubkey: ksp_core_lib::Pubkey,
|
||||
result_view_enabled: bool,
|
||||
view_enabled: bool,
|
||||
wallet_id: String,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/src/lib.rs
|
||||
// version: 11
|
||||
// version: 12
|
||||
|
||||
//! Tauri desktop application shell for KSP Wallet management and inspection.
|
||||
|
||||
@@ -202,6 +202,10 @@ pub(crate) use self::wallet_secrets::discover_wallet_secret_candidates;
|
||||
pub(crate) use self::wallet_secrets::wallet_secret_candidate_count;
|
||||
/// New credential request moved frontend -> Rust only for one explicit VIEW/OWNER-authorized rotation.
|
||||
pub(crate) use self::wallet_security::WalletPasswordRotationRequestDto;
|
||||
/// Safe VIEW security state returned after OWNER-authorized strong disable/recreate operations.
|
||||
pub(crate) use self::wallet_security::WalletViewSecurityStatusDto;
|
||||
/// Builds the safe strong VIEW administration status from the resulting OWNER projection.
|
||||
pub(crate) use self::wallet_security::view_security_status_from_authorized;
|
||||
/// Authorized OWNER projection exposed only after successful creation.
|
||||
pub(crate) use self::wallet_session::WalletAuthorizedDto;
|
||||
/// Create request whose password strings move frontend -> Rust only.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/src/tauri.rs
|
||||
// version: 8
|
||||
// version: 9
|
||||
|
||||
//! Tauri runtime assembly for the KSP wallet desktop application.
|
||||
|
||||
@@ -45,12 +45,14 @@ fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tau
|
||||
create_wallet,
|
||||
delete_wallet_note,
|
||||
deselect_wallet,
|
||||
disable_wallet_view,
|
||||
emit_frontend_log,
|
||||
get_runtime_status,
|
||||
import_wallet,
|
||||
inspect_import_source,
|
||||
list_wallets,
|
||||
lock_wallet,
|
||||
recreate_wallet_view,
|
||||
refresh_wallet_balance,
|
||||
refresh_wallets,
|
||||
rotate_owner_password,
|
||||
@@ -135,6 +137,15 @@ fn deselect_wallet(state: tauri::State<'_, crate::AppState>) -> std::result::Res
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn disable_wallet_view(state: tauri::State<'_, crate::AppState>) -> std::result::Result<crate::WalletViewSecurityStatusDto, crate::CommandErrorDto> {
|
||||
let result = state.disable_wallet_view().await;
|
||||
return match result {
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(crate::CommandErrorDto::from_error(&error)),
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn emit_frontend_log(payload: crate::FrontendLogPayloadDto) -> std::result::Result<(), crate::CommandErrorDto> {
|
||||
let result = crate::emit_frontend_log_event(payload);
|
||||
@@ -206,6 +217,18 @@ async fn inspect_import_source(
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn recreate_wallet_view(
|
||||
request: crate::WalletPasswordRotationRequestDto,
|
||||
state: tauri::State<'_, crate::AppState>,
|
||||
) -> std::result::Result<crate::WalletViewSecurityStatusDto, crate::CommandErrorDto> {
|
||||
let result = state.recreate_wallet_view(request).await;
|
||||
return match result {
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(crate::CommandErrorDto::from_error(&error)),
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn refresh_wallet_balance(state: tauri::State<'_, crate::AppState>) -> std::result::Result<crate::WalletBalanceDto, crate::CommandErrorDto> {
|
||||
let result = state.refresh_wallet_balance().await;
|
||||
|
||||
@@ -1,10 +1,35 @@
|
||||
// file: crates/ksp-app-wallet-desk/src/wallet_security.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
//! VIEW/OWNER credential rotation contracts for Wallet Desk.
|
||||
//! VIEW/OWNER credential and strong VIEW security contracts for Wallet Desk.
|
||||
|
||||
use ts_rs::TS; // rust-rules: trait-import
|
||||
|
||||
/// Safe VIEW security status returned after one OWNER-authorized strong VIEW administration operation.
|
||||
#[derive(serde::Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_wallet_desk/wallet_security/WalletViewSecurityStatusDto.ts")]
|
||||
pub(crate) struct WalletViewSecurityStatusDto {
|
||||
/// Capability that performed the strong VIEW administration operation.
|
||||
pub(crate) capability: String,
|
||||
/// Number of effective Config-owned Wallet password candidates without names or values.
|
||||
pub(crate) configured_secret_candidate_count: usize,
|
||||
/// Whether the current Wallet state exposes a VIEW slot after the operation.
|
||||
pub(crate) view_enabled: bool,
|
||||
/// Root-scoped Wallet identifier.
|
||||
pub(crate) wallet_id: String,
|
||||
}
|
||||
|
||||
/// Builds the safe strong VIEW administration status from an authorized OWNER projection.
|
||||
pub(crate) fn view_security_status_from_authorized(wallet: &crate::WalletAuthorizedDto) -> WalletViewSecurityStatusDto {
|
||||
return WalletViewSecurityStatusDto {
|
||||
capability: wallet.capability.clone(),
|
||||
configured_secret_candidate_count: wallet.configured_secret_candidate_count,
|
||||
view_enabled: wallet.view_enabled,
|
||||
wallet_id: wallet.wallet_id.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
/// New credential moved frontend -> Rust for one explicit Wallet password rotation.
|
||||
#[derive(serde::Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
Reference in New Issue
Block a user