Make Orbit: Read the one fine-grained token permission for GitLab Orbit
What does this MR do and why?
- Adds one fine-grained token permission for GitLab Orbit: Orbit: Read (
read_orbit), under the User tab. - It guards every Orbit REST route and
POST /orbit/mcp. A fine-grained token without it gets a403. - The token check is a gateway, same as Global Search's
/search. Results follow the owner's access. Group and project selections don't limit it, and the token UI says so. read_knowledge_graphandexecute_orbit_mcp_toolstay defined, deprecated and hidden. They expand to raw permissions no Orbit route checks, so tokens that hold them get a403on Orbit. The tokens keep their other permissions and can still rotate, so no migration is needed.- Shows the settings resource as Orbit Setting. The permission name doesn't change.
Background and why we landed here: my comment on #992. Group-limited access moves to a follow-up with /groups/:id/orbit/* routes.
| Token | Orbit |
|---|---|
| Orbit: Read under User | Everything the owner can read |
| Orbit: Read under Group and project, or All memberships | 403 |
| Old Knowledge Graph: Read or MCP tool: Execute | 403, token still rotates |
Legacy PAT with api or read_api |
Unchanged |
References
- Issue: gitlab-org/orbit/knowledge-graph#992 (closed)
- Orbit docs: gitlab-org/orbit/knowledge-graph!2570 (merged)
- Upstream thread: #572694 (closed)
- Aggregation redaction: gitlab-org/orbit/knowledge-graph#347
- Closed attempts: !247199 (closed), !253835 (closed), gitlab-org/orbit/knowledge-graph!2409 (closed)
- Global Search prior art: !222606 (merged), !223999 (merged), Search resources docs
Screenshots or screen recordings
How to set up and validate locally
-
Enable fine-grained tokens:
Feature.enable(:granular_personal_access_tokens) -
Go to User Settings > Personal access tokens > Generate token > Fine-grained token.
-
Open the User tab. Under GitLab Orbit, add Orbit with Read.
-
Query two groups you can read:
curl --header "PRIVATE-TOKEN: <token>" --header "Content-Type: application/json" \ --request POST "https://gdk.test:3443/api/v4/orbit/query" \ --data '{"query":{"query_type":"traversal","nodes":[{"id":"p","entity":"Project","filters":{"full_path":{"starts_with":"acme-corp/"}},"columns":["full_path"]}],"limit":3}}' # both groups: HTTP 200, row_count 3 -
Call MCP with the same token:
curl --header "Authorization: Bearer <token>" --header "Content-Type: application/json" \ --request POST "https://gdk.test:3443/api/v4/orbit/mcp" \ --data '{"jsonrpc":"2.0","method":"tools/list","id":"1","params":{}}' # HTTP 200 -
Try a token without Orbit: Read, one with it only under Group and project access, and one with the old Knowledge Graph: Read:
HTTP 403 {"error":"insufficient_granular_scope", ... "[Orbit: Read]."}
Verified end to end on a GDK VM with the full Orbit stack. 13 checks cover user, group, all-memberships, legacy, old-name, and MCP tokens. One check rotates an old-name token.
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.

