feat: add BPMN inspection and workflow progress visuals

This commit is contained in:
2026-07-30 17:42:10 +02:00
parent a6e0e89829
commit c505e81006
9 changed files with 736 additions and 12 deletions
+91
View File
@@ -29,7 +29,19 @@ from govoplan_workflow.backend.manifest import (
INSTANCE_TRANSITION_SCOPE,
)
from govoplan_workflow.backend.node_library import WORKFLOW_GRAPH_LIBRARY
from govoplan_workflow.backend.bpmn import (
BPMN_MODEL_NAMESPACE,
BpmnInspectionError,
NATIVE_EXECUTION_ELEMENTS,
NATIVE_MAPPING_ELEMENTS,
inspect_bpmn_xml,
)
from govoplan_workflow.backend.schemas import (
BpmnDiagnosticResponse,
BpmnElementSupportResponse,
BpmnInspectionRequest,
BpmnInspectionResponse,
BpmnSupportProfileResponse,
WorkflowConfigFieldResponse,
WorkflowDefinitionActivateRequest,
WorkflowDefinitionCreateRequest,
@@ -204,6 +216,85 @@ def _require_instance_view(instance, principal: ApiPrincipal) -> None:
)
@router.get("/bpmn/profile", response_model=BpmnSupportProfileResponse)
def api_bpmn_support_profile(
principal: ApiPrincipal = Depends(get_api_principal),
) -> BpmnSupportProfileResponse:
_require_any_scope(
principal,
DEFINITION_READ_SCOPE,
DEFINITION_WRITE_SCOPE,
ADMIN_SCOPE,
)
return BpmnSupportProfileResponse(
specification="BPMN 2.0.2",
model_namespace=BPMN_MODEL_NAMESPACE,
interchange=(
"Secure XML inventory and diagnostics are available. Visual "
"round-trip modeling requires the planned bpmn-js adapter."
),
native_runtime=(
"Only the explicitly listed executable subset maps to current "
"native runtime semantics; all other elements are interchange-only."
),
native_execution_elements=sorted(NATIVE_EXECUTION_ELEMENTS),
native_mapping_elements=sorted(
NATIVE_MAPPING_ELEMENTS - NATIVE_EXECUTION_ELEMENTS
),
)
@router.post("/bpmn/inspect", response_model=BpmnInspectionResponse)
def api_inspect_bpmn(
payload: BpmnInspectionRequest,
principal: ApiPrincipal = Depends(get_api_principal),
) -> BpmnInspectionResponse:
_require_any_scope(
principal,
DEFINITION_READ_SCOPE,
DEFINITION_WRITE_SCOPE,
ADMIN_SCOPE,
)
try:
result = inspect_bpmn_xml(payload.xml)
except BpmnInspectionError as exc:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
detail=str(exc),
) from exc
return BpmnInspectionResponse(
valid_xml=result.valid_xml,
definitions_id=result.definitions_id,
target_namespace=result.target_namespace,
process_count=result.process_count,
executable_process_count=result.executable_process_count,
collaboration_count=result.collaboration_count,
choreography_count=result.choreography_count,
element_counts=result.element_counts,
support_counts=result.support_counts,
elements=[
BpmnElementSupportResponse(
element_type=item.element_type,
element_id=item.element_id,
name=item.name,
parent_type=item.parent_type,
parent_id=item.parent_id,
support_level=item.support_level,
)
for item in result.elements
],
diagnostics=[
BpmnDiagnosticResponse(
severity=item.severity,
code=item.code,
message=item.message,
element_id=item.element_id,
)
for item in result.diagnostics
],
)
@router.get("/node-types", response_model=WorkflowNodeLibraryResponse)
def api_node_types(
principal: ApiPrincipal = Depends(get_api_principal),