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
↓ peach-browser-00429fe7.tar.gzatlas at this save
files changed5 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/paired-devices.test.ts+1 −1src/background/paired-devices.ts+5 −17manifest.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": {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",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": {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" },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 [];