Snowflake logoGovernance

Read-Only by Design: The Trust Model Behind CoreModels for Snowflake

Governance tools lose trust in predictable ways: they demand credentials to your most valuable system, they "helpfully" rewrite things nobody asked them to touch, they paper over what they couldn't represent, and one day they act on your infrastructure without a human in the loop. We designed the CoreModels Snowflake integration against that failure list, promise by promise. This article is the trust story, stated plainly enough to be falsifiable.

Read-Only by Design: The Trust Model Behind CoreModels for Snowflake

Governance tools lose trust in predictable ways: they demand credentials to your most valuable system, they "helpfully" rewrite things nobody asked them to touch, they paper over what they couldn't represent, and one day they act on your infrastructure without a human in the loop. We designed the CoreModels Snowflake integration against that failure list, promise by promise. This article is the trust story, stated plainly enough to be falsifiable.

We never hold your warehouse credentials

There is no live connection to your Snowflake account — not as a limitation we're quietly working around, but as the chosen shape of the integration. You run three documented queries in Snowsight, inspect the JSON they produce, and upload exactly that. Everything CoreModels knows about your estate is something you exported, read, and chose to send. The only required artifact is an INFORMATION_SCHEMA extract; key declarations and object dependencies are optional enrichments. A live-sync mode is deliberately deferred, and we say so in the product rather than hiding the gap.

Import adds; it never rewrites

The import verb has one posture: additive. Tables become governed Types, columns become Elements, declared keys become checks and references, dependencies become lineage — and existing governed nodes are never mutated or deleted. Re-import a fresh extract and CoreModels adds what's new, skips what's already governed, and reports both counts. If the estate has moved away from the governed model, import does not "correct" either side. Surfacing that difference is the audit's job, and deciding what to do about it is yours. Changing what something means is a human act performed in the governed model, reviewed like any change to a contract — never a side effect of an upload.

Audits observe; recording is your call

The audit runs read-only at Viewer role — the lowest privilege in the project. It compares your artifacts against the governed model and reports coverage, drift, and conformance findings. By default it writes nothing at all: adding a run to the rolling history is an explicit opt-in flag on the request, because even bookkeeping should be the caller's decision. The one exception proves the rule — the re-audit verb always records its run, because producing a trail entry is precisely what you invoked it to do.

Lossiness is confessed, not hidden

Every translation between systems loses something, and most tools lose it silently. Ours reports it as a first-class result. A successful Snowflake import can still tell you, item by item, what it approximated: NUMBER(38,2) was modeled as a Double, a VARIANT column as a String — and in both cases the exact native type string is preserved in the vendor metadata, so nothing is destroyed by the approximation. The same honesty applies at the edges of capacity: very large estates can exceed the snapshot storage cap (around 1.5 MB encoded), and rather than storing a truncated snapshot, import reports that no snapshot was stored, with a lossiness record explaining the consequence — fresh-artifact audits still work, but re-audit has nothing stored to run against. Generation confesses too: views are skipped from DDL output with a declared reason (they're derived objects), not silently dropped. In our vocabulary, errors mean "could not proceed"; lossiness means "proceeded, and here is exactly what was imperfect." Trust requires the second channel as much as the first.

Drift is evidence, not action

When the audit finds that a field's type has drifted, that a governed dataset has vanished from the estate, or that an allowed-value set has narrowed, it does not fix anything — on either side. It produces evidence: findings with stable codes, severities, and the precise subject (DB.SCHEMA.TABLE.COLUMN), a fingerprint of the artifacts audited, machine-readable counts for CI, and a markdown report written for a human reviewer on a pull request. The CI gate itself is just a threshold on that evidence — errors greater than zero fail the build — and the status badge is the same evidence compressed to a color. Over time, the recorded history turns drift from an anecdote into a dataset. What never happens is remediation without review.

Generation is a proposal, not a deployment

The loop does close back toward the warehouse: CoreModels generates CREATE OR REPLACE TABLE DDL from the governed model, with native types, NOT NULL constraints, informational key declarations, and comments carrying descriptions and governed allowed values. But it hands you a script — it never executes SQL against your account, because it has no way to. The generated file even opens by telling you how to treat it: meaning changes belong in CoreModels; regenerate rather than edit. You review it, your process deploys it. The last mile stays human on purpose.

Trust is what the system refuses to do

Summed up, the integration is defined as much by its refusals as its features: it refuses to hold credentials, refuses to mutate what it imported, refuses to record without being asked, refuses to hide approximation, refuses to remediate drift on its own, and refuses to touch your warehouse even with the DDL it wrote. Meaning changes pass through people; everything else is evidence, honestly labeled.

We think that's the only posture that earns a place in the path of your schema changes — a governance layer you can put in CI precisely because you never have to wonder what else it might do.

The full verb-by-verb walkthrough — import, audit, re-audit, history, badge, generate — is in the CoreModels Snowflake quickstart in our docs.