Snowflake history connector.
A read-only connector that reads your Snowflake account's query history, evaluates every statement with your workspace rules and shows you what Vericto would have blocked. Observe only: by the time Vericto reads a query, it has already run.
Coming soon. The Snowflake history connector is not available yet: this page describes how it will work. Today, Snowflake is protected before execution with the Runtime API, the CLI and MCP.
What it is
You connect a Snowflake account to a Vericto database with the Snowflake dialect. On a schedule, Vericto reads the account's query history (SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY), evaluates every statement with the workspace rules and stores the result as a query event. It answers "what would Vericto have blocked, flagged or masked?" for every query that ran in Snowflake.
It sees the queries that originate inside Snowflake, which no external proxy can see: Snowsight worksheets, Cortex, Snowpark, Notebooks, tasks and BI tools, from every user in the account.
Observe only, after execution. The statements have already run when Vericto reads them. The connector does not block, mask or slow down anything, and it writes nothing to your account. Its findings read "Would block", never "Blocked". To block before execution, use the Runtime API, MCP or the CLI (see the comparison).
Requirements
- A Team or Enterprise plan. If the workspace moves to a lower plan, the connector pauses, and it resumes on its own (within an hour) after moving back to Team or Enterprise.
- A database registered in Vericto with the Snowflake dialect (Dashboard → Databases). There is one history connection per database.
- Someone who can run the setup SQL in Snowflake:
ACCOUNTADMIN, orSECURITYADMINfor the role and the user andSYSADMINfor the warehouse. - Optional:
ACCESS_HISTORYlineage (the columns a query read through views) requires Snowflake Enterprise Edition. On Standard Edition, or if the role cannot read that view, the connector keeps working without it and the connection card says why.
Setup
Vericto generates the RSA key pair (2048 bits), stores the private key encrypted with your workspace key and shows you only the public key, already inside the SQL. You do not generate or copy any private key, and no endpoint returns it. The user is of type SERVICE: it has no password and no MFA, and it cannot sign in to Snowsight.
Run this SQL in Snowflake. The dashboard shows it with your public key in place of the placeholder:
USE ROLE ACCOUNTADMIN; -- or SECURITYADMIN for the role and user, SYSADMIN for the warehouse
CREATE ROLE IF NOT EXISTS VERICTO_HISTORY_ROLE
COMMENT = 'Vericto history connector: read-only access to query history';
-- Query history (and ACCESS_HISTORY on Enterprise Edition). Pick ONE:
GRANT DATABASE ROLE SNOWFLAKE.GOVERNANCE_VIEWER TO ROLE VERICTO_HISTORY_ROLE; -- narrower
-- GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE VERICTO_HISTORY_ROLE; -- every ACCOUNT_USAGE view
CREATE WAREHOUSE IF NOT EXISTS VERICTO_HISTORY_WH
WAREHOUSE_SIZE = XSMALL AUTO_SUSPEND = 60 AUTO_RESUME = TRUE INITIALLY_SUSPENDED = TRUE
COMMENT = 'Vericto history connector';
GRANT USAGE ON WAREHOUSE VERICTO_HISTORY_WH TO ROLE VERICTO_HISTORY_ROLE;
CREATE USER IF NOT EXISTS VERICTO_HISTORY_SVC
TYPE = SERVICE
DEFAULT_ROLE = VERICTO_HISTORY_ROLE
DEFAULT_WAREHOUSE = VERICTO_HISTORY_WH
RSA_PUBLIC_KEY = '<public key shown by Vericto>'
COMMENT = 'Vericto history connector';
GRANT ROLE VERICTO_HISTORY_ROLE TO USER VERICTO_HISTORY_SVC;
SNOWFLAKE.GOVERNANCE_VIEWER is the database role that covers both QUERY_HISTORY and ACCESS_HISTORY. Nothing else is granted: no database, schema or table privilege, so the role cannot read your data. It can read the query text, which includes its literals (see what is stored).
Then test the connection from its card in the dashboard: Vericto checks authentication, the role, the warehouse, reading the history and, if you turned it on, ACCESS_HISTORY. If the test passes, the connection becomes active.
Near-real-time alternative: INFORMATION_SCHEMA
Instead of ACCOUNT_USAGE, the connection can read a database's INFORMATION_SCHEMA.QUERY_HISTORY() function. It has none of the ACCOUNT_USAGE ingestion latency, but it only sees the queries the role can see: its own user's, and those on warehouses where it has MONITOR. Grant USAGE on one database (where the function is called) and MONITOR on each warehouse whose queries you want to see. MONITOR is read-only.
GRANT USAGE ON DATABASE <database> TO ROLE VERICTO_HISTORY_ROLE; -- where INFORMATION_SCHEMA.QUERY_HISTORY() is called
GRANT MONITOR ON WAREHOUSE <warehouse> TO ROLE VERICTO_HISTORY_ROLE; -- one per warehouse whose queries you want to see
Rotating the key. Rotation generates a new pair: the connection goes back to pending and reads stop until you run ALTER USER VERICTO_HISTORY_SVC SET RSA_PUBLIC_KEY = '<new public key>' and the test passes. The read position is kept, so no history is lost.
How history is read
Each connection is read at the interval you choose: 15 or 30 minutes, or 1, 3 or 6 hours. The first read starts 24 hours back. A paused connection resumes where it left off, at most 7 days back.
Latency
ACCOUNT_USAGE.QUERY_HISTORY(default): Snowflake takes up to 45 minutes to publish a query in that view, so Vericto reads only queries that ended more than 1 hour ago.- With
ACCESS_HISTORY: its latency is up to 3 hours, so the wait goes up to 3 h 15 min. That is why it is off by default. INFORMATION_SCHEMA.QUERY_HISTORY(): no ingestion latency; Vericto waits about 2 minutes after the query ends. It covers a 7-day window, with an interval of 15 minutes or more. If a slice has more queries than the function returns, the card warns that the read was truncated.
A row that Snowflake publishes later than those documented maximums is not read: that is the trade-off of reading with a position that always moves forward.
No duplicates. Each query is identified by its QUERY_ID: a query already stored is not evaluated or counted again, even if a read is interrupted and repeated.
Bounded reads. Pages of 1,000 rows, at most 5,000 rows per read and 60 seconds per statement. A larger backlog is caught up over the next reads (the next one starts a minute later) and the card shows the lag.
What is evaluated. Every finished statement, including failed ones (a DROP that failed on permissions is still a finding), except the types that carry no risk: SHOW, DESCRIBE, USE, ALTER SESSION, SET/UNSET, BEGIN/COMMIT/ROLLBACK, EXPLAIN and the stage file commands (LIST, GET, PUT, REMOVE). Running and queued queries are not read. Texts over 65,536 characters are skipped and counted. The connector's own queries carry QUERY_TAG = 'vericto-history-connector' and are excluded.
The same rules as at runtime. Each read uses the same configuration as the Runtime API for that database: active rules and their per-database settings, sensitive columns, the enforcement and parse-error policies, and agent allowlists by database user: a Snowflake USER_NAME with an allowlist on this database is evaluated against it, with the query's database and schema as context.
Lineage with ACCESS_HISTORY (Enterprise Edition). With ACCESS_HISTORY on, Vericto knows the tables and columns a query really read, through views included. If a column tagged sensitive appears there and the SQL analysis did not see it (for example, a view over that column), it is added to the event and a VERICTO-085 finding is recorded with the tag's action as the would-be action. If it is not available, the read continues without it, with no error and without disabling the connection.
What is stored and how it looks
Each evaluated statement is an event in Queries and in the Audit Trail, labelled Observed (history). To see only these events, filter the list by source=observe_history.
- Time: the query's
END_TIME, so charts place it when it ran. - User: the Snowflake
USER_NAME. - Decision: the engine's, except that nothing is stored as blocked, because nothing was blocked. A finding whose action is block shows as Would block and is not counted by any counter, report, compliance export or digest of blocked queries.
- Query text: encrypted at rest with the workspace key, like every event. In a workspace with sanitized telemetry, it is sanitized before it is stored. It never goes into notifications or logs.
Quota. Each observed statement counts toward the plan's monthly query volume, like proxy telemetry: one stored event is one query, with no duplicates. The connection card shows how many queries the connector added this month. If a metered plan's quota runs out, the connector pauses without using your warehouse, keeps its position and resumes on its own (it checks every hour) when the quota allows. A pause you made yourself is never lifted automatically.
Notifications
After a read with new findings that Vericto would have blocked, each realtime destination whose severity filter matches receives one summary: "N findings detected after execution (Snowflake history)", with the top rules, the severities and a link to the queries filtered by source=observe_history. It never includes query text. Webhooks receive type: query.observed.
Digest destinations (5 minutes to 1 day) do not include observed findings: they count blocked queries, and an observed event never is one. The dashboard bell notifies once per read when there is a critical finding that would have been blocked, and when the connection is disabled after authentication errors. More in Alerts & notifications.
Failures and retries
- Authentication: after 3 failures in a row, the connection is disabled and the bell says so. A successful test re-activates it.
- Permissions: the card shows the missing grant (the error names the object) and the read is retried later.
- Warehouse, timeout, network or rate limit: the read is retried later. If Vericto cannot evaluate, it stores nothing and does not move its position, and retries.
Retries wait longer each time: the interval doubles with each consecutive failure, up to 6 hours. A successful read goes back to the normal interval.
Cost in Snowflake
The VERICTO_HISTORY_WH warehouse is yours and Snowflake bills you for it. It resumes for each read: Snowflake bills at least 60 seconds per resume, plus up to 60 seconds idle before it suspends (AUTO_SUSPEND = 60). An X-Small (1 credit per hour) used only by Vericto costs at most about 2 minutes per read, that is 1/30 of a credit.
| Interval | Reads per day | Credits per day (upper bound) |
|---|---|---|
| 15 min | 96 | ≈ 3.2 |
| 60 min | 24 | ≈ 0.8 |
| 6 h | 4 | ≈ 0.13 |
The connection card shows the estimate for the chosen interval; multiply it by your price per credit. The cloud-services credits for the metadata queries usually fall inside Snowflake's 10% daily allowance.
Network policies
The connector uses the Snowflake SQL API over HTTPS, always against https://<account>.snowflakecomputing.com. If your account restricts client IPs with a network policy, allow Vericto's egress IP address. Ask support for it.
Disconnecting
Disconnecting in Vericto deletes the connection and its private key. Then remove the Snowflake objects:
USE ROLE ACCOUNTADMIN;
DROP USER IF EXISTS VERICTO_HISTORY_SVC;
DROP ROLE IF EXISTS VERICTO_HISTORY_ROLE;
DROP WAREHOUSE IF EXISTS VERICTO_HISTORY_WH;
Comparison with the Runtime API, MCP and the CLI
| History connector | Runtime API / MCP / CLI | |
|---|---|---|
| Blocks or masks | No, after execution | Yes, before execution |
| Sees queries from inside Snowflake (worksheets, Cortex, tasks, BI) | Yes, from every user (with ACCOUNT_USAGE) | Only what the caller sends |
| Delay | 1–3 h (ACCOUNT_USAGE), ~2 min (INFORMATION_SCHEMA) | None |
| Lineage through views | With ACCESS_HISTORY (Enterprise Edition) | No |
| Cost in Snowflake | Warehouse time (see cost) | None |
| Setup | Role, service user and warehouse | A code change in each caller |
They complement each other: the connector shows what happened across the whole account, and the Runtime API, MCP and the CLI block before execution on the paths you control.