Skip to content

After loading gator permissions, resolve status for each item#8445

Open
jeffsmale90 wants to merge 1 commit intomainfrom
feat/gator-permissions-status
Open

After loading gator permissions, resolve status for each item#8445
jeffsmale90 wants to merge 1 commit intomainfrom
feat/gator-permissions-status

Conversation

@jeffsmale90
Copy link
Copy Markdown
Contributor

@jeffsmale90 jeffsmale90 commented Apr 14, 2026

Explanation

Gator permissions loaded from storage may be either active, revoked, or expired - this is in addition to the "Revoked" metadata stored with the permission.

With this change, after loading the permissions we resolve the status for each item. While the status is being resolved, we show the previous status held in storage for this item, or "Active" if it doesn't have a previous status.

When resolving the status:

  • if revocationMetadata exists, or revoked onchain - 'Revoked'
  • if expiration after onchain block timestamp 'Expired'
  • otherwise 'Active'

Mocked up UI in Extension:

Screenshot 2026-04-14 at 3 34 54 PM image

References

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

Medium Risk
Adds post-sync on-chain resolution of permission lifecycle status using NetworkController RPC calls, which changes persisted/used-in-UI state shape and introduces new network-dependent logic that could affect performance or correctness across chains.

Overview
After fetching granted permissions from the snap, the controller now derives and maintains a per-permission status (Active/Revoked/Expired) and updates it after sync based on revocation metadata plus on-chain checks.

This introduces a new permissionOnChainStatus module that decodes the permission context, calls DelegationManager.disabledDelegations via eth_call, and compares any TimestampEnforcer expiry against the latest block timestamp, using NetworkController to obtain the chain provider. Tests are expanded and added to cover status merging/defaulting and the on-chain resolution paths, and @metamask/network-controller/@metamask/abi-utils are added as dependencies.

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

- if revocationMetadata exists, or revoked onchain - 'Revoked'
- if expiration after onchain block timestamp 'Expired'
- otherwise 'Active'
@jeffsmale90 jeffsmale90 requested review from a team as code owners April 14, 2026 03:51
Copy link
Copy Markdown

@cursor cursor bot left a comment

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 46e2976. Configure here.

/**
* Whether the permission is active, revoked (off-chain and/or on-chain), or expired by time rule.
*/
status: PermissionStatus;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Required status field missing from older persisted state

Medium Severity

The status field on PermissionInfoWithMetadata is declared as required (status: PermissionStatus), but grantedPermissions is persisted state (persist: true). Entries from before this change will lack status at runtime. The controller internally handles this with ?? 'Active' fallbacks (in #buildPreviousStatusByContext and resolvePermissionStatusAfterSync), confirming status can be undefined — yet the type doesn't reflect this. If initialize() skips syncing (recent lastSyncedTimestamp), consumers reading state will get undefined where the type guarantees a string, causing incorrect comparisons or crashes.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 46e2976. Configure here.

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.

1 participant