Operations

Key Rotation

Rotate API keys and SES credentials safely.

#Encryption key rotation

The app encrypts webhook secrets and BYOSES credentials at rest with AES-256-GCM. Rotate ENCRYPTION_KEY periodically and when you suspect key compromise.

#How ciphertext is versioned

Values written by this repo are tagged with the key version they were encrypted under:

v1:iv:authTag:ciphertext
  • v1 - the current ENCRYPTION_KEY
  • v0 - the previous ENCRYPTION_KEY_PREVIOUS (only used during rollover)

Legacy values written before the tag was introduced have no prefix and are assumed v1.

#Rollover procedure

  1. Generate a new key

    node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
    
  2. Promote the old key to _PREVIOUS and set the new key as primary

    # In Convex env
    npx convex env set ENCRYPTION_KEY_PREVIOUS $OLD_KEY
    npx convex env set ENCRYPTION_KEY $NEW_KEY
    # Same values on Cloudflare Worker
    wrangler secret put ENCRYPTION_KEY_PREVIOUS
    wrangler secret put ENCRYPTION_KEY
    

    Deploy. All new writes are encrypted with the new key (v1); old values (v0 or legacy) still decrypt via ENCRYPTION_KEY_PREVIOUS.

  3. Re-encrypt existing ciphertexts You can either:

    • Run a one-shot migration that reads each row, decrypts, and re-writes (forces the v1 tag). Or:
    • Wait for natural churn: webhook secrets rotate when you rotate them, BYOSES creds rotate on re-connect.
  4. Unset the previous key once you're confident nothing v0-tagged remains:

    npx convex env remove ENCRYPTION_KEY_PREVIOUS
    wrangler secret delete ENCRYPTION_KEY_PREVIOUS
    

#Detecting old ciphertext

import { decryptSecret } from "convex/lib/cryptoWeb";

// Ciphertexts starting with "v0:" are using the previous key.
// Filter webhooks.secret / sesConfigurations.accessKeyId / etc. for those
// and re-encrypt them in a migration script.

#What you must never do

  • Don't unset ENCRYPTION_KEY without first re-encrypting everything. The app will lose the ability to decrypt webhook secrets and BYOSES creds.
  • Don't reuse a previous key value. Treat rotation as strictly forward-only.
  • Don't commit keys to git. They live in Convex env + Worker secrets only.