"""Abstract workflow definition / version store.""" from __future__ import annotations from abc import ABC, abstractmethod from typing import Any class WorkflowDraftConflictError(Exception): """Raised when ``expected_revision`` does not match the stored draft revision.""" def __init__(self, workflow_id: str, current_revision: int) -> None: super().__init__(f"draft conflict for {workflow_id}: current={current_revision}") self.workflow_id = workflow_id self.current_revision = current_revision class WorkflowNotFoundError(Exception): def __init__(self, workflow_id: str) -> None: super().__init__(f"workflow not found: {workflow_id}") self.workflow_id = workflow_id class WorkflowVersionNotFoundError(Exception): def __init__(self, version_id: str) -> None: super().__init__(f"workflow version not found: {version_id}") self.version_id = version_id class WorkflowStore(ABC): @abstractmethod async def list_definitions( self, *, owner_id: str | None = None, status: str | None = None, include_archived: bool = False, ) -> list[dict[str, Any]]: raise NotImplementedError @abstractmethod async def get_definition(self, workflow_id: str, *, include_draft: bool = True) -> dict[str, Any] | None: raise NotImplementedError @abstractmethod async def create_definition(self, data: dict[str, Any]) -> dict[str, Any]: raise NotImplementedError @abstractmethod async def update_definition(self, workflow_id: str, data: dict[str, Any]) -> dict[str, Any] | None: raise NotImplementedError @abstractmethod async def archive_definition(self, workflow_id: str) -> dict[str, Any] | None: raise NotImplementedError @abstractmethod async def save_draft( self, workflow_id: str, *, expected_revision: int, graph: dict[str, Any], updated_by: str | None = None, ) -> dict[str, Any]: """CAS update of ``draft_graph_json``. Raises ``WorkflowDraftConflictError``.""" raise NotImplementedError @abstractmethod async def save_studio_draft( self, workflow_id: str, *, expected_revision: int, graph: dict[str, Any], canvas_schema: str = "{}", updated_by: str | None = None, ) -> dict[str, Any]: """Atomically CAS-update BOTH the execution graph and the canvas document. A single conditional UPDATE bumps ``draft_revision`` and writes ``draft_graph_json`` + ``draft_canvas_schema_json`` together, so the two representations can never diverge across revisions. Raises ``WorkflowDraftConflictError`` on a stale ``expected_revision``. """ raise NotImplementedError @abstractmethod async def publish_version( self, workflow_id: str, *, graph: dict[str, Any], graph_hash: str, published_by: str | None = None, change_note: str = "", canvas_schema_hash: str | None = None, ) -> dict[str, Any]: raise NotImplementedError @abstractmethod async def list_versions(self, workflow_id: str) -> list[dict[str, Any]]: raise NotImplementedError @abstractmethod async def get_version(self, version_id: str) -> dict[str, Any] | None: raise NotImplementedError @abstractmethod async def list_published_summaries(self, *, exclude_workflow_id: str | None = None) -> list[dict[str, Any]]: """Lightweight list for subworkflow resource catalog.""" raise NotImplementedError