Files
buzz/desktop/src/features/onboarding/lib
Taylor Ho 88d08e426c feat(desktop): guide and verify password-protected backups (#3617)
**Category:** improvement
**User Impact:** Users can create a password-protected key backup, save
it locally, and prove that it works before finishing onboarding or
signing out.

**Problem:** Tyler's NIP-49 foundation made encrypted local backup
possible, but the end-to-end ceremony still needed clearer progression,
trustworthy verification, and a Settings treatment consistent with the
rest of Identity. **Solution:** This stack adds a guided
create/download/test flow, verifies the actual saved backup through Rust
without returning secret key material, minimizes password lifetime in
the webview, and restores warm, plain-language presentation across
onboarding and Settings.

> [!NOTE]
> This PR is intentionally stacked on #2937 (`eva/nip49-local-backup`).
Review only the 19 commits in this stack.

<details>
<summary>File changes</summary>

**desktop/src-tauri/src/commands/identity.rs**  
Adds off-thread verification of NIP-49 backups and returns public
identity details only.

**desktop/src-tauri/src/commands/identity_key_backup_tests.rs**  
Covers verification, identity matching, and failure behavior at the
command boundary.

**desktop/src-tauri/src/egress_guard_tests.rs**  
Keeps the NIP-49 source inventory aligned with the new verification
path.

**desktop/src-tauri/src/key_backup.rs**  
Supports real backup decryption for verification while zeroizing
submitted passwords.

**desktop/src-tauri/src/key_backup_tests.rs**  
Exercises valid, wrong-password, damaged, and different-identity
backups.

**desktop/src-tauri/src/lib.rs**  
Registers the verification command with the desktop runtime.

**desktop/src/features/communities/ui/WelcomeSetup.tsx**  
Routes community onboarding through the revised backup ceremony.

**desktop/src/features/onboarding/lib/encryptedBackup.test.mjs**  
Covers the hardened backup state model and password-clearing behavior.

**desktop/src/features/onboarding/lib/encryptedBackup.ts**  
Models creation and verification with opaque request correlation and
short-lived passwords.

**desktop/src/features/onboarding/ui/BackupStep.tsx**  
Presents the backup choice clearly and advances into the dedicated
download step.

**desktop/src/features/onboarding/ui/BackupTestFlow.tsx**  
Adds the polished select-file, enter-password, verification, error, and
success experience.

**desktop/src/features/onboarding/ui/CommunityOnboardingFlow.tsx**  
Connects community onboarding to the updated backup steps.

**desktop/src/features/onboarding/ui/DownloadKeyStep.tsx**  
Adds the dedicated encrypted-backup download step and pre-creation skip
escape hatch.

**desktop/src/features/onboarding/ui/EncryptedBackupCreator.tsx**  
Guides password generation, backup creation, native saving, safe retry,
and re-download.

**desktop/src/features/onboarding/ui/MachineOnboardingFlow.tsx**  
Sequences chooser, download, exact-file test, and setup progression.

**desktop/src/features/onboarding/ui/NostrKeyImportForm.tsx**  
Aligns encrypted-key import behavior with the backup flow.

**desktop/src/features/onboarding/ui/NsecMaskedDisplay.tsx**  
Improves masked/revealed key presentation and safely wraps long private
keys.

**desktop/src/features/onboarding/ui/OnboardingChrome.tsx**  
Supports the revised onboarding layout and transitions.

**desktop/src/features/onboarding/ui/SetupStep.tsx**  
Integrates the completed backup ceremony with final setup.

**desktop/src/features/onboarding/ui/onboardingFlowSteps.test.mjs**  
Updates flow-level assertions for the new step sequence.

**desktop/src/features/settings/ui/EncryptedBackupRow.tsx**  
Adds sibling Create and Test rows that match the surrounding Identity
settings rhythm.

**desktop/src/features/settings/ui/ProfileSettingsCard.tsx**  
Places password-backup controls in the Identity card.

**desktop/src/features/settings/ui/SignOutSection.tsx**  
Uses explicit backup self-attestation plus the existing wipe phrase
without requiring a raw-key reveal first.

**desktop/src/shared/api/tauriIdentity.ts**  
Exposes typed backup verification to the frontend.

**desktop/src/shared/lib/ncryptsecSourceScan.test.mjs**  
Updates the frontend source allowlist for the verification path.

**desktop/src/testing/e2eBridge.ts**  
Models creation, saving, and verification for browser coverage.

**desktop/tests/e2e/onboarding-backup.spec.ts**  
Covers backup creation, exact-file testing, errors, retries, and
completion.

**desktop/tests/e2e/onboarding-docked-cta-screenshots.spec.ts**  
Updates docked CTA visual coverage for the revised progression.

**desktop/tests/e2e/onboarding.spec.ts**  
Keeps broader onboarding coverage aligned with the backup ceremony.

**desktop/tests/e2e/profile-nsec-reveal.spec.ts**  
Covers Settings create/test behavior and updated success copy.

**desktop/tests/e2e/signout-confirmation.spec.ts**  
Covers backup self-attestation, wipe phrase confirmation, and reset
behavior.

**desktop/tests/helpers/fileDrag.ts**  
Adds reusable file-drop support for backup test coverage.

**desktop/tests/helpers/onboarding.ts**  
Routes tests through chooser, download, and skip behavior consistently.

</details>

## Reproduction steps

1. Start fresh onboarding and choose the password-protected backup path.
2. Continue to **Backup your key**, create a password, save the
`.ncryptsec` file, and confirm that **Next** remains gated until testing
succeeds.
3. Select that exact file, enter its password, and verify the **Your
backup works!** success state.
4. Open **Settings → Identity** and confirm that **Create password
backup** and **Test password backup** appear as sibling rows.
5. Test a valid backup, then test wrong-password and different-identity
cases to confirm clear, non-secret-bearing outcomes.
6. Open sign out and confirm that backup self-attestation plus typing
`wipe all my data` remain required.

## Screenshots

### Onboarding flow

| 1. Creating your key | 2. Key created | 3. Create backup password |
|---|---|---|
| <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/fe5ebf60-02ad-4584-8e64-ff137bafac02"
/> | <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/0b8c7c6c-2ae5-494e-bb81-0a7b47ea1b66"
/> | <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/9fa8f6c0-832a-46ec-9af8-55dcae0adbb8"
/> |
| **4. Select the saved backup** | **5. Enter its password** | **6.
Verification succeeds** |
| <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/7ed1528c-6a1f-4411-bd3e-c57413320cdf"
/> | <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/088ec3ed-2735-4b9a-a0c5-6d176b3f06c5"
/> | <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/7081ce32-9371-46b2-9692-23ff77c39d35"
/> |

### Settings flow

| Create and Test tools | Tested backup success |
|---|---|
| <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/978ab672-5510-46d8-9116-6df4f1bda34c"
/> | <img width="1280" height="720" alt="image"
src="https://github.com/user-attachments/assets/56a1764d-3c3e-40e2-9f4b-962c5e96a36c"
/> |

## Verification

- Desktop typecheck
- Full desktop JS: 3,733/3,733
- `pnpm check`
- Rust desktop lib: 1,862 passed, 14 ignored; diagnostic: 3/3
- Focused Playwright: 16/16 with one worker

Native save/cancel remains the residual smoke-test risk: browser E2E
mocks the KDF/native save-dialog boundary, while real decrypt and
identity matching are covered in Rust.

---------

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>
2026-07-29 17:42:55 -04:00
..