da331121f21f
test: prove passkey create+get end-to-end — extend compile-stripped E2E Pro bypass to provider-enable and get gates, drive smoke setup over messages (create/unlock/enable, lockOnClose off), approve in fresh popups; smoke now green (v3.6.140)
- time
- 2026-05-30 20:44 UTC · 4 months ago
- machine
- koh2
- agent
- claude-opus-4-8
- session
- fix passkey document-is-not-defined
- parent
- 071b1347e42d
↓ peach-browser-da331121.tar.gzatlas at this save
files changed3 files
src/background/messages.ts+8 −0src/background/passkey.ts+1 −1tests/passkeys.spec.ts+33 −18src/background/messages.ts+8 −0
@@ -65,6 +65,13 @@6565 upsertPairedDevice as upsertPairedDeviceV3,6666 } from "./paired-devices";6767 68+// Compile-time E2E flag, folded to a literal by Vite's `define` (false in69+// every production build — verified in the bundled output). Mirrors the70+// create-path bypass in passkey.ts so the Playwright passkey smoke can enable71+// the provider without a real Pro licence; the gate is fully intact for users.72+declare const __PEACH_E2E_PASSKEYS__: boolean;73+const PASSKEY_E2E_PRO_BYPASS = __PEACH_E2E_PASSKEYS__ === true;74+6875 let nativeSyncRunnerBootstrapped = false;6976 7077 function unhexBytes(hex: string): Uint8Array {@@ -86,6 +93,7 @@8693 feature: ProFeature,8794 trigger: "user" | "background" = "user"8895 ): Promise<{ allowed: boolean }> {96+ if (PASSKEY_E2E_PRO_BYPASS && feature === "passkeys") return { allowed: true };8997 if (await isProUser()) return { allowed: true };9098 9199 if (trigger === "user") {src/background/passkey.ts+1 −1
@@ -655,7 +655,7 @@655655 // Vault is now unlocked — fall through to authenticate.656656 }657657 658- if (!(await isProUser())) {658+ if (!PASSKEY_CREATE_E2E_BYPASS && !(await isProUser())) {659659 await rejectGet(request.requestId, "NotAllowedError", "Passkey use requires Peach Pro.");660660 broadcastPasskeyProGate();661661 return;tests/passkeys.spec.ts+33 −18
@@ -70,31 +70,46 @@7070 }7171 7272 async function createVaultAndEnablePasskeys(popup: Page) {73- const passwordInput = popup.locator("#master-password");74- if (await passwordInput.isVisible().catch(() => false)) {75- await passwordInput.fill("passkeysmoke123");76- await popup.locator("#confirm-password").fill("passkeysmoke123");77- await popup.getByRole("button", { name: /create vault/i }).click();78- await popup.waitForTimeout(1500);79- }80-81- const response = await popup.evaluate(async () => {82- return new Promise((resolve) => {83- chrome.runtime.sendMessage(84- { type: "SET_PASSKEY_PROVIDER_ENABLED", payload: { enabled: true } },85- (result) => resolve(result)86- );73+ // Drive setup over messages in a single service-worker activation: create the74+ // vault, UNLOCK (which persists the session key so the proxy sees an unlocked75+ // vault on its next wake), enable the provider, and disable lock-on-close so76+ // the approval popup's lifecycle can't lock the vault mid-ceremony. The old77+ // UI-click setup was flaky because createVault alone does not persist a78+ // session key, so a respawned worker handled the ceremony locked.79+ const result = await popup.evaluate(async () => {80+ const send = (m: object) =>81+ new Promise<{ ok?: boolean }>((res) => chrome.runtime.sendMessage(m, res));82+ const create = await send({83+ type: "CREATE_VAULT",84+ payload: { password: "passkeysmoke123" },8785 });86+ const unlock = await send({87+ type: "UNLOCK",88+ payload: { password: "passkeysmoke123" },89+ });90+ await send({ type: "UPDATE_SETTINGS", payload: { lockOnClose: false } });91+ const enable = await send({92+ type: "SET_PASSKEY_PROVIDER_ENABLED",93+ payload: { enabled: true },94+ });95+ return { create, unlock, enable };8896 });8997 90- expect((response as { ok?: boolean }).ok).toBe(true);98+ expect(result.create.ok).toBe(true);99+ expect(result.unlock.ok).toBe(true);100+ expect(result.enable.ok).toBe(true);91101 }92102 93103 async function approvePopupRequest(94- popup: Page,104+ ctx: BrowserContext,105+ extId: string,95106 buttonName: RegExp,96107 expectedTitle: RegExp97108 ) {109+ // Open a fresh popup to catch the pending-request approval surface. The popup110+ // is left open (closed at context teardown); lock-on-close is disabled during111+ // setup so its eventual disconnect cannot lock the vault or deny the request.112+ const popup = await openPopup(ctx, extId);98113 await expect(popup.getByRole("heading", { name: expectedTitle })).toBeVisible({99114 timeout: 15_000,100115 });@@ -125,7 +140,7 @@125140 await page.goto(url);126141 127142 await page.getByRole("button", { name: /create passkey/i }).click();128- await approvePopupRequest(popup, /save passkey/i, /save a passkey\?/i);143+ await approvePopupRequest(ctx, extId, /save passkey/i, /save a passkey\?/i);129144 130145 const createStatus = page.locator("#create-status");131146 await expect(createStatus).toHaveAttribute("data-state", "ok", {@@ -134,7 +149,7 @@134149 await expect(createStatus).toContainText("Created");135150 136151 await page.getByRole("button", { name: /authenticate/i }).click();137- await approvePopupRequest(popup, /sign in/i, /sign in with passkey\?/i);152+ await approvePopupRequest(ctx, extId, /sign in/i, /sign in with passkey\?/i);138153 139154 const getStatus = page.locator("#get-status");140155 await expect(getStatus).toHaveAttribute("data-state", "ok", {