QueryShield

How do I use QueryShield with BigQuery?

BigQuery via sqlglot's BigQuery dialect, with three platform-specific considerations:

1. Slot cost / on-demand pricing. A poorly bounded query on a multi-TB table can cost hundreds of dollars per LLM-generated mistake. QueryShield supports a dry_run_first mode that calls client.query(sql, job_config=QueryJobConfig(dry_run=True)) and rejects if total_bytes_processed exceeds the policy threshold. 2. SELECT * on wide tables is the most common cost incident. Policy can require explicit column lists for tables above a row/byte threshold. 3. Authorized views and column-level access controls are excellent defense-in-depth; QueryShield enforces at the AST and complements them. 4. CREATE TEMP TABLE, EXPORT DATA, MERGE statements should be denylisted for read agents — EXPORT DATA especially, since it can exfil to GCS buckets.

qs = Client(api_key=KEY, policy="bq-analyst", dialect="bigquery")
decision = qs.validate(sql=llm_output, context={"project": "prod", "user": ctx.user_id})
if decision.allowed:
    if decision.estimated_bytes > 10 * 1024**3:  # 10 GB
        return "Query would scan >10 GB; please narrow your filter."
    bq_client.query(decision.sql).result()

Evidence log captures bytes_processed, slot_ms, and the BigQuery job_id for FinOps + audit correlation.