Decrypted views

Two ways to get real PII back. Neither one leaves a copy behind.

Someone on your team always eventually needs the real email address — to send a receipt, run a campaign, sync a contact to an ad platform. Chameleon gives you two sanctioned ways to get it: a direct API call for one-off lookups, or a live-decrypting warehouse view for repeated joins. Both are covered by the same guarantee — plaintext is never written to disk, and it's gone the instant the key is.


Why it matters

Two paths, one guarantee

Call the Key Vault directly for a single value, or declare a view that decrypts a whole table's worth on every query. Either way, nothing decrypted is ever persisted anywhere Chameleon controls.

Shred still works, zero extra code

Crypto-shredding already destroys a user's key on deletion. Both decrypt paths just stop returning that user's data the moment it happens — there's no cascade to build, because there's no copy to clean up.

Invisible to your own PII scanning

A decrypted view lives in its own dataset that your PII-discovery config never scans. Not an allowlist exception — there's structurally nothing at rest there to find.


The problem

The naive way to get plaintext PII creates a second copy of it.

Encrypting everything at rest solves the deletion problem, but it doesn't make the need for real data go away. Someone still has to send the receipt, run the campaign, or sync a contact to an ad platform — and the fastest way to get there is usually a one-off script that decrypts a batch of records and writes the result to a new table. That table is now a second, unmanaged copy of PII, outside the Key Vault's control, that nobody remembers to lock down or delete.

Chameleon closes that gap by never handing out a copy in the first place. Every path back to plaintext runs through the Key Vault at read time, not write time — so there's nothing sitting around for a future ghost-data scan to find, and nothing that survives a crypto-shred by accident.


How it works

Centralized: ask the Vault directly. Decentralized: let the warehouse ask for you.

Centralized decryption is a signed API call: your application sends ciphertext to the Key Vault's /decrypt endpoint and gets plaintext back, one request at a time. It's the right fit for application code that needs a single value on demand — rendering a user's email in a support tool, say.

Decentralized decryption is for warehouse-scale joins. You declare a view once in the console — the source table, which fields need decrypting, and why — and Chameleon creates a BigQuery Authorized View backed by a Remote Function. Query that view like any other table, and BigQuery calls back into the Key Vault live, per query, to decrypt just the rows you asked for. Nothing is written to BigQuery storage, and the result isn't even cached — BigQuery excludes remote function output from its query cache by design, so a shredded user can never surface from a stale cache hit.

The consumer identity you name when declaring the view gets read-only access to that one view — never write access anywhere in the underlying dataset — so it can't be used to materialize a permanent copy inside BigQuery itself.


What crypto-shredding does to it

Delete a user's key, and the view already stopped.

Because nothing is ever persisted, there's no separate cleanup step to build for decrypted views — the same crypto-shred that protects every other copy of a user's data protects this one too. The next time anyone queries the view after that user's key is destroyed, their row simply comes back with the decrypted field set to null. No code changes, no batch job, no cascade to keep in sync.


Chameleon workflow
01 / Declare

In the console, name a source resource already in your PII registry, pick which fields need decrypting, and say why. Only fields with a real crypto anchor — encrypted or tokenized, never a plaintext copy — are eligible.

02 / Provision

Chameleon creates the BigQuery Authorized View and grants your chosen consumer identity dataViewer-only access to it. Nothing else changes in your warehouse.

03 / Query

Query the view like any other table. Each query calls the Key Vault live, decrypts just those rows, and returns them — nothing lands in BigQuery storage.

04 / Revoke or shred

Revoke the view when the use case ends, or do nothing — a user's crypto-shred already makes their row stop decrypting on its own.


Proof surface
declare: campaign_send_email
source: bigquery:chameleon_prod.raw_users
fields: email
justification: join decrypted emails against the campaign mart to send receipts
consumer: campaign-sender@my-project.iam.gserviceaccount.com
grant: bigquery.dataViewer -> decrypted_views.campaign_send_email

FAQ

Common questions

What's the actual difference between centralized and decentralized decryption?

Centralized is a direct, per-value API call to the Key Vault from your own application code — you ask for one thing at a time. Decentralized is a declared BigQuery view: you or a scheduled job queries it like any other table, and the Key Vault decrypts live behind the scenes, in bulk. Both give the same guarantee — plaintext is never written to disk — the difference is just where the decrypt call happens.

Doesn't a decrypted view defeat crypto-shredding?

No — the view is a live query, not a stored copy. It calls back into the Key Vault on every single execution, so it can only ever return what the Key Vault is currently willing to decrypt for that user at that moment. Shred the key and the view starts returning null for that user on its very next query, exactly like calling /decrypt would.

Can someone just copy the decrypted view into a real table?

The consumer identity granted access to a decrypted view only ever gets read (dataViewer) permission on that one view — never write (dataEditor) — anywhere in the underlying dataset, so a CREATE TABLE AS SELECT against it fails with a permission error inside BigQuery. As with any read access, someone could still copy a query result out of BigQuery entirely; that's the same limit any decrypt API has, not something specific to this feature.

Will decrypted views show up in PII-scanning tools, like the chameleon_pii dbt package?

No, by design. Decrypted views live in a BigQuery dataset that's never included in your PII-discovery scan configuration, so there's nothing there for a metadata scanner to find in the first place — that's a structural separation, not an allowlist exception carved out after the fact.


Keep reading

The same key-destruction guarantee, on the deletion side: what a signed certificate actually proves.