"""Stabile Parameterpfade (PLAN.md §10.2). Pfade werden niemals aus sichtbaren Namen gebildet; alle Teile sind UUIDs oder feste Schlüsselwörter. """ from __future__ import annotations import uuid _ALLOWED_ROOTS = {"composition", "output", "cluster", "master"} def _is_uuid(value: str) -> bool: try: uuid.UUID(value) return True except (ValueError, AttributeError): return False def validate_parameter_path(path: str) -> bool: """True, wenn der Pfad dem Muster §10.2 entspricht.""" if not path or path.startswith("/") or "\\" in path or ".." in path: return False parts = path.split("/") root = parts[0] if root not in _ALLOWED_ROOTS: return False if root == "master": return len(parts) == 2 and parts[1] != "" if root in {"composition", "output"}: if len(parts) < 3: return False if not _is_uuid(parts[1]): return False return all(p != "" for p in parts[2:]) # cluster: cluster/group/{uuid}/... oder cluster/node/{uuid}/... if len(parts) >= 3 and parts[1] in {"group", "node"} and _is_uuid(parts[2]): return all(p != "" for p in parts[3:]) return False def layer_opacity_path(composition_id: str, layer_id: str) -> str: return f"composition/{composition_id}/layer/{layer_id}/opacity" def master_intensity_path() -> str: return "master/intensity"