Loading
Add POST /orbit/context endpoint
What does this MR do and why?
Adds POST /api/v4/orbit/context. It takes one token, such as a merge request or work item URL, and returns a short summary from PostgreSQL. With expand, it also attaches the entity's graph neighborhood from a single named query, so one request bills at most one graph query. It also takes epic tokens, which resolve to the epic's work item, and echoes the expansion query, so a client can rerun it through POST /api/v4/orbit/query/:name.
References
- Related to https://gitlab.com/gitlab-org/orbit/knowledge-graph/-/issues/1262
- Design: ADR 021 in the Orbit knowledge-graph repository (kg!2677)
- Depends on the GKG named queries in gitlab-org/orbit/knowledge-graph!2834 (merged)
- Replaces the closed prototype !254189 (closed)
Screenshots or screen recordings
Not applicable, API only.
How to set up and validate locally
- Run
bundle exec rspec ee/spec/requests/api/orbit ee/spec/lib/analytics/orbit/context_token_spec.rb ee/spec/services/analytics/orbit ee/spec/lib/analytics/knowledge_graph. - With a running GKG, call the endpoint with
{"tokens": ["<group>/<project>!1"], "expand": true}. Use a user who is at least a Reporter in a group where Orbit is turned on, otherwiseexpandreturnsoutside_graph_scope.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.
Agent context
Analytics::Orbit::ContextTokenparsesType[id], GIDs, instance URLs,path!iid,path#iidand the epic forms (Epic[id], epic GIDs,/groups/.../-/epics/<iid>URLs,group&iid) from the text alone (invalid_token,unsupported_type).- Epic tokens set
Parsed#epicand keep typeWorkItem. The service resolvesEpic[id]throughEpic#work_item, and iid forms through the group-level work item lookup, requiring an epic work item. The samereadable?check applies, so unlicensed, confidential, missing and wrong-group epics all returnnot_found. Analytics::Orbit::ContextServicelooks up the record (including group-level work items), applies the policy ability and the granular-token boundary, and builds the summary. Every failure after a lookup starts returns the samenot_found; linked records and users are filtered to readable ones before the list is cut, in a fixed order.summary.truncatednames the lists that were cut, and ids are strings like the graph node ids.Analytics::Orbit::ContextExpansionServicerunsexpand_merge_request/expand_work_itemwithnode_idsand a constantlimitthroughQueryRunner. It returnsexpansion_unsupported_typewhen the type has no query, andoutside_graph_scope(with no query and no billing) when the record is outside the user's Reporter+ Orbit-enabled traversal paths. Every expansion carriesquery: {name, parameters}, the exact payload sent to GKG, except forexpansion_unsupported_type. It maps the governing-namespace guard tobilling_namespace_requiredwith the same message, deep link and candidate groups asquery/:name, plusquota_exhausted,timeoutandexecution_error.QueryRunnertakes an optionalrenderer:. The newDataRendererreturns the graph as data instead of an HTTP response, parsed with the safe JSON parser. Because that renderer has no stream frame,QueryRunnerreads chunked results into one body instead of streaming them. An error message, early stream end or deadline during that read maps to the same codes as a non-streamed query.- The route requires a JSON body like
query/:name, usesread_orbit, the same rate limit and namespace ordering asquery/:name,response_formatraworllm, and lifecycle experiment. Docs, fine-grained token table, routes JSON and OpenAPI are updated. - Tests: new request, token, service and expansion specs, plus
DataRenderercases in the runner spec, run locally (all green). The GKG boundary is mocked.mermaidlinthook skipped locally because its node deps are missing. - Merge after kg!2834 is deployed. Until then,
expandreturnsexecution_error, because GKG does not know the query names. - Follow-up: the HTTP router snapshot needs a refresh for the new route (
check_router_routes_sync, which isallow_failure).
Related to https://gitlab.com/gitlab-org/orbit/knowledge-graph/-/work_items/1260
Edited by Michael Angelo Rivera