From d0688a7b644ad3d336f58aaddf3e4609eca922fd Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Fri, 3 Jul 2026 19:14:32 +0200 Subject: [PATCH] Wartung (B10): Restart-Allowlist vereinheitlichen Der ServicesCard-"Anzeige- statt Unit-Name"-Bug ist behoben (Frontend nutzt durchgehend x.unit). Der echte Rest-Fehler lag in der ZWEITEN Restart-Wahrheit: /api/system/restart (system.py) + das MCP-Tool restart_service hatten eine veraltete Allowlist ohne llama-swap (Engine) und hermes-terminal, dafuer mit Geist-Eintrag hermes-webui. Ein Engine-Neustart per Sprache/MCP schlug daher mit "nicht erlaubt" fehl. Fix: /api/system/restart delegiert jetzt an services.maintenance.restart_service (EINE Allowlist-Wahrheit, kennt System- via sudo -n UND User-Dienste, wird auch von der UI genutzt). MCP-Tool-Docstring auf die echten Dienste korrigiert. Co-Authored-By: Claude Opus 4.8 --- backend/routers/system.py | 14 ++++++++------ mcp/mcp_mc.py | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/backend/routers/system.py b/backend/routers/system.py index 0380221..d3c799d 100644 --- a/backend/routers/system.py +++ b/backend/routers/system.py @@ -9,13 +9,14 @@ import logging import os import subprocess -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter from pydantic import BaseModel import httpx from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL, MEM0_SERVICE_URL, VOICE_SERVICE_URL from services import backup as backup_svc +from services import maintenance from services.agent import agent_status from services.gateway import gateway_reachable from services.llamaswap import engine_reachable, list_models @@ -27,8 +28,6 @@ log = logging.getLogger(__name__) router = APIRouter(prefix="/api") -# Nur diese User-Dienste dürfen neugestartet werden. -ALLOWED_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-webui", "mem0-service", "voice-service"} # Quelle für Self-Update (auf der Box ~/mission-control-v2). SOURCE_DIR = os.path.expanduser(os.environ.get("MC2_SOURCE_DIR", "~/mission-control-v2")) @@ -99,9 +98,12 @@ class RestartReq(BaseModel): @router.post("/system/restart") def restart(req: RestartReq) -> dict: - if req.service not in ALLOWED_SERVICES: - raise HTTPException(400, f"Dienst '{req.service}' nicht erlaubt.") - return _run(["systemctl", "--user", "restart", req.service]) + """Dienst neustarten. Delegiert an den Wartungs-Service (EINE Allowlist-Wahrheit): + der kennt System-Dienste (llama-swap, via sudo -n) UND User-Dienste und wird auch von + der UI (/api/maintenance/restart) genutzt. Vorher lag hier eine zweite, veraltete Liste + (ohne llama-swap/hermes-terminal, mit Geist-Eintrag hermes-webui) → Engine-Neustart per + Sprache/MCP schlug fehl.""" + return maintenance.restart_service(req.service) @router.post("/system/self-update") diff --git a/mcp/mcp_mc.py b/mcp/mcp_mc.py index 2b524d7..b9ee3f5 100644 --- a/mcp/mcp_mc.py +++ b/mcp/mcp_mc.py @@ -226,8 +226,9 @@ def list_services() -> str: @mcp.tool() def restart_service(service: str) -> str: - """Startet einen erlaubten Dienst neu - (mission-control-2 | hermes-gateway | hermes-webui | mem0-service | voice-service).""" + """Startet einen erlaubten Dienst neu. Erlaubt: llama-swap (Engine) | mission-control-2 | + hermes-gateway | hermes-terminal | mem0-service | voice-service. Der Engine-Neustart + (llama-swap = System-Dienst) kann das Box-Passwort verlangen, wenn kein NOPASSWD gesetzt ist.""" res = _post("/api/system/restart", {"service": service}) return f"Restart {service}: {'ok' if res.get('ok') else 'Fehler — ' + res.get('err', '')}"