Releases: graphql-hive/router
Release list
hive-router-internal 0.0.41 (2026-08-10)
Features
Expose log correlation to the plugin system
Plugins can now attach a custom correlation (e.g. a tenant or project ID) to every log line of the current request via hive_router::set_log_correlation(key, value), callable from any hook, alongside the built-in request_id and trace_id.
Fixes #1350
Expose the request summary to the plugin system
Plugins can now enrich the request summary log line with custom attributes via hive_router::set_summary_attribute(key, value), callable from any hook (e.g. on_http_request, on_graphql_analysis).
Fixes #1368
Expose the summary message to the plugin system
Plugins can now override the request summary log line's message via hive_router::set_summary_message(message), callable from any hook.
Fixes #1378
Fixes
Add apollo_graphos supergraph source
Adds a new apollo_graphos supergraph source that fetches the supergraph schema from Apollo GraphOS's managed federation Uplink, for routers migrating from Apollo Router/Gateway without needing a separate schema-delivery pipeline.
Configure it with graph_ref and key (or the APOLLO_GRAPH_REF/APOLLO_KEY environment variables), and optionally endpoint (defaults to Apollo's GCP and AWS Uplink endpoints, tried in order), timeout and accept_invalid_certs.
Closes #505
hive-router-config 0.1.11 (2026-08-10)
Features
Add apollo_graphos supergraph source
Adds a new apollo_graphos supergraph source that fetches the supergraph schema from Apollo GraphOS's managed federation Uplink, for routers migrating from Apollo Router/Gateway without needing a separate schema-delivery pipeline.
Configure it with graph_ref and key (or the APOLLO_GRAPH_REF/APOLLO_KEY environment variables), and optionally endpoint (defaults to Apollo's GCP and AWS Uplink endpoints, tried in order), timeout and accept_invalid_certs.
Closes #505
hive-router 0.0.87 (2026-08-05)
Features
Attach the correlation request-id to the root HTTP server span
The root http.server OpenTelemetry span now carries a router.request_id attribute, set to the same request-id used for log correlation (either the incoming correlation header, e.g. x-request-id, or an auto-generated one). This makes it possible to join a trace directly to its logs without cross-referencing trace IDs.
Fixes #1353
Add jwt.scopes_claim
Adds a new jwt.scopes_claim configuration option that lets you specify which JWT claim the @requiresScopes directive should read authorization data from, instead of the hardcoded scope/scopes claim.
This is useful for identity providers that grant authorization data under a different claim name — for example, Microsoft Entra ID, which issues app roles under a roles claim rather than scope. Setting jwt.scopes_claim: roles allows @requiresScopes to authorize requests using Entra app roles without requiring any changes to how the claim is issued.
Add limits.max_request_header_size
Adds a new limits.max_request_header_size configuration option (default: 64KiB) that rejects requests whose HTTP headers exceed the configured size with 431 Request Header Fields Too Large, before the request is processed.
Since the router propagates client headers (cookies, JWTs) to subgraphs, requests with oversized headers would previously be forwarded and rejected by the subgraph server's own header limit (e.g. Tomcat's 8KB default), surfacing as a confusing subgraph error. With this limit, such requests are rejected at the router with a clear error.
Fixes
Expose request correlation IDs to plugins and middlewares
Request/trace correlation IDs are now extracted and scoped by a dedicated middleware that wraps the entire request pipeline, instead of only inside the GraphQL handler.
This means plugins, the coprocessor runtime, and any other middleware can now log with the same request_id/trace_id as the rest of the request.
Fixes #1351
Register the state the subscription callback handler extracts
The subscription callback handler could not serve a single request: every call failed the ntex State extractor with App state is not configured, to configure use App::state(), returning a 500 to the subgraph. Because callbacks are how the subgraph delivers events back to the router, any subscription using the callback transport silently stopped producing messages.
handle_callback extracts two pieces of state:
callback_subscriptions: web::types::State<CallbackSubscriptionsMap>,
telemetry_context: web::types::State<std::sync::Arc<TelemetryContext>>,Neither listener registered a matching pair:
- the dedicated callback server (
subscriptions.callback.listenset) registered the map, but passedtelemetry.context— a bareTelemetryContext, sinceTelemetry::contextis not anArc— where the handler asks forState<Arc<TelemetryContext>>; - the main server (no
listen, callback mounted on the main app) registeredArc<TelemetryContext>viashared_state.telemetry_context, but never registeredCallbackSubscriptionsMapat all.
State<T> is generic, so both mismatches compile; they only fail when the extractor runs. That makes the callback protocol broken in both configurations, with no config-level workaround.
The dedicated server now takes its telemetry context from shared_state.telemetry_context, the same Arc the main server already registers, and the main server gains the missing map.
The e2e suite does not catch this: TestRouter builds its own ntex App rather than reusing the one run_router assembles, and its copy happens to register both states correctly — it reads the telemetry context from shared_state (already an Arc) and registers callback_subscriptions on the main app. listen_on_different_port therefore passes against a build whose callback endpoint 500s on every request.
Accept multipart streaming types with boundary parameters
Hive Router now accepts boundary parameters on multipart/mixed values in the Accept header. This prevents Apollo Client's default Accept header from returning 415 Unsupported Media Type while leaving response boundary selection to the router.
Seed the embedded Hive Laboratory from the router config
Adds optional keys under laboratory: operations, named operations that each open in a pre-filled tab, and collections, named groups of operations shown in the Laboratory's sidebar. Each operation may carry variables, headers and extensions as native YAML maps.
Seeded values are embedded in the served page and visible via "view source", so they must not contain secrets. Seeded operations and collections are refreshed from config on every reload; work a user creates themselves is preserved.
Upgrade to latest laboratory
Upgrades the embedded @graphql-hive/laboratory from 0.2.0 to 0.2.3.
Added
- Copy as cURL in the operation toolbar.
- A reload-schema button in the builder, which introspects over the network even when a schema was
supplied by the host, and spins while the request is in flight. It replaces the previous
"restore default endpoint" button;restoreDefaultEndpointremains available on the API. introspection.pollSchemasetting to turn off the 5 second introspection poll and refresh the
schema only on demand.enableFullScreenprop (defaulttrue) so hosts that already fill the viewport can hide the
full screen control.- The Query Plan tab is now always shown, with an empty state explaining that plans appear when
the gateway returnsextensions.queryPlan.
Fixed
- The builder no longer collapses expanded fields while introspection is polling. An unchanged
schema previously produced a newGraphQLSchemaon every poll, resetting expansion to the depth
of the current document. - Editor hovers now appear on mouse over, so validation messages and schema documentation are
readable. - Monaco's folding chevrons render as icons instead of empty squares. Font faces are now
registered on the document, where browsers resolve them, rather than inside the shadow root
where they are ignored. - Response size is shown in real units instead of always reading
0KB, and is measured in UTF-8
bytes. - Tooltips attached with
asChildnow appear.Button,TooltipTriggerandAlertDialogTrigger
did not forward refs, leaving the tooltip without an element to anchor to. - The builder's tree/list toggle is controlled, cannot be deselected into an empty state, and is
disabled with an explanation until a search is active. - The Query Plan panel no longer throws while rendering when a response body is not JSON.
- monaco-graphql is initialized once and updated in place, so variables validation registers
regardless of which editor mounts first and survives an endpoint change. - Removed invalid nested buttons in builder and collection rows, which also makes the collection
edit and delete actions keyboard reachable. - The query plan visualization no longer updates state during render.
- The builder no longer resets its view when toggling settings, by hardening the merge code.
hive-router-plan-executor 7.0.2 (2026-08-05)
Fixes
Attach the correlation request-id to the root HTTP server span
The root http.server OpenTelemetry span now carries a router.request_id attribute, set to the same request-id used for log correlation (either the incoming correlation header, e.g. x-request-id, or an auto-generated one). This makes it possible to join a trace directly to its logs without cross-referencing trace IDs.
Fixes #1353
Add jwt.scopes_claim
Adds a new jwt.scopes_claim configuration option that lets you specify which JWT claim the @requiresScopes directive should read authorization data from, instead of the hardcoded scope/scopes claim.
This is useful for identity providers that grant authorization data under a different claim name — for example, Microsoft Entra ID, which issues app roles under a roles claim rather than scope. Setting jwt.scopes_claim: roles allows @requiresScopes to authorize requests using Entra app roles without requiring any changes to how the claim is issued.
Add limits.max_request_header_size
Adds a new limits.max_request_header_size configuration option (default: 64KiB) that rejects requests whose HTTP headers exceed the configured size with 431 Request Header Fields Too Large, before the request is processed.
Since the router propagates client headers (cookies, JWTs) to subgraphs, requests with oversized headers would previously be forwarded and rejected by the subgraph server's own header limit (e.g. Tomcat's 8KB default), surfacing as a confusing subgraph error. With this limit, such requests are rejected at the router with a clear error.
Seed the embedded Hive Laboratory from the router config
Adds optional keys under laboratory: operations, named operations that each open in a pre-filled tab, and collections, named groups of operations shown in the Laboratory's sidebar. Each operation may carry variables, headers and extensions as native YAML maps.
Seeded values are embedded in the served page and visible via "view source", so they must not contain secrets. Seeded operations and collections are refreshed from config on every reload; work a user creates themselves is preserved.
hive-router-internal 0.0.40 (2026-08-05)
Features
Attach the correlation request-id to the root HTTP server span
The root http.server OpenTelemetry span now carries a router.request_id attribute, set to the same request-id used for log correlation (either the incoming correlation header, e.g. x-request-id, or an auto-generated one). This makes it possible to join a trace directly to its logs without cross-referencing trace IDs.
Fixes #1353
Fixes
Add jwt.scopes_claim
Adds a new jwt.scopes_claim configuration option that lets you specify which JWT claim the @requiresScopes directive should read authorization data from, instead of the hardcoded scope/scopes claim.
This is useful for identity providers that grant authorization data under a different claim name — for example, Microsoft Entra ID, which issues app roles under a roles claim rather than scope. Setting jwt.scopes_claim: roles allows @requiresScopes to authorize requests using Entra app roles without requiring any changes to how the claim is issued.
Add limits.max_request_header_size
Adds a new limits.max_request_header_size configuration option (default: 64KiB) that rejects requests whose HTTP headers exceed the configured size with 431 Request Header Fields Too Large, before the request is processed.
Since the router propagates client headers (cookies, JWTs) to subgraphs, requests with oversized headers would previously be forwarded and rejected by the subgraph server's own header limit (e.g. Tomcat's 8KB default), surfacing as a confusing subgraph error. With this limit, such requests are rejected at the router with a clear error.
Seed the embedded Hive Laboratory from the router config
Adds optional keys under laboratory: operations, named operations that each open in a pre-filled tab, and collections, named groups of operations shown in the Laboratory's sidebar. Each operation may carry variables, headers and extensions as native YAML maps.
Seeded values are embedded in the served page and visible via "view source", so they must not contain secrets. Seeded operations and collections are refreshed from config on every reload; work a user creates themselves is preserved.
hive-router-config 0.1.10 (2026-08-05)
Features
Add jwt.scopes_claim
Adds a new jwt.scopes_claim configuration option that lets you specify which JWT claim the @requiresScopes directive should read authorization data from, instead of the hardcoded scope/scopes claim.
This is useful for identity providers that grant authorization data under a different claim name — for example, Microsoft Entra ID, which issues app roles under a roles claim rather than scope. Setting jwt.scopes_claim: roles allows @requiresScopes to authorize requests using Entra app roles without requiring any changes to how the claim is issued.
Add limits.max_request_header_size
Adds a new limits.max_request_header_size configuration option (default: 64KiB) that rejects requests whose HTTP headers exceed the configured size with 431 Request Header Fields Too Large, before the request is processed.
Since the router propagates client headers (cookies, JWTs) to subgraphs, requests with oversized headers would previously be forwarded and rejected by the subgraph server's own header limit (e.g. Tomcat's 8KB default), surfacing as a confusing subgraph error. With this limit, such requests are rejected at the router with a clear error.
Fixes
Seed the embedded Hive Laboratory from the router config
Adds optional keys under laboratory: operations, named operations that each open in a pre-filled tab, and collections, named groups of operations shown in the Laboratory's sidebar. Each operation may carry variables, headers and extensions as native YAML maps.
Seeded values are embedded in the served page and visible via "view source", so they must not contain secrets. Seeded operations and collections are refreshed from config on every reload; work a user creates themselves is preserved.
hive-router 0.0.86 (2026-07-28)
Fixes
Regular queries no longer count toward max_long_lived_clients
The long-lived client limit (traffic_shaping.router.max_long_lived_clients) classified requests from the Accept header alone, so clients that advertise streaming support on every operation (e.g. urql sends ..., text/event-stream, multipart/mixed) had all of their queries and mutations counted against — and, past the limit, rejected by — the limit.
Long-lived clients are now counted where they actually become known:
- WebSocket connections are still reserved at upgrade time.
- HTTP subscriptions reserve a slot once the parsed operation is known to be a subscription — still before any planning/execution work — and release it when the client stream ends.
Regular queries and mutations never count toward the limit, regardless of their Accept header, matching the documented behavior. Over-limit rejections keep the same response (503, Retry-After: 5, Too many long-lived clients) and now happen inside the request span, so they are visible to tracing.
Replaced logging request-id generator
Version 0.0.85 introduced new logging runtime that uses Sonyflake crate to generate request-id in requests that doesn't have it passed via HTTP headers.
The Sonyflake runtime can fail on some OS configurations.
This change replaces the Sonyflake runtime with uuid generator, that's more fail-safe.
hive-router-plan-executor 7.0.1 (2026-07-28)
Fixes
Regular queries no longer count toward max_long_lived_clients
The long-lived client limit (traffic_shaping.router.max_long_lived_clients) classified requests from the Accept header alone, so clients that advertise streaming support on every operation (e.g. urql sends ..., text/event-stream, multipart/mixed) had all of their queries and mutations counted against — and, past the limit, rejected by — the limit.
Long-lived clients are now counted where they actually become known:
- WebSocket connections are still reserved at upgrade time.
- HTTP subscriptions reserve a slot once the parsed operation is known to be a subscription — still before any planning/execution work — and release it when the client stream ends.
Regular queries and mutations never count toward the limit, regardless of their Accept header, matching the documented behavior. Over-limit rejections keep the same response (503, Retry-After: 5, Too many long-lived clients) and now happen inside the request span, so they are visible to tracing.
Replaced logging request-id generator
Version 0.0.85 introduced new logging runtime that uses Sonyflake crate to generate request-id in requests that doesn't have it passed via HTTP headers.
The Sonyflake runtime can fail on some OS configurations.
This change replaces the Sonyflake runtime with uuid generator, that's more fail-safe.
hive-router-internal 0.0.39 (2026-07-28)
Fixes
Regular queries no longer count toward max_long_lived_clients
The long-lived client limit (traffic_shaping.router.max_long_lived_clients) classified requests from the Accept header alone, so clients that advertise streaming support on every operation (e.g. urql sends ..., text/event-stream, multipart/mixed) had all of their queries and mutations counted against — and, past the limit, rejected by — the limit.
Long-lived clients are now counted where they actually become known:
- WebSocket connections are still reserved at upgrade time.
- HTTP subscriptions reserve a slot once the parsed operation is known to be a subscription — still before any planning/execution work — and release it when the client stream ends.
Regular queries and mutations never count toward the limit, regardless of their Accept header, matching the documented behavior. Over-limit rejections keep the same response (503, Retry-After: 5, Too many long-lived clients) and now happen inside the request span, so they are visible to tracing.
Replaced logging request-id generator
Version 0.0.85 introduced new logging runtime that uses Sonyflake crate to generate request-id in requests that doesn't have it passed via HTTP headers.
The Sonyflake runtime can fail on some OS configurations.
This change replaces the Sonyflake runtime with uuid generator, that's more fail-safe.
hive-router-config 0.1.9 (2026-07-28)
Fixes
Regular queries no longer count toward max_long_lived_clients
The long-lived client limit (traffic_shaping.router.max_long_lived_clients) classified requests from the Accept header alone, so clients that advertise streaming support on every operation (e.g. urql sends ..., text/event-stream, multipart/mixed) had all of their queries and mutations counted against — and, past the limit, rejected by — the limit.
Long-lived clients are now counted where they actually become known:
- WebSocket connections are still reserved at upgrade time.
- HTTP subscriptions reserve a slot once the parsed operation is known to be a subscription — still before any planning/execution work — and release it when the client stream ends.
Regular queries and mutations never count toward the limit, regardless of their Accept header, matching the documented behavior. Over-limit rejections keep the same response (503, Retry-After: 5, Too many long-lived clients) and now happen inside the request span, so they are visible to tracing.