Avatar for the QWED-AI user
QWED-AI
qwed-verification
BlogDocsChangelog

Performance History

Latest Results

Merge pull request #199 from QWED-AI/fix/issue-189-redis-failclosed fix(cache): enforce fail-closed Redis backend for distributed mode
main
3 days ago
fix(cache): enforce fail-closed Redis backend for distributed mode (closes #189) Issue #189: RedisCache silently fell back to node-local VerificationCache when Redis was unavailable, breaking distributed consistency and enabling policy/rate-limit bypass by routing requests to cold nodes. Root cause: RedisCache.__init__ unconditionally created a VerificationCache fallback when _client is None, and get/set/invalidate/clear silently routed to it. Infrastructure failure became an implicit security-mode downgrade. Fix: Introduce explicit CacheBackendMode enum with three modes -- STRICT_DISTRIBUTED (new default for RedisCache and get_cache): Redis unavailable at startup -> raises CacheBackendUnavailableError. Redis error at runtime (get/set/invalidate/clear) -> raises CacheBackendUnavailableError. No silent node-local fallback, ever. Use this for rate limits, replay protection, policy gates. EXPLICIT_DEGRADED (opt-in): Redis unavailable -> activates VerificationCache fallback, but only after emitting a structured JSON security event to qwed.cache.security logger. Every result from the fallback carries _degraded_mode=True and _cache_backend=local_degraded so callers and auditors can detect the downgrade. Cross-node divergence becomes explicit, not silent. LOCAL_ONLY: Never touches Redis. Pure in-memory VerificationCache. Used by cached_verify() (backward compatible -- its existing behavior was already effectively local-only via silent fallback). Additional changes: - _emit_security_event(): structured JSON log (event, mode, tenant_id, timestamp) emitted on BACKEND_UNAVAILABLE_AT_STARTUP and BACKEND_UNAVAILABLE_AT_RUNTIME - stats() now exposes mode and degraded fields for observability - redis_config.py: add reset_redis_state() for test isolation - VerificationCache: zero changes (backward compatible) - cached_verify(): explicitly LOCAL_ONLY with doc comment explaining why Tests: 25 new tests in tests/test_pr189_redis_failclosed.py covering startup-down, runtime-loss, security event emission, JSON event validity, _degraded_mode tagging, cross-node isolation documentation, get_cache() default mode contract, and cached_verify() backward compatibility. Full regression: 1198 passed, 82 skipped -- no regressions.
fix/issue-189-redis-failclosed
3 days ago
fix(cache): reduce factory complexity
fix/issue-189-redis-failclosed
4 days ago
fix(cache): enforce fail-closed Redis backend for distributed mode (closes #189) Issue #189: RedisCache silently fell back to node-local VerificationCache when Redis was unavailable, breaking distributed consistency and enabling policy/rate-limit bypass by routing requests to cold nodes. Root cause: RedisCache.__init__ unconditionally created a VerificationCache fallback when _client is None, and get/set/invalidate/clear silently routed to it. Infrastructure failure became an implicit security-mode downgrade. Fix: Introduce explicit CacheBackendMode enum with three modes -- STRICT_DISTRIBUTED (new default for RedisCache and get_cache): Redis unavailable at startup -> raises CacheBackendUnavailableError. Redis error at runtime (get/set/invalidate/clear) -> raises CacheBackendUnavailableError. No silent node-local fallback, ever. Use this for rate limits, replay protection, policy gates. EXPLICIT_DEGRADED (opt-in): Redis unavailable -> activates VerificationCache fallback, but only after emitting a structured JSON security event to qwed.cache.security logger. Every result from the fallback carries _degraded_mode=True and _cache_backend=local_degraded so callers and auditors can detect the downgrade. Cross-node divergence becomes explicit, not silent. LOCAL_ONLY: Never touches Redis. Pure in-memory VerificationCache. Used by cached_verify() (backward compatible -- its existing behavior was already effectively local-only via silent fallback). Additional changes: - _emit_security_event(): structured JSON log (event, mode, tenant_id, timestamp) emitted on BACKEND_UNAVAILABLE_AT_STARTUP and BACKEND_UNAVAILABLE_AT_RUNTIME - stats() now exposes mode and degraded fields for observability - redis_config.py: add reset_redis_state() for test isolation - VerificationCache: zero changes (backward compatible) - cached_verify(): explicitly LOCAL_ONLY with doc comment explaining why Tests: 25 new tests in tests/test_pr189_redis_failclosed.py covering startup-down, runtime-loss, security event emission, JSON event validity, _degraded_mode tagging, cross-node isolation documentation, get_cache() default mode contract, and cached_verify() backward compatibility. Full regression: 1198 passed, 82 skipped -- no regressions.
fix/issue-189-redis-failclosed
4 days ago
fix(cache): reduce factory complexity
fix/issue-189-redis-failclosed
4 days ago
fix(cache): harden construction waiter path
fix/issue-189-redis-failclosed
4 days ago
fix(cache): fail waiters on construction errors
fix/issue-189-redis-failclosed
4 days ago

Latest Branches

CodSpeed Performance Gauge
0%
fix(cache): enforce fail-closed Redis backend for distributed mode#199
3 days ago
2fd6709
fix/issue-189-redis-failclosed
CodSpeed Performance Gauge
N/A
8 days ago
cec6b5c
codspeed-wizard-1780238860317
© 2026 CodSpeed Technology
Home Terms Privacy Docs