feat(snowflake): credential-based auth, object pickers, and 9 new operations - #6474
Conversation
…rations Replace the per-block host + PAT fields with a Snowflake service-account credential, move the credential picker to the top of the block, back the object fields with metadata-only pickers, and add nine operations. - credential: snowflake-service-account token service account (account host + programmatic access token), verified against the SQL API with the same headers the tools use - selectors: database, schema, table, warehouse, execution role, file format and procedure pickers behind one /api/tools/snowflake/objects route - new operations: unload_data, list_databases, list_schemas, list_tables, alter_warehouse, resume_task, suspend_task, list_query_history, list_copy_history
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Object pickers for database, schema, table, warehouse, role, file format, and procedure are backed by a new Nine new block operations are documented and wired: unload data, list databases/schemas/tables, alter warehouse, resume/suspend task, list query history, and list copy history. Integration docs add a snowflake-service-account setup guide; action reference tables no longer list Supporting changes: Snowflake PAT credential validation on connect, selector registry/contracts, Reviewed by Cursor Bugbot for commit 2aa6af6. Configure here. |
Greptile SummaryThe PR moves Snowflake tools to credential-based authentication and adds metadata-backed object pickers plus nine operations.
Confidence Score: 5/5The PR appears safe to merge because the previously reported authentication-order issue is fixed and no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/app/api/tools/snowflake/objects/route.ts | Adds an authenticated and credential-authorized metadata selector route; the prior validation-order issue is fixed at current HEAD. |
| apps/sim/blocks/blocks/snowflake.ts | Reworks Snowflake block inputs around a shared credential and adds picker and operation wiring. |
| apps/sim/tools/snowflake/sql.ts | Extends centralized Snowflake SQL construction for the new metadata and operational statements. |
| apps/sim/lib/credentials/token-service-accounts/validators/snowflake.ts | Adds validation for Snowflake account-host and programmatic-access-token credentials. |
| apps/docs/content/docs/en/integrations/snowflake-service-account.mdx | Documents Snowflake programmatic access token creation, configuration, use, and rotation. |
Sequence Diagram
sequenceDiagram
participant UI as Snowflake Block Picker
participant API as /api/tools/snowflake/objects
participant Auth as Session/Internal Auth
participant Cred as Credential Authorization
participant SF as Snowflake SQL API
UI->>API: POST credential, workflowId, kind
API->>Auth: Authenticate before body validation
Auth-->>API: caller userId
API->>API: Validate selector request
API->>Cred: Authorize credential use
Cred-->>API: credential owner
API->>SF: Execute metadata-only statement
SF-->>API: Object rows
API-->>UI: Picker objects
Reviews (7): Last reviewed commit: "fix(snowflake): unload a table, not an i..." | Re-trigger Greptile
…parsing - add SUBBLOCK_ID_MIGRATIONS entries so the renamed object fields map onto their pickers and the removed host/apiKey values are parked - authenticate the caller before contract validation in the selector route, per the API route convention
|
@cursor review |
…rrect docs - assertBalancedQuery now skips // line comments, $$ dollar quoting and rejects ambiguous nested block comments; each hid a paren that let an injected OVERWRITE = TRUE escape the derived table - always emit OVERWRITE so an injected duplicate is rejected by Snowflake rather than silently replacing staged files - _removed_ migration targets now drop the stored value instead of parking it under a dead key, where export scrubbing (which walks the block config) would never clear it - 403 falls back to the shared invalid-credentials message, which names the network policy and SQL API causes Snowflake does not distinguish in the body - correct the network-policy-by-user-type claim: only SERVICE_AGENT is exempt - correct MAX_FILE_SIZE and errorOnly tool descriptions to match the fixed code
|
@cursor review |
…gration - an untouched switch serializes as null, and advanced mode emits every advanced subblock, so alter_warehouse silently sent AUTO_RESUME = FALSE and permanently disabled auto-resume on the warehouse; normalize optional booleans to undefined in tools.config.params - point the subblock migration at the advanced text members: a migrated block has no credential, so a picker cannot hydrate a stored name, and legacy fileFormat values were qualified while the picker lists bare names - add the missing json-object wand type and scope the SQL wand prompt, which promised bindings that unload_data does not accept
|
@cursor review |
- an earlier version of this migration renamed retired fields into _removed_* keys instead of deleting them, so deployed workflows still hold those values; they match no oldId, so a dedicated sweep clears them for every block type - the picker now treats a Snowflake 403 like a 401: it means a network policy or a disabled SQL API, which the credential validator already reports as a credential problem rather than a bad request
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
1 issue from previous review remains unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0307c39. Configure here.
The json-object reinforcement tells the model the response must start with {
and end with }, which fights any field whose contract is an array. Snowflake's
rows, matchColumns and procedureArguments all ask for arrays, so they were
being steered toward an object that the JSON parse would then reject.
Adds a sibling json-array type that strips fences the same way but reinforces
brackets, and points the three array fields at it. bindings and filters are
genuine objects and stay on json-object.
|
@cursor review |
There was a problem hiding this comment.
✅ 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 d5ede2e. Configure here.
The COPY INTO grammar places the source immediately before its copy options, so an inlined query sits one parenthesis from being able to rewrite them. Guarding that means matching Snowflake's tokenizer exactly, and three successive versions of the guard were each defeated: // line comments, $$ dollar quoting, and a bare carriage return, which the scanner did not treat as a line terminator but Snowflake does. Each fix was a guess at a lexer the public docs do not specify. Removes the inline-query source instead of guessing a fourth time. A table name goes through qualifiedIdentifier, which is provably safe. Exporting a query result now means materializing it first — a view, or CREATE TABLE AS SELECT via Execute SQL — which the tool description, the block skill and the docs all say. Also from the final audit: - optionalBoolean accepts the string forms a direct tool call delivers, matching the other boolean readers on this block, and its TSDoc no longer states the serializer rule backwards - the five JSON editors declare language: 'json', so invalid JSON is caught inline instead of at execution - bound the RESULT_SCAN read in SQL, not only by rows_per_resultset - pin every migration target to a live subblock id, for all blocks
|
Final validation round removed a capability rather than guarding it again — flagging since it narrows the PR's scope.
Each fix was a guess at an unspecified lexer, so the fourth guess did not seem better than removing the surface. A table name goes through |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 2aa6af6. Configure here.

Summary
/api/tools/snowflake/objectsroute.docs.sim.ai/integrations/snowflake-service-account.Breaking
Saved Snowflake blocks must be reconnected — the
hostandapiKeyfields are gone. The block shipped in #6407 (same day), so blast radius should be minimal.Type of Change
Testing
Tested manually. Five parallel audits against Snowflake's live docs surfaced and fixed, among others:
errorOnlyon query history filtered on'FAIL', which is not a validINFORMATION_SCHEMAexecution status — the filter matched nothing and returned "no failures" forever.HEADERwas emitted as a copy option inCOPY INTO <location>; the grammar places it after them.canonicalParamId: 'oauthCredential', which left every picker permanently disabled.OVERWRITE = TRUE.Added SQL builder tests for every new statement, credential-validator tests, and block↔tool contract tests covering required-param alignment, canonical groups, and dependsOn wiring.
Checklist