Repository navigation
feat(passkey-login-widget): serverless passkey login and encrypted backup widget (#307) - #308
goodbounties-nanoclaw-agent[bot] wants to merge 5 commits into
Conversation
…, add passkey icon ButtonText was a named component, so Tamagui resolved its theme by falling back to the ancestor light_Button/dark_Button component theme (white text) even inside the `<Theme reset>` that Button applies to non-primary variants. Secondary/outline/ghost/text labels were therefore white on light surfaces. Dropping the component name lets the label inherit the nearest theme. No change to presets.ts/theme.ts was needed. Also adds a `passkey` glyph to Icon, a Button variants story, and a smoke test asserting WCAG AA label contrast in light and dark. Co-Authored-By: Claude Code <noreply@anthropic.com> On-Behalf-Of: BountyCoder[onecli] (yaskkeryodtdijpv)
…n widget WebAuthn PRF key derivation, encrypted Google Drive / iCloud backup storage, flow state machine, adapter hook, screens A1-D6 and the custom element, with unit tests for the crypto, storage and flow logic. Refs #307 Co-Authored-By: Claude Code <noreply@anthropic.com> On-Behalf-Of: BountyCoder[onecli] (yaskkeryodtdijpv)
…r custom storage adapters Host apps and the Storybook mock storage need to signal provider sign-in failures (D4) from their own PasskeyBackupStorage implementations. Co-Authored-By: Claude Code <noreply@anthropic.com> On-Behalf-Of: BountyCoder[onecli] (yaskkeryodtdijpv)
…tion harness, live story and docs Adds A1-D6 screen fixtures, interaction stories on in-memory storage, a manual Live story (VITE_PASSKEY_* values or controls, nothing committed) and the guide. Co-Authored-By: Claude Code <noreply@anthropic.com> On-Behalf-Of: BountyCoder[onecli] (yaskkeryodtdijpv)
…uthenticator flows and QA notes States spec (A1-D6, light and dark), create/backup/restore round trips with a Chromium virtual authenticator (WebAuthn PRF) on mock storage, error recovery, key-safety and version specs, committed screenshots and QA.md. Co-Authored-By: Claude Code <noreply@anthropic.com> On-Behalf-Of: BountyCoder[onecli] (yaskkeryodtdijpv)
|
One or more custom setup steps configured for this repository failed during this Copilot code review run: Setup steps run before each review. If the review above is missing context, or no review was posted at all, the failing step above may be the cause. See the workflow run for failure details, fix your setup steps configuration, and re-request a review. Note You can configure setup steps for Copilot code review separately from Copilot cloud agent with a |
There was a problem hiding this comment.
🔵 Needs a closer look
The review could not be completed because the required GoodDollar contribution guidelines were unavailable locally and could not be retrieved externally.
No open issues 🎉
1 file not reviewed
pnpm-lock.yaml: Generated file
What changed in this PR
Adds @goodwidget/passkey-login-widget for client-side passkey login and encrypted wallet backup, implementing the flows described in #305 and #307 within GoodWidget’s provider and web-component architecture.
Changes:
- Adds passkey creation, account derivation, encrypted backup, and restore flows with Google Drive and iCloud storage adapters.
- Adds themed screens, Storybook fixtures and live configuration, unit tests, and Playwright coverage. Real-provider and physical-authenticator verification remains blocked as documented.
- Updates shared Button label theming for #303, adds contrast regression coverage, and introduces a passkey icon.
| File | Description |
|---|---|
tests/widgets/passkey-login-widget/webauthnFixture.ts |
Virtual authenticator and WebAuthn failure fixtures. |
tests/widgets/passkey-login-widget/version.spec.ts |
Version-label checks across themes and viewports. |
tests/widgets/passkey-login-widget/states.spec.ts |
Screen assertions and light/dark screenshots. |
tests/widgets/passkey-login-widget/restore-existing-passkey.spec.ts |
Restore round trips and exact-key checks. |
tests/widgets/passkey-login-widget/QA.md |
Automated coverage limits and live setup instructions. |
tests/widgets/passkey-login-widget/provider-choice.spec.ts |
Provider selection and remembered-provider tests. |
tests/widgets/passkey-login-widget/new-account.spec.ts |
Account creation, backup, and registration fallback tests. |
tests/widgets/passkey-login-widget/key-safety.spec.ts |
Checks for exposed keys and PRF outputs. |
tests/widgets/passkey-login-widget/interactionHelpers.ts |
Shared flow-driving and storage inspection helpers. |
tests/widgets/passkey-login-widget/existing-user-backup.spec.ts |
Existing-account backup and skip tests. |
tests/widgets/passkey-login-widget/errors-and-recovery.spec.ts |
Error screens, tampering, and recovery tests. |
tests/design-system/smoke.spec.ts |
Non-primary Button label contrast checks. |
pnpm-lock.yaml |
Workspace dependency entries for the widget. |
packages/ui/src/components/Icon.tsx |
Adds the passkey icon. |
packages/ui/src/components/Button.tsx |
Adjusts ButtonText theme inheritance. |
packages/passkey-login-widget/tsup.config.ts |
Package build entry points and output formats. |
packages/passkey-login-widget/tsconfig.json |
Editor and type-check configuration. |
packages/passkey-login-widget/tsconfig.build.json |
Build configuration excluding test sources. |
packages/passkey-login-widget/src/widgetRuntimeContract.ts |
Public props, storage interface, screens, and errors. |
packages/passkey-login-widget/src/webauthn/passkeyErrors.ts |
Maps failures to widget error codes. |
packages/passkey-login-widget/src/webauthn/passkeyErrors.test.ts |
Error mapping and message-safety tests. |
packages/passkey-login-widget/src/webauthn/passkeyClient.ts |
WebAuthn capability checks and PRF retrieval. |
packages/passkey-login-widget/src/testFixtures.ts |
Deterministic PRF and in-memory storage fixtures. |
packages/passkey-login-widget/src/storage/storageAdapter.ts |
Storage type exports and provider-authentication error. |
packages/passkey-login-widget/src/storage/rememberedProvider.ts |
Persists the last successful provider ID. |
packages/passkey-login-widget/src/storage/rememberedProvider.test.ts |
Provider persistence and blocked-storage tests. |
packages/passkey-login-widget/src/storage/loadExternalScript.ts |
Shared browser SDK loader. |
packages/passkey-login-widget/src/storage/iCloudStorage.ts |
CloudKit authentication and private backup storage. |
packages/passkey-login-widget/src/storage/iCloudStorage.test.ts |
Mocked CloudKit adapter tests. |
packages/passkey-login-widget/src/storage/googleDriveStorage.ts |
Google OAuth and Drive app-data storage. |
packages/passkey-login-widget/src/storage/googleDriveStorage.test.ts |
Mocked Drive requests and overwrite tests. |
packages/passkey-login-widget/src/register.ts |
Registers the custom element. |
packages/passkey-login-widget/src/PasskeyLoginWidget.tsx |
Provider-wrapped widget and preview entry points. |
packages/passkey-login-widget/src/index.ts |
Public package exports. |
packages/passkey-login-widget/src/flow/passkeyOperations.ts |
Backup preparation, upload, and verified restore. |
packages/passkey-login-widget/src/flow/passkeyOperations.test.ts |
Backup and restore operation tests. |
packages/passkey-login-widget/src/flow/passkeyFlowMachine.ts |
Screen transitions and recovery state machine. |
packages/passkey-login-widget/src/flow/passkeyFlowMachine.test.ts |
Journey, progress, and retry transition tests. |
packages/passkey-login-widget/src/element.ts |
Web-component bridge and property-only secret input. |
packages/passkey-login-widget/src/crypto/prfDerivation.ts |
Separate account, encryption-key, and file-tag derivations. |
packages/passkey-login-widget/src/crypto/prfDerivation.test.ts |
Derivation and scalar-validation tests. |
packages/passkey-login-widget/src/crypto/encoding.ts |
Byte, hexadecimal, and base64 conversion helpers. |
packages/passkey-login-widget/src/crypto/backupFormat.ts |
Versioned backup validation and address verification. |
packages/passkey-login-widget/src/crypto/backupFormat.test.ts |
Format, encryption round-trip, and tampering tests. |
packages/passkey-login-widget/src/crypto/backupFileName.ts |
Backup filename construction, parsing, and filtering. |
packages/passkey-login-widget/src/crypto/backupErrors.ts |
Backup format and decryption error types. |
packages/passkey-login-widget/src/crypto/backupCipher.ts |
AES-GCM encryption with address-bound authentication. |
packages/passkey-login-widget/src/config.ts |
Widget-local provider-tile themes. |
packages/passkey-login-widget/src/components/ScreenCard.tsx |
Shared screen shell, actions, and waiting state. |
packages/passkey-login-widget/src/components/RestoreScreens.tsx |
Restore provider, progress, and success screens. |
packages/passkey-login-widget/src/components/ProviderTile.tsx |
Selectable provider tiles. |
packages/passkey-login-widget/src/components/ProviderLogo.tsx |
Decorative storage-provider logos. |
packages/passkey-login-widget/src/components/ProviderChoice.tsx |
Provider selection group. |
packages/passkey-login-widget/src/components/ProgressSteps.tsx |
Shared progress-step rendering. |
packages/passkey-login-widget/src/components/PasskeyLoginWidgetView.tsx |
Screen routing and widget version display. |
packages/passkey-login-widget/src/components/LoginScreens.tsx |
Login, warning, and passkey creation screens. |
packages/passkey-login-widget/src/components/ErrorScreens.tsx |
Error layouts and recovery actions. |
packages/passkey-login-widget/src/components/BackupScreens.tsx |
Backup prompt, provider, progress, and success screens. |
packages/passkey-login-widget/src/adapter.ts |
Coordinates asynchronous flows and host callbacks. |
packages/passkey-login-widget/package.json |
Package metadata, exports, scripts, and dependencies. |
examples/storybook/src/stories/passkey-login-widget/PasskeyLoginWidgetQA.stories.tsx |
Deterministic fixtures for all designed screens. |
examples/storybook/src/stories/passkey-login-widget/PasskeyLoginWidgetLive.stories.tsx |
Manual story for real passkeys and providers. |
examples/storybook/src/stories/passkey-login-widget/PasskeyLoginWidgetInteractions.stories.tsx |
Real-widget stories backed by mock storage. |
examples/storybook/src/stories/passkey-login-widget/PasskeyLoginWidget.mdx |
Widget usage and security-model documentation. |
examples/storybook/src/stories/helpers/passkeyLoginWidgetStories.tsx |
Story harnesses, masked event logs, and live configuration. |
examples/storybook/src/stories/design-system/Button.stories.tsx |
Button variant fixtures in both themes. |
examples/storybook/src/globals.d.ts |
Typed passkey provider environment variables. |
examples/storybook/src/fixtures/passkeyMockStorage.ts |
Controllable storage double for interaction tests. |
examples/storybook/package.json |
Adds the widget workspace dependency. |
Review effort: Balanced
Summary
Implements #307 (plan for feature #305): new
packages/passkey-login-widget(@goodwidget/passkey-login-widget,<gw-passkey-login>), a fully client-side passkey login and encrypted backup widget.gwpk-<prfTag>-<address>.json, JSON v1{version,address,iv,ciphertext}.appDataFolder,drive.appdataonly) and iCloud adapter (CloudKit JS, indexedprfTagquery).VITE_PASSKEY_*env or story controls; "not configured" otherwise).Commits
be04f6efix(ui): readableButtonlabels on secondary/text/outline variants +passkeyicon. Standalone first commit so it can be reviewed on its own (on this branch it is the API-signed 440a538).ProviderAuthErrorexport, Storybook stories/docs, Playwright specs + QA.md.Heads-up for reviewers
[DRAFT][PLAN]; BountyAdmin explicitly authorized execution after Hadar approved plan v3.mainis unchanged at 020e67d. TheButtonfix here is independent and its own commit. Closed [WIP] Add passkey login widget to GoodWidget #306 was an earlier Copilot attempt at this widget and is not used.Verification status
Mock / virtual-authenticator results are not live results.
tests/widgets/passkey-login-widget(states 40, flows, errors 13, key-safety 2, version)node --test)pnpm buildtest-storybook, passkey story suitespackages/passkey-login-widgetProfileTextAreaFieldin governance-widget, errors in ai-credits-webtest-storybook, whole repoAiCreditsWidgetQA.stories.tsx(5 tests)pnpm test:demo, whole repoprfTagindexLive setup and CloudKit handover are in
tests/widgets/passkey-login-widget/QA.md.Screenshots (result, 400px; designs are in issue #305)
Version badge: desktop light, desktop dark, mobile light, mobile dark. The sandbox renders the alert glyph as tofu and falls back to a monospace font; that is an environment artifact.
Acceptance criteria (#307 §6)
<gw-passkey-login>,WidgetVersion; no backendonLogin+onBackupComplete; not logged in before backup exists (mock)onSkip; key never changed or returned (mock)onLogin({isNewAccount:false})(mock)gwpk-<prfTag>-<address>.json; restore byprfTagprfTag(unit, fake CloudKit)drive.appdataonly; CloudKit JS; one storage interfaceButtonfix andpasskeyiconpnpm lint/test:storybook/test:demo: see table (pre-existing failures;test:demonot run)Human-reviewer checklist (#307 §7)
Buttonfix reviewed as its own commit; other widgets' buttons smoke-checkedcrypto/*: distinct labels, random IV per encryption, address check after decrypt, no key in logs, file name leaks nothing beyond the public addressprivateKeynot an HTML attribute;onErrorcarries no secretsdrive.appdataonlyprfTagindex deployed to production before release🤖 Generated with Claude Code