Files
orion/docs/architecture/frontend-detection.md
Samir Boulahtit aad18c27ab
Some checks failed
CI / ruff (push) Successful in 11s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
refactor: remove all backward compatibility code across 70 files
Clean up 28 backward compatibility instances identified in the codebase.
The app is not live, so all shims are replaced with the target architecture:

- Remove legacy Inventory.location column (use bin_location exclusively)
- Remove dashboard _extract_metric_value helper (use flat metrics dict)
- Remove legacy stat field duplicates (total_stores, total_imports, etc.)
- Remove 13 re-export shims and class aliases across modules
- Remove module-enabling JSON fallback (use PlatformModule junction table)
- Remove menu_to_legacy_format() conversion (return dataclasses directly)
- Remove title/description from MarketplaceProductBase schema
- Clean billing convenience method docstrings
- Clean test fixtures and backward-compat comments
- Add PlatformModule seeding to init_production.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:20:29 +01:00

243 lines
8.4 KiB
Markdown

# Frontend Detection Architecture
This document describes the centralized frontend detection system that identifies which frontend (ADMIN, STORE, STOREFRONT, or PLATFORM) a request targets.
## Overview
The application serves multiple frontends from a single codebase:
| Frontend | Description | Example URLs |
|----------|-------------|--------------|
| **ADMIN** | Platform administration | `/admin/*`, `/api/v1/admin/*`, `admin.omsflow.lu/*` |
| **STORE** | Store dashboard | `/store/*`, `/api/v1/store/*` |
| **STOREFRONT** | Customer-facing shop | `/storefront/*`, `/stores/*`, `orion.omsflow.lu/*` |
| **PLATFORM** | Marketing pages | `/`, `/pricing`, `/about` |
The `FrontendDetector` class provides centralized, consistent detection of which frontend a request targets.
## Architecture
### Components
```
┌─────────────────────────────────────────────────────────────────┐
│ Request Processing │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. PlatformContextMiddleware → Sets request.state.platform │
│ │
│ 2. StoreContextMiddleware → Sets request.state.store │
│ │
│ 3. FrontendTypeMiddleware → Sets request.state.frontend_type│
│ │ │
│ └──→ Uses FrontendDetector.detect() │
│ │
│ 4. LanguageMiddleware → Uses frontend_type for language │
│ │
│ 5. ThemeContextMiddleware → Uses frontend_type for theming │
│ │
│ 6. FastAPI Router → Handles request │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### Key Files
| File | Purpose |
|------|---------|
| `app/core/frontend_detector.py` | Centralized detection logic |
| `middleware/frontend_type.py` | Middleware that sets `request.state.frontend_type` |
| `app/modules/enums.py` | Defines `FrontendType` enum |
## FrontendType Enum
```python
class FrontendType(str, Enum):
PLATFORM = "platform" # Marketing pages (/, /pricing, /about)
ADMIN = "admin" # Admin panel (/admin/*)
STORE = "store" # Store dashboard (/store/*)
STOREFRONT = "storefront" # Customer shop (/storefront/*, /stores/*)
```
## Detection Priority
The `FrontendDetector` uses the following priority order:
```
1. Admin subdomain (admin.omsflow.lu) → ADMIN
2. Path-based detection:
- /admin/* or /api/v1/admin/* → ADMIN
- /store/* or /api/v1/store/* → STORE
- /storefront/*, /shop/*, /stores/* → STOREFRONT
- /api/v1/platform/* → PLATFORM
3. Store subdomain (orion.omsflow.lu) → STOREFRONT
4. Store context set by middleware → STOREFRONT
5. Default → PLATFORM
```
### Path Patterns
```python
# Admin paths
ADMIN_PATH_PREFIXES = ("/admin", "/api/v1/admin")
# Store dashboard paths
STORE_PATH_PREFIXES = ("/store/", "/api/v1/store")
# Storefront paths
STOREFRONT_PATH_PREFIXES = (
"/storefront",
"/api/v1/storefront",
"/shop", # Legacy support
"/api/v1/shop", # Legacy support
"/stores/", # Path-based store access
)
# Platform paths
PLATFORM_PATH_PREFIXES = ("/api/v1/platform",)
```
### Reserved Subdomains
These subdomains are NOT treated as store storefronts:
```python
RESERVED_SUBDOMAINS = {"www", "admin", "api", "store", "portal"}
```
## Usage
### In Middleware/Routes
```python
from middleware.frontend_type import get_frontend_type
from app.modules.enums import FrontendType
@router.get("/some-route")
async def some_route(request: Request):
frontend_type = get_frontend_type(request)
if frontend_type == FrontendType.ADMIN:
# Admin-specific logic
pass
elif frontend_type == FrontendType.STOREFRONT:
# Storefront-specific logic
pass
```
### Direct Detection (without request)
```python
from app.core.frontend_detector import FrontendDetector
from app.modules.enums import FrontendType
# Full detection
frontend_type = FrontendDetector.detect(
host="orion.omsflow.lu",
path="/products",
has_store_context=True
)
# Returns: FrontendType.STOREFRONT
# Convenience methods
if FrontendDetector.is_admin(host, path):
# Admin logic
pass
if FrontendDetector.is_storefront(host, path, has_store_context=True):
# Storefront logic
pass
```
## Detection Scenarios
### Development Mode (localhost)
| Request | Host | Path | Frontend |
|---------|------|------|----------|
| Admin page | localhost | /admin/stores | ADMIN |
| Admin API | localhost | /api/v1/admin/users | ADMIN |
| Store dashboard | localhost | /store/settings | STORE |
| Store API | localhost | /api/v1/store/products | STORE |
| Storefront | localhost | /storefront/products | STOREFRONT |
| Storefront (path-based) | localhost | /stores/orion/products | STOREFRONT |
| Marketing | localhost | /pricing | PLATFORM |
### Production Mode (domains)
| Request | Host | Path | Frontend |
|---------|------|------|----------|
| Admin subdomain | admin.omsflow.lu | /dashboard | ADMIN |
| Store subdomain | orion.omsflow.lu | /products | STOREFRONT |
| Custom domain | mybakery.lu | /products | STOREFRONT |
| Platform root | omsflow.lu | /pricing | PLATFORM |
## Request State
After `FrontendTypeMiddleware` runs, the following is available:
```python
request.state.frontend_type # FrontendType enum value
```
This is used by:
- `LanguageMiddleware` - to determine language resolution strategy
- `ErrorRenderer` - to select appropriate error templates
- `ExceptionHandler` - to redirect to correct login page
- Route handlers - for frontend-specific logic
## Testing
### Unit Tests
Tests are located in:
- `tests/unit/core/test_frontend_detector.py` - FrontendDetector tests
- `tests/unit/middleware/test_frontend_type.py` - Middleware tests
### Running Tests
```bash
# Run all frontend detection tests
pytest tests/unit/core/test_frontend_detector.py tests/unit/middleware/test_frontend_type.py -v
# Run with coverage
pytest tests/unit/core/test_frontend_detector.py tests/unit/middleware/test_frontend_type.py --cov=app.core.frontend_detector --cov=middleware.frontend_type
```
## Best Practices
### DO
1. **Use `get_frontend_type(request)`** in route handlers
2. **Use `FrontendDetector.detect()`** when you have host/path but no request
3. **Use convenience methods** like `is_admin()`, `is_storefront()` for boolean checks
4. **Import from the correct location:**
```python
from app.modules.enums import FrontendType
from middleware.frontend_type import get_frontend_type
from app.core.frontend_detector import FrontendDetector
```
### DON'T
1. **Don't duplicate path detection logic** - use FrontendDetector
2. **Don't hardcode path patterns** in middleware - they're centralized in FrontendDetector
3. **Don't check `request.state.context_type`** - use `request.state.frontend_type`
## Architecture Rules
These rules are enforced by `scripts/validate/validate_architecture.py`:
| Rule | Description |
|------|-------------|
| MID-001 | Use FrontendDetector for frontend detection |
| MID-002 | Don't hardcode path patterns in middleware |
| MID-003 | Use FrontendType enum, not RequestContext |
## Related Documentation
- [Middleware Stack](middleware.md) - Overall middleware architecture
- [Request Flow](request-flow.md) - How requests are processed
- [URL Routing](url-routing/overview.md) - URL structure and routing patterns
- [Multi-Tenant Architecture](multi-tenant.md) - Tenant detection and isolation