Skip to content

Zero-trust by design

Your data never leaves your network.

The Subveil CLI does the subsetting and masking inside your infrastructure. Subveil Cloud is a control plane for policies and receipts, and never sees a row.

Zero-trust execution

Runs entirely in your VPC or CI runner

subveil pull connects from your network to your databases. The only outbound traffic to Subveil Cloud is metadata and hashed receipts.

Your VPC · GitHub Actions runner · laptop

Production Postgres

read-only snapshot

subveil pull

subset + mask in-flight

Staging / PR DB

masked copy

Raw rows: stay here.

row data
hashes · counts · names

Subveil Cloud

  • Schema metadata and PII hints
  • Masking policies
  • Audit receipts (hashes, counts)
  • Accounts and billing

What Subveil Cloud stores

  • Account, team and billing records
  • Table and column names, types and PII hints
  • Masking and subsetting policies
  • Audit receipts: run IDs, timestamps, hashes, row counts, masked column names

What it never receives

  • Row values from your databases
  • Database connection strings or credentials
  • Your SUBVEIL_SEED
  • Anything the CLI reads from the source other than catalog metadata

Read-only source guarantee

Your source database is never mutated

Every pull reads the source inside a single REPEATABLE READ snapshot opened as read-only. All tables are read as of the same instant, so the slice is consistent even while production keeps taking writes.

  • Source access is read-only: the database itself rejects writes.
  • The CLI refuses to run when source and target are the same database.
  • The CLI refuses a non-empty target unless you pass --truncate.
  • The target is written in one transaction: it fully succeeds or leaves nothing.
  • Row values never appear in logs or error messages.
source session
BEGIN ISOLATION LEVEL REPEATABLE READ, READ ONLY;
-- every table is read from this one consistent snapshot
SELECT … FROM public.users WHERE …;
SELECT … FROM public.orders WHERE …;
COMMIT;

Deterministic HMAC masking

Joins survive. PII doesn't.

Masking is keyed by SUBVEIL_SEED. The same input with the same seed always produces the same fake output, so a customer email masked in users and in billing stays identical, and foreign keys and unique constraints still hold.

Without the seed the mapping can't be recomputed. The seed lives in your environment or CI secret store and is never uploaded.

same input, same output

Audit receipts

Evidence for your SOC 2 and HIPAA reviews

After every pull the CLI submits a receipt. It records what ran (hashes of the policy, source and target hosts, row counts, masked column names) and never what the data was. Receipts are kept as an immutable log you can export for auditors.

Receipts help you evidence your controls. They do not by themselves make an environment SOC 2 or HIPAA compliant.

audit receipt
{
"run_id": "9b1e6f0a-3c52-4d7e-8a41-2f7c5d9e1b30",
"started_at": "2026-10-21T10:00:00Z",
"finished_at": "2026-10-21T10:01:15Z",
"status": "success",
"source_host_hash": "sha256:4be1…9c07",
"target_host_hash": "sha256:a3f2…71d8",
"policy_hash": "sha256:9f2c…b71e",
"total_rows_copied": 2360000,
"tables_summary": [
{ "table": "public.users", "rows_copied": 50000, "masked_columns": ["email", "phone"] }
]
}

Questions from your security team?

Read how the pipeline works, or report a vulnerability to [email protected].