ioredis cache-aside helpers, Cache-Control middleware, and AES key rotation
Dshamir adds three independent backend-ops primitives: a Redis client with cache-aside helpers, HTTP Cache-Control middleware, and an encryption key rotation module for stored user API keys.
The Redis module (redis.ts) wraps ioredis with a lazy-connect client and three thin helpers: cacheGet(key), cacheSet(key, value, ttlSeconds), and cacheDelete(key). No cache-aside logic is applied to any route yet - this is infrastructure ahead of the planned endpoint-level caching work noted in the roadmap.
The HTTP cache middleware (middleware/cache.ts) adds two functions: setCacheHeaders(maxAge) returns a middleware that sets Cache-Control: private, max-age=N, and noCache sets Cache-Control: no-store. Twelve lines total. Again, nothing calls these yet; they are available for wiring to specific routes.
Key rotation (keyRotation.ts) is more immediately useful. It reads USER_API_KEYS_ENCRYPTION_SECRET and USER_API_KEYS_ENCRYPTION_SECRET_V2 from the environment, derives a 32-byte key from each via SHA-256, and exposes tryDecrypt() which tries all keys in reverse order (newest first). The idea is that you can add _V2 when rotating, re-encrypt stored rows under the new key without downtime, then remove the old secret. The userApiKeys.ts module was updated to delegate to this module. A follow-up in the security hardening work upgrades this further: SHA-256 key derivation is replaced with HKDF with a random 16-byte per-row salt stored in a new salt column.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?