task(passkey): Implement POST /passkey/wraps - #21116
Open
nshirley wants to merge 1 commit into
Open
Conversation
nshirley
force-pushed
the
FXA-13142-2
branch
2 times, most recently
from
August 31, 2026 19:18
4879ede to
fac0711
Compare
nshirley
force-pushed
the
FXA-13142-2
branch
7 times, most recently
from
August 31, 2026 22:55
9a2999e to
103a29e
Compare
nshirley
marked this pull request as ready for review
August 31, 2026 23:20
Contributor
There was a problem hiding this comment.
Pull request overview
Adds create-only passkey wrap storage for passwordless Sync, protected by verified sessions and feature gating.
Changes:
- Adds the validated, rate-limited, audited
POST /passkey/wrapsroute. - Registers and documents the endpoint.
- Adds unit and remote integration coverage.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
test/remote/passkey_wraps.in.spec.ts |
Tests end-to-end storage and failures. |
lib/routes/passkeys.ts |
Exports the credential ID validator. |
lib/routes/passkey-wraps.ts |
Implements the endpoint. |
lib/routes/passkey-wraps.spec.ts |
Tests routing and validation. |
lib/routes/index.js |
Registers the new route. |
docs/swagger/passkey-wraps-api.ts |
Documents the API contract. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Because: - Passwordless Sync needs somewhere to store the envelope that lets a passkey unlock kB without a password. - A wrap is create-only: rotating kB invalidates it, so a stale one is replaced by deleting the passkey and re-enrolling, never by an update. This commit: - Adds POST /passkey/wraps, one envelope per credential, behind a verified session token and the passwordlessSyncEnabled flag. - Pins each of the five envelope fields to its one legal v1 width, which the fixed-width BINARY columns would otherwise zero-pad on a short one. - Reports created:false on an identical repeat and 409s a different one, since there is no update path. - Records wrap_created / wrap_creation_failure through a guarded helper, so an audit write cannot 500 a committed wrap or mask the error that preceded it. Closes #FXA-13142
nshirley
force-pushed
the
FXA-13142-2
branch
from
September 1, 2026 14:24
103a29e to
739b428
Compare
vpomerleau
self-requested a review
September 1, 2026 18:12
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Because
kBwithout a password.kBinvalidates it, so a stale one is replaced by deleting the passkey and re-enrolling, never by an update.This pull request
POST /passkey/wraps, one envelope per credential, behind a verified session token and thepasswordlessSyncEnabledflag.BINARYcolumns would otherwise zero-pad on a short one.created: falseon an identical repeat and 409s a different one, since there is no update path.wrap_created/wrap_creation_failurethrough a guarded helper, so an audit write cannot 500 a committed wrap or mask the error that preceded it.Issue that this pull request solves
Closes: FXA-13142
Checklist
Put an
xin the boxes that applyHow to review (Optional)
packages/fxa-auth-server/lib/routes/passkey-wraps.tsmfa:passkeyscope registration and deletion take. Reasoning is in the handler JSDoc — the credential already cleared that bar at registration, and a wrap is inert without its PRF output.Screenshots (Optional)
Please attach the screenshots of the changes made in case of change in user interface.
Other information (Optional)
authentication/finish, gated onwraps.createdAtbeing newer than the account'skeysChangedAt, is scoped to the GET ticket.