refactor: remove backward compatibility code for pre-launch baseline

Clean up accumulated backward-compat shims, deprecated wrappers, unused
aliases, and legacy code across the codebase. Since the platform is not
live yet, this establishes a clean baseline.

Changes:
- Delete deprecated middleware/context.py (RequestContext, get_request_context)
- Remove unused factory get_store_email_settings_service()
- Remove deprecated pagination_full macro, /admin/platform-homepage route
- Remove ConversationResponse, InvoiceSettings* unprefixed aliases
- Simplify celery_config.py (remove empty LEGACY_TASK_MODULES)
- Standardize billing exceptions: *Error aliases → *Exception names
- Consolidate duplicate TierNotFoundError/FeatureNotFoundError classes
- Remove deprecated is_admin_request() from Store/PlatformContextManager
- Remove is_platform_default field, MediaUploadResponse legacy flat fields
- Remove MediaItemResponse.url alias, update JS to use file_url
- Update all affected tests and documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 21:58:59 +01:00
parent 531487f5c9
commit 8968e7d9cd
31 changed files with 172 additions and 774 deletions

View File

@@ -172,41 +172,6 @@ if FrontendDetector.is_storefront(host, path, has_store_context=True):
| Custom domain | mybakery.lu | /products | STOREFRONT |
| Platform root | oms.lu | /pricing | PLATFORM |
## Migration from RequestContext
The previous `RequestContext` enum is deprecated. Here's the mapping:
| Old (RequestContext) | New (FrontendType) |
|---------------------|-------------------|
| `API` | Use `FrontendDetector.is_api_request()` + FrontendType |
| `ADMIN` | `FrontendType.ADMIN` |
| `STORE_DASHBOARD` | `FrontendType.STORE` |
| `SHOP` | `FrontendType.STOREFRONT` |
| `FALLBACK` | `FrontendType.PLATFORM` |
### Code Migration
**Before (deprecated):**
```python
from middleware.context import RequestContext, get_request_context
context = get_request_context(request)
if context == RequestContext.SHOP:
# Storefront logic
pass
```
**After:**
```python
from middleware.frontend_type import get_frontend_type
from app.modules.enums import FrontendType
frontend_type = get_frontend_type(request)
if frontend_type == FrontendType.STOREFRONT:
# Storefront logic
pass
```
## Request State
After `FrontendTypeMiddleware` runs, the following is available:
@@ -255,10 +220,9 @@ pytest tests/unit/core/test_frontend_detector.py tests/unit/middleware/test_fron
### DON'T
1. **Don't use `RequestContext`** - it's deprecated
2. **Don't duplicate path detection logic** - use FrontendDetector
3. **Don't hardcode path patterns** in middleware - they're centralized in FrontendDetector
4. **Don't check `request.state.context_type`** - use `request.state.frontend_type`
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

View File

@@ -186,19 +186,19 @@ All middleware components follow a consistent naming pattern for maintainability
```
✅ Good:
middleware/logging.py
middleware/context.py
middleware/store_context.py
middleware/auth.py
❌ Avoid:
middleware/logging_middleware.py
middleware/context_middleware.py
middleware/store_context_middleware.py
middleware/auth_middleware.py
```
**Rationale**:
- Keeps names concise and consistent
- Follows Django, Flask, and FastAPI conventions
- Makes imports cleaner: `from middleware.logging import LoggingMiddleware`
- Makes imports cleaner: `from middleware.store_context import StoreContextMiddleware`
- Reduces redundancy (the `middleware/` directory already indicates the purpose)
#### Test File Naming: Mirror the Source File
@@ -206,10 +206,9 @@ middleware/auth_middleware.py
Test files directly mirror the middleware filename with a `test_` prefix:
```
middleware/logging.py → tests/unit/middleware/test_logging.py
middleware/context.py → tests/unit/middleware/test_context.py
middleware/auth.py → tests/unit/middleware/test_auth.py
middleware/logging.py → tests/unit/middleware/test_logging.py
middleware/store_context.py → tests/unit/middleware/test_store_context.py
middleware/auth.py → tests/unit/middleware/test_auth.py
```
#### One Component Per File
@@ -229,19 +228,15 @@ class FrontendTypeMiddleware: # ASGI wrapper for frontend detection
class AuthManager: # Authentication logic
```
> **Note**: The old `middleware/context.py` with `ContextMiddleware` and `RequestContext` is deprecated.
> Use `FrontendTypeMiddleware` and `FrontendType` enum instead.
> See [Frontend Detection Architecture](frontend-detection.md) for migration guide.
#### One Test File Per Component
Follow the Single Responsibility Principle - each test file tests exactly one component:
```
✅ Good:
tests/unit/middleware/test_logging.py # Tests only LoggingMiddleware
tests/unit/middleware/test_context.py # Tests only ContextManager/Middleware
tests/unit/middleware/test_decorators.py # Tests only rate_limit decorator
tests/unit/middleware/test_logging.py # Tests only LoggingMiddleware
tests/unit/middleware/test_store_context.py # Tests only StoreContextManager/Middleware
tests/unit/middleware/test_decorators.py # Tests only rate_limit decorator
❌ Avoid:
tests/unit/middleware/test_all_middleware.py # Tests multiple components
@@ -261,12 +256,12 @@ When importing middleware components, use explicit imports:
```python
# ✅ Preferred - Explicit and clear
from middleware.logging import LoggingMiddleware
from middleware.context import ContextManager, RequestContext
from middleware.store_context import StoreContextManager
from middleware.auth import AuthManager
# ❌ Avoid - Less clear
from middleware import logging_middleware
from middleware import context_middleware
from middleware import store_context_middleware
```
**See**: [Complete Naming Conventions Guide](../development/naming-conventions.md) for project-wide standards.

View File

@@ -1,7 +1,7 @@
# Error Handling System - Developer Documentation
**Version:** 1.0.0
**Last Updated:** 2025
**Version:** 1.0.0
**Last Updated:** 2025
**Status:** Phase 1 Complete (Admin), Phase 2-3 Pending (Store, Shop)
---
@@ -120,12 +120,13 @@ class RequestContext(str, Enum):
**Usage:**
```python
from middleware.context_middleware import get_request_context, RequestContext
from middleware.frontend_type import get_frontend_type
from app.modules.enums import FrontendType
def my_handler(request: Request):
context = get_request_context(request)
if context == RequestContext.ADMIN:
frontend_type = get_frontend_type(request)
if frontend_type == FrontendType.ADMIN:
# Handle admin-specific logic
pass
```
@@ -285,7 +286,7 @@ API endpoints MUST always return JSON, even if the client sends `Accept: text/ht
### 2. HTML Error Pages (HTML Page Requests)
**When:**
**When:**
- NOT an API request
- GET request
- Accept header includes `text/html`
@@ -309,7 +310,7 @@ API endpoints MUST always return JSON, even if the client sends `Accept: text/ht
### 3. Login Redirects (401 Unauthorized)
**When:**
**When:**
- HTML page request
- 401 status code
@@ -628,7 +629,7 @@ message="SELECT * FROM products WHERE id=123 returned 0 rows"
error_code="PRODUCT_OUT_OF_STOCK"
error_code="PAYMENT_PROCESSING_FAILED"
# Bad
# Bad
error_code="error1"
error_code="ProductOutOfStockException"
```
@@ -789,25 +790,18 @@ raise ServiceUnavailableException("Maintenance in progress")
**Test Context Detection:**
```python
# tests/test_context_middleware.py
from middleware.context_middleware import ContextManager, RequestContext
from fastapi import Request
# tests/test_frontend_detector.py
from app.core.frontend_detector import FrontendDetector
from app.modules.enums import FrontendType
def test_api_context_detection():
request = MockRequest(path="/api/v1/stores")
context = ContextManager.detect_context(request)
assert context == RequestContext.API
def test_admin_detection():
assert FrontendDetector.is_admin("localhost", "/admin/dashboard") is True
def test_admin_context_detection():
request = MockRequest(path="/admin/dashboard")
context = ContextManager.detect_context(request)
assert context == RequestContext.ADMIN
def test_shop_context_detection():
request = MockRequest(path="/products")
request.state.store = MockStore(id=1, name="Test Store")
context = ContextManager.detect_context(request)
assert context == RequestContext.SHOP
def test_storefront_detection():
frontend_type = FrontendDetector.detect(
host="localhost", path="/storefront/products", has_store_context=True
)
assert frontend_type == FrontendType.STOREFRONT
```
**Test Error Renderer:**
@@ -966,7 +960,7 @@ def test_error_page_performance(client: TestClient):
)
assert response.status_code == 404
duration = time.time() - start
# Should complete in reasonable time (< 5 seconds)
assert duration < 5.0
print(f"100 error pages rendered in {duration:.2f}s")
@@ -1196,45 +1190,26 @@ if context_type == RequestContext.SHOP:
## API Reference
### Context Detection
### Frontend Type Detection
#### `ContextManager.detect_context(request: Request) -> RequestContext`
#### `get_frontend_type(request: Request) -> FrontendType`
Detects the request context type.
Gets the frontend type for the current request.
**Parameters:**
- `request` (Request): FastAPI request object
**Returns:**
- RequestContext enum value
- FrontendType enum value
**Example:**
```python
from middleware.context_middleware import ContextManager, RequestContext
context = ContextManager.detect_context(request)
if context == RequestContext.ADMIN:
# Handle admin-specific logic
pass
```
#### `get_request_context(request: Request) -> RequestContext`
Helper function to get current request context from request state.
**Parameters:**
- `request` (Request): FastAPI request object
**Returns:**
- RequestContext enum value (defaults to FALLBACK if not set)
**Example:**
```python
from middleware.context_middleware import get_request_context, RequestContext
from middleware.frontend_type import get_frontend_type
from app.modules.enums import FrontendType
def my_handler(request: Request):
context = get_request_context(request)
return {"context": context.value}
frontend_type = get_frontend_type(request)
return {"frontend_type": frontend_type.value}
```
### Error Rendering
@@ -1398,28 +1373,28 @@ STATUS_CODE_MESSAGES = {
## Best Practices Summary
### DO:
✅ Use specific exception classes for different error scenarios
✅ Provide clear, user-friendly error messages
✅ Include relevant details in the `details` dictionary
✅ Use consistent error codes across the application
✅ Test both API and HTML responses
✅ Keep error templates simple and accessible
✅ Use debug mode responsibly (admin only)
✅ Follow the template inheritance pattern
✅ Document any new exception types
✅ Test error pages manually in browsers
✅ Use specific exception classes for different error scenarios
✅ Provide clear, user-friendly error messages
✅ Include relevant details in the `details` dictionary
✅ Use consistent error codes across the application
✅ Test both API and HTML responses
✅ Keep error templates simple and accessible
✅ Use debug mode responsibly (admin only)
✅ Follow the template inheritance pattern
✅ Document any new exception types
✅ Test error pages manually in browsers
### DON'T:
❌ Expose sensitive information in error messages
❌ Use generic exceptions for domain-specific errors
❌ Return HTML for API endpoints
❌ Skip the Accept header check
❌ Hardcode HTML in exception handlers
❌ Forget to add fallback templates
❌ Show technical details to customers
❌ Use complex JavaScript in error pages
❌ Forget to test 401 redirects
❌ Mix API and page response logic
❌ Expose sensitive information in error messages
❌ Use generic exceptions for domain-specific errors
❌ Return HTML for API endpoints
❌ Skip the Accept header check
❌ Hardcode HTML in exception handlers
❌ Forget to add fallback templates
❌ Show technical details to customers
❌ Use complex JavaScript in error pages
❌ Forget to test 401 redirects
❌ Mix API and page response logic
---
@@ -1435,7 +1410,7 @@ For questions or issues with the error handling system:
---
**Document Version:** 1.0.0
**Last Updated:** 2025
**Maintained By:** [Your team name]
**Document Version:** 1.0.0
**Last Updated:** 2025
**Maintained By:** [Your team name]
**Next Review:** After Phase 2 & 3 completion

View File

@@ -160,14 +160,14 @@ Response:
"slug": "about",
"title": "About Wizamart", // Store override
"is_store_override": true,
"is_platform_default": false
"is_platform_page": false
},
{
"id": 2,
"slug": "shipping",
"title": "Shipping Information", // Platform default
"is_store_override": false,
"is_platform_default": true
"is_platform_page": true
}
]
```

View File

@@ -582,11 +582,11 @@ Custom exceptions for billing operations (`app/modules/billing/exceptions.py`):
| Exception | HTTP Status | Description |
|-----------|-------------|-------------|
| `PaymentSystemNotConfiguredError` | 503 | Stripe not configured |
| `TierNotFoundError` | 404 | Invalid tier code |
| `StripePriceNotConfiguredError` | 400 | No Stripe price for tier |
| `NoActiveSubscriptionError` | 400 | Operation requires subscription |
| `SubscriptionNotCancelledError` | 400 | Cannot reactivate active subscription |
| `PaymentSystemNotConfiguredException` | 503 | Stripe not configured |
| `TierNotFoundException` | 404 | Invalid tier code |
| `StripePriceNotConfiguredException` | 400 | No Stripe price for tier |
| `NoActiveSubscriptionException` | 400 | Operation requires subscription |
| `SubscriptionNotCancelledException` | 400 | Cannot reactivate active subscription |
## Testing