fix(chat): wipe typed plaintext on a wallet switch + per-thread draft

Audit B1/B5/B8:
- The chat composer / new-conversation buffers are file-static char[]; on a wallet
  switch or lock the plaintext a user typed for wallet A (a private message, or a
  recipient z-address) resurfaced verbatim in wallet B's composer and lingered
  unwiped in RAM. Add ui::ResetChatTab() (sodium_memzero the buffers + clear the
  selection ids) and call it from App::resetChatSession().
- Wipe the single composer draft when the active conversation changes, so text
  typed for one contact can't be sent to another (B5).
- Refresh the stale "read-only / Phase 3" docs — composing/sending is wired (B8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 15:40:19 -05:00
parent d9911a9bc9
commit 6f6ad89c9f
3 changed files with 41 additions and 8 deletions

View File

@@ -11,17 +11,26 @@ class App;
namespace ui {
/**
* @brief Render the Chat tab (read-only HushChat conversation view — Phase 3).
* @brief Render the Chat tab (HushChat conversation view).
*
* A two-pane view: a conversation list on the left and the selected thread on
* the right, both read from the App-owned ChatService store (App::chatService()).
* Peer z-addresses are resolved to contact names via the address book when known.
* Read-only for now — composing/sending arrives in a later phase. The tab is only
* reachable when built with DRAGONX_ENABLE_CHAT (gated via WalletUiSurface::Chat).
* A two-pane view: a conversation list on the left and the selected thread on the
* right, both read from the App-owned ChatService store (App::chatService()). Peer
* z-addresses are resolved to contact names via the address book when known.
* Composing/sending and starting new conversations are wired (App::sendChatMessage /
* startChatConversation). Reachable when built with DRAGONX_ENABLE_CHAT
* (gated via WalletUiSurface::Chat).
*
* @param app Pointer to the app instance.
*/
void RenderChatTab(App* app);
/**
* @brief Securely wipe the Chat tab's UI-local state (composer / new-conversation
* plaintext buffers + the selected-conversation ids). Called by
* App::resetChatSession() on a wallet switch/lock so one wallet's typed
* plaintext can't resurface (or linger unwiped in RAM) under the next wallet.
*/
void ResetChatTab();
} // namespace ui
} // namespace dragonx