refactor(arch): revamp API-003 rule for exception handling pattern
Change API-003 from "must catch exceptions" to "must NOT raise HTTPException directly". This aligns with the architecture where: - Domain exceptions bubble up to global exception handler - Endpoints should NOT catch and convert exceptions - HTTPException should only be used by the global handler Also adds: - EXC-004: Domain exceptions must inherit from WizamartException - EXC-005: Global exception handler must be registered 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ principles:
|
||||
description: "Use Pydantic models for request/response validation. Use SQLAlchemy models for database."
|
||||
|
||||
- name: "Proper Exception Handling"
|
||||
description: "Services throw domain exceptions. Routes catch and convert to HTTPException."
|
||||
description: "Services throw domain exceptions. Global handler converts to HTTP responses. Endpoints do NOT catch or raise HTTPException."
|
||||
|
||||
- name: "Multi-Tenancy"
|
||||
description: "All queries must be scoped to vendor_id. No cross-vendor data access."
|
||||
@@ -66,14 +66,19 @@ api_endpoint_rules:
|
||||
- "db.query("
|
||||
|
||||
- id: "API-003"
|
||||
name: "Endpoint must catch service exceptions and convert to HTTPException"
|
||||
name: "Endpoint must NOT raise HTTPException directly"
|
||||
severity: "error"
|
||||
description: |
|
||||
API endpoints must catch domain exceptions from services and convert them
|
||||
to appropriate HTTPException with proper status codes.
|
||||
API endpoints should NOT raise HTTPException directly. Instead, let domain
|
||||
exceptions bubble up to the global exception handler which converts them
|
||||
to appropriate HTTP responses. This ensures consistent error formatting
|
||||
and centralized error handling.
|
||||
pattern:
|
||||
file_pattern: "app/api/v1/**/*.py"
|
||||
check: "exception_handling"
|
||||
anti_patterns:
|
||||
- "raise HTTPException"
|
||||
exceptions:
|
||||
- "app/exceptions/handler.py" # Handler is allowed to use HTTPException
|
||||
|
||||
- id: "API-004"
|
||||
name: "Endpoint must have proper authentication/authorization"
|
||||
@@ -250,6 +255,32 @@ exception_rules:
|
||||
- "logger.error"
|
||||
- "exc_info=True"
|
||||
|
||||
- id: "EXC-004"
|
||||
name: "Domain exceptions must inherit from WizamartException"
|
||||
severity: "error"
|
||||
description: |
|
||||
All custom domain exceptions must inherit from WizamartException (or its
|
||||
subclasses like ResourceNotFoundException, ValidationException, etc.).
|
||||
This ensures the global exception handler catches and converts them properly.
|
||||
pattern:
|
||||
file_pattern: "app/exceptions/**/*.py"
|
||||
required_base_class: "WizamartException"
|
||||
example_good: |
|
||||
class VendorNotFoundException(ResourceNotFoundException):
|
||||
def __init__(self, vendor_code: str):
|
||||
super().__init__(resource_type="Vendor", identifier=vendor_code)
|
||||
|
||||
- id: "EXC-005"
|
||||
name: "Exception handler must be registered"
|
||||
severity: "error"
|
||||
description: |
|
||||
The global exception handler must be set up in app initialization to
|
||||
catch WizamartException and convert to HTTP responses.
|
||||
pattern:
|
||||
file_pattern: "app/main.py"
|
||||
required_patterns:
|
||||
- "setup_exception_handlers"
|
||||
|
||||
# ============================================================================
|
||||
# NAMING CONVENTION RULES
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user