Snowflake Governance Coverage Auditor
Purpose
Compare an owner-approved hashed denominator with trusted schema-2 current
receipts and separately trusted, sanitized POLICY_CONTEXT simulations. Missing,
stale, capped, privilege-filtered, unsupported, or context-mismatched evidence is
never a pass; the result distinguishes observable coverage from evidence gaps
without exposing governed data or claiming compliance.
Read the input contract and
the source notes before assembling evidence.
Prerequisites
Use Python 3.10+, an owner-approved hashed denominator, and an existing Snowflake
CLI read-only profile. Establish independent evidence and policy trust boundaries
before analysis; do not accept credentials, raw identifiers, policy text, tag
values, customer rows, or ad hoc SQL.
Workflow
Have the governance owner approve the exact asset and simulation denominator.
Collect one classification receipt per database and one tag plus one policy
receipt per governed object. Use fixed unquoted selectors only:
python3 "${CLAUDE_SKILL_DIR}/scripts/collect_snowflake_evidence.py" \
--surface governance-classification-current --connection readonly-observer \
--governance-database GOVERNED_DB --output ./classification.json
python3 "${CLAUDE_SKILL_DIR}/scripts/collect_snowflake_evidence.py" \
--surface governance-tags-current --connection readonly-observer \
--governance-object GOVERNED_DB.GOVERNED_SCHEMA.GOVERNED_TABLE \
--governance-domain TABLE --output ./tags.json
python3 "${CLAUDE_SKILL_DIR}/scripts/collect_snowflake_evidence.py" \
--surface governance-policies-current --connection readonly-observer \
--governance-object GOVERNED_DB.GOVERNED_SCHEMA.GOVERNED_TABLE \
--governance-domain TABLE --output ./policies.json
Independently verify the collection role's complete visibility over exactly
those hashes and produce the scope receipt. Execute the approved
POLICY_CONTEXT cases outside this collector; retain only the strict hash-only
receipt contract. Never add EXECUTE USING to the shared collector.
Record evidence and policy digests at their independent trusted boundaries:
# Record only at trusted local boundaries.
python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_governance.py" evidence.json \
--print-input-sha256
python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_governance.py" evidence.json \
--policy-file policy.json --print-policy-sha256
Analyze only with the previously recorded digests and policy-bound clock:
# Replace the quoted placeholder with the owner-policy timestamp.
python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_governance.py" evidence.json \
--policy-file policy.json --evaluated-at "YYYY-MM-DDTHH:MM:SSZ" \
--trusted-input-sha256 sha256:RECORDED_EVIDENCE_DIGEST \
--trusted-policy-sha256 sha256:RECORDED_POLICY_DIGEST --pretty
Recomputing a digest from suspect evidence is not trust. Preserve every finding,
precedence observation, non-claim, and the dry-run remediation packet.
Decision boundaries
- Unknown or Standard edition, unverified preview support, missing scope proof,
role filtering, caps, duplicates, mixed contexts, or stale receipts suppress a
positive bounded result.
- Account Usage classification is latency-bounded observation. A newer failed
attempt, absent profile-scope proof, non-current status, or stale success is a
gap.
CREATE OR REPLACE profile operations can detach automatic
classification and must be reviewed separately.
- Direct policy assignments take precedence over tag assignments. For aggregation
policies, a direct assignment shadows a tag assignment only for the same entity
keys; different entity-key sets remain cumulative.
- Any relevant non-
ACTIVE provider status, including a missing conditional
masking secondary argument, is a gap.
- Row access evaluates before masking. Projection applies to final output only;
it is not proof against inner-query or
WHERE exposure.
- Tag-based masking is generally available. Tag-based row access, projection,
join, and aggregation require explicit owner-attested preview support.
- Privacy-policy combinations with masking, aggregation, or projection remain a
blocked design review even when assignment succeeds.
- Every owner-approved sanitized simulation for each asset/control pair is
cumulative; any mismatch or error blocks coverage. Each role, context,
query-shape, expected outcome, account, and trusted input digest must match.
Output
The collector uses reviewed SELECT statements only; it does not execute
POLICY_CONTEXT, mutation SQL, shell payloads, or network operations. Receipts and
reports contain only organization/account-scoped hashes, fixed enums, timestamps,
counts, and booleans. Never collect policy bodies, tag values, names, customer
rows, SQL text, errors, secrets, or query results. Exit 2 is a fixed generic
invalid-evidence error and never reflects rejected input.
Every remediation item has mutation_sql: null and
requires_separate_authorization: true. The skill never applies tags, policies,
profiles, grants, feature flags, or edition changes.
Error Handling
Exit 2 means the evidence, policy, trust digest, freshness, context, cap, or
schema check failed. The fixed error intentionally omits rejected values. Recheck
the independent denominator and recollect; never infer health or escalate roles.
Example
An inherited required tag plus one ACTIVE applicable policy and a matching
simulation can support bounded coverage. A missing secondary masking argument,
newer failed classification attempt, unverified preview, or missing scope receipt
produces a fixed hash-scoped gap and a non-executable remediation item.
Resources
1---2name: snowflake-governance-coverage-auditor3description: Audit trusted Snowflake classification, tags, masking, row access, projection, join, aggregation, and privacy-policy evidence without reading customer data. Use when governance enforcement may be missing or ambiguous. Trigger with "Snowflake governance coverage", "policy precedence", "tag policy gaps", "classification failure", or "POLICY_CONTEXT verification".4license: MIT5---6
7# Snowflake Governance Coverage Auditor
8
9## Purpose
10
11Compare an owner-approved hashed denominator with trusted schema-2 current
12receipts and separately trusted, sanitized `POLICY_CONTEXT` simulations. Missing,
13stale, capped, privilege-filtered, unsupported, or context-mismatched evidence is
14never a pass; the result distinguishes observable coverage from evidence gaps
15without exposing governed data or claiming compliance.
16
17Read [the input contract](references/input-contract.md) and
18[the source notes](references/source-notes.md) before assembling evidence.
19
20## Prerequisites
21
22Use Python 3.10+, an owner-approved hashed denominator, and an existing Snowflake
23CLI read-only profile. Establish independent evidence and policy trust boundaries
24before analysis; do not accept credentials, raw identifiers, policy text, tag
25values, customer rows, or ad hoc SQL.
26
27## Workflow
28
291. Have the governance owner approve the exact asset and simulation denominator.
302. Collect one classification receipt per database and one tag plus one policy
31 receipt per governed object. Use fixed unquoted selectors only:
32
33 ```bash
34 python3 "${CLAUDE_SKILL_DIR}/scripts/collect_snowflake_evidence.py" \
35 --surface governance-classification-current --connection readonly-observer \
36 --governance-database GOVERNED_DB --output ./classification.json
37
38 python3 "${CLAUDE_SKILL_DIR}/scripts/collect_snowflake_evidence.py" \
39 --surface governance-tags-current --connection readonly-observer \
40 --governance-object GOVERNED_DB.GOVERNED_SCHEMA.GOVERNED_TABLE \
41 --governance-domain TABLE --output ./tags.json
42
43 python3 "${CLAUDE_SKILL_DIR}/scripts/collect_snowflake_evidence.py" \
44 --surface governance-policies-current --connection readonly-observer \
45 --governance-object GOVERNED_DB.GOVERNED_SCHEMA.GOVERNED_TABLE \
46 --governance-domain TABLE --output ./policies.json
47 ```
48
493. Independently verify the collection role's complete visibility over exactly
50 those hashes and produce the scope receipt. Execute the approved
51 `POLICY_CONTEXT` cases outside this collector; retain only the strict hash-only
52 receipt contract. Never add `EXECUTE USING` to the shared collector.
534. Record evidence and policy digests at their independent trusted boundaries:
54
55 ```bash
56 # Record only at trusted local boundaries.
57 python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_governance.py" evidence.json \
58 --print-input-sha256
59 python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_governance.py" evidence.json \
60 --policy-file policy.json --print-policy-sha256
61 ```
62
635. Analyze only with the previously recorded digests and policy-bound clock:
64
65 ```bash
66 # Replace the quoted placeholder with the owner-policy timestamp.
67 python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_governance.py" evidence.json \
68 --policy-file policy.json --evaluated-at "YYYY-MM-DDTHH:MM:SSZ" \
69 --trusted-input-sha256 sha256:RECORDED_EVIDENCE_DIGEST \
70 --trusted-policy-sha256 sha256:RECORDED_POLICY_DIGEST --pretty
71 ```
72
73Recomputing a digest from suspect evidence is not trust. Preserve every finding,
74precedence observation, non-claim, and the dry-run remediation packet.
75
76## Decision boundaries
77
78- Unknown or Standard edition, unverified preview support, missing scope proof,
79 role filtering, caps, duplicates, mixed contexts, or stale receipts suppress a
80 positive bounded result.
81- Account Usage classification is latency-bounded observation. A newer failed
82 attempt, absent profile-scope proof, non-current status, or stale success is a
83 gap. `CREATE OR REPLACE` profile operations can detach automatic
84 classification and must be reviewed separately.
85- Direct policy assignments take precedence over tag assignments. For aggregation
86 policies, a direct assignment shadows a tag assignment only for the same entity
87 keys; different entity-key sets remain cumulative.
88- Any relevant non-`ACTIVE` provider status, including a missing conditional
89 masking secondary argument, is a gap.
90- Row access evaluates before masking. Projection applies to final output only;
91 it is not proof against inner-query or `WHERE` exposure.
92- Tag-based masking is generally available. Tag-based row access, projection,
93 join, and aggregation require explicit owner-attested preview support.
94- Privacy-policy combinations with masking, aggregation, or projection remain a
95 blocked design review even when assignment succeeds.
96- Every owner-approved sanitized simulation for each asset/control pair is
97 cumulative; any mismatch or error blocks coverage. Each role, context,
98 query-shape, expected outcome, account, and trusted input digest must match.
99
100## Output
101
102The collector uses reviewed `SELECT` statements only; it does not execute
103`POLICY_CONTEXT`, mutation SQL, shell payloads, or network operations. Receipts and
104reports contain only organization/account-scoped hashes, fixed enums, timestamps,
105counts, and booleans. Never collect policy bodies, tag values, names, customer
106rows, SQL text, errors, secrets, or query results. Exit `2` is a fixed generic
107invalid-evidence error and never reflects rejected input.
108
109Every remediation item has `mutation_sql: null` and
110`requires_separate_authorization: true`. The skill never applies tags, policies,
111profiles, grants, feature flags, or edition changes.
112
113## Error Handling
114
115Exit `2` means the evidence, policy, trust digest, freshness, context, cap, or
116schema check failed. The fixed error intentionally omits rejected values. Recheck
117the independent denominator and recollect; never infer health or escalate roles.
118
119## Example
120
121An inherited required tag plus one ACTIVE applicable policy and a matching
122simulation can support bounded coverage. A missing secondary masking argument,
123newer failed classification attempt, unverified preview, or missing scope receipt
124produces a fixed hash-scoped gap and a non-executable remediation item.
125
126## Resources
127
128- [Current-state and trust boundary](references/current-state.md)
129- [Input and receipt contract](references/input-contract.md)
130- [Read-only boundaries](references/privilege-and-boundaries.md)
131- [Primary-source notes](references/source-notes.md)
132- [Snowflake POLICY_REFERENCES](https://docs.snowflake.com/en/sql-reference/functions/policy_references)