Return namespace plan, group stats and bans to fine-grained tokens
What does this MR do and why?
A fine-grained personal access token gets null for the fields below, even when it can read the group or remove the ban, because their types declare no authorize_granular_token directive. Each type is returned only by these fields, whose parent already authorizes the token, so each now declares skip_reason: :parent_authorizes and leaves authorization_todo.txt:
| Type | Returned only by | Token checked at |
|---|---|---|
NamespacePlan |
Namespace.plan, inherited by Group |
Namespace, read_namespace; Group, read_group |
GroupStats |
Group.stats |
Group, read_group |
NamespaceBan |
NamespaceBanDestroyPayload.namespaceBan |
NamespaceBanDestroy, delete_namespace_ban |
The checks for the user stay: admin_namespace on plan, read_group on GroupStats and unban_group_member on the mutation.
GroupReleaseStats (GroupStats.releaseStats) stays on the list: it needs a release permission of its own. TargetedMessage is left to #636861, which plans to remove it in 19.7.
If !266839 (merged) lands first, I will add parent_permissions: [:read_namespace, :read_group] to NamespacePlan, like NamespaceAvailableFeatures there.
References
- Related to #593878, the GraphQL gaps for fine-grained tokens.
- !252874 (merged) gave the MLOps child types the same annotation.
I found this while working on gitlab-mcp-server.
Screenshots or screen recordings
No UI change.
How to set up and validate locally
-
In a private top-level group you own, create a fine-grained token with Group: Read and Namespace: Read for it, and run:
query { group(fullPath: "<group>") { plan { name } stats { __typename } } namespace(fullPath: "<group>") { plan { name } } } -
On master
planandstatsarenull; on this branch they return data. -
Ban a user in the Rails console (
Namespaces::NamespaceBan.create!(namespace: group, user: other_user)), then runmutation { namespaceBanDestroy(input: { id: "<ban global ID>" }) { namespaceBan { id } } }with a token that has Namespace Ban: Delete:namespaceBanisnullon master and the removed ban on this branch.
I ran steps 1 to 3 as the new examples of the EE request specs group_query_spec.rb, namespace_query_spec.rb and namespace_bans/destroy_spec.rb: with a fine-grained token holding the parent's permission, the fields are null on master's code and return data on this branch.
Checks I ran (Ruby 3.3.11)
- With master's types and todo list, the new examples give 7 examples, 4 failures: every example that expects data fails.
- Putting back any one type file from master fails only the examples that read that type.
- On this branch, the three changed specs and the
GroupStatsandNamespacePlantype specs: 49 examples, 0 failures. gitlab:permissions:validate, RuboCop and the commit linter pass;gitlab:permissions:graphql:compile_docschanges nothing. Left to the pipeline: Ruby 3.4.10 and the FOSS run.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.