Skip to content

feat(auth): sort OAuth scopes by service, then access level#413

Open
anshul-garg27 wants to merge 3 commits intogoogleworkspace:mainfrom
anshul-garg27:feat/sort-scopes-by-service
Open

feat(auth): sort OAuth scopes by service, then access level#413
anshul-garg27 wants to merge 3 commits intogoogleworkspace:mainfrom
anshul-garg27:feat/sort-scopes-by-service

Conversation

@anshul-garg27
Copy link
Contributor

Summary

Sort OAuth scopes in the TUI picker by service name first (grouping all Drive scopes together, all Gmail together, etc.), then by access level (read-only before write), then by sensitivity classification.

Problem

The current sort order groups scopes by risk level (restricted → sensitive → non-sensitive), which scatters scopes from the same service across different sections of the list. When a user wants to select specific Drive or Gmail scopes, they have to scan through the entire list.

Solution

Changed the sort key in fetch_scopes_for_apis() from:

classification (desc) → short name (asc)

to:

api_name (asc) → is_readonly (desc, read-only first) → classification (asc, safe first) → short name (asc)

Before: Scopes scattered by risk level
After: All Drive scopes together, all Gmail scopes together, read-only variants listed before write variants

Test plan

  • Added unit test verifying sort groups by service, then read-only first, then classification
  • Existing tests unaffected (sort change only affects display order, not functionality)

Closes #319

Previously scopes were sorted by risk classification first (restricted,
sensitive, non-sensitive), making it hard to find all scopes for a
specific service. Now scopes are grouped by service name (Drive, Gmail,
etc.), then by access level (read-only first), then by classification
(safe before restricted), then alphabetically.

This makes the scope picker much easier to navigate when selecting
scopes for specific services.

Closes googleworkspace#319
@changeset-bot
Copy link

changeset-bot bot commented Mar 11, 2026

🦋 Changeset detected

Latest commit: bf99daf

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the OAuth scope sorting mechanism within the TUI picker to provide a more intuitive and user-friendly experience. Previously, scopes were scattered based on risk level, making selection cumbersome. The new sorting prioritizes grouping by service and access level, streamlining the process for users to identify and choose necessary permissions.

Highlights

  • Improved OAuth Scope Sorting: The sorting logic for OAuth scopes in the TUI picker has been updated to group scopes first by service name, then by access level (read-only before write), and finally by sensitivity classification.
  • Enhanced User Experience: This change significantly improves the usability of the scope selection interface by presenting related scopes together, making it easier for users to find and select specific permissions.
Changelog
  • .changeset/sort-scopes-by-service.md
    • Added a new changeset file to document the updated OAuth scope sorting logic.
  • src/setup.rs
    • Modified the fetch_scopes_for_apis function to implement the new sorting order for OAuth scopes.
    • Added a new unit test to validate that scopes are correctly sorted by service, access level, and classification.
Activity
  • No specific activity (comments, reviews, or progress updates) was found for this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves the user experience by sorting OAuth scopes more logically in the TUI. The implementation of the new sorting logic is correct. However, I've identified two areas for improvement in the new unit test:

  1. There is code duplication between the test and the production code, which should be refactored to improve maintainability.
  2. The test case is incomplete and doesn't fully validate all aspects of the new sorting criteria.
    Please see my detailed comments for suggestions on how to address these points.

src/setup.rs Outdated
Comment on lines +2357 to +2363
scopes.sort_by(|a, b| {
a.api_name
.cmp(&b.api_name)
.then_with(|| b.is_readonly.cmp(&a.is_readonly))
.then_with(|| a.classification.cmp(&b.classification))
.then_with(|| a.short.cmp(&b.short))
});
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This sorting logic is a duplicate of the implementation in fetch_scopes_for_apis. Duplicating production logic in tests makes the code harder to maintain. If the sorting rules change in the future, they would need to be updated in two places, and it's easy to forget the test, leading to it no longer verifying the correct behavior.

To avoid this, I recommend extracting the comparison logic into a new private helper function at the module level.

For example:

// In src/setup.rs (module level)
fn compare_scopes(a: &DiscoveredScope, b: &DiscoveredScope) -> std::cmp::Ordering {
    a.api_name
        .cmp(&b.api_name)
        .then_with(|| b.is_readonly.cmp(&a.is_readonly))
        .then_with(|| a.classification.cmp(&b.classification))
        .then_with(|| a.short.cmp(&b.short))
}

Then, both fetch_scopes_for_apis and this test can use all_scopes.sort_by(compare_scopes); and scopes.sort_by(compare_scopes); respectively. This ensures you're testing the exact same logic that runs in production.

Comment on lines +2321 to +2371
fn scope_sort_groups_by_service_then_access_then_classification() {
let mut scopes = vec![
DiscoveredScope {
url: "https://www.googleapis.com/auth/gmail".to_string(),
short: "gmail".to_string(),
description: "Full Gmail access".to_string(),
api_name: "Gmail".to_string(),
is_readonly: false,
classification: ScopeClassification::Restricted,
},
DiscoveredScope {
url: "https://www.googleapis.com/auth/drive.readonly".to_string(),
short: "drive.readonly".to_string(),
description: "Read-only Drive".to_string(),
api_name: "Drive".to_string(),
is_readonly: true,
classification: ScopeClassification::NonSensitive,
},
DiscoveredScope {
url: "https://www.googleapis.com/auth/drive".to_string(),
short: "drive".to_string(),
description: "Full Drive access".to_string(),
api_name: "Drive".to_string(),
is_readonly: false,
classification: ScopeClassification::Restricted,
},
DiscoveredScope {
url: "https://www.googleapis.com/auth/gmail.readonly".to_string(),
short: "gmail.readonly".to_string(),
description: "Read-only Gmail".to_string(),
api_name: "Gmail".to_string(),
is_readonly: true,
classification: ScopeClassification::NonSensitive,
},
];

scopes.sort_by(|a, b| {
a.api_name
.cmp(&b.api_name)
.then_with(|| b.is_readonly.cmp(&a.is_readonly))
.then_with(|| a.classification.cmp(&b.classification))
.then_with(|| a.short.cmp(&b.short))
});

// Drive scopes first (alphabetically before Gmail)
assert_eq!(scopes[0].short, "drive.readonly");
assert_eq!(scopes[1].short, "drive");
// Gmail scopes second
assert_eq!(scopes[2].short, "gmail.readonly");
assert_eq!(scopes[3].short, "gmail");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The test plan mentions verifying the sort order by service, access level, and classification, but this test case only effectively validates the first two criteria (api_name and is_readonly). The current test data doesn't include items that would have the same api_name and is_readonly status but different classification or short names, so the third and fourth levels of the sort logic are not being exercised.

To make the test more robust and fully cover the new sorting logic, please consider adding more scopes to the test vector. For example, you could add two scopes with the same api_name and is_readonly value but different classifications to verify that classification sorting works as expected.

Address Gemini review feedback:
- Extract inline sort closure into a reusable compare_scopes function
  to avoid duplicating sort logic between production code and tests
- Add a Sensitive-classified scope to the test to verify all four
  sort criteria (service, access level, classification, name)
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the OAuth scope sorting logic to group scopes by service and then access level, which improves the user experience in the TUI picker. The implementation correctly extracts the sorting logic into a dedicated compare_scopes function and adds a unit test to verify the new behavior. My feedback includes a suggestion to make the new test assertions more robust and maintainable.

@googleworkspace-bot
Copy link
Collaborator

/gemini review

Replace brittle index-based assertions with a collected Vec comparison
so the test remains maintainable as scopes change over time.
@anshul-garg27 anshul-garg27 force-pushed the feat/sort-scopes-by-service branch from 6f6bdfc to bf99daf Compare March 12, 2026 20:34
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request changes the sorting order of OAuth scopes in the TUI picker. The new logic sorts scopes by service name, then access level, then sensitivity classification. This is achieved by introducing a new compare_scopes function and applying it in fetch_scopes_for_apis. A new unit test is included to verify the correctness of the new sorting logic. The implementation appears to correctly reflect the intended changes.

@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new sorting logic for OAuth scopes in the TUI picker, grouping them by service, then access level, and finally classification. The implementation is clean, with a dedicated compare_scopes function for the new logic and a comprehensive unit test to verify its correctness. The changes effectively address the issue of scattered scopes and improve the user experience when selecting them. The code is well-structured and the changes are correctly implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAuth scopes are not properly ordered

3 participants