Skip to content

feat: agentic-approval deeplink handling#30935

Merged
ieow merged 37 commits into
mainfrom
cw/agentic-approval
Jun 4, 2026
Merged

feat: agentic-approval deeplink handling#30935
ieow merged 37 commits into
mainfrom
cw/agentic-approval

Conversation

@ieow

@ieow ieow commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

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-cli universal links into a modal WebView that completes the hosted dashboard MFA flow while keeping auth tokens and navigation inside an allowlisted origin policy.

Flow

  1. DeeplinkACTIONS.AGENTIC_CLI is registered in universal-link handling (whitelisted, no interstitial). handleAgenticCliApproval parses query params (projectId, approvalId, optional approvalPagePath, mimirSignature, operationType, subjectId), validates paths under /agentic/…, and navigates to Routes.AGENTIC_CLI_APPROVAL.CONFIRM after a short settle delay (same pattern as other pending deeplinks).
  2. AuthAgenticCliApprovalService selects the dashboard host from build type (test / dev / prod Web3Auth or developer.metamask.io), exchanges the wallet Hydra bearer via mm-qr-login/token, and loads the page with approval query params plus #auth_token=… in the URL fragment (not sent on the HTTP request).
  3. WebView — Allowlisted origins only (dashboard hosts, Web3Auth auth, Stripe embeds, MetaMask auth APIs). Disallowed top-frame URLs open in the OS browser; subframes are blocked without external open. The screen listens for mm-cli-mfa postMessages (approved / rejected / close / error), matches approvalId to route params, and shows localized load/submit errors with retry.

Notable details

  • Dashboard host is always chosen on-device; deeplink may only override approvalPagePath (default /agentic/login).
  • mimirSignature is 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-cli universal links.

Related issues

Fixes:

Manual testing steps

Feature: Agentic CLI approval deeplink

  Scenario: user approves a CLI request from a universal link
    Given the user is onboarded, vault unlocked, and signed in (Hydra bearer available)
    And a dev/UAT/prod build matching the target dashboard host

    When the app is opened via a link such as:
      https://link.metamask.io/agentic-cli?projectId=<id>&approvalId=<id>&mimirSignature=<sig>
      (optional: approvalPagePath=/agentic/approval, operationType, subjectId)
    Then the Agentic CLI approval modal opens
    And the WebView loads the hosted login/approval page with auth in the fragment
    And approving on the hosted page closes the modal (postMessage `approved` + matching approvalId)

  Scenario: user rejects or closes the hosted flow
    Given the approval modal is open
    When the hosted page posts `rejected` or `close`
    Then the modal closes without treating it as a load failure

  Scenario: disallowed navigation is blocked or opened externally
    Given the approval WebView is loaded
    When a top-frame navigation targets a non-allowlisted origin
    Then it opens in the system browser instead of the WebView

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)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

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-cli universal links.

Deeplink → screen: Registers ACTIONS.AGENTIC_CLI in universal-link handling (whitelisted, no interstitial), analytics route mapping, and handleAgenticCliApproval, which requires projectId + approvalId, validates optional approvalPagePath under /agentic/…, decodes mimirSignature (raw query so + in signatures is preserved), and navigates to Routes.AGENTIC_CLI_APPROVAL.CONFIRM after a 200ms settle delay.

Auth + WebView: New AgenticCliApprovalService picks the dashboard host from build type (getBuildType exported), exchanges wallet Hydra bearer via mm-qr-login/token, loads the page with approval query params and #auth_token in the fragment, enforces an origin allowlist (dashboard, Web3Auth, Stripe, MetaMask auth APIs), and parses mm-cli-mfa postMessages. The modal screen exchanges token on mount, handles load/submit errors with retry, matches approvalId on 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.

tylerc-consensys and others added 19 commits May 6, 2026 19:40
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
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

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.

Comment thread app/components/Views/AgenticCliApproval/index.tsx Outdated
@ieow ieow changed the title Cw/agentic-approval feat: agentic-approval deeplink handling Jun 3, 2026
Comment thread app/components/Views/AgenticCliApproval/index.tsx
Comment thread app/components/Views/AgenticCliApproval/AgenticCliApprovalAuthService.ts Outdated
Comment thread app/components/Views/AgenticCliApproval/index.tsx

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

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 e1c6d39. Configure here.

const hydraToken =
await Engine.context.AuthenticationController.getBearerToken(
getPrimaryEntropySourceId(),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e1c6d39. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we are getting the primary keyring ( first srp imported during wallet creation)
subjectId is not related to keyring in multi-wallet users

@ieow ieow marked this pull request as ready for review June 3, 2026 09:08
@ieow ieow requested review from a team as code owners June 3, 2026 09:08
@github-actions github-actions Bot added the risk:medium AI analysis: medium risk label Jun 3, 2026
@ieow ieow added the team-onboarding Onboarding team label Jun 3, 2026
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeWalletPlatform
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 72%
click to see 🤖 AI reasoning details

E2E Test Selection:
This PR introduces a completely new "Agentic CLI Approval" feature via deeplinks. All changes are purely additive:

  1. New deeplink action (AGENTIC_CLI) added to constants and SUPPORTED_ACTIONS/WHITELISTED_ACTIONS — doesn't modify existing deeplink handling
  2. New deeplink handler (handleAgenticCliApproval.ts) — new file, no impact on existing handlers
  3. New screen (AgenticCliApproval/index.tsx) — new WebView-based approval screen
  4. New service (AgenticCliApprovalService.ts) — new file
  5. App.tsx — adds a new Stack.Screen for the new route (modal presentation), doesn't modify existing screens
  6. Routes.ts — adds new AGENTIC_CLI_APPROVAL route, doesn't modify existing routes
  7. OAuthService/constants.ts — exports a new getBuildType() function without changing existing behavior
  8. Analytics — adds new AGENTIC_CLI route mapping

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:

  • App.tsx navigation stack was modified (new modal screen added)
  • Routes.ts was modified (new route added)
  • These are core navigation infrastructure files that all tests depend on
  • Running a basic wallet platform smoke test validates the navigation stack still works correctly

No other tags are warranted since:

  • No existing deeplink E2E tests exist for this new feature
  • The changes don't touch confirmations, accounts, identity, networks, swap, stake, browser, snaps, or other feature areas
  • The new feature has no existing test coverage to validate against

Performance Test Selection:
No performance impact expected. All changes are additive new feature additions (new screen, new deeplink handler, new service). No changes to existing UI rendering, data loading, state management, account/network lists, or critical user flows. The new AgenticCliApproval WebView screen is only triggered by a specific deeplink and doesn't affect app startup, login, or other performance-sensitive paths.

View GitHub Actions results

@weitingsun weitingsun left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@weitingsun weitingsun Jun 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍 nice yes we are migrating to using HeaderStandard

@ieow ieow enabled auto-merge June 4, 2026 04:19
@ieow ieow added this pull request to the merge queue Jun 4, 2026
Merged via the queue into main with commit 0ea9c24 Jun 4, 2026
302 of 308 checks passed
@ieow ieow deleted the cw/agentic-approval branch June 4, 2026 08:03
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 4, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.81.0 Issue or pull request that will be included in release 7.81.0 label Jun 4, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.81.0 Issue or pull request that will be included in release 7.81.0 risk:medium AI analysis: medium risk size-XL team-onboarding Onboarding team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants