import time import shlex from typing import Any, Dict, Optional import logging import httpx from fastapi import APIRouter, Depends, HTTPException, Request from sqlmodel import Session, select from clients.edge.errors import log_edge_failure, summarize_edge_exception from clients.edge.http import HttpEdgeClient from core.cache import cache from core.database import get_session from models.bot import BotInstance from providers.target import ProviderTarget from providers.selector import get_runtime_provider from schemas.platform import ( ManagedNodeConnectivityResult, ManagedNodeNativePreflightResult, ManagedNodePayload, PlatformSettingsPayload, SystemSettingPayload, ) from services.node_registry_service import ManagedNode from services.platform_service import ( build_node_resource_overview, build_platform_overview, create_or_update_system_setting, delete_system_setting, get_platform_settings, list_system_settings, list_activity_events, list_usage, save_platform_settings, ) router = APIRouter() logger = logging.getLogger(__name__) PLATFORM_OVERVIEW_CACHE_KEY = "platform:overview" PLATFORM_OVERVIEW_CACHE_TTL_SECONDS = 15 PLATFORM_NODES_CACHE_KEY = "platform:nodes:list" PLATFORM_NODES_CACHE_TTL_SECONDS = 20 def _cached_platform_overview_payload() -> Optional[Dict[str, Any]]: cached = cache.get_json(PLATFORM_OVERVIEW_CACHE_KEY) return cached if isinstance(cached, dict) else None def _store_platform_overview_payload(payload: Dict[str, Any]) -> Dict[str, Any]: cache.set_json(PLATFORM_OVERVIEW_CACHE_KEY, payload, ttl=PLATFORM_OVERVIEW_CACHE_TTL_SECONDS) return payload def _invalidate_platform_overview_cache() -> None: cache.delete(PLATFORM_OVERVIEW_CACHE_KEY) def _cached_platform_nodes_payload() -> Optional[Dict[str, Any]]: cached = cache.get_json(PLATFORM_NODES_CACHE_KEY) if not isinstance(cached, dict): return None items = cached.get("items") if not isinstance(items, list): return None return {"items": items} def _store_platform_nodes_payload(items: list[Dict[str, Any]]) -> Dict[str, Any]: payload = {"items": items} cache.set_json(PLATFORM_NODES_CACHE_KEY, payload, ttl=PLATFORM_NODES_CACHE_TTL_SECONDS) return payload def _invalidate_platform_nodes_cache() -> None: cache.delete(PLATFORM_NODES_CACHE_KEY) def _normalize_node_payload(payload: ManagedNodePayload) -> ManagedNodePayload: normalized_node_id = str(payload.node_id or "").strip().lower() if not normalized_node_id: raise HTTPException(status_code=400, detail="node_id is required") transport_kind = str(payload.transport_kind or "edge").strip().lower() or "edge" if transport_kind != "edge": raise HTTPException(status_code=400, detail="Only edge transport is supported") runtime_kind = str(payload.runtime_kind or "docker").strip().lower() or "docker" core_adapter = str(payload.core_adapter or "nanobot").strip().lower() or "nanobot" native_sandbox_mode = _normalize_native_sandbox_mode(payload.native_sandbox_mode) base_url = str(payload.base_url or "").strip() if transport_kind == "edge" and not base_url: raise HTTPException(status_code=400, detail="base_url is required for edge nodes") return payload.model_copy( update={ "node_id": normalized_node_id, "display_name": str(payload.display_name or normalized_node_id).strip() or normalized_node_id, "base_url": base_url, "auth_token": str(payload.auth_token or "").strip(), "transport_kind": transport_kind, "runtime_kind": runtime_kind, "core_adapter": core_adapter, "workspace_root": str(payload.workspace_root or "").strip(), "native_command": str(payload.native_command or "").strip(), "native_workdir": str(payload.native_workdir or "").strip(), "native_sandbox_mode": native_sandbox_mode, } ) def _normalize_native_sandbox_mode(raw_value: Any) -> str: text = str(raw_value or "").strip().lower() if text in {"workspace", "sandbox", "strict"}: return "workspace" if text in {"full_access", "full-access", "danger-full-access", "escape"}: return "full_access" return "inherit" def _managed_node_from_payload(payload: ManagedNodePayload) -> ManagedNode: normalized = _normalize_node_payload(payload) return ManagedNode( node_id=normalized.node_id, display_name=normalized.display_name, base_url=normalized.base_url, enabled=bool(normalized.enabled), auth_token=normalized.auth_token, metadata={ "transport_kind": normalized.transport_kind, "runtime_kind": normalized.runtime_kind, "core_adapter": normalized.core_adapter, "workspace_root": normalized.workspace_root, "native_command": normalized.native_command, "native_workdir": normalized.native_workdir, "native_sandbox_mode": normalized.native_sandbox_mode, }, ) def _node_status(node: ManagedNode, *, refresh_failed: bool = False) -> str: if not bool(node.enabled): return "disabled" transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower() if transport_kind != "edge": return "unknown" if refresh_failed: return "offline" return "online" if node.last_seen_at else "unknown" def _serialize_node(node: ManagedNode, *, refresh_failed: bool = False) -> Dict[str, Any]: metadata = dict(node.metadata or {}) return { "node_id": node.node_id, "display_name": node.display_name, "base_url": node.base_url, "enabled": bool(node.enabled), "transport_kind": str(metadata.get("transport_kind") or ""), "runtime_kind": str(metadata.get("runtime_kind") or ""), "core_adapter": str(metadata.get("core_adapter") or ""), "workspace_root": str(metadata.get("workspace_root") or ""), "native_command": str(metadata.get("native_command") or ""), "native_workdir": str(metadata.get("native_workdir") or ""), "native_sandbox_mode": str(metadata.get("native_sandbox_mode") or "inherit"), "metadata": metadata, "capabilities": dict(node.capabilities or {}), "resources": dict(getattr(node, "resources", {}) or {}), "last_seen_at": node.last_seen_at, "status": _node_status(node, refresh_failed=refresh_failed), } def _test_edge_connectivity(resolve_edge_client, node: ManagedNode) -> ManagedNodeConnectivityResult: started = time.perf_counter() try: client = resolve_edge_client( ProviderTarget( node_id=node.node_id, transport_kind="edge", runtime_kind=str((node.metadata or {}).get("runtime_kind") or "docker"), core_adapter=str((node.metadata or {}).get("core_adapter") or "nanobot"), ) ) node_self = _edge_node_self_with_native_preflight(client=client, node=node) latency_ms = max(1, int((time.perf_counter() - started) * 1000)) return ManagedNodeConnectivityResult( ok=True, status="online", latency_ms=latency_ms, detail="dashboard-edge reachable", node_self=node_self, ) except Exception as exc: latency_ms = max(1, int((time.perf_counter() - started) * 1000)) return ManagedNodeConnectivityResult( ok=False, status="offline", latency_ms=latency_ms, detail=summarize_edge_exception(exc), node_self=None, ) def _split_native_command(raw_command: Optional[str]) -> list[str]: text = str(raw_command or "").strip() if not text: return [] try: return [str(item or "").strip() for item in shlex.split(text) if str(item or "").strip()] except Exception: return [text] def _runtime_native_supported(node_self: Dict[str, Any]) -> bool: capabilities = dict(node_self.get("capabilities") or {}) runtime_caps = dict(capabilities.get("runtime") or {}) return bool(runtime_caps.get("native") is True) def _test_edge_native_preflight( resolve_edge_client, node: ManagedNode, *, native_command: Optional[str] = None, native_workdir: Optional[str] = None, ) -> ManagedNodeNativePreflightResult: started = time.perf_counter() command_hint = _split_native_command(native_command) workdir_hint = str(native_workdir or "").strip() try: client = resolve_edge_client( ProviderTarget( node_id=node.node_id, transport_kind="edge", runtime_kind=str((node.metadata or {}).get("runtime_kind") or "docker"), core_adapter=str((node.metadata or {}).get("core_adapter") or "nanobot"), ) ) node_self = dict(client.heartbeat_node() or {}) preflight = dict( client.preflight_native( native_command=native_command, native_workdir=native_workdir, ) or {} ) latency_ms = max(1, int((time.perf_counter() - started) * 1000)) command = [str(item or "").strip() for item in list(preflight.get("command") or []) if str(item or "").strip()] workdir = str(preflight.get("workdir") or "") detail = str(preflight.get("detail") or "") if not detail: detail = "native launcher ready" if bool(preflight.get("ok")) else "native launcher not ready" return ManagedNodeNativePreflightResult( ok=bool(preflight.get("ok")), status="online", latency_ms=latency_ms, detail=detail, command=command, workdir=workdir, command_available=bool(preflight.get("command_available")), workdir_exists=bool(preflight.get("workdir_exists")), runtime_native_supported=_runtime_native_supported(node_self), node_self=node_self, ) except Exception as exc: latency_ms = max(1, int((time.perf_counter() - started) * 1000)) return ManagedNodeNativePreflightResult( ok=False, status="offline", latency_ms=latency_ms, detail=summarize_edge_exception(exc), command=command_hint, workdir=workdir_hint, command_available=False, workdir_exists=False if workdir_hint else True, runtime_native_supported=False, node_self=None, ) def _edge_node_self_with_native_preflight(*, client: HttpEdgeClient, node: ManagedNode) -> Dict[str, Any]: node_self = dict(client.heartbeat_node() or {}) metadata = dict(node.metadata or {}) native_command = str(metadata.get("native_command") or "").strip() or None native_workdir = str(metadata.get("native_workdir") or "").strip() or None runtime_kind = str(metadata.get("runtime_kind") or "docker").strip().lower() should_probe = bool(native_command or native_workdir or runtime_kind == "native") if not should_probe: return node_self try: preflight = dict(client.preflight_native(native_command=native_command, native_workdir=native_workdir) or {}) except Exception as exc: log_edge_failure( logger, key=f"platform-node-native-preflight:{node.node_id}", exc=exc, message=f"Failed to run native preflight for node_id={node.node_id}", ) return node_self caps = dict(node_self.get("capabilities") or {}) process_caps = dict(caps.get("process") or {}) if preflight.get("command"): process_caps["command"] = list(preflight.get("command") or []) process_caps["available"] = bool(preflight.get("ok")) process_caps["command_available"] = bool(preflight.get("command_available")) process_caps["workdir_exists"] = bool(preflight.get("workdir_exists")) process_caps["workdir"] = str(preflight.get("workdir") or "") process_caps["detail"] = str(preflight.get("detail") or "") caps["process"] = process_caps node_self["capabilities"] = caps node_self["native_preflight"] = preflight return node_self def _apply_platform_runtime_changes(request: Request) -> None: _invalidate_platform_overview_cache() _invalidate_platform_nodes_cache() speech_service = getattr(request.app.state, "speech_service", None) if speech_service is not None and hasattr(speech_service, "reset_runtime"): speech_service.reset_runtime() @router.get("/api/platform/overview") def get_platform_overview(request: Request, session: Session = Depends(get_session)): cached_payload = _cached_platform_overview_payload() if cached_payload is not None: return cached_payload def _read_runtime(bot): provider = get_runtime_provider(request.app.state, bot) status = str(provider.get_runtime_status(bot_id=str(bot.id or "")) or "STOPPED").upper() runtime = dict(provider.get_resource_snapshot(bot_id=str(bot.id or "")) or {}) runtime.setdefault("docker_status", status) return status, runtime payload = build_platform_overview(session, read_runtime=_read_runtime) return _store_platform_overview_payload(payload) @router.get("/api/platform/nodes") def list_platform_nodes(request: Request, session: Session = Depends(get_session)): cached_payload = _cached_platform_nodes_payload() if cached_payload is not None: return cached_payload node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "list_nodes"): return {"items": []} resolve_edge_client = getattr(request.app.state, "resolve_edge_client", None) refreshed_items = [] for node in node_registry.list_nodes(): metadata = dict(node.metadata or {}) refresh_failed = False if ( callable(resolve_edge_client) and str(metadata.get("transport_kind") or "").strip().lower() == "edge" and bool(node.enabled) ): try: client = resolve_edge_client( ProviderTarget( node_id=node.node_id, transport_kind="edge", runtime_kind=str(metadata.get("runtime_kind") or "docker"), core_adapter=str(metadata.get("core_adapter") or "nanobot"), ) ) node_self = _edge_node_self_with_native_preflight(client=client, node=node) node = node_registry.mark_node_seen( session, node_id=node.node_id, display_name=str(node.display_name or node_self.get("display_name") or node.node_id), capabilities=dict(node_self.get("capabilities") or {}), resources=dict(node_self.get("resources") or {}), ) except Exception as exc: refresh_failed = True log_edge_failure( logger, key=f"platform-node-refresh:{node.node_id}", exc=exc, message=f"Failed to refresh edge node metadata for node_id={node.node_id}", ) refreshed_items.append((node, refresh_failed)) items = [] for node, refresh_failed in refreshed_items: items.append(_serialize_node(node, refresh_failed=refresh_failed)) return _store_platform_nodes_payload(items) @router.get("/api/platform/nodes/{node_id}") def get_platform_node(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") node = node_registry.get_node(normalized_node_id) if node is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") return _serialize_node(node) @router.post("/api/platform/nodes") def create_platform_node(payload: ManagedNodePayload, request: Request, session: Session = Depends(get_session)): node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") normalized = _normalize_node_payload(payload) if node_registry.get_node(normalized.node_id) is not None: raise HTTPException(status_code=409, detail=f"Node already exists: {normalized.node_id}") node = node_registry.upsert_node(session, _managed_node_from_payload(normalized)) _invalidate_platform_overview_cache() _invalidate_platform_nodes_cache() return _serialize_node(node) @router.put("/api/platform/nodes/{node_id}") def update_platform_node(node_id: str, payload: ManagedNodePayload, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") existing = node_registry.get_node(normalized_node_id) if existing is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") normalized = _normalize_node_payload(payload) if normalized.node_id != normalized_node_id: raise HTTPException(status_code=400, detail="node_id cannot be changed") node = node_registry.upsert_node( session, ManagedNode( node_id=normalized_node_id, display_name=normalized.display_name, base_url=normalized.base_url, enabled=bool(normalized.enabled), auth_token=normalized.auth_token or existing.auth_token, metadata={ "transport_kind": normalized.transport_kind, "runtime_kind": normalized.runtime_kind, "core_adapter": normalized.core_adapter, "workspace_root": normalized.workspace_root, "native_command": normalized.native_command, "native_workdir": normalized.native_workdir, "native_sandbox_mode": normalized.native_sandbox_mode, }, capabilities=dict(existing.capabilities or {}), resources=dict(existing.resources or {}), last_seen_at=existing.last_seen_at, ), ) _invalidate_platform_overview_cache() _invalidate_platform_nodes_cache() return _serialize_node(node) @router.delete("/api/platform/nodes/{node_id}") def delete_platform_node(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() if normalized_node_id == "local": raise HTTPException(status_code=400, detail="Local node cannot be deleted") node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") if node_registry.get_node(normalized_node_id) is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") attached_bot_ids = session.exec(select(BotInstance.id).where(BotInstance.node_id == normalized_node_id)).all() if attached_bot_ids: raise HTTPException( status_code=400, detail=f"Node {normalized_node_id} still has bots assigned: {', '.join(str(item) for item in attached_bot_ids[:5])}", ) node_registry.delete_node(session, normalized_node_id) _invalidate_platform_overview_cache() _invalidate_platform_nodes_cache() return {"status": "deleted", "node_id": normalized_node_id} @router.post("/api/platform/nodes/test") def test_platform_node(payload: ManagedNodePayload, request: Request): normalized = _normalize_node_payload(payload) temp_node = _managed_node_from_payload(normalized) result = _test_edge_connectivity( lambda _target: HttpEdgeClient( node=temp_node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), temp_node, ) return result.model_dump() @router.post("/api/platform/nodes/native/preflight") def test_platform_node_native_preflight(payload: ManagedNodePayload, request: Request): normalized = _normalize_node_payload(payload) temp_node = _managed_node_from_payload(normalized) result = _test_edge_native_preflight( lambda _target: HttpEdgeClient( node=temp_node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), temp_node, native_command=str(normalized.native_command or "").strip() or None, native_workdir=str(normalized.native_workdir or "").strip() or None, ) return result.model_dump() @router.post("/api/platform/nodes/{node_id}/test") def test_saved_platform_node(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") node = node_registry.get_node(normalized_node_id) if node is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower() if transport_kind != "edge": _invalidate_platform_nodes_cache() raise HTTPException(status_code=400, detail="Only edge transport is supported") result = _test_edge_connectivity( lambda target: HttpEdgeClient( node=node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), node, ) if result.ok: node_registry.mark_node_seen( session, node_id=node.node_id, display_name=str(node.display_name or result.node_self.get("display_name") or node.node_id) if result.node_self else node.display_name, capabilities=dict(result.node_self.get("capabilities") or {}) if result.node_self else dict(node.capabilities or {}), resources=dict(result.node_self.get("resources") or {}) if result.node_self else dict(getattr(node, "resources", {}) or {}), ) _invalidate_platform_nodes_cache() return result.model_dump() @router.post("/api/platform/nodes/{node_id}/native/preflight") def test_saved_platform_node_native_preflight(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") node = node_registry.get_node(normalized_node_id) if node is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower() if transport_kind != "edge": _invalidate_platform_nodes_cache() raise HTTPException(status_code=400, detail="Only edge transport is supported") metadata = dict(node.metadata or {}) result = _test_edge_native_preflight( lambda _target: HttpEdgeClient( node=node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), node, native_command=str(metadata.get("native_command") or "").strip() or None, native_workdir=str(metadata.get("native_workdir") or "").strip() or None, ) if result.status == "online" and result.node_self: node_registry.mark_node_seen( session, node_id=node.node_id, display_name=str(node.display_name or result.node_self.get("display_name") or node.node_id), capabilities=dict(result.node_self.get("capabilities") or {}), resources=dict(result.node_self.get("resources") or {}), ) _invalidate_platform_nodes_cache() return result.model_dump() @router.get("/api/platform/nodes/{node_id}/resources") def get_platform_node_resources(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is not None and hasattr(node_registry, "get_node"): node = node_registry.get_node(normalized_node_id) if node is not None: metadata = dict(getattr(node, "metadata", {}) or {}) if str(metadata.get("transport_kind") or "").strip().lower() == "edge": resolve_edge_client = getattr(request.app.state, "resolve_edge_client", None) if callable(resolve_edge_client): from providers.target import ProviderTarget base = build_node_resource_overview(session, node_id=normalized_node_id, read_runtime=None) client = resolve_edge_client( ProviderTarget( node_id=normalized_node_id, transport_kind="edge", runtime_kind=str(metadata.get("runtime_kind") or "docker"), core_adapter=str(metadata.get("core_adapter") or "nanobot"), ) ) try: resource_report = dict(client.get_node_resources() or {}) except Exception as exc: log_edge_failure( logger, key=f"platform-node-resources:{normalized_node_id}", exc=exc, message=f"Failed to load edge node resources for node_id={normalized_node_id}", ) return base base["resources"] = dict(resource_report.get("resources") or resource_report) if resource_report: base["node_report"] = resource_report return base def _read_runtime(bot): provider = get_runtime_provider(request.app.state, bot) status = str(provider.get_runtime_status(bot_id=str(bot.id or "")) or "STOPPED").upper() runtime = dict(provider.get_resource_snapshot(bot_id=str(bot.id or "")) or {}) runtime.setdefault("docker_status", status) return status, runtime return build_node_resource_overview(session, node_id=normalized_node_id, read_runtime=_read_runtime) @router.get("/api/platform/settings") def get_platform_settings_api(session: Session = Depends(get_session)): return get_platform_settings(session).model_dump() @router.put("/api/platform/settings") def update_platform_settings_api(payload: PlatformSettingsPayload, request: Request, session: Session = Depends(get_session)): result = save_platform_settings(session, payload).model_dump() _apply_platform_runtime_changes(request) return result @router.post("/api/platform/cache/clear") def clear_platform_cache(): _invalidate_platform_overview_cache() _invalidate_platform_nodes_cache() return {"status": "cleared"} @router.post("/api/platform/reload") def reload_platform_runtime(request: Request): _apply_platform_runtime_changes(request) return {"status": "reloaded"} @router.get("/api/platform/usage") def get_platform_usage( bot_id: Optional[str] = None, limit: int = 100, offset: int = 0, session: Session = Depends(get_session), ): return list_usage(session, bot_id=bot_id, limit=limit, offset=offset) @router.get("/api/platform/events") def get_platform_events(bot_id: Optional[str] = None, limit: int = 100, session: Session = Depends(get_session)): return {"items": list_activity_events(session, bot_id=bot_id, limit=limit)} @router.get("/api/platform/system-settings") def get_system_settings(search: str = "", session: Session = Depends(get_session)): return {"items": list_system_settings(session, search=search)} @router.post("/api/platform/system-settings") def create_system_setting(payload: SystemSettingPayload, request: Request, session: Session = Depends(get_session)): try: result = create_or_update_system_setting(session, payload) _apply_platform_runtime_changes(request) return result except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc @router.put("/api/platform/system-settings/{key}") def update_system_setting(key: str, payload: SystemSettingPayload, request: Request, session: Session = Depends(get_session)): try: result = create_or_update_system_setting(session, payload.model_copy(update={"key": key})) _apply_platform_runtime_changes(request) return result except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc @router.delete("/api/platform/system-settings/{key}") def remove_system_setting(key: str, request: Request, session: Session = Depends(get_session)): try: delete_system_setting(session, key) _apply_platform_runtime_changes(request) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc return {"status": "deleted", "key": key}