chore: Add Expiry Extraction Utilities to gator-permissions-controller#7195
Merged
chore: Add Expiry Extraction Utilities to gator-permissions-controller#7195
Conversation
Merged
7 tasks
mj-kiwi
previously approved these changes
Nov 19, 2025
packages/gator-permissions-controller/src/decodePermission/decodePermission.ts
Outdated
Show resolved
Hide resolved
packages/gator-permissions-controller/src/decodePermission/decodePermission.ts
Show resolved
Hide resolved
MoMannn
requested changes
Nov 20, 2025
Member
MoMannn
left a comment
There was a problem hiding this comment.
I think that instead of a util function the expiry should be decoded and saved under Rules in the permission. So that anyone fetching the permissions would already get decoded expiry and does not need to decode every time.
- Export extractExpiryFromPermissionContext to extract expiry from delegation contexts - Export DELEGATION_FRAMEWORK_VERSION constant for consistency - Add extractExpiryFromCaveatTerms helper for parsing TimestampEnforcer terms - Add validation for terms length (must be exactly 32 bytes) - Add overflow protection for timestamps exceeding Number.MAX_SAFE_INTEGER - Add comprehensive test coverage for new functions - Refactor existing code to use new shared expiry extraction logic
- Fix import of DELEGATION_FRAMEWORK_VERSION in test file - Remove redundant Number.isSafeInteger check (hexToNumber already validates) - Update extractExpiry tests to reflect actual error behavior - Update error message tests in decodePermission.test.ts
- Add tests with real encoded delegations using encodeDelegations - Cover success case: extraction from valid context with timestamp caveat - Cover edge cases: no timestamp caveat, zero expiry, multiple delegations - Cover error cases: invalid context, unsupported chain, malformed data - This increases coverage for lines 276-299 in decodePermission.ts
- Add test mocking decodeDelegations to return array with undefined element - This covers line 278: the defensive check for null/undefined delegation - Should achieve 100% code coverage
…sionResponseSanitized - Export DELEGATION_FRAMEWORK_VERSION constant for version consistency - Include rules property in PermissionResponseSanitized for stronger typing - Remove extractExpiryFromPermissionContext (no longer needed) - Keep extractExpiryFromCaveatTerms as internal implementation detail - Update tests and remove unused exports - Fix linting issues
a544388 to
b90b881
Compare
MoMannn
requested changes
Nov 21, 2025
packages/gator-permissions-controller/src/decodePermission/extractExpiry.test.ts
Outdated
Show resolved
Hide resolved
packages/gator-permissions-controller/src/decodePermission/decodePermission.ts
Outdated
Show resolved
Hide resolved
- Move extractExpiryFromCaveatTerms tests to decodePermission.test.ts for consistency - Make extractExpiryFromCaveatTerms internal (remove export) as it's only used within decodePermission.ts - Add comprehensive edge case tests through getPermissionDataAndExpiry: - Terms too short/long validation - Safe integer validation for expiry timestamps - Large valid timestamp handling - Delete separate extractExpiry.test.ts file - All 49 tests passing with 100% coverage of extraction logic
MoMannn
previously approved these changes
Nov 24, 2025
Member
MoMannn
left a comment
There was a problem hiding this comment.
There are some merge conflicts in changelog
mj-kiwi
reviewed
Nov 26, 2025
packages/gator-permissions-controller/src/GatorPermissionsController.test.ts
Outdated
Show resolved
Hide resolved
- Update test to verify rules are preserved (not removed) in sanitized responses - Add test case with rules containing expiry to demonstrate rules can include expiry data - Remove assertion that rules should be undefined (rules are now preserved per PR #7195)
Resolved CHANGELOG.md conflict by properly organizing Added and Changed sections
- Add test to verify that when timestampBeforeThreshold is 0, expiry returns null - This covers the missing branch in extractExpiryFromCaveatTerms function - Achieves 100% branch coverage
jeffsmale90
previously approved these changes
Nov 27, 2025
packages/gator-permissions-controller/src/decodePermission/decodePermission.ts
Outdated
Show resolved
Hide resolved
- Add validation to reject timestampBeforeThreshold === 0 - Update extractExpiryFromCaveatTerms to throw on zero expiry - Update test to expect error instead of null for zero expiry - Document validation errors in CHANGELOG
Resolved conflicts: - CHANGELOG.md: Combined both sets of changes - GatorPermissionsController.test.ts: Kept both imports
MoMannn
previously approved these changes
Nov 28, 2025
Resolved conflicts: - CHANGELOG.md: Moved unreleased changes to new Unreleased section after 0.7.0 release
jeffsmale90
reviewed
Dec 2, 2025
Contributor
jeffsmale90
left a comment
There was a problem hiding this comment.
This looks good - it would be great to add a reference to the PR to the changelog
Resolved conflicts: - CHANGELOG.md: Combined timestamp validation changes with transaction-controller bump
github-merge-queue bot
pushed a commit
to MetaMask/metamask-extension
that referenced
this pull request
Jan 12, 2026
## **Description** Fixes #464 - Gator permissions with expiry were displaying "No expiration" in the UI. **Root Cause:** The expiry timestamp was excluded as part of a sanitization of the permissions response because it was stored in the permission. **Solution:** - Include the rules as part of the permissions responde so we can find the expirty inside, this part of the work is done in the gator-permissions-controller ## **Changelog** CHANGELOG entry: Fixed gator permissions displaying "No expiration" when expiry timestamp exists ## **Related issues** Fixes: #464 ## **Manual testing steps** 1. Create a gator permission with an expiry timestamp from `jeff.dripfund.xyz` 2. Navigate to Settings → Permissions → All Permissions 3. Locate the gator permission from `jeff.dripfund.xyz` 4. Expand the permission details 5. Verify the expiration date displays correctly (e.g., "11/13/2026") instead of "No expiration" ## **Screenshots/Recordings** ### **Before** Permission showed "No expiration" despite having an expiry timestamp in the delegation context. ### **After** Permission now correctly displays the expiration date (e.g., "11/13/2026") extracted from the `TimestampEnforcer` caveat. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable (7 comprehensive test cases covering all edge cases) - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] 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. <img width="1278" height="2074" alt="image" src="https://github.com/user-attachments/assets/b5e29995-4127-49b1-bac5-c6e49a73dd41" /> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Fixes incorrect "No expiration" display by sourcing expiry from delegation rules. > > - Use `extractExpiryToReadableDate(permissionResponse.rules || [])` in `ReviewGatorPermissionItem` for stream/periodic/revocation permissions; fallback to `gatorPermissionNoExpiration` when no expiry rule exists > - Update memo/callback dependencies to include `permissionResponse.rules` > - Tests: add expiry rule to mocks and assert exact dates; add cases for no rules and non-expiry rules showing "No expiration"; cover native and ERC20 stream/periodic, revocation, and date formatting > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 464f0b5. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Depends on this one MetaMask/core#7195 Pending to upgrade to the gator-permissions-controller: ^0.6.0 --------- Co-authored-by: Tadej Vengust <tadej.vengust@consensys.net>
github-merge-queue bot
pushed a commit
to MetaMask/metamask-extension
that referenced
this pull request
Jan 12, 2026
## **Description** Fixes #464 - Gator permissions with expiry were displaying "No expiration" in the UI. **Root Cause:** The expiry timestamp was excluded as part of a sanitization of the permissions response because it was stored in the permission. **Solution:** - Include the rules as part of the permissions responde so we can find the expirty inside, this part of the work is done in the gator-permissions-controller ## **Changelog** CHANGELOG entry: Fixed gator permissions displaying "No expiration" when expiry timestamp exists ## **Related issues** Fixes: #464 ## **Manual testing steps** 1. Create a gator permission with an expiry timestamp from `jeff.dripfund.xyz` 2. Navigate to Settings → Permissions → All Permissions 3. Locate the gator permission from `jeff.dripfund.xyz` 4. Expand the permission details 5. Verify the expiration date displays correctly (e.g., "11/13/2026") instead of "No expiration" ## **Screenshots/Recordings** ### **Before** Permission showed "No expiration" despite having an expiry timestamp in the delegation context. ### **After** Permission now correctly displays the expiration date (e.g., "11/13/2026") extracted from the `TimestampEnforcer` caveat. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable (7 comprehensive test cases covering all edge cases) - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] 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. <img width="1278" height="2074" alt="image" src="https://github.com/user-attachments/assets/b5e29995-4127-49b1-bac5-c6e49a73dd41" /> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Fixes incorrect "No expiration" display by sourcing expiry from delegation rules. > > - Use `extractExpiryToReadableDate(permissionResponse.rules || [])` in `ReviewGatorPermissionItem` for stream/periodic/revocation permissions; fallback to `gatorPermissionNoExpiration` when no expiry rule exists > - Update memo/callback dependencies to include `permissionResponse.rules` > - Tests: add expiry rule to mocks and assert exact dates; add cases for no rules and non-expiry rules showing "No expiration"; cover native and ERC20 stream/periodic, revocation, and date formatting > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 464f0b5. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Depends on this one MetaMask/core#7195 Pending to upgrade to the gator-permissions-controller: ^0.6.0 --------- Co-authored-by: Tadej Vengust <tadej.vengust@consensys.net>
github-merge-queue bot
pushed a commit
to MetaMask/metamask-extension
that referenced
this pull request
Jan 13, 2026
## **Description** Fixes #464 - Gator permissions with expiry were displaying "No expiration" in the UI. **Root Cause:** The expiry timestamp was excluded as part of a sanitization of the permissions response because it was stored in the permission. **Solution:** - Include the rules as part of the permissions responde so we can find the expirty inside, this part of the work is done in the gator-permissions-controller ## **Changelog** CHANGELOG entry: Fixed gator permissions displaying "No expiration" when expiry timestamp exists ## **Related issues** Fixes: #464 ## **Manual testing steps** 1. Create a gator permission with an expiry timestamp from `jeff.dripfund.xyz` 2. Navigate to Settings → Permissions → All Permissions 3. Locate the gator permission from `jeff.dripfund.xyz` 4. Expand the permission details 5. Verify the expiration date displays correctly (e.g., "11/13/2026") instead of "No expiration" ## **Screenshots/Recordings** ### **Before** Permission showed "No expiration" despite having an expiry timestamp in the delegation context. ### **After** Permission now correctly displays the expiration date (e.g., "11/13/2026") extracted from the `TimestampEnforcer` caveat. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable (7 comprehensive test cases covering all edge cases) - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] 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. <img width="1278" height="2074" alt="image" src="https://github.com/user-attachments/assets/b5e29995-4127-49b1-bac5-c6e49a73dd41" /> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Fixes incorrect "No expiration" display by sourcing expiry from delegation rules. > > - Use `extractExpiryToReadableDate(permissionResponse.rules || [])` in `ReviewGatorPermissionItem` for stream/periodic/revocation permissions; fallback to `gatorPermissionNoExpiration` when no expiry rule exists > - Update memo/callback dependencies to include `permissionResponse.rules` > - Tests: add expiry rule to mocks and assert exact dates; add cases for no rules and non-expiry rules showing "No expiration"; cover native and ERC20 stream/periodic, revocation, and date formatting > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 464f0b5. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Depends on this one MetaMask/core#7195 Pending to upgrade to the gator-permissions-controller: ^0.6.0 --------- Co-authored-by: Tadej Vengust <tadej.vengust@consensys.net>
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.
Explanation
This PR export the delegation framework version and skips the rules from the sanitization of the permissions response. The rules include the expiry.
Solution
This PR introduces:
Skip rules from sanitizationDELEGATION_FRAMEWORK_VERSIONconstantconstants.tsfile to prevent circular dependenciesReferences
Checklist
Note
Keeps
rulesin sanitized permission responses, introduces strict TimestampEnforcer expiry parsing/validation, and exportsDELEGATION_FRAMEWORK_VERSIONfrom a newconstants.ts.extractExpiryFromCaveatTermsand enforce strictTimestampEnforcerterms: exact length,timestampAfterThresholdmust be 0,timestampBeforeThreshold> 0, and safe-integer checks; update error messages accordingly.dependencyInfoandsigner; preservespermissionResponse.rules.PermissionResponseSanitizedupdated to retainrules.DELEGATION_FRAMEWORK_VERSIONto newconstants.tsand export via package index; update imports.rulesand new expiry validation scenarios.Written by Cursor Bugbot for commit 9313be3. This will update automatically on new commits. Configure here.