Skip to main content
Defense in depth. Denialbase encrypts data at the disk, bucket, row, column, and wire levels — with customer-managed keys wherever GCP supports them.

At rest

Cloud SQL (PostgreSQL)

AES-256 with customer-managed encryption keys (CMEK) in Google Cloud KMS. 90-day automatic key rotation. Keys live in a dedicated KMS key ring per environment.

Cloud Storage (documents)

EOBs, denial letters, appeal letters, and medical records are stored in CMEK-encrypted GCS buckets with uniform_bucket_level_access and public_access_prevention = enforced.

Memorystore Redis

Session caches, rate-limit counters, and 2FA tokens use CMEK-encrypted Memorystore. Connection is TLS (rediss://) over private VPC.

Terraform state

Our infrastructure state bucket uses a separate CMEK key with access restricted to CI/CD via Workload Identity Federation — no static keys.

In transit

  • External traffic: TLS 1.2+ only. Enforced at the Google Cloud load balancer. HSTS preload.
  • Internal traffic: GCP services communicate over Google’s private backbone; cross-region traffic is encrypted in transit.
  • Database connections: Cloud SQL connections are TLS-encrypted; app-to-DB goes over a private VPC peering link.
  • Redis connections: rediss:// TLS endpoint with private IP only.

Column-level PHI encryption

On top of the disk-level CMEK encryption, specific PHI columns are encrypted with Active Record Encryption before being written to the database. This means even a direct SQL query against the table returns ciphertext.

What’s encrypted today

ModelEncrypted columnsDeterministic?
Userfirst_name, last_nameDeterministic (queryable)
Userphone_number, address_line1, address_line2, date_of_birthNon-deterministic
InsuranceMembername, phone_number, email, address_line1, date_of_birthMix
InsuranceProfilemember_id, group_numberDeterministic
InsuranceProfilepolicy_number, insurer_phone, appeals_phone, insurer_fax, claims_address, patient_addressNon-deterministic
OverturnableDenialdiagnosis_codes (JSON), patient_name, patient_dobNon-deterministic

Migration status

The column-level encryption rollout is partially complete. Some PHI columns on the OverturnableDenial and ProviderPatientLink tables are declared as encrypts on the model but remain as plaintext string columns in the underlying schema — meaning the backfill migration was started but not completed. All data remains encrypted at the CMEK/disk level, so no data is ever stored on unencrypted media; the gap is the “additional” application-level encryption layer.Target: complete by Q2 2026. See SOC 2 readiness for the tracker.

Key management

  • Encryption keys live in GCP Secret Manager, not in source code or environment files.
  • Three keys per environment: primary encryption key, deterministic encryption key, key-derivation salt.
  • Access to keys is granted via IAM bindings only to the application’s runtime service account.
  • Access to Secret Manager is audit-logged by Google’s Cloud Audit Logs.

Key rotation

KeyRotation cadence
CMEK (Cloud SQL, GCS, Redis)Automatic, every 90 days
Terraform state CMEKAutomatic, every 90 days
Active Record encryption keysManual — rotation requires re-encryption of all data. Procedure documented in our internal secret-rotation runbook.
JWT signing keyManual — dual-secret validation for zero-downtime rotation is in progress (target Q2 2026).

Encryption the customer controls

Customers interacting with Denialbase via the web app or API never need to manage encryption keys themselves — all of the above is handled server-side. For customers with additional sovereignty requirements (BYOK, dedicated KMS key), contact security@denialbase.com.