refactor: Make service dependencies explicit and injectable
Remove hidden cross-service coupling by making dependencies explicit through dependency injection while maintaining backward compatibility via lazy imports. Key changes: - history_service and ban_service: Removed direct module-level imports of fail2ban_metadata_service, added optional service parameters to functions - Added get_fail2ban_metadata_service() provider to dependencies.py - Updated history router to inject Fail2BanMetadataService dependency - history_service functions now use lazy imports in fallback paths for backward compatibility when service is not explicitly injected - All test patches updated to use internal _get_fail2ban_db_path() helper - jail_config_service and jail_service already follow best practices This pattern prevents circular imports, makes services testable via explicit mocking, and documents service dependencies clearly. Fixes: Instructions.md #2 - Hidden cross-service coupling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,26 +1,3 @@
|
||||
## 1) Broad exception catching in backend services
|
||||
- Where found:
|
||||
- [backend/app/services/ban_service.py](backend/app/services/ban_service.py)
|
||||
- [backend/app/services/geo_cache.py](backend/app/services/geo_cache.py)
|
||||
- [backend/app/services/blocklist_service.py](backend/app/services/blocklist_service.py)
|
||||
- Why this is needed:
|
||||
- Catching broad Exception hides root causes and weakens operational debugging.
|
||||
- Goal:
|
||||
- Replace broad catches with targeted exception handling and predictable failure paths.
|
||||
- What to do:
|
||||
- Inventory each broad catch.
|
||||
- Replace with explicit exception classes.
|
||||
- Keep one top-level safety catch only where unavoidable, with full context logging.
|
||||
- Possible traps and issues:
|
||||
- Over-tightening catches can expose previously hidden runtime failures.
|
||||
- Docs changes needed:
|
||||
- Add service error-handling policy and allowed catch patterns.
|
||||
- Doc references:
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
- https://docs.python.org/3/tutorial/errors.html
|
||||
|
||||
|
||||
---
|
||||
## 2) Hidden cross-service coupling (service imports service)
|
||||
- Where found:
|
||||
- [backend/app/services/jail_service.py](backend/app/services/jail_service.py)
|
||||
@@ -43,6 +20,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 3) Blocklist import flow mixes too many responsibilities
|
||||
- Where found:
|
||||
- [backend/app/services/blocklist_service.py](backend/app/services/blocklist_service.py)
|
||||
@@ -62,6 +40,7 @@
|
||||
- [Docs/Features.md](Docs/Features.md)
|
||||
|
||||
---
|
||||
|
||||
## 4) Module-level mutable runtime flags in service layer
|
||||
- Where found:
|
||||
- [backend/app/services/jail_service.py](backend/app/services/jail_service.py)
|
||||
@@ -80,6 +59,7 @@
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
|
||||
---
|
||||
|
||||
## 5) Inconsistent domain exception contracts across services
|
||||
- Where found:
|
||||
- [backend/app/routers/jails.py](backend/app/routers/jails.py)
|
||||
@@ -101,6 +81,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 6) Raw DB connection exposed as dependency for all routes
|
||||
- Where found:
|
||||
- [backend/app/dependencies.py](backend/app/dependencies.py)
|
||||
@@ -119,6 +100,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 7) Service layer coupled to response/presentation models
|
||||
- Where found:
|
||||
- [backend/app/services/ban_service.py](backend/app/services/ban_service.py)
|
||||
@@ -137,6 +119,7 @@
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
|
||||
---
|
||||
|
||||
## 8) Inconsistent modeling style (TypedDict vs Pydantic)
|
||||
- Where found:
|
||||
- [backend/app/services/jail_service.py](backend/app/services/jail_service.py)
|
||||
@@ -156,6 +139,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 9) Repository protocol coverage is incomplete
|
||||
- Where found:
|
||||
- [backend/app/repositories/protocols.py](backend/app/repositories/protocols.py)
|
||||
@@ -175,6 +159,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 10) Startup sequence depends on implicit ordering
|
||||
- Where found:
|
||||
- [backend/app/startup.py](backend/app/startup.py)
|
||||
@@ -193,6 +178,7 @@
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
|
||||
---
|
||||
|
||||
## 11) Logging semantics are inconsistent across backend modules
|
||||
- Where found:
|
||||
- [backend/app/services](backend/app/services)
|
||||
@@ -212,6 +198,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 12) Prop drilling in jail overview page
|
||||
- Where found:
|
||||
- [frontend/src/pages/jails/JailOverviewSection.tsx](frontend/src/pages/jails/JailOverviewSection.tsx)
|
||||
@@ -231,6 +218,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 13) Config page is over-centralized
|
||||
- Where found:
|
||||
- [frontend/src/pages/ConfigPage.tsx](frontend/src/pages/ConfigPage.tsx)
|
||||
@@ -249,6 +237,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 14) Error boundary granularity is too coarse
|
||||
- Where found:
|
||||
- [frontend/src/App.tsx](frontend/src/App.tsx)
|
||||
@@ -269,6 +258,7 @@
|
||||
- https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary
|
||||
|
||||
---
|
||||
|
||||
## 15) Fragmented async error UX handling in components
|
||||
- Where found:
|
||||
- [frontend/src/pages/jails/BanUnbanForm.tsx](frontend/src/pages/jails/BanUnbanForm.tsx)
|
||||
@@ -288,6 +278,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 16) API usage pattern is inconsistent across components/hooks
|
||||
- Where found:
|
||||
- [frontend/src/pages/JailsPage.tsx](frontend/src/pages/JailsPage.tsx)
|
||||
@@ -307,6 +298,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 17) Weak typed error contracts in generic hooks
|
||||
- Where found:
|
||||
- [frontend/src/hooks/useListData.ts](frontend/src/hooks/useListData.ts)
|
||||
@@ -326,6 +318,7 @@
|
||||
- [frontend/src/api/client.ts](frontend/src/api/client.ts)
|
||||
|
||||
---
|
||||
|
||||
## 18) Duplicate polling/list loading behavior across hooks
|
||||
- Where found:
|
||||
- [frontend/src/hooks/useListData.ts](frontend/src/hooks/useListData.ts)
|
||||
@@ -344,6 +337,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 19) Provider dependency chain is implicit
|
||||
- Where found:
|
||||
- [frontend/src/App.tsx](frontend/src/App.tsx)
|
||||
@@ -362,6 +356,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 20) Loading UX lacks progressive/skeleton states
|
||||
- Where found:
|
||||
- [frontend/src/pages](frontend/src/pages)
|
||||
@@ -379,6 +374,7 @@
|
||||
- [Docs/Web-Design.md](Docs/Web-Design.md)
|
||||
|
||||
---
|
||||
|
||||
## 21) Silent auth error swallow in fetch error utility
|
||||
- Where found:
|
||||
- [frontend/src/utils/fetchError.ts](frontend/src/utils/fetchError.ts)
|
||||
@@ -396,6 +392,7 @@
|
||||
- [frontend/src/providers/AuthProvider.tsx](frontend/src/providers/AuthProvider.tsx)
|
||||
|
||||
---
|
||||
|
||||
## 22) Magic strings are scattered in frontend storage keys
|
||||
- Where found:
|
||||
- [frontend/src/providers/AuthProvider.tsx](frontend/src/providers/AuthProvider.tsx)
|
||||
@@ -415,6 +412,7 @@
|
||||
- [frontend/src/utils/constants.ts](frontend/src/utils/constants.ts)
|
||||
|
||||
---
|
||||
|
||||
## 23) No global cancellation policy on route transitions
|
||||
- Where found:
|
||||
- [frontend/src/hooks](frontend/src/hooks)
|
||||
@@ -432,6 +430,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 24) API response wrapper shape is inconsistent
|
||||
- Where found:
|
||||
- [backend/app/routers/dashboard.py](backend/app/routers/dashboard.py)
|
||||
@@ -452,6 +451,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 25) No canonical snake_case/camelCase serialization policy
|
||||
- Where found:
|
||||
- [backend/app/models/server.py](backend/app/models/server.py)
|
||||
@@ -471,6 +471,7 @@
|
||||
- https://docs.pydantic.dev/latest/concepts/alias/
|
||||
|
||||
---
|
||||
|
||||
## 26) Pagination contract is not standardized across endpoints
|
||||
- Where found:
|
||||
- [backend/app/routers/dashboard.py](backend/app/routers/dashboard.py)
|
||||
@@ -490,6 +491,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 27) Error response body shape is inconsistent
|
||||
- Where found:
|
||||
- [backend/app/main.py](backend/app/main.py)
|
||||
@@ -509,6 +511,7 @@
|
||||
- [Docs/Backend-Development.md](Docs/Backend-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 28) Login failure delay can enable app-layer DoS
|
||||
- Where found:
|
||||
- [backend/app/routers/auth.py](backend/app/routers/auth.py#L110)
|
||||
@@ -526,6 +529,7 @@
|
||||
- [backend/app/utils/rate_limiter.py](backend/app/utils/rate_limiter.py)
|
||||
|
||||
---
|
||||
|
||||
## 29) Blocklist URL validation has DNS-rebinding window
|
||||
- Where found:
|
||||
- [backend/app/utils/ip_utils.py](backend/app/utils/ip_utils.py#L145)
|
||||
@@ -545,6 +549,7 @@
|
||||
- https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html
|
||||
|
||||
---
|
||||
|
||||
## 30) Setup persistence is non-atomic across DB contexts
|
||||
- Where found:
|
||||
- [backend/app/services/setup_service.py](backend/app/services/setup_service.py)
|
||||
@@ -563,6 +568,7 @@
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
|
||||
---
|
||||
|
||||
## 31) Fire-and-forget reschedule may fail silently
|
||||
- Where found:
|
||||
- [backend/app/tasks/blocklist_import.py](backend/app/tasks/blocklist_import.py#L108)
|
||||
@@ -580,6 +586,7 @@
|
||||
- [Docs/Features.md](Docs/Features.md)
|
||||
|
||||
---
|
||||
|
||||
## 32) RateLimiter cleanup function is not scheduled/used
|
||||
- Where found:
|
||||
- [backend/app/utils/rate_limiter.py](backend/app/utils/rate_limiter.py#L84)
|
||||
@@ -598,6 +605,7 @@
|
||||
- [backend/app/utils/rate_limiter.py](backend/app/utils/rate_limiter.py)
|
||||
|
||||
---
|
||||
|
||||
## 33) Trusted proxy configuration is hardcoded in auth router
|
||||
- Where found:
|
||||
- [backend/app/routers/auth.py](backend/app/routers/auth.py#L46)
|
||||
@@ -617,6 +625,7 @@
|
||||
- [Docs/Instructions.md](Docs/Instructions.md)
|
||||
|
||||
---
|
||||
|
||||
## 34) Setup redirect allowlist uses broad prefix matching
|
||||
- Where found:
|
||||
- [backend/app/main.py](backend/app/main.py#L434)
|
||||
@@ -634,6 +643,7 @@
|
||||
- [backend/app/main.py](backend/app/main.py)
|
||||
|
||||
---
|
||||
|
||||
## 35) API client sends JSON and CSRF header for every request method
|
||||
- Where found:
|
||||
- [frontend/src/api/client.ts](frontend/src/api/client.ts)
|
||||
@@ -652,6 +662,7 @@
|
||||
- [backend/app/middleware/csrf.py](backend/app/middleware/csrf.py)
|
||||
|
||||
---
|
||||
|
||||
## 36) Polling continues when tab is not visible
|
||||
- Where found:
|
||||
- [frontend/src/hooks/usePolledData.ts](frontend/src/hooks/usePolledData.ts#L90)
|
||||
@@ -670,6 +681,7 @@
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 37) Multi-worker safety check depends on one environment variable
|
||||
- Where found:
|
||||
- [backend/app/startup.py](backend/app/startup.py#L61)
|
||||
@@ -687,6 +699,7 @@
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
|
||||
---
|
||||
|
||||
## 38) History archive query paths may need explicit indexing plan
|
||||
- Where found:
|
||||
- [backend/app/db.py](backend/app/db.py)
|
||||
@@ -707,6 +720,7 @@
|
||||
- https://www.sqlite.org/queryplanner.html
|
||||
|
||||
---
|
||||
|
||||
## 39) No explicit DI container strategy for backend service graph
|
||||
- Where found:
|
||||
- [backend/app/dependencies.py](backend/app/dependencies.py)
|
||||
@@ -725,6 +739,7 @@
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
|
||||
---
|
||||
|
||||
## 40) Frontend and backend observability are not aligned
|
||||
- Where found:
|
||||
- [backend/app/main.py](backend/app/main.py)
|
||||
@@ -741,4 +756,4 @@
|
||||
- Add observability and privacy-safe logging guidelines.
|
||||
- Doc references:
|
||||
- [Docs/Architekture.md](Docs/Architekture.md)
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
Reference in New Issue
Block a user