Include granular_scopes in personal access token create and rotate API responses
Summary
Granular personal access tokens have scopes stored as granular_scopes, but several create and rotate endpoints do not return them. The caller sees granular: true and scopes: ["granular"] and cannot confirm which scopes were set or copied. GET /personal_access_tokens, GET /personal_access_tokens/:id and POST /personal_access_tokens/:id/rotate already return them.
Affected endpoints
POST /user/personal_access_tokens-lib/api/users.rb:1893. Acceptsgranular_scopes(exactly_one_ofscopes/granular_scopes) and creates the token withcreate_granular_token, but presents it withPersonalAccessTokenWithTokenand no options. The response omits the scopes the caller just set.POST /personal_access_tokens/self/rotate-lib/api/personal_access_tokens/self_rotation.rb:41.RotateServicecopies granular scopes to the new token (app/services/personal_access_tokens/rotate_service.rb:66-68), and a granular token can call this route (rotate_personal_access_tokenpermission). The response omitsgranular_scopes. The siblingPOST /personal_access_tokens/:id/rotatealready returns them.POST /groups/:id/manage/personal_access_tokens/:pat_id/rotate-ee/lib/api/manage/groups.rb:134. Presents the rotated token the same way, without options.
Cause
API::Entities::PersonalAccessToken (lib/api/entities/personal_access_token.rb:25-27) exposes granular_scopes only when token.granular? && options[:with_granular_scopes]. PersonalAccessTokenWithToken inherits from it. The endpoints above present without the option, so the field is never rendered.
Verified on master by rendering the entity for a granular token in a development console: no granular_scopes key without the option, present with it.
Proposed fix
Follow the pattern used by GET /personal_access_tokens, GET /personal_access_tokens/:id and POST /personal_access_tokens/:id/rotate (lib/api/personal_access_tokens.rb:44,69,103, added by !243754 (merged)):
- Preload
granular_scopes: :namespace. - Present with
with_granular_scopes: trueandproject_ids_by_namespace_id: project_ids_by_namespace_id_for([token])(helper inlib/api/helpers/personal_access_tokens_helpers.rb).
!259764 (merged) applies the same pattern to GET /personal_access_tokens/self and is a good model, including specs.
The change is additive: the field only appears for granular tokens. Update the matching API docs page for each endpoint.
Acceptance criteria
- The three endpoints return
granular_scopesfor granular tokens. - Legacy token responses are unchanged and run no
granular_scopesquery. - A project-scoped granular scope resolves
project_id. - An N+1 spec covers the new presentation.
- API docs are updated for each endpoint.
References
- !243754 (merged)
- !259764 (merged)
- #629849 (fine-grained PAT self-introspection)