Skip to content

improvement(supabase): add Edge Functions tool; correct storage output shapes + harden tools#5112

Merged
waleedlatif1 merged 8 commits into
stagingfrom
validate/supabase-tools
Jun 17, 2026
Merged

improvement(supabase): add Edge Functions tool; correct storage output shapes + harden tools#5112
waleedlatif1 merged 8 commits into
stagingfrom
validate/supabase-tools

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Supabase

  • Add supabase_invoke_function tool to invoke Supabase Edge Functions over HTTP (/functions/v1/{name}), with configurable method, JSON body, and custom headers — wired through the block (new operation, subBlocks, params mapping, inputs, skill)
  • Flesh out existing tools against the live API: upsert now supports on_conflict; storage upload now supports cache-control
  • Correct storage output properties to match what the API actually returns: copy ({Id,Key}), move ({message,Id,Key}), upload ({Id,Key,path,bucket,publicUrl}), delete_bucket ({message})
  • get_public_url builds the URL via directExecution (no spurious network round-trip); dropped its now-unused apiKey param
  • Harden identifier handling: rpc validates/encodes functionName (parity with vector_search); text_search validates column and language
  • Remove non-TSDoc section-label comments per repo style

Tavily (follow-up validation pass)

  • Mark 29 optional search/extract/crawl/map subBlocks as mode: advanced (kept query/urls/url/apiKey basic)
  • Fix search transformResponse: populate content from result.content (was result.snippet, so the output was always empty)
  • Array-safety on data.results; corrected country placeholder; rewrote stale response interfaces and removed dead duplicates

Type of Change

  • Improvement / enhancement
  • Bug fix (Tavily empty content output)

Testing

Validated every endpoint against the live Supabase storage-api source, PostgREST, Tavily, and Edge Functions docs, with independent parallel re-validation. bun run lint, tsc, check:api-validation, and the Supabase unit tests all pass. Backward compatible — no tool IDs, param names, operation values, or existing I/O keys renamed/removed.

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)

…t shapes + harden tools

- Add supabase_invoke_function tool (POST/GET/PUT/PATCH/DELETE /functions/v1/{name})
- upsert: support on_conflict; storage upload: support cache-control
- Fix storage copy/move/upload/delete-bucket output properties to match live API
- get_public_url: build URL via directExecution (no spurious network call)
- text_search: validate column identifier
- Strip non-TSDoc section-label comments
@vercel

vercel Bot commented Jun 17, 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 17, 2026 7:13pm

Request Review

@cursor

cursor Bot commented Jun 17, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New Edge Function HTTP calls use the service role secret and user-supplied headers/body; storage output property renames and Tavily field fixes may affect workflows that depended on old shapes or empty search snippets.

Overview
Adds Invoke Edge Function to the Supabase block and a new supabase_invoke_function tool (method, JSON body, custom headers, function-name validation), with param mapping that only forwards Edge Function fields for that operation and new unit tests so stale method/headers cannot leak into other tools.

Supabase follow-ups: upsert gains optional on_conflict; storage upload accepts Cache-Control (API route + contract); storage list adds last_accessed_at sort; storage tool output metadata is aligned to API shapes (Id/Key, upload extras); get public URL uses directExecution and drops the unused apiKey param; RPC and text search get stricter identifier validation/encoding.

Tavily: most optional subBlocks move to advanced mode; search results map content from the API (replacing empty snippet); safer results handling and refreshed response types.

Reviewed by Cursor Bugbot for commit 8947057. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a supabase_invoke_function tool for calling Supabase Edge Functions over HTTP, fixes a longstanding Tavily bug where content was always empty (the field was mapped from the non-existent result.snippet instead of result.content), and corrects storage output shapes to match the real Supabase REST/Storage API responses.

  • New Edge Function tool (invoke_function.ts): validates function names, supports all HTTP verbs, handles JSON/text response content negotiation, and scopes custom headers/body strictly to invoke_function operations to prevent field leakage.
  • Storage output fixes: copy, move, upload, and delete_bucket output properties now reflect the actual API response shapes ({ Id, Key }, { message, Id, Key }, etc.); storage_get_public_url is converted to directExecution since the URL is fully deterministic.
  • Hardening: rpc and text_search now run validateDatabaseIdentifier on their free-text inputs; upsert gains on_conflict column targeting; storage_upload gains cache-control support.

Confidence Score: 5/5

Safe to merge — the changes are additive, well-tested, and fix real output-shape bugs without touching any breaking API surface.

The new Edge Function tool is cleanly isolated, its identifier validation prevents path injection, and the block-level params builder correctly scopes new fields so they cannot leak into unrelated operations. The Tavily content fix corrects a consistently empty output field. Storage output-shape corrections and the directExecution conversion for public URL are accurate against the Supabase API. The two observations flagged are HTTP-semantics nits that are unlikely to produce observable failures with Supabase's infrastructure today.

No files require special attention; the invoke_function.ts Content-Type and fallback-body observations are minor and do not affect correctness on current Supabase infrastructure.

Important Files Changed

Filename Overview
apps/sim/tools/supabase/invoke_function.ts New Edge Function tool — function name validation, method allow-list, and content-type-aware response parsing are all correct; minor: Content-Type: application/json is emitted even for GET requests where body is undefined
apps/sim/tools/tavily/search.ts Genuine bug fix: result.snippet → result.content corrects empty content output; array-safety guard (data.results ?? []) added
apps/sim/blocks/blocks/supabase.ts invoke_function subBlocks wired correctly; method/functionBody/functionHeaders are explicitly destructured out of rest to prevent field leakage to other tools; params mapping and tool selection switch are consistent
apps/sim/tools/supabase/types.ts Storage output property constants corrected to match Supabase REST API shapes; STORAGE_DELETE_BUCKET_OUTPUT_PROPERTIES confirmed present; new invoke-function types added cleanly
apps/sim/tools/supabase/upsert.ts on_conflict appended as URL-encoded query param; correctly URL-encodes comma-separated column lists; Prefer header already includes resolution=merge-duplicates
apps/sim/tools/supabase/storage_get_public_url.ts Converted to directExecution — correct since URL is fully deterministic; apiKey param removed as intended; dead request block kept to satisfy ToolConfig type constraint
apps/sim/blocks/blocks/supabase.test.ts New unit tests cover tool selection, field-leakage prevention, invoke_function body/headers parsing, and invalid-headers rejection — good coverage of the riskiest new logic
apps/sim/tools/supabase/storage_copy.ts Import corrected from STORAGE_MOVE_OUTPUT_PROPERTIES to STORAGE_COPY_OUTPUT_PROPERTIES; output description updated to match
apps/sim/tools/supabase/storage_delete_bucket.ts Import corrected to STORAGE_DELETE_BUCKET_OUTPUT_PROPERTIES; constant confirmed present in types.ts
apps/sim/tools/supabase/rpc.ts validateDatabaseIdentifier + encodeURIComponent added to functionName, matching the pattern already used in vector_search
apps/sim/tools/supabase/text_search.ts column and language now both validated with validateDatabaseIdentifier before being embedded in URL query params
apps/sim/tools/tavily/types.ts Dead duplicate interfaces removed; TavilySearchResult corrected (content field, optional score); TavilyExtractResponse rewritten to match actual API shape
apps/sim/app/api/tools/supabase/storage-upload/route.ts cache-control header added with bare-integer → max-age=N normalization

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Block params] --> B{operation?}
    B -->|invoke_function| C[destructure method / functionBody / functionHeaders]
    B -->|other ops| D[fields excluded from result - no leakage]

    C --> E[parse functionBody as JSON to result.body]
    C --> F[validate and parse functionHeaders to result.headers]
    C --> G[pass method to result.method]

    E & F & G --> H[supabase_invoke_function tool]

    H --> I[validateFunctionName]
    I -->|invalid| J[throw Error]
    I -->|valid| K[resolveMethod - default POST]

    K -->|GET| L[body = undefined]
    K -->|non-GET| M[body = params.body]

    L & M --> N[fetch /functions/v1/name with auth headers]
    N --> O{response content-type}
    O -->|application/json| P[response.json to results]
    O -->|other| Q[response.text to results]
    P & Q --> R[return success output]
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
    A[Block params] --> B{operation?}
    B -->|invoke_function| C[destructure method / functionBody / functionHeaders]
    B -->|other ops| D[fields excluded from result - no leakage]

    C --> E[parse functionBody as JSON to result.body]
    C --> F[validate and parse functionHeaders to result.headers]
    C --> G[pass method to result.method]

    E & F & G --> H[supabase_invoke_function tool]

    H --> I[validateFunctionName]
    I -->|invalid| J[throw Error]
    I -->|valid| K[resolveMethod - default POST]

    K -->|GET| L[body = undefined]
    K -->|non-GET| M[body = params.body]

    L & M --> N[fetch /functions/v1/name with auth headers]
    N --> O{response content-type}
    O -->|application/json| P[response.json to results]
    O -->|other| Q[response.text to results]
    P & Q --> R[return success output]
Loading

Reviews (5): Last reviewed commit: "fix(supabase): include last_accessed_at ..." | Re-trigger Greptile

Comment thread apps/sim/app/api/tools/supabase/storage-upload/route.ts
Comment thread apps/sim/tools/supabase/storage_get_public_url.ts
Comment thread apps/sim/blocks/blocks/supabase.ts Outdated
…blic_url apiKey

- rpc: validate + encode functionName (SSRF/injection parity with vector_search)
- text_search: validate language config interpolated into the PostgREST operator
- get_public_url: remove unused apiKey param + dead auth headers (public endpoint needs no auth)
- create_bucket: tighten output description to match the {name}-only response
… output

- Mark 29 optional search/extract/crawl/map subBlocks as mode: advanced (keep query/urls/url/apiKey basic)
- Fix search transformResponse: populate content from result.content (was result.snippet, always empty)
- Guard data.results with ?? []; correct country placeholder to a lowercase name
- Rewrite stale TavilySearch/Extract response interfaces; drop dead duplicate interfaces
…ionName description

- storage upload: expand a bare numeric cache-control to `max-age=<n>` (a raw number is not a valid Cache-Control header)
- block: functionName input description now covers RPC, vector search, and Edge Function invoke
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

Thanks @cursor — addressing the two flagged points:

  • Service-role key transport: calls go over HTTPS — the base URL is pinned to https://<ref>.supabase.co via supabaseBaseUrl / validateSupabaseProjectId (rejects anything that could alter the host). The service-role key is Supabase's standard server-side auth and is used identically by every other tool in this block — no plaintext transport, no new secret-handling surface.
  • Storage field "renames" (id/fullPathId/Key): these correct output documentation metadata, not runtime data. The upload route never returned id/fullPath — it returns { Id, Key, path, bucket, publicUrl } — so a reference to results.fullPath was already undefined before this PR. Block-level results is opaque JSON, so <supabase.results.*> references resolve identically. No saved workflow breaks.

Pushed fixes for greptile's P1 (valid Cache-Control directive) and P2 (functionName description) in bb72c7cd. Re-requesting review.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/supabase/invoke_function.ts Outdated
Comment thread apps/sim/blocks/blocks/supabase.ts Outdated
- invoke_function: drop unreachable !response.ok branch (executor throws on non-OK before transformResponse runs and surfaces the error body); document the success-only contract
- invoke_function: ignore non-object (array) headers so JSON arrays can't produce numeric-index header names
- block: reject array/non-object Edge Function headers with a clear error in config.params
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/blocks/blocks/supabase.ts
…tion

Prevents a stale `method` value (e.g. from the Edge Function field) from leaking
into other operations' params. The tool executor lets `params.method` override a
tool's static verb (tools/utils.ts), so an unscoped value could turn a read into
DELETE/POST against PostgREST. Now method/body/headers are only passed for the
invoke_function operation. Adds a block-level regression test.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/blocks/blocks/supabase.ts Outdated
Stale or invalid functionBody/functionHeaders left in the block (common when
switching operations) were parsed and validated for every operation, so they
could throw before unrelated tools ran even while hidden. Moved parsing and
validation inside the invoke_function guard; added a regression test.
@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 7687d28. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

The Storage list API accepts last_accessed_at for sortBy; add it to the tool
description and the block dropdown so the surfaced options match the API.
@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 8947057. Configure here.

@waleedlatif1 waleedlatif1 merged commit c907b11 into staging Jun 17, 2026
16 checks passed
@waleedlatif1 waleedlatif1 deleted the validate/supabase-tools branch June 17, 2026 19:23
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