00429fe70a82

refactor: remove dead chrome.storage.sync paired-device migration — registry is local-only, no sync evacuation path needed; zero storage.sync references in paired-devices.ts (v3.6.122)

time
2026-05-28 20:42 UTC · 5 months ago
machine
koh2
parent
811c39d3ce63
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/paired-devices.test.ts+1 −1src/background/paired-devices.ts+5 −17
manifest.firefox.json+1 −1
@@ -2,7 +2,7 @@22   "_comment_audio_capture": "Firefox does not honor the Chrome 'audioCapture' optional_permission — getUserMedia in WebExtensions is gated solely by the runtime permission prompt. Microphone access for chirp pairing works from the popup under the existing '<all_urls>' host permission; no manifest entry is required or accepted here.",33   "manifest_version": 3,44   "name": "Peach Password Manager",5-  "version": "3.6.121",5+  "version": "3.6.122",66   "description": "Zero-knowledge password manager",77   "browser_specific_settings": {88     "gecko": {

view file

manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "3.6.121",4+  "version": "3.6.122",55   "description": "Zero-knowledge password manager",66   "action": {77     "default_popup": "src/popup/index.html",

view file

package.json+1 −1
@@ -1,6 +1,6 @@11 {22   "name": "peach",3-  "version": "3.6.121",3+  "version": "3.6.122",44   "description": "Zero-knowledge password manager",55   "type": "module",66   "scripts": {

view file

src/background/paired-devices.test.ts+1 −1
@@ -138,7 +138,7 @@138138   });139139 140140   it("listPairedDevices ignores garbage entries silently", async () => {141-    (globalThis as unknown as { chrome: { storage: { sync: { set: (v: Record<string, unknown>) => Promise<void> } } } }).chrome.storage.sync.set({141+    (globalThis as unknown as { chrome: { storage: { local: { set: (v: Record<string, unknown>) => Promise<void> } } } }).chrome.storage.local.set({142142       peach_paired_devices_v3: [143143         { deviceId: "real", pairedAt: 1, deviceName: "x", deviceType: "android", longTermPublicKeyHex: "0".repeat(64) },144144         { not: "a device" },

view file

src/background/paired-devices.ts+5 −17
@@ -14,10 +14,11 @@1414 // per device but rotates if the user reinstalls before re-pairing, so we1515 // key on deviceId and update the key in place during re-pair.1616 //17-// Migration note: earlier builds stored the registry in `chrome.storage.sync`.18-// `listPairedDevices` transparently migrates any existing sync-stored19-// registry to local storage on first read. This is a one-time, local-only20-// unpair is the security boundary — see removePairedDeviceById for details.17+// The registry has only ever lived in `chrome.storage.local` for released18+// builds, so no cross-profile evacuation path is needed — the public keys19+// never leave the device via a third-party sync back-end. Unpairing is20+// local-only; Noise XX rejection on the next connection is the security21+// boundary (see removePairedDeviceById).2122 2223 import type { PairedDevice } from "../shared/sync-types";2324 @@ -31,19 +32,6 @@3132     const result = await chrome.storage.local.get(REGISTRY_KEY);3233     const devices = (result as Record<string, unknown>)[REGISTRY_KEY];3334     if (Array.isArray(devices)) return devices.filter(isPairedDevice);34-    // One-time migration from the earlier chrome.storage.sync location.35-    // If local storage is empty but sync has data, move it over and clear36-    // the sync copy so keys stop leaving the device.37-    try {38-      const syncResult = await chrome.storage.sync.get(REGISTRY_KEY);39-      const syncDevices = (syncResult as Record<string, unknown>)[REGISTRY_KEY];40-      if (Array.isArray(syncDevices) && syncDevices.length > 0) {41-        const valid = syncDevices.filter(isPairedDevice);42-        await chrome.storage.local.set({ [REGISTRY_KEY]: valid });43-        await chrome.storage.sync.remove(REGISTRY_KEY).catch(() => undefined);44-        return valid;45-      }46-    } catch { /* sync unavailable in Firefox or context — skip migration */ }4735     return [];4836   } catch {4937     return [];

view file