diff --git a/src-tauri/src/commands/session.rs b/src-tauri/src/commands/session.rs index 9bb7c40..8f23302 100644 --- a/src-tauri/src/commands/session.rs +++ b/src-tauri/src/commands/session.rs @@ -436,9 +436,17 @@ async fn receive_loop(app: AppHandle, mut reader: tokio::io::ReadHalf { if let Err(e) = handle_incoming_message(&app, &frame).await { + // Decryption errors are fatal - close session and notify user + let error_msg = format!("Decryption failed: {}", e); + let _ = app.emit("decryption_error", error_msg); + + let state = app.state::(); + *state.session.lock().await = None; + let _ = app.emit("session_closed", ()); + #[cfg(debug_assertions)] - log::warn!("message handling error: {}", e); - let _ = e; + log::warn!("decryption error - closing session: {}", e); + break; } } Err(e) => { @@ -478,7 +486,12 @@ async fn handle_incoming_message(app: &AppHandle, frame: &[u8]) -> anyhow::Resul let plaintext_buf = { let mut sess = state.session.lock().await; let session = sess.as_mut().ok_or_else(|| anyhow::anyhow!("no session"))?; - session.ratchet.decrypt(&ct, wire.n)? + // Log decryption attempt with context for debugging + #[cfg(debug_assertions)] + log::debug!("attempting to decrypt message with counter={}", wire.n); + + session.ratchet.decrypt(&ct, wire.n) + .map_err(|e| anyhow::anyhow!("ratchet decrypt failed (counter={}): {}", wire.n, e))? }; let mut content = String::from_utf8(plaintext_buf.as_bytes().to_vec())?;