f0787b007df5

breach status clears immediately on password change — optimistic clear before async HIBP check (v2.27.1)

time
2026-05-03 13:31 UTC · 5 months ago
machine
koh2
parent
9578774143bf
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/vault.ts+15 −10src/popup/views/Settings.tsx+1 −0
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach",4-  "version": "2.27.0",4+  "version": "2.27.1",55   "description": "Zero-knowledge password manager",66   "browser_specific_settings": {77     "gecko": {

view file

manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach",4-  "version": "2.27.0",4+  "version": "2.27.1",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": "2.26.0",3+  "version": "2.27.1",44   "description": "Zero-knowledge password manager",55   "type": "module",66   "scripts": {

view file

src/background/vault.ts+15 −10
@@ -981,16 +981,21 @@981981 982982   await persistEntries();983983 984-  // Fire-and-forget breach check when password changes (if monitoring enabled and entry is a login)985-  if ("password" in patch && settings.breachMonitoring !== false && entries[idx].type === "login" && entries[idx].password) {986-    const password = entries[idx].password!;987-    checkBreach(password).then(async (count) => {988-      const i = entries.findIndex((e) => e.id === id);989-      if (i !== -1) {990-        entries[i] = { ...entries[i], breach: count > 0 ? count : undefined, modifiedAt: Date.now() };991-        await persistEntries();992-      }993-    });984+  // Breach check when password changes: clear immediately so old breach doesn't linger,985+  // then async-check the new password and only re-set if it's also found.986+  if ("password" in patch && settings.breachMonitoring !== false && entries[idx].type === "login") {987+    entries[idx] = { ...entries[idx], breach: undefined };988+    await persistEntries();989+    const password = entries[idx].password;990+    if (password) {991+      checkBreach(password).then(async (count) => {992+        const i = entries.findIndex((e) => e.id === id);993+        if (i !== -1 && count > 0) {994+          entries[i] = { ...entries[i], breach: count, modifiedAt: Date.now() };995+          await persistEntries();996+        }997+      });998+    }994999   }9951000 }9961001 

view file

src/popup/views/Settings.tsx+1 −0
@@ -232,6 +232,7 @@232232   const [autofillEnabled, setAutofillEnabled] = createSignal(false);233233   const [biometricEnabled, setBiometricEnabled] = createSignal(false);234234   const isAndroid = Capacitor.getPlatform() === "android";235+  const isMobile = Capacitor.isNativePlatform();235236   const [canaryTestingId, setCanaryTestingId] = createSignal<string | null>(null);236237   const [canaryTestResult, setCanaryTestResult] = createSignal<{id: string; ok: boolean} | null>(null);237238 

view file