From 0870c050cb17384e256013058a67f13cd7d27bed Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 03:57:53 +0000 Subject: [PATCH] fix: sync code not transferring identity when encryption enabled _getAllData() was reading raw storage which contains encrypted blobs when at-rest encryption is enabled. The sync code export would send { _ssLocalEncrypted: true, data: } instead of actual identity data. The importing browser couldn't use these blobs. Fixed _getAllData() to use Storage._readSecure() which decrypts transparently. Fixed _applyData() to use Storage._writeSecure() so imported data gets encrypted on the receiving end. Also: hide the Auto-Sync Folder section entirely in browsers that don't support File System Access API (Firefox, Brave, Safari) instead of showing a broken-looking error message. https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- src/lib/sync.js | 36 ++++++++++++++++++++++++++---------- src/options/options.html | 2 +- src/options/options.js | 7 +++++++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/lib/sync.js b/src/lib/sync.js index 80c743a..b6a6b4e 100644 --- a/src/lib/sync.js +++ b/src/lib/sync.js @@ -791,25 +791,41 @@ const SilentSendSync = { // ---------------------------------------------------------------- async _getAllData() { - const result = await api.storage.local.get(null); + // Use dynamic import to avoid circular dependency + const StorageModule = (await import('./storage.js')).default; + const identity = await StorageModule._readSecure('ss_identity'); + const mappings = await StorageModule._readSecure('ss_mappings'); + const settings = await StorageModule._readSecure('ss_settings'); + const result = await api.storage.local.get('ss_lastModified'); return { version: '1', lastModified: result.ss_lastModified || Date.now(), - identity: result.ss_identity || {}, - mappings: result.ss_mappings || [], - settings: result.ss_settings || {}, + identity: identity || {}, + mappings: mappings || [], + settings: settings || {}, }; }, async _applyData(data, source = 'unknown') { - const toSet = { + const StorageModule = (await import('./storage.js')).default; + + // Write through Storage module so data gets encrypted if at-rest + // encryption is enabled + if (data.identity !== undefined) { + await StorageModule._writeSecure('ss_identity', data.identity); + } + if (data.mappings !== undefined) { + await StorageModule._writeSecure('ss_mappings', data.mappings); + } + if (data.settings !== undefined) { + await StorageModule._writeSecure('ss_settings', data.settings); + } + + // Metadata stays plaintext + await api.storage.local.set({ ss_lastModified: data.lastModified, ss_sync_notification: { source, time: Date.now() }, - }; - if (data.identity !== undefined) toSet.ss_identity = data.identity; - if (data.mappings !== undefined) toSet.ss_mappings = data.mappings; - if (data.settings !== undefined) toSet.ss_settings = data.settings; - await api.storage.local.set(toSet); + }); }, async _getSyncChunkKeys() { diff --git a/src/options/options.html b/src/options/options.html index ea8ce0a..4c4f82e 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -238,7 +238,7 @@
-
+

Auto-Sync Folder — fully automatic, no copy-paste

Pick the same folder in each browser once. Changes are written to diff --git a/src/options/options.js b/src/options/options.js index fbf0b11..ee75ddb 100644 --- a/src/options/options.js +++ b/src/options/options.js @@ -721,6 +721,13 @@ let syncDirHandle = null; const SYNC_FILE_NAME = 'silent-send-sync.json'; async function initFileSync() { + // Hide the entire section if File System Access API isn't supported + if (!window.showDirectoryPicker) { + const section = $('#fileSyncSection'); + if (section) section.style.display = 'none'; + return; + } + syncDirHandle = await SilentSendSync.loadSyncDirHandle(); updateFileSyncUI(); if (syncDirHandle) {