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

@@ -6,7 +6,7 @@ Defines the analytics module including its features, menu items,
route configurations, and self-contained module settings.
"""
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition
from app.modules.enums import FrontendType
@@ -37,6 +37,27 @@ analytics_module = ModuleDefinition(
"export_reports", # Export to CSV/Excel
"usage_metrics", # Usage and performance metrics
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="analytics.view",
label_key="analytics.permissions.view",
description_key="analytics.permissions.view_desc",
category="analytics",
),
PermissionDefinition(
id="analytics.export",
label_key="analytics.permissions.export",
description_key="analytics.permissions.export_desc",
category="analytics",
),
PermissionDefinition(
id="analytics.manage_dashboards",
label_key="analytics.permissions.manage_dashboards",
description_key="analytics.permissions.manage_dashboards_desc",
category="analytics",
),
],
menu_items={
FrontendType.ADMIN: [
# Analytics appears in dashboard for admin

View File

@@ -6,7 +6,7 @@ Defines the billing module including its features, menu items,
route configurations, and scheduled tasks.
"""
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, ScheduledTask
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition, ScheduledTask
from app.modules.enums import FrontendType
@@ -42,6 +42,39 @@ billing_module = ModuleDefinition(
"trial_management", # Manage vendor trial periods
"limit_overrides", # Override tier limits per vendor
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="billing.view_tiers",
label_key="billing.permissions.view_tiers",
description_key="billing.permissions.view_tiers_desc",
category="billing",
),
PermissionDefinition(
id="billing.manage_tiers",
label_key="billing.permissions.manage_tiers",
description_key="billing.permissions.manage_tiers_desc",
category="billing",
),
PermissionDefinition(
id="billing.view_subscriptions",
label_key="billing.permissions.view_subscriptions",
description_key="billing.permissions.view_subscriptions_desc",
category="billing",
),
PermissionDefinition(
id="billing.manage_subscriptions",
label_key="billing.permissions.manage_subscriptions",
description_key="billing.permissions.manage_subscriptions_desc",
category="billing",
),
PermissionDefinition(
id="billing.view_invoices",
label_key="billing.permissions.view_invoices",
description_key="billing.permissions.view_invoices_desc",
category="billing",
),
],
menu_items={
FrontendType.ADMIN: [
"subscription-tiers", # Manage tier definitions

View File

@@ -6,7 +6,8 @@ This module provides shopping cart functionality for customer storefronts.
It is session-based and does not require customer authentication.
"""
from app.modules.base import ModuleDefinition
from app.modules.base import ModuleDefinition, PermissionDefinition
module = ModuleDefinition(
code="cart",
@@ -15,4 +16,29 @@ module = ModuleDefinition(
version="1.0.0",
is_self_contained=True,
requires=["inventory"], # Checks inventory availability
features=[
"cart_management", # Basic cart CRUD operations
"cart_persistence", # Session and database persistence
"cart_item_operations", # Add, update, remove items
"shipping_calculation", # Calculate shipping for cart
"promotion_application", # Apply discounts and promotions
],
# Note: Cart is primarily session-based storefront functionality.
# These permissions are for admin access to cart data/settings.
permissions=[
PermissionDefinition(
id="cart.view",
label_key="cart.permissions.view",
description_key="cart.permissions.view_desc",
category="cart",
),
PermissionDefinition(
id="cart.manage",
label_key="cart.permissions.manage",
description_key="cart.permissions.manage_desc",
category="cart",
),
],
# Cart is storefront-only - no admin/vendor menus needed
menu_items={},
)

View File

@@ -16,6 +16,14 @@ module = ModuleDefinition(
version="1.0.0",
is_self_contained=True,
requires=["inventory"],
features=[
"product_catalog", # Core product catalog functionality
"product_search", # Search and filtering
"product_variants", # Product variants management
"product_categories", # Category organization
"product_attributes", # Custom attributes
"product_import_export", # Bulk import/export
],
# Module-driven permissions
permissions=[
PermissionDefinition(

View File

@@ -1,7 +1,13 @@
# app/modules/checkout/definition.py
"""Checkout module definition."""
"""
Checkout module definition.
This module handles the checkout flow, converting cart contents into orders.
Orchestrates payment processing and order creation.
"""
from app.modules.base import ModuleDefinition, PermissionDefinition
from app.modules.base import ModuleDefinition
module = ModuleDefinition(
code="checkout",
@@ -10,4 +16,29 @@ module = ModuleDefinition(
version="1.0.0",
is_self_contained=True,
requires=["cart", "orders", "payments", "customers"],
features=[
"checkout_flow", # Multi-step checkout process
"order_creation", # Create orders from cart
"payment_processing", # Payment integration during checkout
"checkout_validation", # Address, inventory, payment validation
"guest_checkout", # Allow checkout without account
],
# Note: Checkout is primarily storefront functionality.
# These permissions are for admin access to checkout settings.
permissions=[
PermissionDefinition(
id="checkout.view_settings",
label_key="checkout.permissions.view_settings",
description_key="checkout.permissions.view_settings_desc",
category="checkout",
),
PermissionDefinition(
id="checkout.manage_settings",
label_key="checkout.permissions.manage_settings",
description_key="checkout.permissions.manage_settings_desc",
category="checkout",
),
],
# Checkout is storefront-only - no admin/vendor menus needed
menu_items={},
)

View File

@@ -12,7 +12,7 @@ This is a self-contained module with:
- Templates: app.modules.cms.templates (namespaced as cms/)
"""
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition
from app.modules.enums import FrontendType
@@ -35,6 +35,7 @@ cms_module = ModuleDefinition(
code="cms",
name="Content Management",
description="Content pages, media library, and vendor themes.",
version="1.0.0",
features=[
"cms_basic", # Basic page editing
"cms_custom_pages", # Custom page creation
@@ -43,6 +44,39 @@ cms_module = ModuleDefinition(
"cms_seo", # SEO tools
"media_library", # Media file management
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="cms.view_pages",
label_key="cms.permissions.view_pages",
description_key="cms.permissions.view_pages_desc",
category="cms",
),
PermissionDefinition(
id="cms.manage_pages",
label_key="cms.permissions.manage_pages",
description_key="cms.permissions.manage_pages_desc",
category="cms",
),
PermissionDefinition(
id="cms.view_media",
label_key="cms.permissions.view_media",
description_key="cms.permissions.view_media_desc",
category="cms",
),
PermissionDefinition(
id="cms.manage_media",
label_key="cms.permissions.manage_media",
description_key="cms.permissions.manage_media_desc",
category="cms",
),
PermissionDefinition(
id="cms.manage_themes",
label_key="cms.permissions.manage_themes",
description_key="cms.permissions.manage_themes_desc",
category="cms",
),
],
menu_items={
FrontendType.ADMIN: [
"content-pages", # Platform content pages

View File

@@ -85,20 +85,8 @@ dev_tools_module = ModuleDefinition(
schemas_path="app.modules.dev_tools.schemas",
exceptions_path="app.modules.dev_tools.exceptions",
tasks_path="app.modules.dev_tools.tasks",
# =========================================================================
# Scheduled Tasks
# =========================================================================
# Note: Code quality and test tasks are on-demand, not scheduled.
# If scheduled scans are desired, they can be added here:
# scheduled_tasks=[
# ScheduledTask(
# name="dev_tools.nightly_code_scan",
# task="app.modules.dev_tools.tasks.code_quality.execute_code_quality_scan",
# schedule="0 2 * * *", # Daily at 02:00
# options={"queue": "long_running"},
# ),
# ],
scheduled_tasks=[],
# If scheduled scans are desired, add ScheduledTask entries here.
)

View File

@@ -6,7 +6,7 @@ Defines the loyalty module including its features, menu items,
route configurations, and scheduled tasks.
"""
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, ScheduledTask
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition, ScheduledTask
from app.modules.enums import FrontendType
@@ -24,11 +24,11 @@ def _get_vendor_router():
return vendor_router
def _get_public_router():
"""Lazy import of public router to avoid circular imports."""
from app.modules.loyalty.routes.api.public import public_router
def _get_platform_router():
"""Lazy import of platform router to avoid circular imports."""
from app.modules.loyalty.routes.api.platform import platform_router
return public_router
return platform_router
# Loyalty module definition
@@ -60,6 +60,33 @@ loyalty_module = ModuleDefinition(
"loyalty_stats", # Dashboard statistics
"loyalty_reports", # Transaction reports
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="loyalty.view_programs",
label_key="loyalty.permissions.view_programs",
description_key="loyalty.permissions.view_programs_desc",
category="loyalty",
),
PermissionDefinition(
id="loyalty.manage_programs",
label_key="loyalty.permissions.manage_programs",
description_key="loyalty.permissions.manage_programs_desc",
category="loyalty",
),
PermissionDefinition(
id="loyalty.view_rewards",
label_key="loyalty.permissions.view_rewards",
description_key="loyalty.permissions.view_rewards_desc",
category="loyalty",
),
PermissionDefinition(
id="loyalty.manage_rewards",
label_key="loyalty.permissions.manage_rewards",
description_key="loyalty.permissions.manage_rewards_desc",
category="loyalty",
),
],
menu_items={
FrontendType.ADMIN: [
"loyalty-programs", # View all programs
@@ -168,8 +195,7 @@ def get_loyalty_module_with_routers() -> ModuleDefinition:
"""
loyalty_module.admin_router = _get_admin_router()
loyalty_module.vendor_router = _get_vendor_router()
# Note: public_router needs to be attached separately in main.py
# as it doesn't require authentication
loyalty_module.platform_router = _get_platform_router()
return loyalty_module

View File

@@ -8,7 +8,7 @@ dependencies, route configurations, and scheduled tasks.
Note: This module requires the inventory module to be enabled.
"""
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, ScheduledTask
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition, ScheduledTask
from app.modules.enums import FrontendType
@@ -43,6 +43,27 @@ marketplace_module = ModuleDefinition(
"order_import", # Import orders from marketplace
"marketplace_analytics", # Marketplace performance metrics
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="marketplace.view_integration",
label_key="marketplace.permissions.view_integration",
description_key="marketplace.permissions.view_integration_desc",
category="marketplace",
),
PermissionDefinition(
id="marketplace.manage_integration",
label_key="marketplace.permissions.manage_integration",
description_key="marketplace.permissions.manage_integration_desc",
category="marketplace",
),
PermissionDefinition(
id="marketplace.sync_products",
label_key="marketplace.permissions.sync_products",
description_key="marketplace.permissions.sync_products_desc",
category="marketplace",
),
],
menu_items={
FrontendType.ADMIN: [
"marketplace-letzshop", # Marketplace monitoring

View File

@@ -6,7 +6,7 @@ Defines the messaging module including its features, menu items,
route configurations, and self-contained module settings.
"""
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition
from app.modules.base import MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition
from app.modules.enums import FrontendType
@@ -37,6 +37,27 @@ messaging_module = ModuleDefinition(
"message_attachments", # File attachments
"admin_notifications", # System admin notifications
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="messaging.view_messages",
label_key="messaging.permissions.view_messages",
description_key="messaging.permissions.view_messages_desc",
category="messaging",
),
PermissionDefinition(
id="messaging.send_messages",
label_key="messaging.permissions.send_messages",
description_key="messaging.permissions.send_messages_desc",
category="messaging",
),
PermissionDefinition(
id="messaging.manage_templates",
label_key="messaging.permissions.manage_templates",
description_key="messaging.permissions.manage_templates_desc",
category="messaging",
),
],
menu_items={
FrontendType.ADMIN: [
"messages", # Admin messages

View File

@@ -15,7 +15,7 @@ This separation allows:
3. Orders without billing (customer payments only)
"""
from app.modules.base import ModuleDefinition
from app.modules.base import ModuleDefinition, PermissionDefinition
from app.modules.enums import FrontendType
@@ -51,6 +51,27 @@ payments_module = ModuleDefinition(
"bank_transfer", # Bank transfer support
"transaction_history", # Transaction records
],
# Module-driven permissions
permissions=[
PermissionDefinition(
id="payments.view_gateways",
label_key="payments.permissions.view_gateways",
description_key="payments.permissions.view_gateways_desc",
category="payments",
),
PermissionDefinition(
id="payments.manage_gateways",
label_key="payments.permissions.manage_gateways",
description_key="payments.permissions.manage_gateways_desc",
category="payments",
),
PermissionDefinition(
id="payments.view_transactions",
label_key="payments.permissions.view_transactions",
description_key="payments.permissions.view_transactions_desc",
category="payments",
),
],
menu_items={
FrontendType.ADMIN: [
"payment-gateways", # Configure payment gateways
@@ -61,7 +82,14 @@ payments_module = ModuleDefinition(
},
is_core=False,
is_internal=False,
is_self_contained=True, # Enable auto-discovery from routes/api/
# =========================================================================
# Self-Contained Module Configuration
# =========================================================================
is_self_contained=True,
services_path="app.modules.payments.services",
models_path="app.modules.payments.models",
schemas_path="app.modules.payments.schemas",
exceptions_path="app.modules.payments.exceptions",
)