docs: make provider dependency chain explicit with documentation and tests

This addresses issue #19 by making the implicit provider dependency order
explicit and order-sensitive.

Changes:
1. Created PROVIDER_ORDER.md - comprehensive documentation explaining:
   - The provider hierarchy from outermost to innermost
   - Why each provider must be at its position
   - Order-sensitive pitfalls and what would break
   - Guidelines for adding new providers in the future

2. Added provider composition tests (providerComposition.test.tsx):
   - 13 comprehensive tests validating provider order and dependencies
   - Tests verify all providers mount correctly
   - Tests check that hooks only work inside correct providers
   - Tests validate async initialization (AuthProvider, TimezoneProvider)
   - Tests verify theme persistence and notification propagation

3. Updated App.tsx with inline documentation:
   - Added detailed provider order contract in JSDoc header
   - Inline comments explaining each provider's position
   - Reference to PROVIDER_ORDER.md for detailed rationale

4. Updated Web-Development.md:
   - Added new section 5.5 'Provider Order Contract'
   - Documents provider hierarchy and rationale
   - Links to comprehensive provider documentation
   - References regression test suite

All tests pass. TypeScript compilation succeeds. Build succeeds.
The provider order is now explicit and future refactors can validate
compliance through the regression test suite.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-28 09:30:22 +02:00
parent d10145e5d6
commit 2fea513c9c
5 changed files with 748 additions and 26 deletions

View File

@@ -1,4 +1,4 @@
## 18) Provider dependency chain is implicit
## 19) Provider dependency chain is implicit
- Where found:
- [frontend/src/App.tsx](frontend/src/App.tsx)
- Why this is needed:
@@ -17,7 +17,7 @@
---
## 19) Loading UX lacks progressive/skeleton states
## 20) Loading UX lacks progressive/skeleton states
- Where found:
- [frontend/src/pages](frontend/src/pages)
- Why this is needed:
@@ -35,7 +35,7 @@
---
## 20) Silent auth error swallow in fetch error utility
## 21) Silent auth error swallow in fetch error utility
- Where found:
- [frontend/src/utils/fetchError.ts](frontend/src/utils/fetchError.ts)
- Why this is needed:
@@ -53,7 +53,7 @@
---
## 21) Magic strings are scattered in frontend storage keys
## 22) Magic strings are scattered in frontend storage keys
- Where found:
- [frontend/src/providers/AuthProvider.tsx](frontend/src/providers/AuthProvider.tsx)
- [frontend/src/layouts/MainLayout.tsx](frontend/src/layouts/MainLayout.tsx)
@@ -73,7 +73,7 @@
---
## 22) No global cancellation policy on route transitions
## 23) No global cancellation policy on route transitions
- Where found:
- [frontend/src/hooks](frontend/src/hooks)
- Why this is needed:
@@ -91,7 +91,7 @@
---
## 23) API response wrapper shape is inconsistent
## 24) API response wrapper shape is inconsistent
- Where found:
- [backend/app/routers/dashboard.py](backend/app/routers/dashboard.py)
- [backend/app/routers/jails.py](backend/app/routers/jails.py)
@@ -112,7 +112,7 @@
---
## 24) No canonical snake_case/camelCase serialization policy
## 25) No canonical snake_case/camelCase serialization policy
- Where found:
- [backend/app/models/server.py](backend/app/models/server.py)
- [frontend/src/types/server.ts](frontend/src/types/server.ts)
@@ -132,7 +132,7 @@
---
## 25) Pagination contract is not standardized across endpoints
## 26) Pagination contract is not standardized across endpoints
- Where found:
- [backend/app/routers/dashboard.py](backend/app/routers/dashboard.py)
- [backend/app/routers/history.py](backend/app/routers/history.py)
@@ -152,7 +152,7 @@
---
## 26) Error response body shape is inconsistent
## 27) Error response body shape is inconsistent
- Where found:
- [backend/app/main.py](backend/app/main.py)
- [backend/app/routers](backend/app/routers)
@@ -172,7 +172,7 @@
---
## 27) Login failure delay can enable app-layer DoS
## 28) Login failure delay can enable app-layer DoS
- Where found:
- [backend/app/routers/auth.py](backend/app/routers/auth.py#L110)
- Why this is needed:
@@ -190,7 +190,7 @@
---
## 28) Blocklist URL validation has DNS-rebinding window
## 29) Blocklist URL validation has DNS-rebinding window
- Where found:
- [backend/app/utils/ip_utils.py](backend/app/utils/ip_utils.py#L145)
- [backend/app/services/blocklist_service.py](backend/app/services/blocklist_service.py#L81)
@@ -210,7 +210,7 @@
---
## 29) Setup persistence is non-atomic across DB contexts
## 30) Setup persistence is non-atomic across DB contexts
- Where found:
- [backend/app/services/setup_service.py](backend/app/services/setup_service.py)
- [backend/app/repositories/settings_repo.py](backend/app/repositories/settings_repo.py)
@@ -229,7 +229,7 @@
---
## 30) Fire-and-forget reschedule may fail silently
## 31) Fire-and-forget reschedule may fail silently
- Where found:
- [backend/app/tasks/blocklist_import.py](backend/app/tasks/blocklist_import.py#L108)
- Why this is needed:
@@ -247,7 +247,7 @@
---
## 31) RateLimiter cleanup function is not scheduled/used
## 32) RateLimiter cleanup function is not scheduled/used
- Where found:
- [backend/app/utils/rate_limiter.py](backend/app/utils/rate_limiter.py#L84)
- [backend/app/startup.py](backend/app/startup.py)
@@ -266,7 +266,7 @@
---
## 32) Trusted proxy configuration is hardcoded in auth router
## 33) Trusted proxy configuration is hardcoded in auth router
- Where found:
- [backend/app/routers/auth.py](backend/app/routers/auth.py#L46)
- [backend/app/utils/client_ip.py](backend/app/utils/client_ip.py)
@@ -286,7 +286,7 @@
---
## 33) Setup redirect allowlist uses broad prefix matching
## 34) Setup redirect allowlist uses broad prefix matching
- Where found:
- [backend/app/main.py](backend/app/main.py#L434)
- Why this is needed:
@@ -304,7 +304,7 @@
---
## 34) API client sends JSON and CSRF header for every request method
## 35) API client sends JSON and CSRF header for every request method
- Where found:
- [frontend/src/api/client.ts](frontend/src/api/client.ts)
- Why this is needed:
@@ -323,7 +323,7 @@
---
## 35) Polling continues when tab is not visible
## 36) Polling continues when tab is not visible
- Where found:
- [frontend/src/hooks/usePolledData.ts](frontend/src/hooks/usePolledData.ts#L90)
- [frontend/src/hooks/useBlocklistStatus.ts](frontend/src/hooks/useBlocklistStatus.ts)
@@ -342,7 +342,7 @@
---
## 36) Multi-worker safety check depends on one environment variable
## 37) Multi-worker safety check depends on one environment variable
- Where found:
- [backend/app/startup.py](backend/app/startup.py#L61)
- Why this is needed:
@@ -360,7 +360,7 @@
---
## 37) History archive query paths may need explicit indexing plan
## 38) History archive query paths may need explicit indexing plan
- Where found:
- [backend/app/db.py](backend/app/db.py)
- [backend/app/repositories/history_archive_repo.py](backend/app/repositories/history_archive_repo.py)
@@ -381,7 +381,7 @@
---
## 38) No explicit DI container strategy for backend service graph
## 39) No explicit DI container strategy for backend service graph
- Where found:
- [backend/app/dependencies.py](backend/app/dependencies.py)
- [backend/app/services](backend/app/services)
@@ -400,7 +400,7 @@
---
## 39) Frontend and backend observability are not aligned
## 40) Frontend and backend observability are not aligned
- Where found:
- [backend/app/main.py](backend/app/main.py)
- [frontend/src](frontend/src)