Add Kubernetes liveness/readiness probes and middleware order validation

- Split /health into /health/live (liveness) and /health/ready (readiness)
  following Kubernetes conventions. Combined /health retained for backward
  compatibility with existing Docker HEALTHCHECK definitions.
- Add ReadyCheck and ReadyResponse models for structured readiness output.
- Add _assert_middleware_order() startup check enforcing:
  RateLimit → Csrf → CorrelationId middleware chain.
- Register CorrelationIdMiddleware, CsrfMiddleware, RateLimitMiddleware
  in create_app() with documented required order (reverse of processing).
- Add correlation.py, csrf.py, rate_limit.py middleware modules.
- Add health probe tests in test_health_probes.py.
- Update test_main.py with middleware order assertion tests.
- Update frontend useFetchData hook tests.
- Docs: update Deployment.md with Kubernetes probe config examples.
This commit is contained in:
2026-05-04 02:42:09 +02:00
parent 65fe747cba
commit eb339efcfd
13 changed files with 882 additions and 129 deletions

View File

@@ -1,84 +1,3 @@
### Issue #56: MEDIUM - No API Versioning or Deprecation Strategy
**Where found**:
- All backend routers register under `/api/v1/` prefix but no versioning mechanism exists
**Why this is needed**:
Breaking backend changes immediately break all frontend clients. Without a deprecation path, there is no safe way to evolve the API.
**Goal**:
Define and implement an API lifecycle policy.
**What to do**:
1. Document the versioning strategy (URL versioning is already in place; formalize it).
2. Add a `Deprecation` response header to endpoints scheduled for removal.
3. Implement a `/api/v2/` prefix for the next breaking change cycle.
4. Add a CI check that flags new breaking changes against the OpenAPI spec.
**Possible traps and issues**:
- Running two API versions simultaneously doubles maintenance surface; set a sunset date policy.
**Docs changes needed**:
- `Docs/`: create `API_VERSIONING.md` documenting the lifecycle and deprecation process.
**Doc references**:
- All router files under `backend/app/routers/`
---
### Issue #57: MEDIUM - Health Endpoint Does Not Check Subsystems
**Where found**:
- `backend/app/routers/health.py`
**Why this is needed**:
A process that is running but cannot reach the fail2ban socket, database, or config directory still returns `200 OK`. Load balancers and orchestrators treat it as healthy and route traffic to it, causing silent failures.
**Goal**:
Health endpoint reflects true readiness of all critical subsystems.
**What to do**:
1. Add a structured health check that tests: database connectivity, fail2ban socket accessibility, config directory read access, scheduler liveness.
2. Return `200` only when all checks pass; return `503` with a JSON body listing failed checks otherwise.
3. Expose a separate `/health/live` (process alive) and `/health/ready` (subsystems ready) endpoint for Kubernetes probes.
**Possible traps and issues**:
- Slow health checks (e.g., DB connect timeout) can overwhelm the endpoint under load; set short timeouts per check.
**Docs changes needed**:
- `Docs/Deployment.md`: document liveness vs readiness probe URLs.
**Doc references**:
- `backend/app/routers/health.py`
---
### Issue #58: MEDIUM - Abort Signal Not Propagated in Request Deduplication
**Where found**:
- `frontend/src/hooks/useFetchData.ts:93-113`
**Why this is needed**:
When multiple hook instances share a `requestKey`, they await a single in-flight promise. When one component unmounts and aborts its signal, the shared request continues and calls `setData()` / `onSuccess()` on the unmounted component, causing React "state update on unmounted component" warnings and memory leaks.
**Goal**:
Unmounting a component that joined a deduplicated request must not receive the result.
**What to do**:
1. In the deduplication await path, check the component's own abort signal before calling `setData()` or `onSuccess()`.
2. Wrap the deduplication subscriber list so each subscriber can individually opt out on abort.
**Possible traps and issues**:
- If all subscribers abort before the request resolves, consider whether the underlying request should also be cancelled.
**Docs changes needed**:
- `frontend/src/hooks/README.md`: document abort signal contract for deduplicated requests.
**Doc references**:
- `frontend/src/hooks/README.md`
---
### Issue #59: MEDIUM - Middleware Registration Order Not Validated at Startup
**Where found**: