Redis failure-mode coverage in 3 middleware sites — class-of-bugs fix
2026-05-07
What We Built
Three middleware sites had if (redis) { await redis.X(); ... } blocks with no try/catch. If Redis was unavailable they fell through to in-memory; if Redis threw, the unhandled exception propagated as middleware 500. Wrapped each block in try/catch that falls back to the existing in-memory or fail-open path.
Why It Matters
Predicted by user memory feedback_redis_failure_modes.md: Redis-using code must guard BOTH getRedis() === undefined AND redis.X() throws. PR #176 fixed only the latter for auth; this PR addressed all three remaining sites in one class-of-bugs sweep.
How It Works
Three regression tests, one per finding, each mocks getRedis to return an object whose method throws. Asserts the middleware does NOT return 500 — falls through to in-memory rate limiter / fail-open default.
Lockstep Checklist
- [x] No API route changes (middleware/internal — lockstep N/A)
- [x] No SDK changes
- [x] No MCP tool changes
- [x] Regression test included (test-first invariant per /quality-fleet protocol)
- [x] Linked to /quality-fleet R1 dashboard at
.quality/dashboard.md
Provenance
Auto-found by /quality-fleet R1 (2026-05-07) scanner round, fixed in fix-agent batch under "go for all of it" autonomy grant. PR #205 merged to main as commit e74a38d38. Finding(s) tracked at .quality/findings.jsonl (entries: "b2c3d4e5f6a7", "c3d4e5f6a7b8", "d4e5f6a7b8c9"). Production-deployed via ECS task-def revision 732 series.