docs: add session note for modular platform architecture

Documents the complete implementation of Phases 1-5:
- Module foundation and registry
- Menu integration and route protection
- Billing, inventory, orders, marketplace module extractions
- Admin UI for module management
- Pending optional next steps

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-25 22:17:59 +01:00
parent 7ecd554454
commit f29f1113cd

View File

@@ -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`