Add Orbit entity context API
What does this MR do and why?
Adds GET /api/v4/orbit/context so Orbit clients can resolve graph entity references into compact Merge Request and Issue summaries. Rails applies normal permissions and returns indistinguishable not_found results for missing or inaccessible records. The endpoint supports ordered batches and raw or LLM-oriented output.
References
Related to https://gitlab.com/gitlab-org/orbit/knowledge-graph/-/work_items/1262
Screenshots or screen recordings
Not applicable. This change adds an API endpoint without UI changes.
| Before | After |
|---|---|
| No entity context endpoint | Permission-aware entity context endpoint |
How to set up and validate locally
-
Enable the
knowledge_graphfeature flag and ensure the Orbit licensed feature is available. -
Configure a Knowledge Graph-enabled namespace for the user.
-
Run:
bundle exec rspec ee/spec/requests/api/orbit/data_context_spec.rb bundle exec rubocop ee/lib/api/orbit/data.rb \ ee/app/services/analytics/orbit/context_service.rb \ ee/app/services/analytics/orbit/context_llm_formatter.rb \ ee/lib/api/entities/orbit/context.rb \ ee/spec/requests/api/orbit/data_context_spec.rb scripts/lint-doc.sh doc/api/orbit.md bin/rake gitlab:openapi:v3:check_docs
MR acceptance checklist
Evaluated against the MR acceptance checklist.
Agent context details
Contract
The endpoint accepts one to 20 repeated refs[] parameters in Type[id] form. Supported types are MergeRequest, Issue, and the WorkItem alias, which normalizes to Issue. It preserves input order and reports entry-level invalid_ref, unsupported_type, or not_found errors.
Raw output follows this shape:
{
"version": "1.0.0",
"entities": [
{
"ref": "MergeRequest[123]",
"type": "MergeRequest",
"id": 123,
"found": true,
"summary": {}
}
]
}response_format=llm returns a compact text/plain key/value rendering.
Mechanics and safeguards
- Reuses Orbit authentication, license and feature gates, granular
read_knowledge_graphauthorization, enabled-namespace checks, and theorbit_queryrate limit. - Bulk-loads the requested records and bounded related data. Reviewers and assignees are limited to 10, labels to 20, and linked entities to 10 per parent.
- Applies
read_merge_request,read_issue, andread_pipelinechecks. Forbidden and missing records have the same response. - Quotes table and column identifiers in the bounded window queries.
- Keeps the beta route hidden from generated OpenAPI, matching the existing Orbit endpoints.
Validation
bundle exec rspec ee/spec/requests/api/orbit/data_context_spec.rb
24 examples, 0 failures, 2 expected pending
bundle exec rubocop <five changed Ruby files>
5 files inspected, no offenses detected
scripts/lint-doc.sh doc/api/orbit.md
Markdownlint: 0 errors
Vale: 0 errors, 0 warnings, 0 suggestions
bin/rake gitlab:openapi:v3:check_docs
OpenAPI v3 documentation is up to dateThe request specs cover authentication and authorization gates, malformed requests, mixed batches, permission filtering, both response formats, rate limiting, bounded collections, pipeline visibility, and query growth.
Alternatives considered
The endpoint could call existing per-type REST endpoints, but that would require several requests and duplicate identifier resolution in clients. Resolving in Rails keeps local database identifiers and permission checks with the application that owns them. Free-form graph queries remain available for fields outside the compact summaries.
Example requests
curl --request GET \
--header "PRIVATE-TOKEN: <token>" \
--url "https://gitlab.example.com/api/v4/orbit/context?refs[]=MergeRequest%5B123%5D&refs[]=Issue%5B456%5D"
curl --request GET \
--header "PRIVATE-TOKEN: <token>" \
--url "https://gitlab.example.com/api/v4/orbit/context?refs[]=Issue%5B456%5D&response_format=llm"