Skip to content

feat(backup): back up and restore the encrypted vault from the menu - #16

Merged
pyramation merged 1 commit into
mainfrom
feat/vault-backup
Aug 7, 2026
Merged

feat(backup): back up and restore the encrypted vault from the menu#16
pyramation merged 1 commit into
mainfrom
feat/vault-backup

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

The vault is already a single sealed file, so backup is a copy — no new format, no second key. This adds File → Back Up Vault… (⌘⇧B) and Restore from Backup…, mirrored as buttons in Settings → Backup, with copy that spells out that the copy is encrypted and only the master password opens it (so putting it in iCloud Drive/OneDrive/Dropbox is safe).

The app had no menu at all before (autoHideMenuBar: true + Electron's default template), so menu.ts adds a real one; the menu is now always visible on Windows/Linux since it carries the backup items.

Three things worth calling out in the implementation:

// service.flush(): the debounced save is up to 2s behind the UI, so a backup
// taken right after an edit would silently miss it
await service.flush();          // cancels the timer, awaits any in-flight lock, saves
await fs.copyFile(vaultFilePath(), chosen);
// restore validates before it destroys anything — parseHeader throws
// CorruptEnvelopeError on a non-envelope, so a stray .jpg can't replace a vault
await assertEnvelope(chosen);
await service.lock();
const kept = `${dir}/replaced-${backupName()}`;
await fs.rename(target, kept);               // recoverable if the user picked wrong
try { await fs.copyFile(chosen, target); }
catch (err) { await fs.rename(kept, target); throw err; }   // never leave no vault

Restore fires lockedEvent so the renderer drops to the unlock screen — the restored file needs the password it was made with, which may not be the current one.

totp.code's TotpEntry | null from #15 is unchanged here; the new IPC surface is backup.create/restore/revealVault.

Link to Devin session: https://app.devin.ai/sessions/04636534e07048089ffb6b78142e12cd
Requested by: @pyramation

@pyramation pyramation self-assigned this Aug 7, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@pyramation
pyramation merged commit ed7e764 into main Aug 7, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant