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
↓ peach-browser-5c2e4bb0.tar.gzatlas at this save
files changed4 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/passkey.ts+32 −2manifest.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": {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",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": {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