Skip to content

Feat/passkey controller messenger migration#9548

Merged
chaitanyapotti merged 9 commits into
mainfrom
feat/passkey-controller-messenger-migration
Jul 21, 2026
Merged

Feat/passkey controller messenger migration#9548
chaitanyapotti merged 9 commits into
mainfrom
feat/passkey-controller-messenger-migration

Conversation

@lwin-kyaw

@lwin-kyaw lwin-kyaw commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Explanation

Motivation

Update @metamask/passkey-controller to messenger oriented controller. This is the first step of migration to use UI messengers.

Current state

PasskeyController today handles WebAuthn ceremonies and vault-key wrap/unwrap only. Product flows (unlock, password change, passkey removal, SRP/account export) are orchestrated in the extension's MetaMaskController, which calls KeyringController directly alongside passkey helpers. That splits ownership across layers and makes messenger-based wiring harder.

Solution

This PR makes PasskeyController the single owner of passkey product flows by orchestrating a fixed set of KeyringController messenger actions inside the controller.

Referenced document: https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/401773985849/PasskeyController+messenger+migration

New orchestrated methods (each exposed as a messenger action):

Method Keyring calls
unlockWithPasskey submitEncryptionKey
protectVaultKeyWithPasskey verifyPassword (when onboarding complete), exportEncryptionKey
changePasswordWithPasskeyVerification exportEncryptionKeychangePasswordexportEncryptionKey → re-wrap passkey blob
removePasskeyWithPasskeyVerification / removePasskeyWithPasswordVerification step-up only, then clear passkey state
exportSeedPhraseWithPasskey exportSeedPhrase with { encryptionKey }
exportAccountsWithPasskey exportAccount with { encryptionKey }

Low-level methods (retrieveVaultKeyWithPasskey, renewVaultKeyProtection) remain available for advanced composition.

Breaking changes

  • PasskeyController constructor now requires getIsOnboardingCompleted: () => boolean (onboarding is not read via messenger; core deliberately diverges from the extension doc's OnboardingController dependency).
  • protectVaultKeyWithPasskey no longer accepts vaultKey; it fetches the current encryption key via KeyringController:exportEncryptionKey. When onboarding is complete, password is required for step-up (verifyPassword) before export.
  • removePasskey / PasskeyController:removePasskey removed; use removePasskeyWithPasskeyVerification, removePasskeyWithPasswordVerification, or clearState.
  • PasskeyControllerMessenger must allow the KeyringController actions listed in the README.

Non-obvious design choices

  • Onboarding gate via constructor callback, not messenger — OnboardingController is extension-only; integrators pass () => onboardingController.state.completedOnboarding.
  • Password-change re-wrap failure — if vault-key renewal fails after changePassword, the passkey is removed and VaultKeyRenewalFailed is thrown (password change is not rolled back).
  • Operation mutex — orchestrated async methods are serialized with async-mutex (runExclusive) to prevent concurrent vault/keyring races within PasskeyController.
  • Keyring unlock precondition — several KeyringController actions (exportEncryptionKey, changePassword, exportSeedPhrase, exportAccount) assert the keyring is unlocked. unlockWithPasskey calls submitEncryptionKey; other flows assume the integrator has already unlocked the keyring (typical for in-session settings/export flows). Post-onboarding enrollment uses verifyPassword for step-up but does not unlock — the vault must already be unlocked when exportEncryptionKey runs.

Dependencies added

  • @metamask/keyring-controller — types for allowed messenger actions used during orchestration.
  • async-mutex — serializes orchestrated passkey operations.

Other changes

  • Options/messenger types moved to types.ts.
  • Test helper: tests/mocks/passkey-controller-messenger.ts.
  • README, CHANGELOG, and JSDoc updated; migration tracker in docs/messenger-migration.md

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

High Risk
Touches vault encryption, password change, unlock, and sensitive export paths with breaking API changes; failed passkey re-wrap after password change removes the passkey without rolling back the new password.

Overview
PasskeyController becomes the single layer for passkey product flows by calling KeyringController messenger actions (unlock, enroll, password change, removal, SRP/account export) instead of leaving that orchestration to the extension.

New orchestrated APIs and messenger actions include unlockWithPasskey, changePasswordWithPasskeyVerification, removePasskeyWithPasskeyVerification / removePasskeyWithPasswordVerification, exportSeedPhraseWithPasskey, and exportAccountsWithPasskey. Orchestrated async work is serialized with an async-mutex to avoid vault/keyring races.

Breaking: constructor now requires getIsOnboardingCompleted; protectVaultKeyWithPasskey drops vaultKey and pulls the encryption key via KeyringController:exportEncryptionKey (optional password step-up when onboarding is complete); public removePasskey is removed in favor of the step-up removal methods. PasskeyControllerMessenger must allow the documented KeyringController actions. Adds @metamask/keyring-controller and async-mutex dependencies.

Reviewed by Cursor Bugbot for commit 1ed0878. Bugbot is set up for automated code reviews on this repo. Configure here.

@lwin-kyaw
lwin-kyaw requested review from a team as code owners July 20, 2026 07:25

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a96c601. Configure here.

Comment thread packages/passkey-controller/src/PasskeyController.ts
@lwin-kyaw

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.5-preview-eade524
@metamask-previews/accounts-controller@39.0.5-preview-eade524
@metamask-previews/address-book-controller@7.1.2-preview-eade524
@metamask-previews/ai-controllers@0.8.0-preview-eade524
@metamask-previews/analytics-controller@1.2.1-preview-eade524
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-eade524
@metamask-previews/announcement-controller@8.1.0-preview-eade524
@metamask-previews/app-metadata-controller@2.0.1-preview-eade524
@metamask-previews/approval-controller@9.0.2-preview-eade524
@metamask-previews/assets-controller@11.0.0-preview-eade524
@metamask-previews/assets-controllers@109.4.1-preview-eade524
@metamask-previews/authenticated-user-storage@3.0.1-preview-eade524
@metamask-previews/base-controller@9.1.0-preview-eade524
@metamask-previews/base-data-service@0.1.3-preview-eade524
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-eade524
@metamask-previews/bridge-controller@77.5.0-preview-eade524
@metamask-previews/bridge-status-controller@74.3.0-preview-eade524
@metamask-previews/build-utils@3.0.4-preview-eade524
@metamask-previews/chain-agnostic-permission@1.7.0-preview-eade524
@metamask-previews/chomp-api-service@3.1.0-preview-eade524
@metamask-previews/claims-controller@0.5.3-preview-eade524
@metamask-previews/client-controller@1.0.1-preview-eade524
@metamask-previews/client-utils@1.1.0-preview-eade524
@metamask-previews/compliance-controller@2.1.0-preview-eade524
@metamask-previews/composable-controller@12.0.1-preview-eade524
@metamask-previews/config-registry-controller@0.4.1-preview-eade524
@metamask-previews/connectivity-controller@0.3.0-preview-eade524
@metamask-previews/controller-utils@12.3.0-preview-eade524
@metamask-previews/core-backend@6.5.0-preview-eade524
@metamask-previews/delegation-controller@3.0.2-preview-eade524
@metamask-previews/earn-controller@12.2.2-preview-eade524
@metamask-previews/eip-5792-middleware@3.0.5-preview-eade524
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-eade524
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-eade524
@metamask-previews/ens-controller@19.1.5-preview-eade524
@metamask-previews/eth-block-tracker@15.0.1-preview-eade524
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-eade524
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-eade524
@metamask-previews/foundryup@1.0.1-preview-eade524
@metamask-previews/gas-fee-controller@26.2.4-preview-eade524
@metamask-previews/gator-permissions-controller@4.2.3-preview-eade524
@metamask-previews/geolocation-controller@0.1.3-preview-eade524
@metamask-previews/java-tron-up@1.0.0-preview-eade524
@metamask-previews/json-rpc-engine@10.5.0-preview-eade524
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-eade524
@metamask-previews/keyring-controller@27.1.0-preview-eade524
@metamask-previews/local-node-utils@1.0.0-preview-eade524
@metamask-previews/logging-controller@8.0.2-preview-eade524
@metamask-previews/message-manager@14.1.2-preview-eade524
@metamask-previews/messenger@2.0.0-preview-eade524
@metamask-previews/messenger-cli@0.2.0-preview-eade524
@metamask-previews/money-account-api-data-service@0.1.0-preview-eade524
@metamask-previews/money-account-balance-service@2.2.0-preview-eade524
@metamask-previews/money-account-controller@0.3.3-preview-eade524
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-eade524
@metamask-previews/multichain-account-service@13.0.0-preview-eade524
@metamask-previews/multichain-api-middleware@4.0.1-preview-eade524
@metamask-previews/multichain-network-controller@3.2.1-preview-eade524
@metamask-previews/multichain-transactions-controller@7.1.1-preview-eade524
@metamask-previews/name-controller@9.1.2-preview-eade524
@metamask-previews/network-connection-banner-controller@0.1.0-preview-eade524
@metamask-previews/network-controller@34.0.0-preview-eade524
@metamask-previews/network-enablement-controller@5.6.0-preview-eade524
@metamask-previews/notification-services-controller@25.0.0-preview-eade524
@metamask-previews/passkey-controller@2.1.0-preview-eade524
@metamask-previews/permission-controller@13.1.1-preview-eade524
@metamask-previews/permission-log-controller@5.1.0-preview-eade524
@metamask-previews/perps-controller@9.2.1-preview-eade524
@metamask-previews/phishing-controller@17.3.0-preview-eade524
@metamask-previews/platform-api-docs@0.0.0-preview-eade524
@metamask-previews/polling-controller@16.0.8-preview-eade524
@metamask-previews/preferences-controller@23.1.0-preview-eade524
@metamask-previews/profile-metrics-controller@4.0.2-preview-eade524
@metamask-previews/profile-sync-controller@28.3.0-preview-eade524
@metamask-previews/ramps-controller@17.0.0-preview-eade524
@metamask-previews/rate-limit-controller@7.0.1-preview-eade524
@metamask-previews/react-data-query@0.2.2-preview-eade524
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-eade524
@metamask-previews/sample-controllers@5.0.3-preview-eade524
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-eade524
@metamask-previews/selected-network-controller@26.1.5-preview-eade524
@metamask-previews/sentinel-api-service@1.0.0-preview-eade524
@metamask-previews/shield-controller@5.1.3-preview-eade524
@metamask-previews/signature-controller@39.2.7-preview-eade524
@metamask-previews/smart-transactions-controller@25.0.1-preview-eade524
@metamask-previews/snap-account-service@2.0.0-preview-eade524
@metamask-previews/social-controllers@2.5.0-preview-eade524
@metamask-previews/solana-test-validator-up@1.0.0-preview-eade524
@metamask-previews/stellar-quickstart-up@0.0.0-preview-eade524
@metamask-previews/storage-service@1.0.2-preview-eade524
@metamask-previews/subscription-controller@6.2.1-preview-eade524
@metamask-previews/transaction-controller@69.0.0-preview-eade524
@metamask-previews/transaction-pay-controller@25.0.0-preview-eade524
@metamask-previews/user-operation-controller@41.2.7-preview-eade524
@metamask-previews/wallet@7.0.1-preview-eade524
@metamask-previews/wallet-cli@0.0.0-preview-eade524

@lwin-kyaw

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eade524275

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1007 to +1008
if (!password) {
throw new Error(PasskeyControllerErrorMessage.EnrollmentPasswordRequired);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Return a coded error for missing enrollment password

When onboarding is complete and protectVaultKeyWithPasskey is called without a password, this path throws a plain Error instead of a PasskeyControllerError with a stable code. Product callers are directed to key off PasskeyControllerError.code for expected operational failures, so they cannot reliably distinguish the normal “prompt for password” case from unexpected malformed input errors; add a coded controller error for EnrollmentPasswordRequired.

Useful? React with 👍 / 👎.

- `exportAccountsWithPasskey`
- `PasskeyControllerOptions` with required `getIsOnboardingCompleted` constructor callback for enrollment step-up gating. ([#9548](https://github.com/MetaMask/core/pull/9548))
- Added new error constants, `PasskeyControllerErrorCode.VaultKeyRenewalFailed`, `PasskeyControllerErrorMessage.VaultKeyRenewalFailed` and `PasskeyControllerErrorMessage.EnrollmentPasswordRequired`. ([#9548](https://github.com/MetaMask/core/pull/9548))
- `@metamask/keyring-controller` dependency for KeyringController messenger action types used during orchestration

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add the missing PR link to this changelog entry

The AGENTS.md changelog rule says each changelog entry should be followed by links to the PR(s) that introduced the change, but this new dependency entry has no PR link while the neighboring entries cite #9548. Please add the PR link so the unreleased changelog remains traceable and validation/release review does not have to infer where this change came from.

Useful? React with 👍 / 👎.

Comment thread packages/passkey-controller/README.md Outdated

Manages passkey-based vault key protection using [WebAuthn](https://www.w3.org/TR/webauthn-3/). Orchestrates the full passkey lifecycle: generating WebAuthn ceremony options, verifying authenticator responses, and protecting/retrieving the vault encryption key via AES-256-GCM wrapping with HKDF-derived keys.

For the messenger migration design and extension wiring checklist, see [docs/messenger-migration.md](./docs/messenger-migration.md).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Restore the referenced migration document

This new README link points to ./docs/messenger-migration.md, but I searched the package (rg --files packages/passkey-controller | rg 'messenger-migration|docs/') and there is no docs directory or migration document. Anyone following the setup guidance lands on a broken link, so either add the document or update/remove the reference.

Useful? React with 👍 / 👎.

@lwin-kyaw

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.5-preview-1ed087802
@metamask-previews/accounts-controller@39.0.5-preview-1ed087802
@metamask-previews/address-book-controller@7.1.2-preview-1ed087802
@metamask-previews/ai-controllers@0.8.0-preview-1ed087802
@metamask-previews/analytics-controller@1.2.1-preview-1ed087802
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-1ed087802
@metamask-previews/announcement-controller@8.1.0-preview-1ed087802
@metamask-previews/app-metadata-controller@2.0.1-preview-1ed087802
@metamask-previews/approval-controller@9.0.2-preview-1ed087802
@metamask-previews/assets-controller@11.0.0-preview-1ed087802
@metamask-previews/assets-controllers@109.4.1-preview-1ed087802
@metamask-previews/authenticated-user-storage@3.0.1-preview-1ed087802
@metamask-previews/base-controller@9.1.0-preview-1ed087802
@metamask-previews/base-data-service@0.1.3-preview-1ed087802
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-1ed087802
@metamask-previews/bridge-controller@77.5.0-preview-1ed087802
@metamask-previews/bridge-status-controller@74.3.0-preview-1ed087802
@metamask-previews/build-utils@3.0.4-preview-1ed087802
@metamask-previews/chain-agnostic-permission@1.7.0-preview-1ed087802
@metamask-previews/chomp-api-service@3.1.0-preview-1ed087802
@metamask-previews/claims-controller@0.5.3-preview-1ed087802
@metamask-previews/client-controller@1.0.1-preview-1ed087802
@metamask-previews/client-utils@1.1.0-preview-1ed087802
@metamask-previews/compliance-controller@2.1.0-preview-1ed087802
@metamask-previews/composable-controller@12.0.1-preview-1ed087802
@metamask-previews/config-registry-controller@0.4.1-preview-1ed087802
@metamask-previews/connectivity-controller@0.3.0-preview-1ed087802
@metamask-previews/controller-utils@12.3.0-preview-1ed087802
@metamask-previews/core-backend@6.5.0-preview-1ed087802
@metamask-previews/delegation-controller@3.0.2-preview-1ed087802
@metamask-previews/earn-controller@12.2.2-preview-1ed087802
@metamask-previews/eip-5792-middleware@3.0.5-preview-1ed087802
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-1ed087802
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-1ed087802
@metamask-previews/ens-controller@19.1.5-preview-1ed087802
@metamask-previews/eth-block-tracker@15.0.1-preview-1ed087802
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-1ed087802
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-1ed087802
@metamask-previews/foundryup@1.0.1-preview-1ed087802
@metamask-previews/gas-fee-controller@26.2.4-preview-1ed087802
@metamask-previews/gator-permissions-controller@4.2.3-preview-1ed087802
@metamask-previews/geolocation-controller@0.1.3-preview-1ed087802
@metamask-previews/java-tron-up@1.0.0-preview-1ed087802
@metamask-previews/json-rpc-engine@10.5.0-preview-1ed087802
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-1ed087802
@metamask-previews/keyring-controller@27.1.0-preview-1ed087802
@metamask-previews/local-node-utils@1.0.0-preview-1ed087802
@metamask-previews/logging-controller@8.0.2-preview-1ed087802
@metamask-previews/message-manager@14.1.2-preview-1ed087802
@metamask-previews/messenger@2.0.0-preview-1ed087802
@metamask-previews/messenger-cli@0.2.0-preview-1ed087802
@metamask-previews/money-account-api-data-service@0.1.0-preview-1ed087802
@metamask-previews/money-account-balance-service@2.2.0-preview-1ed087802
@metamask-previews/money-account-controller@0.3.3-preview-1ed087802
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-1ed087802
@metamask-previews/multichain-account-service@13.0.0-preview-1ed087802
@metamask-previews/multichain-api-middleware@4.0.1-preview-1ed087802
@metamask-previews/multichain-network-controller@3.2.1-preview-1ed087802
@metamask-previews/multichain-transactions-controller@7.1.1-preview-1ed087802
@metamask-previews/name-controller@9.1.2-preview-1ed087802
@metamask-previews/network-connection-banner-controller@0.1.0-preview-1ed087802
@metamask-previews/network-controller@34.0.0-preview-1ed087802
@metamask-previews/network-enablement-controller@5.6.0-preview-1ed087802
@metamask-previews/notification-services-controller@25.0.0-preview-1ed087802
@metamask-previews/passkey-controller@2.1.0-preview-1ed087802
@metamask-previews/permission-controller@13.1.1-preview-1ed087802
@metamask-previews/permission-log-controller@5.1.0-preview-1ed087802
@metamask-previews/perps-controller@9.2.1-preview-1ed087802
@metamask-previews/phishing-controller@17.3.0-preview-1ed087802
@metamask-previews/platform-api-docs@0.0.0-preview-1ed087802
@metamask-previews/polling-controller@16.0.8-preview-1ed087802
@metamask-previews/preferences-controller@23.1.0-preview-1ed087802
@metamask-previews/profile-metrics-controller@4.0.2-preview-1ed087802
@metamask-previews/profile-sync-controller@28.3.0-preview-1ed087802
@metamask-previews/ramps-controller@17.0.0-preview-1ed087802
@metamask-previews/rate-limit-controller@7.0.1-preview-1ed087802
@metamask-previews/react-data-query@0.2.2-preview-1ed087802
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-1ed087802
@metamask-previews/sample-controllers@5.0.3-preview-1ed087802
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-1ed087802
@metamask-previews/selected-network-controller@26.1.5-preview-1ed087802
@metamask-previews/sentinel-api-service@1.0.0-preview-1ed087802
@metamask-previews/shield-controller@5.1.3-preview-1ed087802
@metamask-previews/signature-controller@39.2.7-preview-1ed087802
@metamask-previews/smart-transactions-controller@25.0.1-preview-1ed087802
@metamask-previews/snap-account-service@2.0.0-preview-1ed087802
@metamask-previews/social-controllers@2.5.0-preview-1ed087802
@metamask-previews/solana-test-validator-up@1.0.0-preview-1ed087802
@metamask-previews/stellar-quickstart-up@0.0.0-preview-1ed087802
@metamask-previews/storage-service@1.0.2-preview-1ed087802
@metamask-previews/subscription-controller@6.2.1-preview-1ed087802
@metamask-previews/transaction-controller@69.0.0-preview-1ed087802
@metamask-previews/transaction-pay-controller@25.0.0-preview-1ed087802
@metamask-previews/user-operation-controller@41.2.7-preview-1ed087802
@metamask-previews/wallet@7.0.1-preview-1ed087802
@metamask-previews/wallet-cli@0.0.0-preview-1ed087802

@tanguyenvn

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 1ed087802c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chaitanyapotti
chaitanyapotti added this pull request to the merge queue Jul 21, 2026
Merged via the queue into main with commit f4859ae Jul 21, 2026
427 checks passed
@chaitanyapotti
chaitanyapotti deleted the feat/passkey-controller-messenger-migration branch July 21, 2026 09:40
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