feat(server): add named query discovery RPC
What does this MR do and why?
Since presets moved server-side, the Orbit graph explorer can no longer show the query text when a preset is selected — clients only hold names, so the DSL becomes visible only after executing. This adds a discovery RPC that lists the server-defined named queries with their name, description, and DSL rendered for the calling user, letting the editor populate on selection without clients owning query text again. A Rails follow-up exposes it as GET /api/v4/orbit/templates.
Related Issues
Relates to #955
Testing
- Unit tests cover the new handler: catalog is non-empty, every entry renders to valid placeholder-free JSON, and identity bindings resolve to the caller's user id.
- Verified end-to-end with grpcurl against a local
mise run devserver backed by GDK: all six embedded named queries returned with bindings and example parameters rendered.
Performance Analysis
Unary RPC over the in-memory embedded catalog (currently six templates); no ClickHouse or Rails round-trip involved.
- This merge request does not introduce any performance regression. If a performance regression is expected, explain why.
Agent context — long-form analysis, file-by-file walkthroughs, profiler output, alternatives considered
New surface
gkg.proto:ListNamedQueries(ListNamedQueriesRequest) returns (ListNamedQueriesResponse);NamedQueryDefinition { name, description, query_dsl }.query_dslis the rendered query DSL as a JSON string, executable as-is.crates/gkg-server/src/grpc/service.rs: handler authenticates via the standard JWT context, buildsnamed_queries::BindingValues { current_user_id }from claims, and renders each embedded template withNamedQuery::renderusingexample_parameters()for$paramplaceholders — the same combination the build script uses to compile every template, so render failures here are unreachable in practice and mapped tointernal.- Rust stubs regenerated via
cargo build --features regenerate-protos; Go stubs (clients/gkgpb) viamise proto:go(CI gateproto-go-check).
Rendering semantics
$binding(currently onlycurrent_user_id) resolves from JWT claims, so the catalog is per-user and the returned DSL reproduces exactly whatQUERY_TYPE_NAMEDexecution would run.$paramplaceholders are filled with each parameter's declaredexamplevalue, producing executable JSON rather than placeholder syntax.
Alternatives considered
- Echoing the rendered DSL inside the query response (injected before the result JSON is sent). Dropped: it only populates the editor after execution, changes the raw response schema (schema +
RAW_OUTPUT_FORMAT_VERSIONchurn), and doesn't give clients a catalog. A discovery RPC restores populate-on-select and lets the frontend drop its hardcoded preset list entirely. - Route naming: the REST leg will be
GET /api/v4/orbit/templates(matches existing single-word orbit routes); the gRPC/server-side concept keeps the canonical "named query" term perCONTEXT.md.
Docs updated in this MR
docs/design-documents/querying/README.md: replaced the "There is no discovery RPC" statement with the as-built catalog description.docs/dev/agents-reference-index.md: named-query row now mentionsListNamedQueries.
Follow-ups (separate MRs, other repos)
- Rails:
GET /api/v4/orbit/templatesproxying this RPC. - Frontend: drive the preset dropdown and editor population from the catalog instead of
NAMED_QUERY_TEMPLATES; display-text/i18n decision needed sincedescriptionis untranslated YAML text.
%{all_commits}