Apply group IP address restrictions to Orbit graph queries
What does this MR do and why?
Orbit graph queries (/api/v4/orbit/query and /api/v4/orbit/mcp) authorize their results through a redaction callback that runs read_project / read_group. That callback is served on an internal endpoint, and internal endpoints do not receive the request IP, so group IP address restrictions are not applied to Orbit results the way they are on the standard REST and UI paths.
This MR aligns Orbit with the platform behavior: it forwards the request IP resolved at the user-facing endpoint through Workhorse to the redaction callback and evaluates the authorization policy with it, mirroring how the git internal API re-establishes the IP on its own internal endpoint.
Raised via the forum: https://forum.gitlab.com/t/orbit-and-api-networking-access/134447
Changed files
ee/lib/ee/gitlab/workhorse.rb—send_orbit_queryforwardsGitlab::IpAddressState.currentas theClientIpsend-data param (the user-facing request is non-internal, so the IP is already set).workhorse/internal/orbit/sendquery.go,workhorse/internal/orbit/redaction.go— carryClientIPthrough and set theX-Gitlab-Orbit-Client-Ipheader on the redaction callback.ee/lib/api/internal/orbit.rb— wrapRedactionServiceinGitlab::IpAddressState.with(request.headers['X-Gitlab-Orbit-Client-Ip']).ee/spec/requests/api/internal/orbit_redaction_spec.rb— regression coverage: resource redacted from a disallowed IP, authorized from an allowed IP.
The header is set only by Workhorse on the internal callback (guarded by verify_workhorse_api!), so it is not client-controllable.
How to set up and validate locally
Verified end to end on GDK. With a group that has an IP address range set and a request from an IP outside it:
/orbit/queryand MCPquery_graphnow return no rows for projects/definitions in that group, matching the standard API behavior.- A request from an in-range IP still returns the rows, and removing the range restores them. Non-restricted queries are unaffected.
Tests: existing redaction/workhorse specs green (25 examples) plus 2 new IP examples; Go orbit package tests green.
Performance
No N+1. One additional ip_restrictions load per distinct root namespace in the redaction batch (measured +1 query for a 16-project batch sharing one root; timing within noise). This is the same policy check the standard request path already performs.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.