5c2e4bb0970a

diag: log every branch in handleCreateRequest, setupPasskeyProxy, attachPasskeyProxy, denyAllPendingPasskeyRequests — instant-fail with no SW errors leaves no signal otherwise (v3.6.108)

time
2026-05-28 17:37 UTC · 5 months ago
machine
koh2
parent
549991994e90
4 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/passkey.ts+32 −2
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.107",5+  "version": "3.6.108",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.107",4+  "version": "3.6.108",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.107",3+  "version": "3.6.108",44   "description": "Zero-knowledge password manager",55   "type": "module",66   "scripts": {

view file

src/background/passkey.ts+32 −2
@@ -53,6 +53,11 @@5353  * APPROVAL_TIMEOUT_MS (60s) (M8/COR-009).5454  */5555 export async function denyAllPendingPasskeyRequests(): Promise<void> {56+  if (approvals.size === 0 && unlockWaiters.size === 0) return;57+  console.log("[Peach passkey] denyAllPendingPasskeyRequests (popup disconnected)", {58+    approvals: approvals.size,59+    unlockWaiters: unlockWaiters.size,60+  });5661   for (const [rid, { resolve, timeoutId }] of approvals.entries()) {5762     clearTimeout(timeoutId);5863     resolve(false);@@ -276,9 +281,11 @@276281     await chrome.webAuthenticationProxy.attach();277282     attached = true;278283     conflict = undefined;284+    console.log("[Peach passkey] proxy attached successfully");279285   } catch (error) {280286     attached = false;281287     conflict = error instanceof Error ? error.message : "Another provider is active.";288+    console.warn("[Peach passkey] proxy attach failed", { conflict });282289   }283290 }284291 @@ -347,18 +354,25 @@347354 async function handleCreateRequest(348355   request: chrome.webAuthenticationProxy.CreateRequest349356 ): Promise<void> {357+  console.log("[Peach passkey] create event received", {358+    requestId: request.requestId,359+    detailsJson: request.requestDetailsJson,360+  });350361   const options = JSON.parse(request.requestDetailsJson) as PublicKeyCredentialCreationOptionsJSON;351362   const rpId = options.rp.id;352363   const rpName = options.rp.name ?? options.rp.id;353364   const userName = options.user.name;354365   const userDisplayName = options.user.displayName ?? options.user.name;366+  console.log("[Peach passkey] create parsed", { rpId, rpName, userName, unlocked: vault.isUnlocked() });355367 356368   if (!rpId) {369+    console.warn("[Peach passkey] reject: missing rp.id");357370     await rejectCreate(request.requestId, "NotSupportedError", "Missing RP ID");358371     return;359372   }360373 361374   if (!PASSKEY_CREATE_E2E_BYPASS && !(await isProUser())) {375+    console.warn("[Peach passkey] reject: user is not Pro");362376     await rejectCreate(363377       request.requestId,364378       "NotAllowedError",@@ -370,6 +384,7 @@370384   }371385 372386   if (!vault.isUnlocked()) {387+    console.log("[Peach passkey] vault locked, summoning inline unlock");373388     // Same wait-for-unlock pattern handleGetRequest uses: summon the inline374389     // unlock prompt on the active tab so the user can unlock without leaving375390     // the page, then hold the create request open until the vault unlocks or@@ -379,11 +394,15 @@379394       chrome.tabs.query({ active: true, lastFocusedWindow: true }, resolve)380395     );381396     const activeTab = tabs[0];397+    console.log("[Peach passkey] active tab for unlock summon", { id: activeTab?.id, url: activeTab?.url });382398     if (activeTab?.id) {383399       chrome.tabs.sendMessage(activeTab.id, {384400         type: 'SUMMON_AUTOFILL',385401         source: 'passkey-unlock',386-      }).catch(() => { void openApprovalPopup(); });402+      }).catch((err) => {403+        console.warn("[Peach passkey] SUMMON_AUTOFILL failed, falling back to popup", err);404+        void openApprovalPopup();405+      });387406     } else {388407       await openApprovalPopup();389408     }@@ -396,13 +415,16 @@396415       unlockWaiters.set(request.requestId, { resolve, timeoutId });397416     });398417 418+    console.log("[Peach passkey] unlock wait resolved", { unlocked, vaultUnlocked: vault.isUnlocked() });399419     if (!unlocked || !vault.isUnlocked()) {420+      console.warn("[Peach passkey] reject: unlock timeout");400421       await rejectCreate(request.requestId, "NotAllowedError", "Not unlocked in time.");401422       return;402423     }403424     // Vault is now unlocked — fall through to approval.404425   }405426 427+  console.log("[Peach passkey] requesting approval via popup");406428   const approved = await promptUserApproval({407429     requestId: request.requestId,408430     type: "create",@@ -411,16 +433,20 @@411433     userName,412434     userDisplayName,413435   });436+  console.log("[Peach passkey] approval resolved", { approved });414437   if (!approved) {438+    console.warn("[Peach passkey] reject: user denied");415439     await rejectCreate(request.requestId, "NotAllowedError", "User denied request.");416440     return;417441   }418442 419443   const algorithm = pickPasskeyAlgorithm(options.pubKeyCredParams ?? []);420444   if (!algorithm) {445+    console.warn("[Peach passkey] reject: no supported algorithm", options.pubKeyCredParams);421446     await rejectCreate(request.requestId, "NotSupportedError", "No supported algorithm offered.");422447     return;423448   }449+  console.log("[Peach passkey] algorithm selected", algorithm);424450 425451   const credentialIdBytes = crypto.getRandomValues(new Uint8Array(32));426452   const { publicKeyCose, publicKeySpki, privateKeyJwk } = await generatePasskeyKeypair(@@ -1140,7 +1166,10 @@11401166 }11411167 11421168 export async function setupPasskeyProxy(): Promise<void> {1143-  if (!isPasskeySupported()) return;1169+  if (!isPasskeySupported()) {1170+    console.log("[Peach passkey] setupPasskeyProxy: not supported on this browser");1171+    return;1172+  }11441173 11451174   // Firefox doesn't expose chrome.webAuthenticationProxy listeners. The11461175   // popup-context credential creator is the entry point; nothing to wire here.@@ -1150,6 +1179,7 @@11501179   }11511180 11521181   if (!listenersRegistered) {1182+    console.log("[Peach passkey] registering webAuthenticationProxy listeners");11531183     chrome.webAuthenticationProxy.onIsUvpaaRequest.addListener((requestInfo) => {11541184       // Peach is a user-verifying platform authenticator whenever the proxy11551185       // is attached. The lock state is irrelevant here — the create/get

view file