Changelog
0.13.0
Fix: No redirect from the cluster is followed, in any credentials mode. Go's HTTP client keeps
Authorizationon a redirect to a subdomain of the host and on an https-to-http downgrade, and copies every other header, theX-ClickHouse-Keypassword among them, to any host; a proxy in front of the cluster or a mis-pointed datasource could send the credential somewhere nobody configured. A 3xx now fails the query naming where it pointed.Feature: New credentials type Forward OAuth + Exchange (
forwardOAuthExchange). The signed-in user's token is exchanged for a cluster token (RFC 8693) before querying, for a Grafana whose users sign in through an issuer the cluster does not accept directly. The data source stores no credential; the exchange endpoint and its per-cluster credentials come from a[plugin.hydrolix-hydrolix-datasource]section in Grafana's configuration file, which reaches the plugin asGF_PLUGIN_EXCHANGE_URL/GF_PLUGIN_EXCHANGE_CLIENT_SECRETS. The audience is always the data source's host. Requires verified TLS to the cluster, with Skip TLS verify refused, and anhttpsexchange URL whose redirects are not followed. Requires the HTTP protocol — native binds its credential to the connection and cannot carry a refreshed token — and Grafana'suse_refresh_token, since every exchange after the sign-in token expires is refused. A cluster token is reused only by the exact sign-in token it was minted from, so a refresh costs one exchange.Fix: A query's own
connectionArgsno longer reach the connection cache in any credentials mode. sqlds reads them from the query JSON the browser sends, so a caller could otherwise choose which cached connection a query ran onFix:
Save & teston either forwarding mode reported a working data source as degraded. The check ran on the bootstrap connection, which has no signed-in user, so it tested something no query uses. Both modes now report what can actually be established at configuration timeFix:
$__adHocFilter(<table>)with an explicit argument rejected a Hydrolix custom view or any quoted table name withinvalid $__adHocFilter argument(HDX-12561): the argument allowed only baretableordatabase.table. It now also accepts backtick- and double-quoted names, so$__adHocFilter(akamai.`logs#redacted`)resolves the view's columns. As in the table variable, quote a view name; an unquoted#is still rejectedFix: Ad hoc filter values showed "No options found" when the ad hoc table variable named a Hydrolix custom view (
akamai.`logs#redacted`) or any backtick- or double-quoted table (HDX-12543). Plain-column keys still loaded, but the primary-key lookup behind the preloads searchedsystem.tablesfor the quoted spelling and found no row: the value query was never sent, andMapcolumns (attrs['…']) dropped out of the key list because their key discovery runs a$__timeFilter()that failed on the backend. In any query whose FROM names such a table,$__timeFilter(),$__timeFilter_ms(),$__timeInterval()and$__timeInterval_ms()without a column argument failed the same way withprimary key not found. The lookup now uses the bare name; each custom view has its ownsystem.tablesrow carrying the base table's primary key. The table variable no longer needs a view name in backticks: the plugin quotes any part that is not a plain identifier, soakamai.logs#redactedis sent asakamai.`logs#redacted`. A name without a database (including a quoted one containing a dot,`my.logs`) now takes the datasource's default database for DESCRIBE and the value query too, not only for the key lookupFix: Ad hoc filters on a table without a primary key (HDX-11399). The key and value dropdowns came up empty when
system.tables.primary_keyis"", and map-key discovery (attrs['…']) on such a table failed with a ClickHouse parse error because the empty key was interpolated into$__timeFilter(). Both now issue a keyless preload: no$__timeFilter, no time range, still bounded bytopK(100),hdx_query_max_execution_time = 10and the sharedSETTINGSsuffix. Keyed tables issue the same statements as before. Asystem.tableslookup that fails is no longer mistaken for a keyless table: it is not memoized and issues no preload. On the backend,$__timeFilter(),$__timeFilter_ms(),$__timeInterval()and$__timeInterval_ms()without a column argument on a keyless table now fail withtable has no primary key, naming the table and hinting to pass the time column as the argumentFix: The signed-in user's auth header did not reach the plugin backend's metadata lookups. It is set on
HdxQuery.Headers, which isjson:"-", so the/interpolateroute marshalled it away and the QueryData path never filled it — the macros found nil. It now travels on the request context, set at both entry points. Two things were broken by that and are fixed together: the per-user metadata cache scope below, and a macro's metadata lookup, which on a cold cache reached the cluster with no credential at all (forwardOAuth: missing OAuth token in connection args)Fix: Schema metadata was cached across users in
forwardOAuthmode.MetadataProviderkeyed a table's primary key and a CTE's columns on the table or CTE alone, for an hour per datasource instance, and the caller's token reached the cluster only on a miss — so one user's lookup served every other user of that datasource that table's primary key and column name→type map, without the cluster authorizing them. Schema shape, not rows. Both caches now key on the forwarded identity; modes that forward no identity are unchanged. Behaviour change forforwardOAuthusers: cache hit rate falls, so more metadata queries reach the clusterSecurity: Bump
source-map-jsto 1.2.2 to clear CVE-2026-93749 (GHSA-68fv-2mgg-jv7q, high severity), which fails the plugin validator. Build-time dependency only; it is not shipped in the pluginSecurity: Override
follow-redirectsto 1.16.1 to clear CVE-2026-111755 and CVE-2026-111756 (both high severity), which fail the plugin validator. Reached only through the dev dependencynode-rest-client-promise; not shipped in the pluginChore: Pin Go to 1.27.3 and
golang.org/x/netto 0.61.0 — Grafana's govulncheck reported twelve reachable advisories against 1.26.8 and two against x/net 0.59.0; it now finds none. The go directive, CI, release and nightly workflows, the dev container and the e2e exchange stub move togetherChore: Update create-plugin scaffold to 7.11.0
Chore: Add a nightly compatibility canary (HDX-12393) that runs the e2e suite against every supported Grafana release with
datetime.useLuxonoff, and against the nightly image with the toggle off and on; a failing night files or updates a labelled GitHub issue naming the failing cellsChore: Let Dependabot and fork PRs pass CI without the signing token (HDX-12501) — PR CI packages the plugin unsigned when the token is absent, and the release workflow asserts that exactly one signed zip exists before publishing
Feature: Validate queries in the query editor before they run (HDX-11409). About a second after you stop typing, a status bar under the SQL editor dry-runs the query with
EXPLAINon the cluster and reports Query is valid or the cluster's error (unknown column/table, syntax, permissions). It also warns when a table's primary (timestamp) key is not filtered inWHERE— add$__timeFilter()to avoid scanning the whole table; a filter in the query that reads a CTE or subquery counts. Validation never blocks running the query; only SELECT statements are dry-run. TheEXPLAINdry-run carriesquery-validationin${__hydrolix.app}/${__hydrolix.query_source}, so it can be told apart in query logs. Limitations: the primary-key warning covers single-table SELECTs (queries with a JOIN, comma join orARRAY JOINare not checked), it is a name match (any mention of the key column inWHERE/PREWHEREcounts, while a key referenced only through aSELECTalias is reported as unfiltered), and tables without a primary key are never warnedFeature: Replace the unused Ad hoc filter default time range setting with Ad hoc filter suggestion lookback (
adHocTimeRangeLookback, default24h; supported unitss,m,h). It sets the ad hoc key/value suggestion window, the cap applied to longer dashboard ranges, and thehdx_query_max_timerange_secguardrail (lookback + 10m). In the config editor an invalid value is cleared when the field loses focus; an invalid value that bypasses the editor (e.g. provisioned) falls back to 24h at runtime.dis still accepted for existing values. A previously saved default time range is ignored; it was never appliedBreaking: Drop Grafana 10.4 support —
grafanaDependencyis now>=11.0.0, and 10.4 is removed from the e2e, compatibility-check and nightly matrices. Instances on 10.4 will no longer be offered the plugin update
0.12.2 (compatible with Grafana <=13.3.0-34421444802 pre-release)
- Fix: Plugin fails to import on Grafana builds with the Luxon-backed datetime layer (
datetime.useLuxonfeature toggle, Grafana Cloud / upcoming 13.3) —dateTime().subtract("5m")in the default ad-hoc time range used an invalid argument that Moment silently ignored but Luxon rejects at module load - Fix: An invalid round interval (query editor and datasource default) is now reset to empty when the field loses focus, instead of being saved and silently skipped by the backend; field descriptions now list the actually supported units (s, m, h —
mswas never accepted) - Chore: Pin
nwsapito 2.2.24 — 2.2.26+ hangs@testing-library/user-eventon portal-rendered elements (Grafana renders tooltips in a portal), which stalled the frontend test suite (upstreamdperini/nwsapi#214) - Chore: Run every CI job on Node 24, matching
.nvmrcand theenginesfloor — the e2e job had no Node setup and fell back to the runner default (Node 22 / npm 10), which cannot install an npm 11 lockfile - Chore: Stop leaking the Grafana image tag into the e2e test process —
@grafana/plugin-e2ereadsGRAFANA_VERSIONas a semver, so thenightlytag made every internal version comparison returnNaNand the page models took their oldest code paths (13 nightly tests timed out clicking a Grafana-8 "Add new panel" testid)
0.12.1 (compatible with Grafana <=13.2)
- Fix: Plugin fails to load on Grafana ≥ 13.2 (React 19) — replace the bundled React 18
jsx-runtimewith a version-agnostic shim built onReact.createElement, so a single bundle works on React 16–19 / Grafana 10.4–13.2 - Fix: Drop
console.errorfrom the query error path; errors are reported via@grafana/runtimelogError - Security: Bump
grpc(1.83.2),fast-uri, andjs-yaml(4.3.2 / 3.15.2) to clear osv-scanner high-severity findings - Chore: Pin Go to 1.26.8 (same security backports as 1.27.1) so Grafana's govulncheck source scan can run — its govulncheck is still built with Go 1.26
- Chore: Extend the compatibility-check matrix to current Grafana patch releases, including 13.1 and 13.2
0.12.0 (compatible with Grafana <=13.1)
- Feature: Grafana Assistant support via context integration and MCP skill (HDX-11525)
- Feature: Support UUID, IPv4, and IPv6 column types (HDX-12151)
- Fix: Dashboard ad-hoc filter value dropdown times out on high-cardinality columns — bounded
topKpreload with query guardrails (HDX-11854) - Refactor: Pass editor/ad-hoc interpolation context explicitly instead of caching request state on the datasource; the interpolated-query preview follows the current time-picker selection (HDX-11854)
- Docs: Document that ad-hoc key/value suggestions are bounded, and recommend enabling the ad-hoc variable's Allow custom values option so unlisted keys/values can still be filtered on (HDX-11854)
- Chore: Bind provenance to release tags via tag-driven channels (HDX-12163)
- Chore: Update create-plugin scaffold to 7.10.0 and fix dependency CVEs from the Aikido report (HDX-12187)
0.11.0
- Feature: Add Grafana annotations support (HDX-11579)
- Feature: Support Grafana 13 while keeping Grafana 10 compatibility (GRAP-160)
- Feature: Attribute queries via
hdx_query_commentwith canonicalpanelId/panelNamedefaults - Refactor: Retire the Hydrolix
sqldsfork and adopt upstreamgrafana/sqldsv5.2.0 (AST interpolator, CTE extraction, TTL connection cache, OAuth/Org-Id keyed pooling, ClickHouse time/date macros, HTTP custom routes) - Security: Close SQL injection in metadata queries
- Security: Close ad-hoc filter operator and map-key injection
- Security: Resolve WITH-alias CTEs for ad-hoc filters
- Security: Fix tasks from Aikido report (#159) and address reported CVEs
- Fix: Revert Grafana User telemetry
- Chore: Address Grafana plugin review remarks and add the
plugin-validatorrelease gate - Chore: Update create-plugin scaffold to 7.9.0 (webpack toolchain, ESLint 9 flat config, Prettier 3,
@grafana/*13.1.0), bumpgrafana-plugin-sdk-goand CI actions, addgolangci-lintconfig
0.10.6
- Fix: Default compression value
- Feature: Improve Grafana User telemetry
0.10.5
- Feature: Add Grafana User telemetry
0.10.2
- Fix: Query Editor doesn't store default query type (GRAP-165)
0.10.1
- Fix: Address Grafana plugin review feedback
0.10.0
- Feature: Add support for setting Hydrolix query options per query through Grafana plugin UI (GRAP-59)
- Feature: Expose datasource errors to grafana variables (GRAP-155)
- Fix: Query interpolation fails when cte dependent plugin is commented (GRAP-152)
- Fix: AST parser, support of REGEXP operator (GRAP-154)
0.9.0
- Feature: Remove Query Assistant from Grafana plugin (GRAP-135)
- Feature: Support regex patterns for ad hoc filtering (GRAP-77)
- Feature: AST Parser should handle || and '' (GRAP-84)
- Feature: Add optional parameter for adHocFilter macro to define CTE (GRAP-87)
- Feature: Support ad-hoc filtering for subquery variables by escaping macro in Grafana plugin (GRAP-131)
- Fix: Error Beautifier doesn't transform error when connection type is native (GRAP-123)
- Fix: src/components/ConfigEditor.tsx mutates React props (GRAP-129)
- Fix: Trim adHocFilterTableName varible value (GRAP-127)
- Fix: Authorization header is missing for HTTP connections when secure=false in data source configuration (GRAP-126)
0.8.0
- Feature: Grafana Query Assistant v1 (GRAP-88)
0.7.0
- Feature: Support externally shared dashboards (GRAP-39)
- Fix: All macros support for alerts (GRAP-79)
- Fix: Support of Math expressions using Hydrolix queries (GRAP-104)
- Fix: failing when macro name is present in comment (GRAP-102)
0.6.0
- Feature: Service Account support (GRAP-41)
- Feature: Support of limit values for ad-hoc filter (GRAP-78)
- Feature: Add “Run Query” button to the query editor (GRAP-35)
- Fix: Query parsing error when user tries to format query (GRAP-75)
- Fix: Incorrect handling of single quotes inside ad-hoc filter values (GRAP-80)
0.5.0
- Feature: Support $__timeFilter and $__timeInterval macros without timestamp (GRAP-71)
- Feature: Support automatic timestamp column detection in ad hoc filters (GRAP-68)
0.4.0
- Feature: Support configurable Hydrolix query settings per data source (GRAP-46)
0.3.1
- Fix: Some queries in template variables fail in Grafana 10.x (GRAP-64)
0.3.0
- Feature: Support
*wildcard in ad hoc filters and convert to SQL%(HDX-8167) - Feature: Support synthetic ad hoc filter values
__empty__and__null__(HDX-8468) - Fix: Do not crash when ad hoc tag values are missing in dashboard time range (HDX-8605)
- Fix: Tooltip for invalid round value causes layout shift in query editor (HDX-8391)
- Fix: No loading spinner when changing round value in query editor (HDX-8491)
0.2.0
- Feature: Add support for
one-of(=|) andnot-one-of(!=|) ad hoc filter operators (HDX-8336) - Fix: Do not crash on complex queries with ad hoc filters (HDX-8193)
- Data source config: Drop support for ad hoc query definitions in data source settings (HDX-8173)
- Chore: Update plugin screenshots and exclude test Go code from release build (HDX-8422)
0.1.6
- Fix: Apply default round setting to queries defined in template variables
0.1.5
- Feature: Add option to show interpolated SQL in the query editor
- Feature: Add new column type support for ad hoc filter keys
0.1.4
- Fix: Resolve issues reported by the Grafana plugin validator to comply with publishing requirements
0.1.3
- Fix: Rename plugin ID to follow the naming convention
0.1.2
- Feature: Add support for alerting
0.1.1
- Compatibility: Improve compatibility with Grafana 10.4.x
0.1.0
- Initial beta release.