Skip to content

feat(grafana): validate integration and add folder, health, and contact-point tools#5082

Merged
waleedlatif1 merged 2 commits into
stagingfrom
validate/grafana-integration
Jun 16, 2026
Merged

feat(grafana): validate integration and add folder, health, and contact-point tools#5082
waleedlatif1 merged 2 commits into
stagingfrom
validate/grafana-integration

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Validated every existing Grafana tool against the live HTTP API docs and fixed the issues found
  • Block now requires alert-rule title/ruleGroup/data (create previously could 400 with only folder set)
  • Trim UID path params across dashboard + alert-rule tools to avoid copy-paste 404s
  • Use Grafana brand color (#F46800) for the block background
  • Surface previously-unsettable list params: limit, starred, annotation type
  • Add 6 new tools: get/update/delete folder, check data source health, get health, create contact point
  • Stripped non-TSDoc comments; regenerated docs and integrations.json

Type of Change

  • New feature
  • Bug fix

Testing

Tested manually; bun run lint and typecheck pass clean for all Grafana files.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…ct-point tools

- Require alert-rule title/ruleGroup/data in the block (create would 400 without them)
- Trim UID path params across dashboard and alert-rule tools to avoid copy-paste 404s
- Use Grafana brand color for the block background
- Surface previously-unsettable list params (limit, starred, annotation type)
- Add get/update/delete folder, check data source health, get health, and create contact point tools
- Strip non-TSDoc comments; regenerate docs and integrations.json
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 16, 2026 1:59am

Request Review

@cursor

cursor Bot commented Jun 16, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New mutating Grafana APIs (folder delete, contact-point create) can change production alerting config; scope is limited to standard bearer-token calls with existing patterns, including DNS-pinned fetch on folder update.

Overview
Expands the Grafana integration from 19 to 25 operations with six new API tools: instance health, data-source health check, create contact point, and folder get / update / delete (including optional forceDeleteRules on delete).

The workflow block gains matching operations and UI fields (contact-point type/settings, folder management, list limit / starred / annotation type), switches block→tool param mapping to per-operation switch logic, and enforces title, ruleGroup, and query data when creating alert rules. Grafana branding uses #F46800 in docs, block, and integrations.json.

Fixes: .trim() on dashboard and alert-rule UIDs in request URLs to avoid stray-whitespace 404s; alert-rule custom UID trimmed on create.

Docs, registry wiring, types, and a provision-alerting skill (plus audit-dashboards health-check step) are updated. Minor unrelated change: MicrosoftIcon SVG redraw.

Reviewed by Cursor Bugbot for commit 014c928. Configure here.

Comment thread apps/sim/blocks/blocks/grafana.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR validates all existing Grafana tools against the live API docs and adds six new tools: get/update/delete folder, check data source health, get health, and create contact point. It also fixes several bugs in the existing block, including required-field enforcement on alert-rule creation, UID trimming on path params, and the previous contactPointType/annotationType interaction issue.

  • New tools: get_folder, update_folder, delete_folder, check_data_source_health, get_health, create_contact_point — all registered in tools/registry.ts, exported from index.ts, and wired into the block's access list.
  • Block improvements: The params() switch now routes per-operation params explicitly, preventing field bleed between operations; starred, limit, and annotationType filters are newly surfaced in the UI; required-field markers added for alertTitle, ruleGroup, and queryData on create.
  • update_folder uses the same GET-then-PUT pattern as update_dashboard and update_alert_rule, calling secureFetchWithPinnedIP + validateUrlWithDNS in postProcess for SSRF protection on the mutation leg.

Confidence Score: 5/5

Safe to merge — the new tools follow existing patterns correctly and the block param-routing refactor is logically sound.

All six new tools correctly wire their params (via the block's pass-through mechanism where subBlock IDs match tool param names, and via explicit switch-case mapping where they don't). The update_folder two-step GET+PUT correctly applies SSRF protection on the mutation leg, consistent with update_dashboard and update_alert_rule. The previously reported contactPointType/annotationType interaction bug is fixed by the per-operation switch. No incorrect data flows, missing required side effects, or broken contracts were found.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/blocks/blocks/grafana.ts Block config refactored: per-operation switch eliminates cross-operation field bleed, six new operations added with correct conditions and UI fields, required markers added on alert-rule create params.
apps/sim/tools/grafana/update_folder.ts Implements GET-then-PUT pattern (matching update_dashboard / update_alert_rule); uses validateUrlWithDNS + secureFetchWithPinnedIP for SSRF protection on the mutation; reads current folder version to avoid version conflicts.
apps/sim/tools/grafana/create_contact_point.ts New tool for POST /api/v1/provisioning/contact-points; correctly parses JSON settings string, handles X-Disable-Provenance header, and returns full contact-point response.
apps/sim/tools/grafana/delete_folder.ts New tool for DELETE /api/folders/{uid}; conditionally appends ?forceDeleteRules=true; uses .catch(()=>{}) on response.json() since DELETE responses may have no body.
apps/sim/tools/grafana/check_data_source_health.ts New tool for GET /api/datasources/uid/{uid}/health; correctly uses dataSourceUid (not legacy numeric id) and trims the path parameter.
apps/sim/tools/grafana/get_health.ts New tool for GET /api/health; returns commit, version, and database status; apiKey declared required for consistency with other Grafana tools.
apps/sim/tools/grafana/types.ts Type interfaces for all six new tools added and exported; GrafanaResponse union extended correctly.
apps/sim/tools/registry.ts All six new tools correctly imported and registered under their canonical string IDs.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    UI[Block UI\nOperation dropdown] --> Switch{params switch\nper operation}

    Switch -->|grafana_create_contact_point| CP[create_contact_point\nPOST /api/v1/provisioning/contact-points]
    Switch -->|grafana_get_folder| GF[get_folder\nGET /api/folders/:uid]
    Switch -->|grafana_update_folder| UF_GET[GET /api/folders/:uid\ninitial fetch]
    Switch -->|grafana_delete_folder| DF[delete_folder\nDELETE /api/folders/:uid\n?forceDeleteRules=true optional]
    Switch -->|grafana_check_data_source_health| DSH[check_data_source_health\nGET /api/datasources/uid/:uid/health]
    Switch -->|grafana_get_health| GH[get_health\nGET /api/health]

    UF_GET --> TR[transformResponse\nstores _existingFolder]
    TR --> PP[postProcess\nvalidateUrlWithDNS\nsecureFetchWithPinnedIP]
    PP --> UF_PUT[PUT /api/folders/:uid\nwith version + new title]

    CP --> Grafana[(Grafana API)]
    GF --> Grafana
    UF_PUT --> Grafana
    DF --> Grafana
    DSH --> Grafana
    GH --> Grafana
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    UI[Block UI\nOperation dropdown] --> Switch{params switch\nper operation}

    Switch -->|grafana_create_contact_point| CP[create_contact_point\nPOST /api/v1/provisioning/contact-points]
    Switch -->|grafana_get_folder| GF[get_folder\nGET /api/folders/:uid]
    Switch -->|grafana_update_folder| UF_GET[GET /api/folders/:uid\ninitial fetch]
    Switch -->|grafana_delete_folder| DF[delete_folder\nDELETE /api/folders/:uid\n?forceDeleteRules=true optional]
    Switch -->|grafana_check_data_source_health| DSH[check_data_source_health\nGET /api/datasources/uid/:uid/health]
    Switch -->|grafana_get_health| GH[get_health\nGET /api/health]

    UF_GET --> TR[transformResponse\nstores _existingFolder]
    TR --> PP[postProcess\nvalidateUrlWithDNS\nsecureFetchWithPinnedIP]
    PP --> UF_PUT[PUT /api/folders/:uid\nwith version + new title]

    CP --> Grafana[(Grafana API)]
    GF --> Grafana
    UF_PUT --> Grafana
    DF --> Grafana
    DSH --> Grafana
    GH --> Grafana
Loading

Reviews (3): Last reviewed commit: "fix(grafana): scope block param remaps p..." | Re-trigger Greptile

Comment thread apps/sim/blocks/blocks/grafana.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 014c928. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1 waleedlatif1 merged commit 324189e into staging Jun 16, 2026
16 checks passed
@waleedlatif1 waleedlatif1 deleted the validate/grafana-integration branch June 16, 2026 02:09
waleedlatif1 added a commit that referenced this pull request Jun 16, 2026
…5082)

PR #5082 added .trim() on dashboardUid/alertRuleUid in the original tool URL
builders. Those tools now build their URLs in the internal routes, so apply the
same trim there to preserve that behavior.
waleedlatif1 added a commit that referenced this pull request Jun 16, 2026
#5082 added a grafana update_folder tool that does SSRF-pinned fetch in its
postProcess, re-introducing the client-bundle leak. Convert it to the internal
API route pattern like the other update tools so the def is declarative and
input-validation.server stays out of the client bundle.
waleedlatif1 added a commit that referenced this pull request Jun 16, 2026
* refactor(connectors): split client metadata from server runtime + cover node:net in client bundle

The browser build broke with `Cannot find module 'node:net'`. Server-only
SSRF code in `input-validation.server.ts` (`dns/promises`, and since PR #5060
`undici` → `node:net`/`node:tls`) is statically reachable from the client
bundle via the tool/connector registries, which the workflow editor imports
for metadata. Node networking builtins have no browser shim, so Turbopack
cannot compile them for the client.

Two changes:

1. Split each connector's client-safe declarative metadata into a sibling
   `meta.ts` (`<name>ConnectorMeta`), mirroring the `XBlockMeta` /
   `BLOCK_META_REGISTRY` pattern. `connectors/registry.ts` is now the
   client-safe `CONNECTOR_META_REGISTRY` (+ `getConnectorMeta` /
   `getAllConnectorMeta`); the full registry with runtime fns moves to
   `connectors/registry.server.ts`. Client components consume the meta
   registry; the sync engine and knowledge API routes consume the server
   registry. This removes connectors from the client's server-only graph.
   Connector metadata is byte-for-byte identical before/after; runtime fns
   are untouched.

2. Extend the existing #4899 `turbopack.resolveAlias` browser stub — which
   already mapped `dns`/`dns/promises` to an empty module for the browser —
   to also cover `net`/`tls` (+ `node:` variants), since `undici` now pulls
   those in. The remaining tool/provider definitions still reach
   `input-validation.server` server-side; the browser-only stub keeps those
   Node builtins out of the client bundle while the real modules stay on the
   server, so SSRF validation and IP pinning are unaffected.

Connector authoring/validation skills updated to teach the meta.ts split.

* fix(icons): use Square logo glyph only, drop wordmark

* fix(connectors): share Discord max-messages default across meta and runtime

Discord defined DEFAULT_MAX_MESSAGES separately in meta.ts (config placeholder)
and discord.ts (sync behavior), which could drift. Export it from meta.ts and
import it in the runtime, matching the single-source pattern used by the other
connectors (e.g. gmail, intercom).

* refactor(tools): route grafana/agiloft egress server-side, drop SSRF browser shim

Move the server-only SSRF-pinned fetch out of the grafana (update_dashboard,
update_alert_rule) and agiloft (11 record/search tools) definitions and into
internal API routes, the same pattern the rest of the server-side tools (and
agiloft's own attach/retrieve) already use. The tool definitions are now purely
declarative (request → internal route), so they no longer import
`input-validation.server` and the tools registry is fully client-safe.

With connectors (meta split) and these tools no longer reaching server-only code
from the client bundle, the browser no longer pulls in `dns`/`net`/`tls`:

- Add `import 'server-only'` to `input-validation.server.ts` so any future client
  import fails loudly at build time instead of silently bloating the bundle.
- Remove the `turbopack.resolveAlias` browser stub and delete
  `empty-node-fallback.browser.ts` — the root cause is fixed, the shim is gone.

Behavior is unchanged: each route runs the exact merge/validation/fetch logic the
tool ran before (every header, param branch, JSON-parse guard, error string, and
SSRF pinning preserved); only the location of execution moved from the client-
bundled definition to a server route.

* fix(connectors): move onedrive tagDefinitions into meta; drop server-only guard

- onedrive's tagDefinitions lived in the runtime file, so the client meta
  registry returned undefined for it and the add-connector tag opt-out section
  stopped rendering for onedrive. Move it into meta.ts like the other connectors
  so client and server see identical metadata (verified across all 50).
- Remove the 'server-only' import from input-validation.server.ts: the meta/route
  split already keeps it out of the client bundle, and blocks/tools registries
  don't use the guard either.

* fix(grafana): surface upstream error when the prefetch GET fails

Check response.ok on the existing-resource GET in both update routes and return
the upstream status/body, matching how the tool framework surfaced GET errors
before the move to internal routes (the framework checks response.ok before
transformResponse). Without this, a failed prefetch produced a generic
'Failed to fetch existing ...' message and dropped Grafana's error detail.

* fix(grafana): reject invalid panels JSON instead of silently ignoring it

Grafana's dashboard API treats panels as a required array and returns 400 on
invalid JSON; this route already errors on every other JSON param. Return
'Invalid JSON for panels parameter' instead of swallowing the parse error and
proceeding with a misleading success.

* fix(grafana): trim dashboard/alert-rule UID in route URLs (carry over #5082)

PR #5082 added .trim() on dashboardUid/alertRuleUid in the original tool URL
builders. Those tools now build their URLs in the internal routes, so apply the
same trim there to preserve that behavior.

* fix(grafana): route update_folder egress server-side (carry over #5082)

#5082 added a grafana update_folder tool that does SSRF-pinned fetch in its
postProcess, re-introducing the client-bundle leak. Convert it to the internal
API route pattern like the other update tools so the def is declarative and
input-validation.server stays out of the client bundle.

* fix(grafana): surface route failures in transformResponse instead of masking them

The grafana update tools' transformResponse hardcoded success: true and dropped
the route's error, so an upstream/validation failure (HTTP 200 with
{ success: false, error }) was reported to the workflow as a success. Forward
data.success and data.error (matching the agiloft tools) so failures propagate
as before the move to internal routes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant