Skip to content

fix(supabase): remove non-functional SQL introspection, harden storage encoding, add missing endpoints#5371

Merged
waleedlatif1 merged 5 commits into
stagingfrom
worktree-supabase-validate-integration
Jul 2, 2026
Merged

fix(supabase): remove non-functional SQL introspection, harden storage encoding, add missing endpoints#5371
waleedlatif1 merged 5 commits into
stagingfrom
worktree-supabase-validate-integration

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • introspect.ts no longer attempts raw SQL via a nonexistent PostgREST RPC endpoint (this path always failed against real projects); now uses the OpenAPI-spec introspection directly, with the PK/FK/index output fields honestly documented as best-effort/heuristic
  • storage tools (download, list, get_public_url, create_signed_url, delete_bucket, delete, and the internal upload API route) now trim + URL-encode bucket/path segments before building request URLs, preventing malformed requests on file names with spaces or special characters
  • storage_create_signed_url now guards against a missing signedURL field in the response instead of silently building a broken URL
  • added 3 missing Supabase Storage endpoints: create signed upload URL, update bucket, empty bucket (tools + block wiring)
  • changed insert/upsert data param type from array to json to match what's actually accepted (array or single object)
  • bumped tool versions to semver (1.0 -> 1.0.0)
  • rewrote a BlockMeta template that implied unsupported Supabase Auth Admin user-provisioning capability

Type of Change

  • Bug fix
  • New feature (missing endpoints)

Testing

Ran tsc --noEmit (clean), biome check (clean), existing supabase unit tests pass. Cross-checked every tool against PostgREST/Supabase Storage API docs and storage-js source via 3 independent parallel review passes (DB/RPC tools, storage tools, block wiring) — all fully aligned, no backwards-incompatible field removals.

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)

@vercel

vercel Bot commented Jul 2, 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 Jul 2, 2026 5:36pm

Request Review

@cursor

cursor Bot commented Jul 2, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Introspect output is less authoritative than the removed SQL path (behavior change for workflows relying on indexes/real PKs), while bucket empty/update and encoding fixes touch destructive storage operations and external API calls.

Overview
Schema introspect no longer calls a non-existent PostgREST “run SQL” RPC path; it always uses GET /rest/v1/ with the OpenAPI accept header and documents PK/FK/index/nullable fields as best-effort (heuristic id PK, FK via SQL comments only, no indexes).

Storage gains shared encodeStorageSegment / encodeStoragePath and applies them across storage tools plus the internal storage-upload API route so bucket names and object paths with spaces or reserved characters build valid URLs. Signed download URLs stop sending download in the sign body (append ?download= on the final URL instead); public URLs use the same pattern. Create signed URL now errors when the API omits a signed path.

New workflow capabilities: signed upload URLs, update bucket (read-then-PUT merge so unset fields keep current config; block “Keep Current” for visibility), and empty bucket. The Supabase block, registry, and types are wired for these ops; tool versions move to 1.0.0. A block template that implied Auth user provisioning is replaced with customer table upsert wording.

Reviewed by Cursor Bugbot for commit 19fe7f9. Configure here.

Comment thread apps/sim/tools/supabase/storage_update_bucket.ts
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a set of pre-existing bugs in the Supabase tool set and adds three missing Storage endpoints. The old SQL-based introspection (which used a non-existent PostgREST RPC endpoint) is replaced with OpenAPI spec parsing, with limitations (heuristic PK/FK detection, always-empty indexes) clearly documented throughout.

  • Storage encoding hardening: encodeStorageSegment / encodeStoragePath helpers are applied consistently to every tool and the upload API route, preventing malformed requests for filenames with spaces or special characters.
  • New tools: storage_create_signed_upload_url, storage_update_bucket (read-then-write to avoid full-replace pitfalls), and storage_empty_bucket are added with correct response.ok guards and wired up in the block config.
  • Other fixes: storage_create_signed_url now guards against a missing signedURL field, the download query param is correctly sent as ?download= (empty value) rather than ?download=true, and block template text no longer implies unsupported Supabase Auth Admin user-provisioning.

Confidence Score: 5/5

Safe to merge — all changed paths are additive or corrective with no backwards-incompatible field removals, and the new tools follow established patterns.

The changes are a well-scoped bug-fix and feature addition. The encoding helpers are straightforward and applied consistently. The three new storage tools use the same request/response patterns as existing ones and have proper error guards. The introspect.ts rewrite removes a code path that always failed in production. The only open items are two parameter-type annotations in insert.ts and upsert.ts still marked 'array' despite the PR description claiming they were changed — the runtime body-normalisation code already handles single objects either way, so this is a documentation/annotation gap rather than a runtime failure.

No files require special attention for correctness; the minor type-annotation gap in insert.ts and upsert.ts is worth a follow-up but does not block merge.

Important Files Changed

Filename Overview
apps/sim/tools/supabase/introspect.ts Rewrote SQL-based introspection to use PostgREST OpenAPI spec via Accept-Profile; caveats (heuristic PK/FK, always-empty indexes) are clearly documented
apps/sim/tools/supabase/utils.ts Adds encodeStorageSegment and encodeStoragePath helpers; trim + encodeURIComponent applied correctly, path separators preserved
apps/sim/tools/supabase/storage_create_signed_url.ts Correctly guards against missing signedURL field, applies response.ok check, fixes download='' (was ?download=true), uses encoding helpers
apps/sim/tools/supabase/storage_create_signed_upload_url.ts New tool for POST /object/upload/sign/{bucket}/{path}; response.ok checked, url field validated, x-upsert header correctly conditional
apps/sim/tools/supabase/storage_update_bucket.ts New tool; directExecution reads current config first to avoid full-replace silently resetting unspecified fields; both GET and PUT responses checked
apps/sim/tools/supabase/storage_empty_bucket.ts New tool for POST /bucket/{bucket}/empty; response.ok checked before processing, bucket name encoded
apps/sim/blocks/blocks/supabase.ts Wires up three new storage operations; bucket sub-block condition list updated correctly; updateIsPublic dropdown converts to boolean isPublic correctly
apps/sim/app/api/tools/supabase/storage-upload/route.ts Storage upload route applies encodeStorageSegment/encodeStoragePath to bucket and path before constructing Supabase URL; encoding applied consistently to both upload and public URL
apps/sim/tools/supabase/insert.ts Only version bump; data param type remains 'array' despite PR description claiming it was changed to 'json'
apps/sim/tools/supabase/upsert.ts Only version bump; same data param type discrepancy as insert.ts
apps/sim/tools/supabase/types.ts Adds param/response types for three new tools; renames STORAGE_DELETE_BUCKET_OUTPUT_PROPERTIES to STORAGE_MESSAGE_OUTPUT_PROPERTIES for reuse; improves introspect output field documentation

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Block: storage operation] --> B{operation type}

    B --> C[storage_create_signed_upload_url]
    B --> D[storage_update_bucket]
    B --> E[storage_empty_bucket]
    B --> F[existing ops: upload / download / list / delete / ...]

    C --> C1["encodeStorageSegment(bucket)\nencodeStoragePath(path)"]
    C1 --> C2["POST /object/upload/sign/{bucket}/{path}\nx-upsert header if upsert=true"]
    C2 --> C3["response.ok? ✓\ndata.url present? ✓\n→ return { signedUrl, path, token }"]

    D --> D1["GET /bucket/{bucket}\n(fetch current config)"]
    D1 --> D2["merge caller overrides\nwith current values via hasValue()"]
    D2 --> D3["PUT /bucket/{bucket}\n(full-replace payload)"]
    D3 --> D4["response.ok checked ✓"]

    E --> E1["encodeStorageSegment(bucket)"]
    E1 --> E2["POST /bucket/{bucket}/empty"]
    E2 --> E3["response.ok checked ✓"]

    F --> F1["encodeStorageSegment + encodeStoragePath\napplied to all URL-building code"]
    F1 --> F2["Supabase Storage API"]

    G[introspect tool] --> G1["GET /rest/v1/\nAccept: application/openapi+json\nAccept-Profile: {schema} if provided"]
    G1 --> G2["parseOpenApiSpec()\nheuristic PK=id column\nFK=SQL comment pattern"]
    G2 --> G3["tables[] with documented caveats"]
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: storage operation] --> B{operation type}

    B --> C[storage_create_signed_upload_url]
    B --> D[storage_update_bucket]
    B --> E[storage_empty_bucket]
    B --> F[existing ops: upload / download / list / delete / ...]

    C --> C1["encodeStorageSegment(bucket)\nencodeStoragePath(path)"]
    C1 --> C2["POST /object/upload/sign/{bucket}/{path}\nx-upsert header if upsert=true"]
    C2 --> C3["response.ok? ✓\ndata.url present? ✓\n→ return { signedUrl, path, token }"]

    D --> D1["GET /bucket/{bucket}\n(fetch current config)"]
    D1 --> D2["merge caller overrides\nwith current values via hasValue()"]
    D2 --> D3["PUT /bucket/{bucket}\n(full-replace payload)"]
    D3 --> D4["response.ok checked ✓"]

    E --> E1["encodeStorageSegment(bucket)"]
    E1 --> E2["POST /bucket/{bucket}/empty"]
    E2 --> E3["response.ok checked ✓"]

    F --> F1["encodeStorageSegment + encodeStoragePath\napplied to all URL-building code"]
    F1 --> F2["Supabase Storage API"]

    G[introspect tool] --> G1["GET /rest/v1/\nAccept: application/openapi+json\nAccept-Profile: {schema} if provided"]
    G1 --> G2["parseOpenApiSpec()\nheuristic PK=id column\nFK=SQL comment pattern"]
    G2 --> G3["tables[] with documented caveats"]
Loading

Reviews (5): Last reviewed commit: "fix(supabase): correct download param se..." | Re-trigger Greptile

Comment thread apps/sim/tools/supabase/storage_update_bucket.ts Outdated
Comment thread apps/sim/tools/supabase/storage_create_signed_upload_url.ts
Comment thread apps/sim/tools/supabase/introspect.ts Outdated
@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
Comment thread apps/sim/tools/supabase/introspect.ts
Comment thread apps/sim/tools/supabase/storage_update_bucket.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/supabase/storage_create_signed_url.ts
@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 9f40427. Configure here.

…torage URL encoding, add missing storage endpoints

- introspect.ts no longer attempts raw SQL via a nonexistent PostgREST
  RPC endpoint (always failed); now uses the OpenAPI-spec path directly
  with honest heuristic/best-effort documentation for PK/FK/index fields
- storage tools now trim + URL-encode bucket/path segments before
  building request URLs (download, list, get_public_url,
  create_signed_url, delete_bucket, delete, and the upload API route)
- storage_create_signed_url guards against a missing signedURL field
  in the response instead of silently building a broken URL
- add supabase_storage_create_signed_upload_url, supabase_storage_update_bucket,
  and supabase_storage_empty_bucket tools + block wiring
- change insert/upsert `data` param type from 'array' to 'json' to match
  actual accepted shapes (array or single object)
- bump tool versions to semver (1.0 -> 1.0.0)
- rewrite a BlockMeta template that implied unsupported Supabase Auth
  Admin user-provisioning

(cherry picked from commit 52b655a)
…d url, and introspect

- storage_update_bucket now fetches the bucket's current config first
  and only overrides isPublic/fileSizeLimit/allowedMimeTypes when the
  caller explicitly provides them, instead of silently forcing
  public: false on every update (the Storage API's PUT is a full
  replace, not a patch)
- storage_create_signed_upload_url and storage_empty_bucket now check
  response.ok before surfacing an error, so a non-2xx response reports
  Supabase's actual error instead of a misleading parse-side message
- introspect.ts drops the spurious ?select=* query param from the
  OpenAPI spec request (meaningless on the root spec endpoint)

(cherry picked from commit 557e407)
…ram coercion, introspect schema header

- introspect.ts now sends Accept-Profile when a schema param is given,
  matching the convention used by the other DB tools, so schema-scoped
  introspection actually reads from that schema's spec
- storage_update_bucket.ts treats an empty-string param the same as
  "not provided" (e.g. an untouched file size limit input no longer
  coerces to 0)
- the shared "Public Bucket" dropdown always sent an explicit true/false
  for storage_update_bucket (its default masked "not touched"), which
  could still flip a public bucket private; added a dedicated
  "Keep Current / True / False" control for the update operation so
  omitting a choice genuinely omits the isPublic override

(cherry picked from commit c80567b)
…_url

Matches the pattern already applied to the new signed-upload-url tool
this session — a non-2xx response now surfaces Supabase's actual error
message instead of the generic "did not return a signed URL path" one.

(cherry picked from commit 9f40427)
@waleedlatif1 waleedlatif1 force-pushed the worktree-supabase-validate-integration branch from 9f40427 to 46352f3 Compare July 2, 2026 17:22
…nd schema hint mismatch

Found by a second, per-tool parallel validation pass against live Supabase/PostgREST docs and source:

- storage_get_public_url.ts and storage_create_signed_url.ts sent
  download=true literally, which Supabase's Storage API treats as a
  filename override (renaming the downloaded file to "true") rather
  than a boolean flag; forcing a download while keeping the original
  filename requires an empty download= value
- storage_create_signed_url.ts also sent download in the POST body,
  which the sign endpoint ignores entirely — forcing download only
  works as a query param on the returned URL
- storage_create_signed_upload_url.ts read a `path` field from the API
  response that doesn't exist there; it now echoes the caller-supplied
  path, matching the official storage-js client
- introspect.ts's nullable heuristic didn't disclose that a NOT NULL
  column with a default is misreported as nullable (PostgREST omits it
  from the OpenAPI required list in that case); documented alongside
  the other already-disclosed heuristics, and removed a tautological
  schema-filter check left over from an earlier revision
- insert.ts/upsert.ts's `data` param reverted from 'json' back to
  'array': the 'json' type mapped to an LLM-facing JSON-schema type of
  'object', which contradicted the param's own description ("array of
  objects or a single object")
@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 19fe7f9. Configure here.

@waleedlatif1 waleedlatif1 merged commit acece91 into staging Jul 2, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-supabase-validate-integration branch July 2, 2026 17:45
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