Skip to main content
Local Vault wraps each data key with VAULT_LOCAL_MASTER_KEY (base64, 32 bytes). It does not call AWS. The master key is required. There is no fallback key.

Why

Local development and Jest need envelope encryption without a CMK. The envelope JSON matches AWS KMS so a later provider switch only re-wraps the data key.

Setup

  1. tooling-vault-local is a workspace dependency of apps/backend.
  2. apps/backend/src/configuration/development.ts calls resolveDevelopmentVault(). That returns no vault unless VAULT_PROVIDER=local.
  3. Environment:
Compose sets VAULT_PROVIDER=local on backend and consumer, with VAULT_KMS_CAPABILITY=encrypt on the webapp and decrypt on the consumer.
  1. apps/backend/src/configuration/test.ts omits vault so existing suites boot. Tests that enable vault pass a config object.

Local observability

Domain logs use feature logger vault. Provider errors are VaultError codes. The local package does not log plaintext.

Adding a new provider

Add a package under apps/tools/vault/<name>/, a VaultProvider enum value, a Zod branch, and a dynamic import in the loader. Do not import that package from apps/backend except through the loader variable.

Gotchas

  • Capability is checked before wrap and unwrap. An encrypt-only process fails use() with capability_mismatch and does not unwrap.
  • A blob whose encryption context does not match fails closed (decrypt_failed).
  • Production smoke leaves VAULT_PROVIDER unset and must still boot.

What’s next

AWS KMS for deployed environments: AWS KMS. Design and the incident runbook: Vault.