mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
feat(desktop): add password-protected backups in settings (#3701)
**Category:** new-feature **User Impact:** Users can create, download, and verify a password-protected backup of their private identity from desktop Settings. **Problem:** Buzz does not currently give signed-in users a Settings-based path to protect or validate their private identity independently of onboarding. **Solution:** Add a focused backup menu to the private-key row, keep encryption and verification local in Rust, and preserve completed encrypted backups briefly so native saves can be retried without repeating encryption. <details> <summary>File changes</summary> **desktop/src/features/settings/** Adds the background backup lifecycle, create and test dialogs, private-key menu integration, password handling, and focused unit coverage. **desktop/src/features/onboarding/ui/NsecMaskedDisplay.tsx** Extends the masked private-key display with reusable overflow-menu actions used by Settings. **desktop/src/app/App.tsx** Mounts the backup provider at app scope so encryption and save work survive closing Settings or the modal. **desktop/src/shared/api/tauriIdentity.ts** Adds typed desktop bindings for local backup creation, save, selection, and verification. **desktop/src-tauri/src/key_backup.rs and desktop/src-tauri/src/commands/identity.rs** Implements local NIP-49 encryption, password generation, file handling, and public-identity-only verification results. **desktop/src-tauri/src/egress_guard.rs and guarded call sites** Blocks encrypted secret material from relay, websocket, snapshot, sharing, and huddle egress paths. **desktop/src-tauri tests and fixtures** Covers encryption, verification, file behavior, and fail-closed no-egress protections. **desktop/src/testing/e2eBridge.ts, desktop/tests/, and desktop/playwright.config.ts** Expands the mock native bridge and browser coverage across create, retry, expiry, and current/different-identity verification states. **desktop/src-tauri/Cargo.toml, Cargo.lock, and assets** Adds the local cryptography/password-generation dependencies and embedded short-word list. </details> ## Reproduction steps 1. Run the desktop app and open **Settings → Profile → Identity**. 2. Open the private-key overflow menu and choose **Create backup**. 3. Enter or generate a valid password, submit, and confirm progress continues if the dialog or Settings is closed. 4. Save the resulting `.ncryptsec` file; cancel and retry to confirm the temporary download remains available. 5. Choose **Test backup**, select the file, enter a wrong password, then retry with the correct password. 6. Confirm success identifies whether the backup matches the current identity and displays only the public `npub`. ## Screenshots | Settings identity | Private-key menu | Create backup | |---|---|---| | <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/981e391b-6829-4081-95ca-ca75a369de71" /> | <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/7972c68e-7635-47d8-b0ad-9639390d3e6c" /> | <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/4709c8f7-cf02-46f1-bec9-b3f98fe56fb2" /> | | Encrypting | Download available | Test success | |---|---|---| | <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/1ac3e934-2b4b-4135-bae6-126c715c8c59" /> | <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/cb6f07ee-a16f-44a5-b9a0-6b9fe0e4d40d" /> | <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/ea58b1b1-966c-46aa-8d59-92c9f06a25bd" /> | Visual review and additional states: [Buzz thread](buzz://message?channel=50ca7ef1-201e-4159-9499-40de3964b7c3&id=87eceb5f0f82fd50c32e560de3d35be48e293760f6620718aafdcef289d475fe) --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>
This commit is contained in:
co-authored by
npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w
parent
f44b5a2477
commit
bd0bff24bf
@@ -49,3 +49,52 @@ export async function persistCurrentIdentity(): Promise<Identity> {
|
||||
export async function signOut(): Promise<void> {
|
||||
await invokeTauri("sign_out");
|
||||
}
|
||||
|
||||
export type GeneratePassphraseOptions = {
|
||||
/** Word count; Rust clamps to its allowed range (currently 3–10). */
|
||||
words?: number;
|
||||
/** Separator joined between words. Defaults to a space in Rust. */
|
||||
separator?: string;
|
||||
};
|
||||
|
||||
/** Generate a word passphrase (EFF short wordlist, OS entropy) in Rust. */
|
||||
export async function generateBackupPassphrase(
|
||||
options?: GeneratePassphraseOptions,
|
||||
): Promise<string> {
|
||||
return invokeTauri<string>("generate_backup_passphrase", {
|
||||
words: options?.words,
|
||||
separator: options?.separator,
|
||||
});
|
||||
}
|
||||
|
||||
/** Encrypt the current identity as an in-memory NIP-49 backup for native save. */
|
||||
export async function createNcryptsecBackup(password: string): Promise<string> {
|
||||
return invokeTauri<string>("create_ncryptsec_backup", { password });
|
||||
}
|
||||
|
||||
/** Save a portable backup copy. Returns null when the native dialog is cancelled. */
|
||||
export async function saveNcryptsecCopy(
|
||||
ncryptsec: string,
|
||||
): Promise<string | null> {
|
||||
return (
|
||||
(await invokeTauri<string | null>("save_ncryptsec_copy", { ncryptsec })) ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
export type BackupVerification = {
|
||||
pubkey: string;
|
||||
npub: string;
|
||||
matchesCurrentIdentity: boolean;
|
||||
};
|
||||
|
||||
/** Decrypt locally and return only the backup's public identity and match state. */
|
||||
export async function verifyNcryptsecBackup(
|
||||
ncryptsec: string,
|
||||
password: string,
|
||||
): Promise<BackupVerification> {
|
||||
return invokeTauri<BackupVerification>("verify_ncryptsec_backup", {
|
||||
ncryptsec,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user