diff --git a/docs/architecture/menu-management.md b/docs/architecture/menu-management.md new file mode 100644 index 00000000..3355a3aa --- /dev/null +++ b/docs/architecture/menu-management.md @@ -0,0 +1,403 @@ +# Menu Management Architecture + +The Wizamart platform provides a flexible menu system that supports per-platform and per-user customization. This document explains the menu architecture, configuration options, and how menus integrate with the module system. + +## Overview + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ MENU REGISTRY (Source of Truth) │ +│ app/config/menu_registry.py │ +│ │ +│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │ +│ │ ADMIN_MENU_REGISTRY │ │ VENDOR_MENU_REGISTRY │ │ +│ │ (Admin panel menus) │ │ (Vendor dashboard menus) │ │ +│ └─────────────────────────────┘ └─────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ VISIBILITY CONFIGURATION │ +│ models/database/admin_menu_config.py │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ AdminMenuConfig Table │ │ +│ │ Stores visibility overrides (hidden items only) │ │ +│ │ - Platform scope: applies to platform admins/vendors │ │ +│ │ - User scope: applies to specific super admin │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ FILTERED MENU OUTPUT │ +│ │ +│ Registry - Hidden Items - Disabled Modules = Visible Menu Items │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +## Frontend Types + +The system supports two distinct frontend types: + +| Frontend | Description | Users | +|----------|-------------|-------| +| `ADMIN` | Admin panel | Super admins, platform admins | +| `VENDOR` | Vendor dashboard | Vendors on a platform | + +```python +from models.database.admin_menu_config import FrontendType + +# Use in code +FrontendType.ADMIN # "admin" +FrontendType.VENDOR # "vendor" +``` + +## Menu Registry + +The menu registry (`app/config/menu_registry.py`) is the **single source of truth** for menu structure. The database only stores visibility overrides. + +### Admin Menu Structure + +```python +ADMIN_MENU_REGISTRY = { + "frontend_type": FrontendType.ADMIN, + "sections": [ + { + "id": "main", + "label": None, # No header + "items": [ + {"id": "dashboard", "label": "Dashboard", "icon": "home", "url": "/admin/dashboard"}, + ], + }, + { + "id": "superAdmin", + "label": "Super Admin", + "super_admin_only": True, # Only visible to super admins + "items": [ + {"id": "admin-users", "label": "Admin Users", "icon": "shield", "url": "/admin/admin-users"}, + ], + }, + # ... more sections + ], +} +``` + +### Admin Menu Sections + +| Section ID | Label | Description | +|------------|-------|-------------| +| `main` | (none) | Dashboard - always at top | +| `superAdmin` | Super Admin | Super admin only tools | +| `platformAdmin` | Platform Administration | Companies, vendors, messages | +| `vendorOps` | Vendor Operations | Products, customers, inventory, orders | +| `marketplace` | Marketplace | Letzshop integration | +| `billing` | Billing & Subscriptions | Tiers, subscriptions, billing history | +| `contentMgmt` | Content Management | Platforms, content pages, themes | +| `devTools` | Developer Tools | Components, icons | +| `platformHealth` | Platform Health | Capacity, testing, code quality | +| `monitoring` | Platform Monitoring | Imports, tasks, logs, notifications | +| `settingsSection` | Platform Settings | General settings, email templates, my menu | + +### Vendor Menu Sections + +| Section ID | Label | Description | +|------------|-------|-------------| +| `main` | (none) | Dashboard, analytics | +| `products` | Products & Inventory | Products, inventory, marketplace import | +| `sales` | Sales & Orders | Orders, Letzshop orders, invoices | +| `customers` | Customers | Customers, messages, notifications | +| `shop` | Shop & Content | Content pages, media library | +| `account` | Account & Settings | Team, profile, billing, settings | + +### Menu Item Properties + +Each menu item has these properties: + +| Property | Type | Description | +|----------|------|-------------| +| `id` | string | Unique identifier (used for config and access control) | +| `label` | string | Display text | +| `icon` | string | Heroicons icon name | +| `url` | string | Route URL | +| `super_admin_only` | boolean | (Optional) Only visible to super admins | + +## Visibility Configuration + +### Opt-Out Model + +The system uses an **opt-out model**: +- All menu items are **visible by default** +- Only **hidden** items are stored in the database +- This keeps the database small and makes the default state explicit + +### Mandatory Items + +Certain menu items cannot be hidden: + +```python +MANDATORY_MENU_ITEMS = { + FrontendType.ADMIN: frozenset({ + "dashboard", # Landing page + "companies", # Platform admin core + "vendors", # Platform admin core + "admin-users", # Super admin core + "settings", # Configuration access + "my-menu", # Must be able to undo changes + }), + FrontendType.VENDOR: frozenset({ + "dashboard", # Landing page + "settings", # Configuration access + }), +} +``` + +### Scope Types + +Menu configuration supports two scopes: + +| Scope | Field | Description | Use Case | +|-------|-------|-------------|----------| +| Platform | `platform_id` | Applies to all users on platform | Hide features not used by platform | +| User | `user_id` | Applies to specific super admin | Personal preference customization | + +**Important Rules:** +- Exactly one scope must be set (platform XOR user) +- User scope is only allowed for admin frontend (super admins only) +- Vendor frontend only supports platform scope + +### Resolution Order + +**Admin Frontend:** +``` +Platform admin → Check platform config → Fall back to default (all visible) +Super admin → Check user config → Fall back to default (all visible) +``` + +**Vendor Frontend:** +``` +Vendor → Check platform config → Fall back to default (all visible) +``` + +## Database Model + +### AdminMenuConfig Table + +```sql +CREATE TABLE admin_menu_configs ( + id SERIAL PRIMARY KEY, + frontend_type VARCHAR(10) NOT NULL, -- 'admin' or 'vendor' + platform_id INTEGER REFERENCES platforms(id), + user_id INTEGER REFERENCES users(id), + menu_item_id VARCHAR(50) NOT NULL, + is_visible BOOLEAN NOT NULL DEFAULT TRUE, + created_at TIMESTAMP, + updated_at TIMESTAMP, + + -- Constraints + CONSTRAINT uq_frontend_platform_menu_config + UNIQUE (frontend_type, platform_id, menu_item_id), + CONSTRAINT uq_frontend_user_menu_config + UNIQUE (frontend_type, user_id, menu_item_id), + CONSTRAINT ck_admin_menu_config_scope + CHECK ((platform_id IS NOT NULL AND user_id IS NULL) OR + (platform_id IS NULL AND user_id IS NOT NULL)), + CONSTRAINT ck_user_scope_admin_only + CHECK ((user_id IS NULL) OR (frontend_type = 'admin')) +); +``` + +### Examples + +```python +# Platform "OMS" hides inventory from admin panel +AdminMenuConfig( + frontend_type=FrontendType.ADMIN, + platform_id=1, + menu_item_id="inventory", + is_visible=False +) + +# Platform "OMS" hides letzshop from vendor dashboard +AdminMenuConfig( + frontend_type=FrontendType.VENDOR, + platform_id=1, + menu_item_id="letzshop", + is_visible=False +) + +# Super admin "john" hides code-quality from their admin panel +AdminMenuConfig( + frontend_type=FrontendType.ADMIN, + user_id=5, + menu_item_id="code-quality", + is_visible=False +) +``` + +## Module Integration + +Menu items are associated with modules. When a module is disabled for a platform, its menu items are automatically hidden. + +### Module to Menu Item Mapping + +Each module defines its menu items per frontend: + +```python +# In module definition +billing_module = ModuleDefinition( + code="billing", + menu_items={ + FrontendType.ADMIN: ["subscription-tiers", "subscriptions", "billing-history"], + FrontendType.VENDOR: ["billing", "invoices"], + }, +) +``` + +### Menu Filtering Logic + +```python +from app.modules.service import module_service + +# Get available menu items (module-aware) +available_items = module_service.get_module_menu_items( + db, platform_id, FrontendType.ADMIN +) + +# Check if specific menu item's module is enabled +is_available = module_service.is_menu_item_module_enabled( + db, platform_id, "subscription-tiers", FrontendType.ADMIN +) +``` + +### Three-Layer Filtering + +The final visible menu is computed by three layers: + +1. **Registry**: All possible menu items +2. **Module Enablement**: Items from disabled modules are hidden +3. **Visibility Config**: Explicitly hidden items are removed + +``` +Final Menu = Registry Items + - Items from Disabled Modules + - Items with is_visible=False in config + - Items not matching user role (super_admin_only) +``` + +## Helper Functions + +### Getting Menu Items + +```python +from app.config.menu_registry import ( + get_all_menu_item_ids, + get_menu_item, + is_super_admin_only_item, + ADMIN_MENU_REGISTRY, + VENDOR_MENU_REGISTRY, +) + +# Get all item IDs for a frontend +admin_items = get_all_menu_item_ids(FrontendType.ADMIN) +# Returns: {'dashboard', 'admin-users', 'companies', ...} + +# Get specific item details +item = get_menu_item(FrontendType.ADMIN, "subscription-tiers") +# Returns: { +# 'id': 'subscription-tiers', +# 'label': 'Subscription Tiers', +# 'icon': 'tag', +# 'url': '/admin/subscription-tiers', +# 'section_id': 'billing', +# 'section_label': 'Billing & Subscriptions' +# } + +# Check if item requires super admin +is_restricted = is_super_admin_only_item("admin-users") # True +``` + +### Menu Enums + +```python +from app.config.menu_registry import AdminMenuItem, VendorMenuItem + +# Use enums for type safety +AdminMenuItem.DASHBOARD.value # "dashboard" +AdminMenuItem.INVENTORY.value # "inventory" + +VendorMenuItem.PRODUCTS.value # "products" +VendorMenuItem.ANALYTICS.value # "analytics" +``` + +## Access Control + +### Route Protection + +```python +from app.api.deps import require_menu_access + +@router.get("/admin/inventory") +async def inventory_page( + _access: bool = Depends(require_menu_access("inventory", FrontendType.ADMIN)) +): + # Only accessible if menu item is visible for user's context + pass +``` + +### Sidebar Rendering + +The sidebar template filters items based on: +1. Module enablement +2. Visibility configuration +3. User role (super admin check) + +```jinja2 +{% for section in menu_sections %} + {% if not section.super_admin_only or current_user.is_super_admin %} + {% for item in section.items %} + {% if item.id in visible_menu_items %} + {{ item.label }} + {% endif %} + {% endfor %} + {% endif %} +{% endfor %} +``` + +## UI for Menu Configuration + +### Platform Admin Menu Config + +Located at `/admin/platform-menu-config` (accessible by super admins): +- Configure which menu items are visible for platform admins +- Configure which menu items are visible for vendors on this platform +- Mandatory items cannot be unchecked + +### Personal Menu Config (Super Admins) + +Located at `/admin/my-menu`: +- Super admins can customize their own admin panel menu +- Personal preferences that don't affect other users +- Useful for hiding rarely-used features + +## Best Practices + +### Do + +- Use menu item enums (`AdminMenuItem`, `VendorMenuItem`) for type safety +- Check module enablement before showing module-specific menu items +- Respect mandatory items - don't try to hide them +- Use `require_menu_access` dependency to protect routes + +### Don't + +- Hardcode menu item IDs as strings (use enums) +- Store `is_visible=True` in database (default state, wastes space) +- Allow hiding mandatory items via API +- Create menu items without registering them in the registry + +## Related Documentation + +- [Module System](module-system.md) - Module architecture and menu item mapping +- [Multi-Tenant System](multi-tenant.md) - Platform isolation +- [Feature Gating](../implementation/feature-gating-system.md) - Tier-based access diff --git a/docs/architecture/module-system.md b/docs/architecture/module-system.md new file mode 100644 index 00000000..d35bd76f --- /dev/null +++ b/docs/architecture/module-system.md @@ -0,0 +1,421 @@ +# Module System Architecture + +The Wizamart platform uses a modular architecture that allows features to be enabled or disabled per platform. This document explains the module system, its classification tiers, and how modules interact with the rest of the application. + +## Overview + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ FRAMEWORK LAYER │ +│ (Infrastructure that modules depend on - not modules themselves) │ +│ │ +│ Config │ Database │ Auth │ Permissions │ Observability │ Celery │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ MODULE LAYER │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ CORE MODULES (Always Enabled) │ │ +│ │ core │ tenancy │ cms │ customers │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ OPTIONAL MODULES (Per-Platform) │ │ +│ │ payments │ billing │ inventory │ orders │ marketplace │ ...│ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ INTERNAL MODULES (Admin Only) │ │ +│ │ dev-tools │ monitoring │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +## Three-Tier Classification + +### Core Modules (4) + +Core modules are **always enabled** and cannot be disabled. They provide fundamental platform functionality. + +| Module | Description | Key Features | +|--------|-------------|--------------| +| `core` | Dashboard, settings, profile | Basic platform operation | +| `tenancy` | Platform, company, vendor, admin user management | Multi-tenant infrastructure | +| `cms` | Content pages, media library, themes | Content management | +| `customers` | Customer database, profiles, segmentation | Customer data management | + +### Optional Modules (7) + +Optional modules can be **enabled or disabled per platform**. They provide additional functionality that may not be needed by all platforms. + +| Module | Dependencies | Description | +|--------|--------------|-------------| +| `payments` | - | Payment gateway integrations (Stripe, PayPal, etc.) | +| `billing` | `payments` | Platform subscriptions, vendor invoices | +| `inventory` | - | Stock management, locations | +| `orders` | `payments` | Order management, customer checkout | +| `marketplace` | `inventory` | Letzshop integration | +| `analytics` | - | Reports, dashboards | +| `messaging` | - | Messages, notifications | + +### Internal Modules (2) + +Internal modules are **admin-only tools** not exposed to customers or vendors. + +| Module | Description | +|--------|-------------| +| `dev-tools` | Component library, icon browser | +| `monitoring` | Logs, background tasks, Flower, Grafana integration | + +## Framework Layer + +The Framework Layer provides infrastructure that modules depend on. These are **not modules** - they're always available and cannot be disabled. + +| Component | Location | Purpose | +|-----------|----------|---------| +| Config | `app/core/config.py` | Settings management | +| Database | `app/core/database.py` | SQLAlchemy sessions | +| Logging | `app/core/logging.py` | Structured logging | +| Permissions | `app/core/permissions.py` | RBAC definitions | +| Feature Gate | `app/core/feature_gate.py` | Tier-based access | +| Celery | `app/core/celery_config.py` | Task queue | +| Observability | `app/core/observability.py` | Health checks, metrics, Sentry | +| Auth Middleware | `middleware/auth.py` | JWT authentication | +| Context Middleware | `middleware/platform_context.py` | Multi-tenancy | +| Dependencies | `app/api/deps.py` | FastAPI DI | +| Base Exceptions | `app/exceptions/base.py` | Exception hierarchy | + +## Module Definition + +Each module is defined using the `ModuleDefinition` dataclass: + +```python +from app.modules.base import ModuleDefinition +from models.database.admin_menu_config import FrontendType + +billing_module = ModuleDefinition( + # Identity + code="billing", + name="Billing & Subscriptions", + description="Platform subscriptions and vendor invoices", + version="1.0.0", + + # Dependencies + requires=["payments"], # Must have payments enabled + + # Features (for tier-based gating) + features=[ + "subscription_management", + "billing_history", + "invoice_generation", + ], + + # Menu items per frontend + menu_items={ + FrontendType.ADMIN: ["subscription-tiers", "subscriptions"], + FrontendType.VENDOR: ["billing", "invoices"], + }, + + # Classification + is_core=False, + is_internal=False, + + # Configuration schema (optional) + config_schema=BillingConfig, + default_config={"trial_days": 14}, + + # Lifecycle hooks (optional) + on_enable=lambda platform_id: setup_billing(platform_id), + on_disable=lambda platform_id: cleanup_billing(platform_id), + health_check=lambda: {"status": "healthy"}, +) +``` + +### ModuleDefinition Fields + +| Field | Type | Description | +|-------|------|-------------| +| `code` | `str` | Unique identifier (e.g., "billing") | +| `name` | `str` | Display name | +| `description` | `str` | What the module provides | +| `version` | `str` | Semantic version (default: "1.0.0") | +| `requires` | `list[str]` | Module codes this depends on | +| `features` | `list[str]` | Feature codes for tier gating | +| `menu_items` | `dict` | Menu items per frontend type | +| `permissions` | `list[str]` | Permission codes defined by module | +| `is_core` | `bool` | Cannot be disabled if True | +| `is_internal` | `bool` | Admin-only if True | +| `config_schema` | `type[BaseModel]` | Pydantic model for configuration | +| `default_config` | `dict` | Default configuration values | +| `on_enable` | `Callable` | Called when module is enabled | +| `on_disable` | `Callable` | Called when module is disabled | +| `on_startup` | `Callable` | Called on application startup | +| `health_check` | `Callable` | Returns health status dict | +| `migrations_path` | `str` | Path to module migrations (relative) | + +## Module Dependencies + +Modules can depend on other modules. When enabling a module, its dependencies are automatically enabled. + +``` + payments + ↙ ↘ + billing orders + + inventory + ↓ + marketplace +``` + +**Dependency Rules:** + +1. Core modules cannot depend on optional modules +2. Enabling a module auto-enables its dependencies +3. Disabling a module auto-disables modules that depend on it +4. Circular dependencies are not allowed + +## Module Registry + +All modules are registered in `app/modules/registry.py`: + +```python +from app.modules.registry import ( + MODULES, # All modules + CORE_MODULES, # Core only + OPTIONAL_MODULES, # Optional only + INTERNAL_MODULES, # Internal only + get_module, + get_core_module_codes, + get_module_tier, + is_core_module, +) + +# Get a specific module +billing = get_module("billing") + +# Check module tier +tier = get_module_tier("billing") # Returns "optional" + +# Get all core module codes +core_codes = get_core_module_codes() # {"core", "tenancy", "cms", "customers"} +``` + +## Module Service + +The `ModuleService` manages module enablement per platform: + +```python +from app.modules.service import module_service + +# Check if module is enabled +if module_service.is_module_enabled(db, platform_id, "billing"): + # Module is enabled for this platform + pass + +# Get all enabled modules for a platform +modules = module_service.get_platform_modules(db, platform_id) + +# Enable a module (auto-enables dependencies) +module_service.enable_module(db, platform_id, "billing", user_id=current_user.id) + +# Disable a module (auto-disables dependents) +module_service.disable_module(db, platform_id, "billing", user_id=current_user.id) + +# Get module configuration +config = module_service.get_module_config(db, platform_id, "billing") + +# Set module configuration +module_service.set_module_config(db, platform_id, "billing", {"trial_days": 30}) +``` + +## Module Events + +The event system allows components to react to module lifecycle changes: + +```python +from app.modules.events import module_event_bus, ModuleEvent, ModuleEventData + +# Subscribe to events +@module_event_bus.subscribe(ModuleEvent.ENABLED) +def on_module_enabled(data: ModuleEventData): + print(f"Module {data.module_code} enabled for platform {data.platform_id}") + +@module_event_bus.subscribe(ModuleEvent.DISABLED) +def on_module_disabled(data: ModuleEventData): + clear_module_cache(data.platform_id, data.module_code) + +@module_event_bus.subscribe(ModuleEvent.CONFIG_CHANGED) +def on_config_changed(data: ModuleEventData): + print(f"Config changed: {data.config}") + +# Events are emitted by ModuleService automatically +# You can also emit manually: +module_event_bus.emit_enabled("billing", platform_id=1, user_id=42) +``` + +### Event Types + +| Event | When Fired | Data Available | +|-------|------------|----------------| +| `ENABLED` | Module enabled for platform | `module_code`, `platform_id`, `user_id` | +| `DISABLED` | Module disabled for platform | `module_code`, `platform_id`, `user_id` | +| `STARTUP` | Application starting | `module_code` | +| `SHUTDOWN` | Application shutting down | `module_code` | +| `CONFIG_CHANGED` | Module config updated | `module_code`, `platform_id`, `config` | + +## Module-Specific Migrations + +Self-contained modules can have their own database migrations: + +``` +app/modules/cms/ +├── migrations/ +│ └── versions/ +│ ├── cms_001_create_content_pages.py +│ └── cms_002_add_seo_fields.py +├── models/ +├── services/ +└── ... +``` + +**Migration Naming Convention:** +``` +{module_code}_{sequence}_{description}.py +``` + +Alembic automatically discovers module migrations: + +```python +# In alembic/env.py +from app.modules.migrations import get_all_migration_paths + +version_locations = [str(p) for p in get_all_migration_paths()] +``` + +## Self-Contained Module Structure + +Modules can be self-contained with their own services, models, and templates: + +``` +app/modules/cms/ +├── __init__.py +├── definition.py # ModuleDefinition +├── config.py # Configuration schema (optional) +├── exceptions.py # Module-specific exceptions +├── routes/ +│ ├── admin.py # Admin API routes +│ └── vendor.py # Vendor API routes +├── services/ +│ └── content_service.py +├── models/ +│ └── content_page.py +├── schemas/ +│ └── content.py # Pydantic schemas +├── templates/ +│ ├── admin/ +│ └── vendor/ +├── migrations/ +│ └── versions/ +└── locales/ + ├── en.json + └── fr.json +``` + +Configure paths in the definition: + +```python +cms_module = ModuleDefinition( + code="cms", + name="Content Management", + is_self_contained=True, + services_path="app.modules.cms.services", + models_path="app.modules.cms.models", + schemas_path="app.modules.cms.schemas", + templates_path="templates", + exceptions_path="app.modules.cms.exceptions", + locales_path="locales", + migrations_path="migrations", +) +``` + +## Database Storage + +Module enablement is stored in the `platform_modules` table: + +| Column | Type | Description | +|--------|------|-------------| +| `platform_id` | FK | Platform reference | +| `module_code` | string | Module identifier | +| `is_enabled` | boolean | Whether enabled | +| `enabled_at` | timestamp | When enabled | +| `enabled_by_user_id` | FK | Who enabled it | +| `disabled_at` | timestamp | When disabled | +| `disabled_by_user_id` | FK | Who disabled it | +| `config` | JSON | Module-specific configuration | + +## Menu Item Filtering + +Menu items are filtered based on enabled modules: + +```python +from app.modules.service import module_service +from models.database.admin_menu_config import FrontendType + +# Get available menu items for platform +menu_items = module_service.get_module_menu_items( + db, platform_id, FrontendType.ADMIN +) + +# Check if specific menu item's module is enabled +is_available = module_service.is_menu_item_module_enabled( + db, platform_id, "subscription-tiers", FrontendType.ADMIN +) +``` + +## Health Checks + +Modules can provide health checks that are aggregated: + +```python +from app.core.observability import health_registry, register_module_health_checks + +# Register all module health checks on startup +register_module_health_checks() + +# Health endpoint aggregates results +# GET /health returns: +{ + "status": "healthy", + "checks": [ + {"name": "module:billing", "status": "healthy"}, + {"name": "module:payments", "status": "healthy"}, + ... + ] +} +``` + +## Best Practices + +### Do + +- Keep modules focused on a single domain +- Use `requires` for hard dependencies +- Provide `health_check` for critical modules +- Use events for cross-module communication +- Document module features and menu items + +### Don't + +- Create circular dependencies +- Make core modules depend on optional modules +- Put framework-level code in modules +- Skip migration naming conventions +- Forget to register menu items + +## Related Documentation + +- [Menu Management](menu-management.md) - Sidebar and menu configuration +- [Multi-Tenant System](multi-tenant.md) - Platform isolation +- [Feature Gating](../implementation/feature-gating-system.md) - Tier-based access diff --git a/mkdocs.yml b/mkdocs.yml index 4ddf06fd..ec3c88c7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -39,6 +39,8 @@ nav: - Money Handling: architecture/money-handling.md - Company-Vendor Management: architecture/company-vendor-management.md - Middleware Stack: architecture/middleware.md + - Module System: architecture/module-system.md + - Menu Management: architecture/menu-management.md - Request Flow: architecture/request-flow.md - Authentication & RBAC: architecture/auth-rbac.md - Frontend Structure: architecture/frontend-structure.md