Skip to content

task(libs): Add passkeys data model and db migration#20019

Merged
vpomerleau merged 2 commits intomainfrom
FXA-12901
Feb 12, 2026
Merged

task(libs): Add passkeys data model and db migration#20019
vpomerleau merged 2 commits intomainfrom
FXA-12901

Conversation

@vpomerleau
Copy link
Contributor

@vpomerleau vpomerleau commented Feb 9, 2026

Because

  • We are adding WebAuthn/FIDO2 passkey support

This pull request

  • Adds database migration creating passkeys table with composite primary key and proper indexing
  • Generates Kysely types (Passkey, NewPasskey, PasskeyUpdate) with type guards for validation
  • Implements 8 pure repository functions for CRUD operations following FxA patterns
  • Creates PasskeyFactory for generating test data and updates integration test infrastructure
  • Provides comprehensive field documentation in PASSKEY_FIELDS.md covering WebAuthn spec and usage

Issue that this pull request solves

Closes: FXA-12901

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).

Screenshots (Optional)

Please attach the screenshots of the changes made in case of change in user interface.

Other information (Optional)

Any other information that is important to this pull request.

@vpomerleau vpomerleau force-pushed the FXA-12901 branch 2 times, most recently from fe27ff0 to 5907c00 Compare February 10, 2026 17:11
@vpomerleau vpomerleau changed the title wip task(libs): Add passkeys data model and db migration Feb 10, 2026
@vpomerleau vpomerleau marked this pull request as ready for review February 10, 2026 17:15
@vpomerleau vpomerleau requested a review from a team as a code owner February 10, 2026 17:15
@vpomerleau
Copy link
Contributor Author

vpomerleau commented Feb 10, 2026

Tests are currently failing because of the db migration version - I've bumped up the patch number to accommodate #20020 that is approved and likely to land first.

This should now be resolved.

@vpomerleau vpomerleau force-pushed the FXA-12901 branch 3 times, most recently from c003c2b to fdcb65f Compare February 10, 2026 23:04
@dschom dschom self-requested a review February 11, 2026 17:22

### name

- **Type**: string | null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be nullable? Seems like we'd want to be consistent and require a name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, we do want this to be defined even if it's just with a default value like "Passkey"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to me. I don't have a good feeling for what names would typically look like, but that seems fine.

- Software authenticators (browser built-in passkey managers)
- Privacy-focused hardware keys
- Platform authenticators (depending on policy)
- **Normalization**: The PasskeyService normalizes all-zeros AAGUID to `NULL` before storage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious we we need to do and maintain this null conversion on 00000000-0000-0000-0000-000000000000?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly necessary, I can directly store the all-zero value instead.

Copy link
Contributor

@dschom dschom Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with either approach, but if there's not a good argument for storing a null value, I'd lean towards the stance that the fewer nullables we have the better.

Copy link
Contributor

@dschom dschom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. R+WC. The only thing I'd question is if cascade on delete is really a good idea... It's definitely convenient, but want to make sure we know it can also cause problems in some scenarios.

.where('credentialId', '=', credentialId)
.execute();

return result.length;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this always return 1? Thought there was a numUpdatedRows property

* @param uid - User ID (16-byte Buffer)
* @returns Array of passkeys for the user (unordered)
*/
export async function findPasskeysByUid(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe overkill, but I suppose you could write some integration tests to verify the sql.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a few simple tests!

Because:

* We are adding WebAuthn/FIDO2 passkey support

This commit:

* Adds database migration creating passkeys table with composite primary key and proper indexing
* Generates Kysely types (Passkey, NewPasskey, PasskeyUpdate) with type guards for validation
* Implements 8 pure repository functions for CRUD operations following FxA patterns
* Creates PasskeyFactory for generating test data and updates integration test infrastructure
* Provides comprehensive field documentation in PASSKEY_FIELDS.md covering WebAuthn spec and usage

Closes #FXA-12901
@vpomerleau
Copy link
Contributor Author

Thanks @dschom and @vbudhram for comments! I've made some changes in a separate commit for easier review. Promise I'll squash/rebase before merging.

import { AccountManager } from '@fxa/shared/account/account';
import * as PasskeyRepository from './passkey.repository';

describe('PasskeyRepository (Integration)', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

DELETE FROM securityEvents WHERE uid = uidArg;
DELETE FROM sentEmails WHERE uid = uidArg;
DELETE FROM linkedAccounts WHERE uid = uidArg;
DELETE FROM passkeys WHERE uid = uidArg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@dschom dschom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@vpomerleau vpomerleau merged commit 30e2ded into main Feb 12, 2026
22 checks passed
@vpomerleau vpomerleau deleted the FXA-12901 branch February 12, 2026 01:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants