Convex Secret Store

Encrypted secret storage for Convex with envelope encryption, key rotation, expiry, audit logs, and namespace-scoped organization.

Installation

npm install convex-secret-store

About Convex Secret Store

Encrypted secret storage for Convex using envelope encryption and versioned KEKs.

Features:
- namespace-scoped secrets
- per-secret DEKs with AES-GCM
- key rotation without rewriting plaintext
- expiry and cleanup flows
- audit log for writes and maintenance operations
- typed TypeScript client

Includes a full example app showing secret management, safe server-side usage, activity history, and rotation/cleanup workflows.

Benefits

Use cases

how to store API keys securely in Convex

Use the Convex Secret Store component to encrypt API keys with envelope encryption. Store secrets with `secrets.put(ctx, { namespace: 'app:production', name: 'openai', value: apiKey })` and retrieve them with `secrets.get()`. Each secret uses a unique data encryption key wrapped by your master key.

Convex secret management with key rotation

The Convex Secret Store supports key rotation without rewriting encrypted data. Add new key versions to your configuration, then use `secrets.rotateKeys()` to rewrap existing secrets under the new key. Old keys remain available for decryption during the transition.

namespace secrets in Convex by environment

Organize secrets by namespace like `workspace:production` or `team:testing`. The TypeScript client enforces namespace patterns at compile time while storing secrets separately per namespace for isolation and access control.

audit logging for secret access in Convex

The component automatically logs all secret operations (create, update, delete, rotate) to an append-only audit table. Use `secrets.listEvents()` to paginate through audit history filtered by namespace, secret name, or operation type for compliance tracking.

Frequently asked questions

How does the encryption work in Convex Secret Store?

Convex Secret Store uses envelope encryption with two layers: each secret gets a unique AES-GCM data encryption key (DEK), and that DEK is wrapped with your configured key encryption key (KEK). This allows key rotation by rewrapping DEKs without touching the encrypted secret data.

Can I rotate encryption keys without downtime?

Yes, Convex Secret Store supports zero-downtime key rotation. Add the new key version as the first entry in your keys array, deploy, then use the `rotateKeys()` method to rewrap existing secrets. Old keys remain available during the transition period.

How do I handle expired secrets?

The Convex Secret Store automatically handles expiry during reads - expired secrets return `{ ok: false, reason: 'expired' }`. Use the `cleanupSecrets()` method with a retention window to permanently delete expired secrets, and set up a cron job to run cleanup regularly.

What happens if I lose access to an encryption key version?

If you remove a key version from your configuration, secrets encrypted with that version become unreadable and return `{ ok: false, reason: 'key_version_unavailable' }`. Always rotate secrets to newer key versions before removing old keys from your configuration.

How do I organize secrets across multiple environments?

Use namespaces to separate secrets by environment or team, like `myapp:production` or `team-alpha:testing`. The Convex Secret Store TypeScript client can enforce namespace patterns at compile time while keeping secrets isolated at runtime.

Links