diff --git a/AGENTS.md b/AGENTS.md index 375f47a..5e2d45f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,10 +81,13 @@ Password verification uses a test payload (random string encrypted at vault crea - Clipboard auto-clears after 15 seconds. - No browser fingerprinting or anti-keylogger protections. -## Export +## Export / Import -- `exportSelected(groupIds)` replaces the old `exportAll()` — accepts an array of group IDs to export. Pass `null` or `[]` for a full export. Vault meta (salt, test payload) is always included for import decryption. -- `ImportExport.svelte` fetches groups/entries on modal open and shows a checkbox list for group selection with live entry count. +- `exportSelected(groupIds, vaultKey, exportPassword)` — group IDs to export; `null`/`[]` = full export (include `''` for ungrouped). Vault meta (salt, test payload) is always included for plain import decryption. + - **Plain export** (no export password): unchanged — entries keep their source-vault-encrypted passwords; import needs the source vault's master password. + - **Password-protected export**: pass a `vaultKey` (in-memory) plus an independent `exportPassword`. Re-keys every exported entry's password to the export-derived key and AES-256-GCM-seals the entire payload (titles/usernames/notes included). Returns `{ format: 'encrypted-export', salt, data }`. +- `importAll(data, mode, sourcePassword, targetKey)` detects a sealed export (`data.format === 'encrypted-export'`): `sourcePassword` is then the EXPORT password and may differ from any vault's master password. A wrong export password rejects the import (it never silently skips entries). The entry loop decrypts with the source key and re-encrypts under `targetKey`. +- `ImportExport.svelte` fetches groups/entries on modal open and shows a checkbox list for group selection with live entry count. The export dialog has an optional "separate password" field; the import dialog's field is a generic file password (export password for sealed files, source vault master for plain files). ## Known Bug Fixes diff --git a/src/components/ImportExport.svelte b/src/components/ImportExport.svelte index 6f9a206..d02cc16 100644 --- a/src/components/ImportExport.svelte +++ b/src/components/ImportExport.svelte @@ -22,6 +22,7 @@ let exporting = $state(false) let sourcePassword = $state('') let parsedFileData = $state(null) + let exportPassword = $state('') // Group selection for export let allGroups = $state([]) @@ -37,7 +38,12 @@ async function handleExport() { exporting = true try { - exportData = await exportSelected(selectedGroupIds.length === allGroups.length ? null : selectedGroupIds) + exportData = await exportSelected( + selectedGroupIds.length === allGroups.length ? null : selectedGroupIds, + app.encryptionKey, + exportPassword.trim() + ) + exportPassword = '' const json = JSON.stringify(exportData, null, 2) const blob = new Blob([json], { type: 'application/json' }) const url = URL.createObjectURL(blob) @@ -137,7 +143,7 @@