> ## Documentation Index
> Fetch the complete documentation index at: https://trust.denialbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Encryption

> How Denialbase encrypts data — at rest, in transit, and at the column level for PHI.

<Info>
  Defense in depth. Denialbase encrypts data at the disk, bucket, row, column, and wire levels — with customer-managed keys wherever GCP supports them.
</Info>

## At rest

<CardGroup cols={2}>
  <Card title="Cloud SQL (PostgreSQL)" icon="database">
    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.
  </Card>

  <Card title="Cloud Storage (documents)" icon="folder-closed">
    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`.
  </Card>

  <Card title="Memorystore Redis" icon="bolt">
    Session caches, rate-limit counters, and 2FA tokens use CMEK-encrypted Memorystore. Connection is TLS (`rediss://`) over private VPC.
  </Card>

  <Card title="Terraform state" icon="code-branch">
    Our infrastructure state bucket uses a separate CMEK key with access restricted to CI/CD via Workload Identity Federation — no static keys.
  </Card>
</CardGroup>

## 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

| Model                | Encrypted columns                                                                                     | Deterministic?            |
| -------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------- |
| `User`               | `first_name`, `last_name`                                                                             | Deterministic (queryable) |
| `User`               | `phone_number`, `address_line1`, `address_line2`, `date_of_birth`                                     | Non-deterministic         |
| `InsuranceMember`    | `name`, `phone_number`, `email`, `address_line1`, `date_of_birth`                                     | Mix                       |
| `InsuranceProfile`   | `member_id`, `group_number`                                                                           | Deterministic             |
| `InsuranceProfile`   | `policy_number`, `insurer_phone`, `appeals_phone`, `insurer_fax`, `claims_address`, `patient_address` | Non-deterministic         |
| `OverturnableDenial` | `diagnosis_codes` (JSON), `patient_name`, `patient_dob`                                               | Non-deterministic         |

### Migration status

<Warning>
  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](/trust/soc2-iso27001) for the tracker.
</Warning>

### 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

| Key                           | Rotation cadence                                                                                                    |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| CMEK (Cloud SQL, GCS, Redis)  | Automatic, every 90 days                                                                                            |
| Terraform state CMEK          | Automatic, every 90 days                                                                                            |
| Active Record encryption keys | Manual — rotation requires re-encryption of all data. Procedure documented in our internal secret-rotation runbook. |
| JWT signing key               | Manual — 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](mailto:security@denialbase.com).
