ligbox-ops-platform/app/modules/store.py
Ligbox Spec Hub 3a2c64834b Initial import: ligbox-ops-platform + specs + LAPTOP + obsidian merge (CT130)
Source: VM122 /opt + obsidian-infra + LAPTOP
Hub: CT130 spec-hub 10.10.10.130
2026-06-19 17:26:41 +00:00

105 lines
3.1 KiB
Python

"""Persistência e consulta de módulos activos."""
from __future__ import annotations
import json
import os
from pathlib import Path
from app.modules.registry import MODULE_BY_ID, MODULES, role_module_defaults
MODULES_PATH = Path(os.getenv("DESK_MODULES_PATH", "/data/desk_modules.json"))
def _disabled_from_env() -> set[str]:
raw = os.getenv("DESK_MODULES_DISABLED", "").strip()
if not raw:
return set()
return {part.strip() for part in raw.split(",") if part.strip()}
def _load_overrides() -> dict[str, bool]:
if not MODULES_PATH.exists():
return {}
try:
data = json.loads(MODULES_PATH.read_text(encoding="utf-8"))
except (json.JSONDecodeError, OSError):
return {}
overrides: dict[str, bool] = {}
for key, val in data.items():
if isinstance(val, dict) and "enabled" in val:
overrides[key] = bool(val["enabled"])
elif isinstance(val, bool):
overrides[key] = val
return overrides
def _save_overrides(overrides: dict[str, bool]) -> None:
MODULES_PATH.parent.mkdir(parents=True, exist_ok=True)
payload = {mid: {"enabled": overrides[mid]} for mid in overrides if mid in MODULE_BY_ID}
MODULES_PATH.write_text(json.dumps(payload, indent=2), encoding="utf-8")
def is_module_enabled(module_id: str) -> bool:
mod = MODULE_BY_ID.get(module_id)
if not mod:
return False
if mod.locked:
return True
env_disabled = _disabled_from_env()
if module_id in env_disabled:
return False
overrides = _load_overrides()
if module_id in overrides:
return overrides[module_id]
return mod.default_enabled
def set_module_enabled(module_id: str, enabled: bool) -> None:
mod = MODULE_BY_ID.get(module_id)
if not mod:
raise KeyError(f"unknown module: {module_id}")
if mod.locked:
raise ValueError(f"module {module_id} is locked")
overrides = _load_overrides()
for m in MODULES:
if m.id not in overrides:
overrides[m.id] = is_module_enabled(m.id)
overrides[module_id] = enabled
_save_overrides(overrides)
def is_module_enabled_for_role(module_id: str, role: str) -> bool:
if not is_module_enabled(module_id):
return False
defaults = role_module_defaults(role)
if defaults is None:
return True
return module_id in defaults
def list_modules(role: str | None = None) -> list[dict]:
items = []
for mod in MODULES:
global_enabled = is_module_enabled(mod.id)
role_enabled = is_module_enabled_for_role(mod.id, role) if role else global_enabled
items.append(
{
"id": mod.id,
"label": mod.label,
"description": mod.description,
"locked": mod.locked,
"nav_views": list(mod.nav_views),
"enabled": global_enabled,
"enabled_for_role": role_enabled,
}
)
return items
def enabled_nav_views() -> set[str]:
views: set[str] = set()
for mod in MODULES:
if is_module_enabled(mod.id):
views.update(mod.nav_views)
return views