Module Manager
Admin page for enabling and disabling Arcturus-Prime modules, with KV-backed state persistence and sidebar filtering
Module Manager
The Module Manager provides a single admin page for toggling Arcturus-Prime modules on and off. Located at /admin/modules. Admin-only.
Core modules (security, module-manager) cannot be disabled. All other modules can be toggled, and the sidebar updates server-side to hide disabled modules.
Module Inventory
27 modules across 6 categories:
| Category | Count | Modules |
|---|---|---|
| infra | 9 | proxmox, network-discovery, pentest, cloudflare, homelab, health-monitor, jobs, build-swarm, servers |
| ai | 6 | ollama, email, openclaw, chat, workbench, elevenlabs |
| content | 4 | linkedin-studio, content, public-docs-security, docs-hub |
| tools | 3 | sandbox, argonaut, twilio |
| system | 3 | module-manager, security, api-dashboard |
| dev | 2 | deployments, git |
Page UI
- Card grid showing all registered modules with name, description, version, icon, and enable/disable toggle
- Core modules display a locked badge; toggle is disabled
- Summary bar: Total / Enabled / Disabled counts
- Modules grouped by category
- Dependency warnings appear when disabling a module that other enabled modules depend on
State Storage
- KV key:
data:module-states - Format:
{ version: 1, states: { [moduleId]: boolean } } - Missing entries default to enabled (backward compatible)
- 30-second in-memory cache (same pattern as dashboard-profiles)
- Core modules (
manifest.core === true) always return enabled regardless of stored state
Sidebar Filtering
AdminSidebar.astro reads module states at SSR time via getModuleStates(). For each disabled module, all routes listed in its manifest.pages array are added to a disabledRoutes set. Nav items whose href matches a disabled route are filtered out before rendering.
This happens server-side — no client JS involved. The sidebar re-evaluates module states on every page load (subject to the 30s cache).
API
GET /api/admin/modules
Returns all module manifests with current enabled/disabled state. Requires admin auth.
Response:
{
"modules": [
{
"id": "module-manager",
"name": "Module Manager",
"description": "...",
"version": "1.0.0",
"icon": "fa-cubes",
"category": "system",
"pages": ["/admin/modules"],
"apiRoutes": ["/api/admin/modules"],
"dependencies": [],
"core": true,
"enabled": true
}
],
"summary": { "total": 27, "enabled": 27, "disabled": 0 }
}
POST /api/admin/modules
Toggle a single module. Requires admin auth.
Request body: { "id": "string", "enabled": boolean }
Responses:
| Status | Condition |
|---|---|
| 200 | { ok: true, id, enabled, warnings } |
| 400 | Missing id or enabled field |
| 403 | Attempted to disable a core module |
| 404 | Module ID not found |
| 503 | KV unavailable |
The warnings array contains dependency messages when disabling a module that other enabled modules depend on (e.g., "Module X depends on Module Y").
Source Files
| File | Purpose |
|---|---|
src/pages/admin/modules.astro | Module Manager page |
src/pages/api/admin/modules.ts | GET list + POST toggle API |
src/lib/module-states.ts | KV read/write, cache, isModuleEnabled() |
src/config/modules/module-manager.ts | Module manifest + nav item |
src/config/module-registry.ts | moduleManifests, coreModuleIds exports |
src/components/admin/AdminSidebar.astro | Sidebar filtering logic |
Security
API endpoint requires Cloudflare Access admin authentication via validateAdmin(). The page is served under /admin/ which is blocked by middleware for non-Arcturus-Prime.com hosts and protected by Cloudflare Access in production.