Skip to content

ADR-0008: Encryption key rotation and data retention ​

Status: accepted (2026-10-12)

Key rotation ​

  • Ciphertexts use format v2: version byte, 4-byte key id (first bytes of SHA-256 of the key-encryption key), wrapped data key, encrypted payload. Format v1 (no key id) remains readable.
  • QUAVON_ENCRYPTION_KEY is the current key; QUAVON_PREVIOUS_ENCRYPTION_KEYS (comma-separated, *_FILE supported) lists keys being rotated out. New data is always encrypted with the current key; decryption accepts any configured key.
  • Rotation procedure: generate a new key, move the old key to QUAVON_PREVIOUS_ENCRYPTION_KEYS, set the new key, restart, run keys rotate, check keys status shows no remaining data on old keys, then remove the old key and restart.
  • keys rotate re-wraps only the data keys (Cipher.rewrap), so payloads are not re-encrypted. Every encrypted column is listed in one registry, so new encrypted columns cannot be forgotten. Valkey caches (installation tokens, ETags) expire on their own and are not rotated.

Retention ​

  • Daily retention maintenance task. Defaults, overridable in instance settings:
    • retention.webhookPayloadDays (14): webhook payloads are set to null; delivery rows stay for idempotency.
    • retention.outboxDays (7): dispatched outbox rows are deleted.
    • Expired sessions and used or expired setup/break-glass tokens are deleted one day after expiry.
    • llm_calls follow tenants.data_retention_days.
  • The audit log is append-only and not subject to automatic retention until a policy is agreed with counsel.

The open core is released under the Apache License 2.0.