Repository navigation
Conversation
The v2 dashboards API now creates, reads, and updates ADHOC filters (SQL and PromQL source types) and their adhoc saved conditions. Sources and appliesToSourceIds must exist and match the filter's sourceType. MCP keeps hiding ad hoc filters via convertToExternalDashboard's hideAdhoc option.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: d36609d The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| * Returns an error message if an ad hoc filter reads from or applies to a | ||
| * source of a kind its `sourceType` can't query, or null if none does. | ||
| */ | ||
| function getAdhocFilterSourceKindError( |
There was a problem hiding this comment.
🔵 minor — Ad hoc source-kind check copies the internal API's and drops its skip for unchanged references, so GET → PUT can fail
getFilterSourceIds and getAdhocFilterSourceKindError repeat getFilterSourceRefs/validateFilterSources in packages/api/src/routers/api/dashboards.ts:68-109. The internal copy skips references the stored filter with the same ID already had, so a source that was later deleted or changed kind doesn't block unrelated saves. This copy checks every ADHOC filter on each PUT (dashboards.ts:3738). So if a UI-created ad hoc filter points at a source that has since been deleted or changed kind, a verbatim GET → PUT now returns 400. That contradicts the PR's claim that "the internal API enforces the same rule". Fix: move the ref-building and existing-ref skip into one shared helper, for example in common-utils filters or packages/api/src/utils/, and pass existingDashboard.filters from the PUT path, as the heatmap and formula gates already do with existingTiles.
Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond
PR Review
1 finding(s): 🔴 0 critical · 🟠 0 major · 🔵 1 minor 1 posted as inline comment(s) on the changed lines. Severity is the reviewer's own estimate and is used for ordering, not filtering. No finding blocks merge automatically; a maintainer decides. |
Deep Review✅ No critical issues found. No P0/P1 defects: the new ad hoc filter write/read paths are type-safe (exhaustive 🟡 P2 -- recommended
🔵 P3 nitpicks (5)
Reviewers (8): correctness, security, api-contract, adversarial, kieran-typescript, testing, maintainability, project-standards. Testing gaps:
No finding blocks merge automatically. A maintainer will expect P0/P1 findings in code this PR changes to be fixed; P2/P3 are your call -- fix or reply. Never fix findings about surrounding code here; reply instead. Do not widen the PR. How to respond |
Duplicate code analysis2 new clones introduced by this PR.
If one of these duplicates a helper that already exists, import it instead jscpd compared this branch against |
🔴 Tier 4 — CriticalTouches authentication, tenancy data models, the public API or shipped database config — or substantially changes the query rendering engine, background tasks, the OTel pipeline, image build, or release CI. Why this tier:
Review process: Deep review from a domain expert. Synchronous walkthrough may be required. Stats
|
E2E Test Results✅ All tests passed • 465 passed • 1 skipped • 1428s
Tests ran across 4 shards in parallel. |
Stacked on #3658.
Summary
The external v2 dashboards API (
/api/v2/dashboards) can now create, read, and update dashboards withADHOCfilters. Until now it hid them on GET and rejected them on POST/PUT. PromQL external API support is already onmain, so PromQL ad hoc filters (sourceType: "promql") are included alongside SQL ones.ADHOCis a new variant in the external filter schemas, with fields named as stored (sources, notsourceIds) so no translation is needed. Source IDs must be valid ObjectIds. As withSTATIC_LIST,isBroadcastEnabledandisVariableEnabledeach have one allowed value (true), so callers can omit them.savedFilterValuesaccepts and returnsadhocentries, which hold a filter's conditions.sourcesandappliesToSourceIdsmust exist and be a kind the filter'ssourceTypesupports: Log, Trace, or Session forsql, PromQL forpromql. The internal API enforces the same rule.hideAdhocoption toconvertToExternalDashboard, and its input schemas are separate. MCP support is the next PR in this stack.AdhocFilterInput,AdhocSavedFilterValue, andAdhocFilterConditionschemas and regeneratesopenapi.json.How to reproduce
Starting point:
yarn dev, with a personal API key from Team Settings and a Logs source ID.On
main:POST /api/v2/dashboardswithfilters: [{ "type": "ADHOC", "name": "Conditions", "sourceType": "sql", "sources": ["<logs-source-id>"] }]returns 400.filters: [].On this branch:
isBroadcastEnabled: trueandisVariableEnabled: true.savedFilterValues: [{ "type": "adhoc", "name": "Conditions", "conditions": [{ "key": "ServiceName", "operator": "IN", "value": "api" }] }]stores and returns the conditions. Opening the dashboard shows them in the filter input.sourcesat a PromQL source while keepingsourceType: "sql"returns 400 with that source ID in the message.How to test on Vercel preview
N/A. API-only change.
Testing
make dev-int FILE=src/routers/external-api/__tests__/dashboards.int.test.tspasses, and covers GET, POST for SQL and PromQL, a GET → PUT round-trip, schema rejections, and source-kind rejections.make dev-int FILE=src/mcp/__tests__/dashboardspasses, so MCP behavior is unchanged.convertToExternalDashboard({ hideAdhoc }).References