feat: add module definition completeness validation and permissions

Add new validation rules MOD-020 to MOD-023 for module definition
completeness and standardize permissions across all modules.

Changes:
- Add MOD-020: Module definitions must have required attributes
- Add MOD-021: Modules with menus should have features
- Add MOD-022: Feature modules should have permissions
- Add MOD-023: Modules with routers should use get_*_with_routers pattern

Module permissions added:
- analytics: view, export, manage_dashboards
- billing: view_tiers, manage_tiers, view_subscriptions, manage_subscriptions, view_invoices
- cart: view, manage
- checkout: view_settings, manage_settings
- cms: view_pages, manage_pages, view_media, manage_media, manage_themes
- loyalty: view_programs, manage_programs, view_rewards, manage_rewards
- marketplace: view_integration, manage_integration, sync_products
- messaging: view_messages, send_messages, manage_templates
- payments: view_gateways, manage_gateways, view_transactions

Module improvements:
- Complete cart module with features and permissions
- Complete checkout module with features and permissions
- Add features to catalog module
- Add version to cms module
- Fix loyalty platform_router attachment
- Add path definitions to payments module
- Remove empty scheduled_tasks from dev_tools module

Documentation:
- Update module-system.md with new validation rules
- Update architecture-rules.md with MOD-020 to MOD-023

Tests:
- Add unit tests for module definition completeness
- Add tests for permission structure validation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-02 18:23:04 +01:00
parent 30a5c75e74
commit 967f08e4ba
50 changed files with 1014 additions and 66 deletions

View File

@@ -551,3 +551,175 @@ module_rules:
- "__init__.py"
- "base.py"
- "auth.py"
# =========================================================================
# Module Definition Completeness Rules
# =========================================================================
- id: "MOD-020"
name: "Module definition must have required attributes"
severity: "warning"
description: |
Module definitions should include at minimum:
- code: Module identifier
- name: Human-readable name
- description: What the module does
- version: Semantic version
- features: List of features (unless infrastructure module)
- permissions: Access control definitions (unless internal or storefront-only)
EXAMPLES (incomplete):
module = ModuleDefinition(
code="cart",
name="Shopping Cart",
description="...",
version="1.0.0",
# Missing features and permissions
)
EXAMPLES (complete):
module = ModuleDefinition(
code="orders",
name="Order Management",
description="...",
version="1.0.0",
features=["order_management", "fulfillment_tracking"],
permissions=[
PermissionDefinition(id="orders.view", ...),
],
)
EXCEPTIONS:
- is_internal=True modules may skip permissions
- Infrastructure modules (is_core=True with no UI) may skip features
- Storefront-only modules (session-based, no admin UI) may have minimal permissions
WHY THIS MATTERS:
- Consistency: All modules follow the same definition pattern
- RBAC: Permissions enable proper role-based access control
- Feature flags: Features enable selective module functionality
pattern:
file_pattern: "app/modules/*/definition.py"
required_attributes:
- "code"
- "name"
- "description"
- "version"
- id: "MOD-021"
name: "Modules with menus should have features"
severity: "warning"
description: |
If a module defines menu items or menu sections, it should also
define features to describe what functionality it provides.
Menus indicate the module has UI and user-facing functionality,
which should be documented as features.
WRONG:
module = ModuleDefinition(
code="billing",
menus={
FrontendType.ADMIN: [...],
},
# Missing features list
)
RIGHT:
module = ModuleDefinition(
code="billing",
features=[
"subscription_management",
"billing_history",
"invoice_generation",
],
menus={
FrontendType.ADMIN: [...],
},
)
WHY THIS MATTERS:
- Documentation: Features describe what the module does
- Feature flags: Enables/disables specific functionality
- Consistency: All UI modules describe their capabilities
pattern:
file_pattern: "app/modules/*/definition.py"
validates:
- "menus -> features"
- id: "MOD-022"
name: "Feature modules should have permissions"
severity: "info"
description: |
Modules with features should define permissions unless:
- is_internal=True (internal tools like dev_tools)
- Storefront-only module (session-based, no authentication)
Permissions enable role-based access control (RBAC) for module
functionality.
EXCEPTIONS:
- is_internal=True modules (internal tooling)
- Modules with only storefront features (cart, checkout without admin UI)
- Infrastructure modules (contracts, core utilities)
EXAMPLE:
module = ModuleDefinition(
code="billing",
features=["subscription_management", ...],
permissions=[
PermissionDefinition(
id="billing.view_subscriptions",
label_key="billing.permissions.view_subscriptions",
description_key="billing.permissions.view_subscriptions_desc",
category="billing",
),
],
)
WHY THIS MATTERS:
- RBAC: Permissions enable proper access control
- Security: Restrict who can access module features
- Consistency: All feature modules define their access rules
pattern:
file_pattern: "app/modules/*/definition.py"
validates:
- "features -> permissions"
exceptions:
- "is_internal=True"
- id: "MOD-023"
name: "Modules with routers should use get_*_with_routers pattern"
severity: "info"
description: |
Modules that define routers (admin_router, vendor_router, etc.)
should follow the lazy import pattern with a dedicated function:
def get_{module}_module_with_routers() -> ModuleDefinition:
This pattern:
1. Avoids circular imports during module initialization
2. Ensures routers are attached at the right time
3. Provides a consistent API for router registration
WRONG:
# Direct router assignment at module level
module.admin_router = admin_router
RIGHT:
def _get_admin_router():
from app.modules.orders.routes.admin import admin_router
return admin_router
def get_orders_module_with_routers() -> ModuleDefinition:
orders_module.admin_router = _get_admin_router()
return orders_module
WHY THIS MATTERS:
- Prevents circular imports
- Consistent pattern across all modules
- Clear API for module registration
pattern:
file_pattern: "app/modules/*/definition.py"
validates:
- "router imports -> get_*_with_routers function"