diff --git a/docs/proposals/SESSION_NOTE_2026-01-25_modular-platform-architecture.md b/docs/proposals/SESSION_NOTE_2026-01-25_modular-platform-architecture.md new file mode 100644 index 00000000..e9a85100 --- /dev/null +++ b/docs/proposals/SESSION_NOTE_2026-01-25_modular-platform-architecture.md @@ -0,0 +1,235 @@ +# Session Note: Modular Platform Architecture Implementation + +**Date:** 2026-01-25 +**Plan Reference:** `docs/proposals/humble-orbiting-otter.md` + +--- + +## Summary + +Implemented a complete modular platform architecture allowing platforms (OMS, Loyalty, etc.) to enable/disable feature modules. This creates a flexible system where different business products can have different feature sets. + +--- + +## Completed Phases + +### Phase 1: Module Foundation (Commit: `5be42c5`) + +Created the core module system: + +| File | Purpose | +|------|---------| +| `app/modules/__init__.py` | Package init | +| `app/modules/base.py` | `ModuleDefinition` dataclass | +| `app/modules/registry.py` | `MODULES` dict with 12 module definitions | +| `app/modules/service.py` | `ModuleService` class for enablement checks | + +**Key concepts:** +- Modules stored in `Platform.settings["enabled_modules"]` (JSON) +- Core modules (`core`, `platform-admin`) cannot be disabled +- Dependencies auto-resolved (e.g., marketplace requires inventory) + +### Phase 2: Menu Integration & Route Protection (Commit: `cd65a59`) + +Added access control: + +| File | Changes | +|------|---------| +| `app/api/deps.py` | Added `require_module_access()` dependency | +| `app/services/menu_service.py` | Filter menu items by enabled modules | +| `app/routes/admin_pages.py` | Updated routes to use `require_menu_access()` | + +**31 unit tests** in `tests/unit/services/test_module_service.py` + +### Phase 3: Billing Module Extraction (Commit: `c614b7d`) + +First module extraction as template: + +``` +app/modules/billing/ +├── __init__.py +├── definition.py # ModuleDefinition with lazy router loading +└── routes/ + ├── __init__.py + ├── admin.py # Router with require_module_access("billing") + └── vendor.py +``` + +### Phase 4: Additional Module Extractions (Commit: `9d0dc51`) + +Extracted three more modules following the billing pattern: + +- `app/modules/inventory/` - Stock management +- `app/modules/orders/` - Order management +- `app/modules/marketplace/` - Letzshop integration (depends on inventory) + +Updated `app/api/v1/admin/__init__.py` to use module routers. + +### Phase 5: Admin UI for Module Management (Commit: `7ecd554`) + +Created complete Admin UI: + +| File | Purpose | +|------|---------| +| `app/api/v1/admin/modules.py` | API endpoints for module CRUD | +| `app/templates/admin/platform-modules.html` | Module configuration page | +| `static/admin/js/platform-modules.js` | Alpine.js component | +| `app/routes/admin_pages.py` | Added `/admin/platforms/{code}/modules` route | +| `app/templates/admin/platform-detail.html` | Added link in Super Admin section | + +**API Endpoints:** +- `GET /api/v1/admin/modules` - List all modules +- `GET /api/v1/admin/modules/platforms/{id}` - Get platform modules +- `PUT /api/v1/admin/modules/platforms/{id}` - Update modules +- `POST /api/v1/admin/modules/platforms/{id}/enable` - Enable module +- `POST /api/v1/admin/modules/platforms/{id}/disable` - Disable module +- `POST /api/v1/admin/modules/platforms/{id}/enable-all` - Enable all +- `POST /api/v1/admin/modules/platforms/{id}/disable-optional` - Core only + +--- + +## Current Module Registry + +| Module | Type | Description | Dependencies | +|--------|------|-------------|--------------| +| `core` | Core | Dashboard, settings, profile | - | +| `platform-admin` | Core | Companies, vendors, admin users | - | +| `billing` | Optional | Subscriptions, tiers, billing | - | +| `inventory` | Optional | Stock management, locations | - | +| `orders` | Optional | Order management, fulfillment | - | +| `marketplace` | Optional | Letzshop integration | inventory | +| `customers` | Optional | Customer management, CRM | - | +| `cms` | Optional | Content pages, media library | - | +| `analytics` | Optional | Dashboard, reports, exports | - | +| `messaging` | Optional | Messages, notifications | - | +| `dev-tools` | Optional | Components, icons | - | +| `monitoring` | Optional | Logs, background tasks | - | + +--- + +## How It Works + +### Module Enablement Flow + +1. Super admin visits `/admin/platforms/{code}/modules` +2. Toggles modules on/off +3. API calls `module_service.enable_module()` or `disable_module()` +4. Dependencies auto-resolved +5. `Platform.settings["enabled_modules"]` updated + +### Access Control Flow + +1. User accesses route (e.g., `/api/v1/admin/billing/subscriptions`) +2. `require_module_access("billing")` dependency checks: + - Gets platform from request context + - Calls `module_service.is_module_enabled()` + - Returns 403 if disabled +3. Menu items filtered by `module_service.filter_menu_items_by_modules()` + +--- + +## Pending/Optional Next Steps + +### 1. Vendor Router Integration +Wire up vendor module routers to `app/api/v1/vendor/__init__.py`: +```python +from app.modules.billing.routes import vendor_router as billing_vendor_router +# ... etc +``` + +### 2. Extract Remaining Modules +Move inline modules to their own directories: +- `customers` → `app/modules/customers/` +- `cms` → `app/modules/cms/` +- `analytics` → `app/modules/analytics/` +- `messaging` → `app/modules/messaging/` +- `dev-tools` → `app/modules/dev-tools/` +- `monitoring` → `app/modules/monitoring/` + +### 3. Database Table Migration (Optional) +Create `PlatformModule` junction table for better auditability: +```python +class PlatformModule(Base): + platform_id = Column(Integer, ForeignKey("platforms.id")) + module_code = Column(String(50)) + is_enabled = Column(Boolean) + enabled_at = Column(DateTime) + enabled_by_user_id = Column(Integer, ForeignKey("users.id")) +``` + +### 4. Module-Specific Configuration UI +Add per-module config (stored in `Platform.settings["module_config"]`): +```json +{ + "billing": {"stripe_mode": "live"}, + "inventory": {"low_stock_threshold": 10} +} +``` + +### 5. Integration Tests +Add tests for `/api/v1/admin/modules/*` endpoints. + +--- + +## Key Files Reference + +### Core Module System +- `app/modules/base.py` - ModuleDefinition class +- `app/modules/registry.py` - MODULES dict +- `app/modules/service.py` - ModuleService + +### Extracted Modules +- `app/modules/billing/` - Billing module +- `app/modules/inventory/` - Inventory module +- `app/modules/orders/` - Orders module +- `app/modules/marketplace/` - Marketplace module + +### Access Control +- `app/api/deps.py` - `require_module_access()` dependency +- `app/services/menu_service.py` - Menu filtering + +### Admin UI +- `app/api/v1/admin/modules.py` - API endpoints +- `app/templates/admin/platform-modules.html` - Template +- `static/admin/js/platform-modules.js` - JavaScript + +### Tests +- `tests/unit/services/test_module_service.py` - 31 tests + +--- + +## Git Commits (in order) + +``` +5be42c5 feat: implement modular platform architecture (Phase 1) +cd65a59 feat: implement module-based access control (Phase 2) +c614b7d feat: extract billing module with routes (Phase 3) +9d0dc51 feat: extract inventory, orders, and marketplace modules (Phase 4) +7ecd554 feat: add Admin UI for platform module management (Phase 5) +``` + +--- + +## Testing + +Run module service tests: +```bash +python -m pytest tests/unit/services/test_module_service.py -v +``` + +Verify app starts: +```bash +python -c "from main import app; print('OK')" +``` + +--- + +## Access the Module UI + +1. Login as super admin +2. Go to `/admin/platforms` +3. Click on a platform (e.g., OMS) +4. In "Super Admin" section, click "Module Configuration" +5. Toggle modules on/off + +Or directly: `/admin/platforms/oms/modules`