feat: agentic-approval deeplink handling#30935
Conversation
Adds the mobile half of the agentic-CLI MFA approval flow:
- New MfaWebview screen forked from DaimoPayModal; passes
AuthenticationController bearer via source.headers.Authorization
(MMAI-176) plus URL-fragment for the SPA's same-origin XHR.
- Deeplink dispatch for /cli-login + /cli-approve registered in
handleUniversalLink; new handleCliMfa handler navigates to
Routes.MFA_WEBVIEW.CONFIRM with sessionId/server/intent.
- Notifee press routing: subscribes to onForegroundEvent and
onBackgroundEvent for the first time in this codebase. Existing
OPEN_NOTIFICATIONS_VIEW press action was dead code (no listener
subscribed). Also fixes a stale LAUNCH_ACTIVITY constant
('com.metamask.ui.MainActivity' from a pre-io.metamask package
rename) that was silently breaking ALL existing notification
taps app-wide.
- AppState-based getInitialNotification() polling fallback for
warm-start press delivery (Notifee event listeners flake on
Android 9.0.2 in this configuration).
POC scaffold with end-to-end runnable loop against a local mock
backend (lives outside this repo; spec in docs/mfa-webview-poc.md).
Real backend integration deferred — this branch unblocks mobile
work and serves as the executable spec for the backend team.
All debug-only additions are tagged // TEMP debug for removal:
- MfaDebugButton on Wallet home (gated by __DEV__)
- Console logging at each chain checkpoint
- isNotificationsFeatureEnabled force-true
- tryBiometricUnlock short-circuited under __DEV__ to force
password prompt (Android emulator otherwise auto-unlocks)
…view-poc # Conflicts: # app/components/Nav/App/App.tsx # app/components/Views/Wallet/index.tsx # app/constants/deeplinks.ts # app/core/DeeplinkManager/handlers/legacy/handleUniversalLink.ts
…view-poc # Conflicts: # app/components/Views/Wallet/index.tsx
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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 e1c6d39. Configure here.
| const hydraToken = | ||
| await Engine.context.AuthenticationController.getBearerToken( | ||
| getPrimaryEntropySourceId(), | ||
| ); |
There was a problem hiding this comment.
Auth ignores subjectId param
Medium Severity
getAuthToken always exchanges a bearer for the first HD keyring’s entropy source and never maps subjectId from the deeplink to the account or keyring that initiated the approval. Multi-wallet users can load the hosted flow with the wrong dashboard session while the page still shows the intended subjectId.
Reviewed by Cursor Bugbot for commit e1c6d39. Configure here.
There was a problem hiding this comment.
we are getting the primary keyring ( first srp imported during wallet creation)
subjectId is not related to keyring in multi-wallet users
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
There are NO existing E2E tests for this new feature. The risk to existing tests is minimal since all changes are additive. However, the App.tsx navigation stack modification (adding a new modal screen) could theoretically affect navigation behavior in edge cases. SmokeWalletPlatform is selected as a conservative sanity check because:
No other tags are warranted since:
Performance Test Selection: |
weitingsun
left a comment
There was a problem hiding this comment.
platform codeowner files LGTM
| options={{ | ||
| // Header is wired from inside AgenticCliApproval via navigation.setOptions | ||
| // (mirrors SimpleWebview's pattern for title + back button). | ||
| // Overrides clearStackNavigatorOptions defaults from the parent stack. |
There was a problem hiding this comment.
👍 nice yes we are migrating to using HeaderStandard


Description
MetaMask CLI / developer-dashboard flows need users to approve sensitive operations (login, wallet mode changes, transaction requests) on mobile. This PR wires
https://link.metamask.io/agentic-cliuniversal links into a modal WebView that completes the hosted dashboard MFA flow while keeping auth tokens and navigation inside an allowlisted origin policy.Flow
ACTIONS.AGENTIC_CLIis registered in universal-link handling (whitelisted, no interstitial).handleAgenticCliApprovalparses query params (projectId,approvalId, optionalapprovalPagePath,mimirSignature,operationType,subjectId), validates paths under/agentic/…, and navigates toRoutes.AGENTIC_CLI_APPROVAL.CONFIRMafter a short settle delay (same pattern as other pending deeplinks).AgenticCliApprovalServiceselects the dashboard host from build type (test / dev / prod Web3Auth ordeveloper.metamask.io), exchanges the wallet Hydra bearer viamm-qr-login/token, and loads the page with approval query params plus#auth_token=…in the URL fragment (not sent on the HTTP request).mm-cli-mfapostMessages (approved/rejected/close/error), matchesapprovalIdto route params, and shows localized load/submit errors with retry.Notable details
approvalPagePath(default/agentic/login).mimirSignatureis read from the raw query string so literal+in base64-style signatures are not converted to spaces; percent-encoded values are still decoded.getBuildType()is exported for host selection; unit tests cover service, screen, and deeplink handler.Changelog
CHANGELOG entry: Added mobile WebView approval for MetaMask CLI requests opened via
agentic-cliuniversal links.Related issues
Fixes:
Manual testing steps
Suggested deeplink (adjust host/build):
https://link.metamask.io/agentic-cli?projectId=<projectId>&approvalId=<approvalId>&mimirSignature=<signature>Screenshots/Recordings
Before
N/A — feature not present on
main.After
Screen.Recording.2026-06-03.at.5.13.04.PM.mov
Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Note
High Risk
Touches authentication (Hydra → dashboard token), passes tokens in URL fragments, and runs third-party dashboard content in a WebView with origin allowlisting—security-sensitive approval surface.
Overview
Adds end-to-end mobile approval for MetaMask CLI / developer-dashboard requests opened via
agentic-cliuniversal links.Deeplink → screen: Registers
ACTIONS.AGENTIC_CLIin universal-link handling (whitelisted, no interstitial), analytics route mapping, andhandleAgenticCliApproval, which requiresprojectId+approvalId, validates optionalapprovalPagePathunder/agentic/…, decodesmimirSignature(raw query so+in signatures is preserved), and navigates toRoutes.AGENTIC_CLI_APPROVAL.CONFIRMafter a 200ms settle delay.Auth + WebView: New
AgenticCliApprovalServicepicks the dashboard host from build type (getBuildTypeexported), exchanges wallet Hydra bearer viamm-qr-login/token, loads the page with approval query params and#auth_tokenin the fragment, enforces an origin allowlist (dashboard, Web3Auth, Stripe, MetaMask auth APIs), and parsesmm-cli-mfapostMessages. The modal screen exchanges token on mount, handles load/submit errors with retry, matchesapprovalIdon messages, and opens disallowed top-frame URLs externally.Also adds navigation stack registration, English copy, and unit tests for service, screen, and deeplink handler.
Reviewed by Cursor Bugbot for commit ddb2a5f. Bugbot is set up for automated code reviews on this repo. Configure here.