diff --git a/app/api/dependencies.py b/app/api/dependencies.py
index b94a488584440c31c92ec48878745fcd0aa2bd48..eb8d75a1062526e917c610540e75bf78cbb061f5 100644
--- a/app/api/dependencies.py
+++ b/app/api/dependencies.py
@@ -255,7 +255,7 @@ async def get_current_workflow_version(
     git_commit_hash: str = Path(
         ...,
         description="Git commit git_commit_hash of specific version.",
-        regex=r"^([0-9a-f]{40}|latest)$",
+        pattern=r"^([0-9a-f]{40}|latest)$",
         examples=["ba8bcd9294c2c96aedefa1763a84a18077c50c0f"],
     ),
 ) -> WorkflowVersion:
diff --git a/app/api/endpoints/workflow.py b/app/api/endpoints/workflow.py
index 8735fa2066d2fa7fea55e39f84200d2c9795ce3f..ddad1ec42533feb9a3168c622958055551a61bdf 100644
--- a/app/api/endpoints/workflow.py
+++ b/app/api/endpoints/workflow.py
@@ -1,7 +1,7 @@
 from typing import Annotated, Any, Awaitable, Callable, List, Optional, Set
 from uuid import UUID
 
-from clowmdb.models import Workflow, WorkflowVersion
+from clowmdb.models import Workflow, WorkflowMode, WorkflowVersion
 from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query, Response, status
 
 from app.api.dependencies import AuthorizationDependency, CurrentUser, CurrentWorkflow, DBSession, HTTPClient, S3Service
@@ -361,12 +361,10 @@ async def update_workflow(
             detail=f"Workflow Version with git_commit_hash'{version_update.git_commit_hash}' already exists",
         )
     # Get previous version
-    previous_version = await CRUDWorkflowVersion.get_latest(db, workflow.workflow_id, published=False)
+    previous_version: WorkflowVersion = await CRUDWorkflowVersion.get_latest(db, workflow.workflow_id, published=False)
 
     # Get modes of previous version
-    previous_version_modes = await CRUDWorkflowMode.list_modes(
-        db, previous_version.workflow_modes  # type: ignore[union-attr]
-    )
+    previous_version_modes = await CRUDWorkflowMode.list_modes(db, previous_version.git_commit_hash)
 
     if version_update.delete_modes is not None:
         # Check if mode to delete actually exist
@@ -375,7 +373,7 @@ async def update_workflow(
             if delete_mode not in mode_ids:
                 raise HTTPException(
                     status_code=status.HTTP_400_BAD_REQUEST,
-                    detail=f"Workflow mode {delete_mode} does not exist for the latest version of workflow {workflow.workflow_id}",  # noqa: E501
+                    detail=f"Workflow mode {delete_mode} does not exist for the latest version {previous_version.git_commit_hash} of workflow {workflow.workflow_id}",  # noqa: E501
                 )
         # Filter out modes that should be deleted in new workflow version
         previous_version_modes = [
@@ -385,13 +383,13 @@ async def update_workflow(
     # Build a git repository object based on the repository url
     repo = build_repository(workflow.repository_url, version_update.git_commit_hash)
 
-    check_repo_modes = previous_version_modes
+    check_repo_modes = previous_version_modes.copy()
     # If there are new modes, add them to the list for file checking
     if version_update.append_modes is not None:
         check_repo_modes += version_update.append_modes
     await check_repo(repo=repo, client=client, modes=check_repo_modes)
 
-    append_modes_db = []
+    append_modes_db: List[WorkflowMode] = []
     # Create new modes in database
     if version_update.append_modes is not None:
         append_modes_db = await CRUDWorkflowMode.create(db, version_update.append_modes)
diff --git a/app/api/endpoints/workflow_execution.py b/app/api/endpoints/workflow_execution.py
index ca3c30bcfa7d398003f29b8a3386d1cc40dcd323..9052e0c89310097efc3b7fa0f36178b7302a613e 100644
--- a/app/api/endpoints/workflow_execution.py
+++ b/app/api/endpoints/workflow_execution.py
@@ -295,7 +295,7 @@ async def list_workflow_executions(
         None,
         description="Filter for workflow version",
         examples=["ba8bcd9294c2c96aedefa1763a84a18077c50c0f"],
-        regex=r"^[0-9a-f]{40}$",
+        pattern=r"^[0-9a-f]{40}$",
     ),
 ) -> List[WorkflowExecutionOut]:
     """
diff --git a/app/api/endpoints/workflow_version.py b/app/api/endpoints/workflow_version.py
index e910f9431582b43e50d03286fd6a803d46b9a492..6d75cab22f22b4799e765619df071fa4bb166c90 100644
--- a/app/api/endpoints/workflow_version.py
+++ b/app/api/endpoints/workflow_version.py
@@ -108,7 +108,7 @@ async def get_workflow_version(
     git_commit_hash: str = Path(
         ...,
         description="Git commit git_commit_hash of specific version or 'latest'.",
-        regex=r"^([0-9a-f]{40}|latest)$",
+        pattern=r"^([0-9a-f]{40}|latest)$",
         examples=["latest", "ba8bcd9294c2c96aedefa1763a84a18077c50c0f"],
     ),
 ) -> WorkflowVersionSchema:
diff --git a/app/schemas/workflow.py b/app/schemas/workflow.py
index 17f2e0aa274d6c9680fe978b75fd4464aa3cbff1..9359b7129eaa601cf1ccea443084412b6f2a5be6 100644
--- a/app/schemas/workflow.py
+++ b/app/schemas/workflow.py
@@ -138,7 +138,7 @@ class WorkflowUpdate(BaseModel):
         ...,
         description="Version of the Workflow. Should follow semantic versioning",
         examples=["v1.1.0"],
-        minlength=5,
+        min_length=5,
         max_length=10,
     )
     git_commit_hash: str = Field(
diff --git a/app/schemas/workflow_version.py b/app/schemas/workflow_version.py
index cad1201d5c9efcd8970dfee75eae3412d2cec9df..0d5615a6d11f8f91dc601d2635027f8be81d79a3 100644
--- a/app/schemas/workflow_version.py
+++ b/app/schemas/workflow_version.py
@@ -20,7 +20,7 @@ class WorkflowVersion(WorkflowVersionStatus):
         ...,
         description="Version of the Workflow. Should follow semantic versioning",
         examples=["v1.0.0"],
-        minlength=5,
+        min_length=5,
         max_length=10,
     )
     git_commit_hash: str = Field(
diff --git a/app/tests/api/test_workflow.py b/app/tests/api/test_workflow.py
index cc5b51c5350cc8ab4073590cb0b4bb084d3e9060..47058d463e86ba40dd046fce54a47dcf549de140 100644
--- a/app/tests/api/test_workflow.py
+++ b/app/tests/api/test_workflow.py
@@ -415,7 +415,7 @@ class TestWorkflowRoutesCreate(_TestWorkflowRoutes):
         mock_s3_service: MockS3ServiceResource,
     ) -> None:
         """
-        Exhaustive Test for successfully creating a workflow.
+        Exhaustive Test for successfully creating a workflow with a workflow mode.
 
         Parameters
         ----------
@@ -660,6 +660,83 @@ class TestWorkflowRoutesDelete(_TestWorkflowRoutes):
         schema_file = random_workflow.versions[0].git_commit_hash + ".json"
         assert schema_file not in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
 
+    @pytest.mark.asyncio
+    async def test_delete_private_workflow(
+        self,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_private_workflow: WorkflowOut,
+        mock_s3_service: MockS3ServiceResource,
+    ) -> None:
+        """
+        Test for deleting a workflow by its id.
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_private_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        """
+        response = await client.delete(
+            "/".join([self.base_path, str(random_private_workflow.workflow_id)]),
+            headers=random_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_204_NO_CONTENT
+        icon_slug = str(random_private_workflow.versions[0].icon_url).split("/")[-1]
+        assert icon_slug not in mock_s3_service.Bucket(settings.ICON_BUCKET).objects.all_keys()
+        schema_file = random_private_workflow.versions[0].git_commit_hash + ".json"
+        assert schema_file not in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+        scm_file = f"{random_private_workflow.workflow_id.hex}.scm"
+        assert scm_file not in mock_s3_service.Bucket(settings.PARAMS_BUCKET).objects.all_keys()
+
+    @pytest.mark.asyncio
+    async def test_delete_workflow_with_mode(
+        self,
+        client: AsyncClient,
+        db: AsyncSession,
+        random_user: UserWithAuthHeader,
+        random_workflow: WorkflowOut,
+        random_workflow_mode: WorkflowMode,
+        mock_s3_service: MockS3ServiceResource,
+    ) -> None:
+        """
+        Test for deleting a workflow by its id.
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        random_workflow_mode : clowmdb.model.WorkflowMode
+            Random workflow mode for testing
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
+        """
+        response = await client.delete(
+            "/".join([self.base_path, str(random_workflow.workflow_id)]),
+            headers=random_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_204_NO_CONTENT
+        icon_slug = str(random_workflow.versions[0].icon_url).split("/")[-1]
+        assert icon_slug not in mock_s3_service.Bucket(settings.ICON_BUCKET).objects.all_keys()
+        schema_file = f"{random_workflow.versions[0].git_commit_hash}-{random_workflow_mode.mode_id.hex}.json"
+        assert schema_file not in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+
+        mode_db = await db.scalar(
+            select(WorkflowMode).where(WorkflowMode._mode_id == random_workflow_mode.mode_id.bytes)
+        )
+        assert mode_db is None
+
 
 class TestWorkflowRoutesUpdate(_TestWorkflowRoutes):
     @pytest.mark.asyncio
@@ -677,6 +754,8 @@ class TestWorkflowRoutesUpdate(_TestWorkflowRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
         """
         git_commit_hash = random_hex_string()
         version_update = WorkflowUpdate(
@@ -699,6 +778,241 @@ class TestWorkflowRoutesUpdate(_TestWorkflowRoutes):
         assert db_version is not None
         assert db_version.status == WorkflowVersion.Status.CREATED
 
+    @pytest.mark.asyncio
+    async def test_update_workflow_with_append_modes(
+        self,
+        db: AsyncSession,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow: WorkflowOut,
+        random_workflow_mode: WorkflowMode,
+        mock_s3_service: MockS3ServiceResource,
+    ) -> None:
+        """
+        Test for successfully updating a workflow and adding new modes.
+
+        Parameters
+        ----------
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
+        random_workflow_mode : clowmdb.model.WorkflowMode
+            Random workflow mode for testing
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        """
+        git_commit_hash = random_hex_string()
+        version_update = WorkflowUpdate(
+            git_commit_hash=git_commit_hash,
+            version=random_lower_string(8),
+            append_modes=[
+                WorkflowModeIn(
+                    name=random_lower_string(10), entrypoint=random_lower_string(16), schema_path=random_lower_string()
+                )
+            ],
+        ).model_dump()
+        response = await client.post(
+            "/".join([self.base_path, str(random_workflow.workflow_id), "update"]),
+            json=version_update,
+            headers=random_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_201_CREATED
+        created_version = response.json()
+        assert created_version["git_commit_hash"] == git_commit_hash
+        assert created_version["status"] == WorkflowVersion.Status.CREATED
+        assert created_version["icon_url"] == str(random_workflow.versions[0].icon_url)
+        assert created_version["modes"] is not None
+        assert len(created_version["modes"]) == 2
+
+        stmt = select(WorkflowVersion).where(WorkflowVersion.git_commit_hash == git_commit_hash)
+        db_version = await db.scalar(stmt)
+        assert db_version is not None
+        assert db_version.status == WorkflowVersion.Status.CREATED
+
+        new_mode_id = next((UUID(m) for m in created_version["modes"] if m != str(random_workflow_mode.mode_id)), None)
+        assert new_mode_id is not None
+        assert (
+            f"{git_commit_hash}-{new_mode_id.hex}.json"
+            in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+        )
+        assert (
+            f"{git_commit_hash}-{random_workflow_mode.mode_id.hex}.json"
+            in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+        )
+
+        # Clean up after test
+        await db.execute(delete(WorkflowMode).where(WorkflowMode._mode_id == new_mode_id.bytes))
+        await db.commit()
+        mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).Object(f"{git_commit_hash}-{new_mode_id.hex}.json").delete()
+
+    @pytest.mark.asyncio
+    async def test_update_workflow_with_delete_non_existing_modes(
+        self,
+        db: AsyncSession,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow: WorkflowOut,
+    ) -> None:
+        """
+        Test for updating a workflow and delete an non-existing mode.
+
+        Parameters
+        ----------
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
+        """
+        git_commit_hash = random_hex_string()
+        version_update = WorkflowUpdate(
+            git_commit_hash=git_commit_hash, version=random_lower_string(8), delete_modes=[str(uuid4())]
+        ).model_dump_json()
+        response = await client.post(
+            "/".join([self.base_path, str(random_workflow.workflow_id), "update"]),
+            data=version_update,  # type: ignore[arg-type]
+            headers=random_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_400_BAD_REQUEST
+
+    @pytest.mark.asyncio
+    async def test_update_workflow_with_delete_modes(
+        self,
+        db: AsyncSession,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow: WorkflowOut,
+        random_workflow_mode: WorkflowMode,
+        mock_s3_service: MockS3ServiceResource,
+    ) -> None:
+        """
+        Test for successfully updating a workflow and delete an old mode.
+
+        Parameters
+        ----------
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
+        random_workflow_mode : clowmdb.model.WorkflowMode
+            Random workflow mode for testing
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        """
+        git_commit_hash = random_hex_string()
+        version_update = WorkflowUpdate(
+            git_commit_hash=git_commit_hash,
+            version=random_lower_string(8),
+            delete_modes=[str(random_workflow_mode.mode_id)],
+        ).model_dump_json()
+        response = await client.post(
+            "/".join([self.base_path, str(random_workflow.workflow_id), "update"]),
+            data=version_update,  # type: ignore[arg-type]
+            headers=random_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_201_CREATED
+        created_version = response.json()
+        assert created_version["git_commit_hash"] == git_commit_hash
+        assert created_version["status"] == WorkflowVersion.Status.CREATED
+        assert created_version["icon_url"] == str(random_workflow.versions[0].icon_url)
+        assert created_version["modes"] is not None
+        assert created_version["modes"] is None or len(created_version["modes"]) == 0
+
+        stmt = select(WorkflowVersion).where(WorkflowVersion.git_commit_hash == git_commit_hash)
+        db_version = await db.scalar(stmt)
+        assert db_version is not None
+        assert db_version.status == WorkflowVersion.Status.CREATED
+
+        assert (
+            f"{git_commit_hash}-{random_workflow_mode.mode_id.hex}.json"
+            not in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+        )
+
+    @pytest.mark.asyncio
+    async def test_update_workflow_with_append_and_delete_modes(
+        self,
+        db: AsyncSession,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow: WorkflowOut,
+        random_workflow_mode: WorkflowMode,
+        mock_s3_service: MockS3ServiceResource,
+    ) -> None:
+        """
+        Test for successfully updating a workflow with adding a new mode and delete an old mode.
+
+        Parameters
+        ----------
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
+        random_workflow_mode : clowmdb.model.WorkflowMode
+            Random workflow mode for testing
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        """
+        git_commit_hash = random_hex_string()
+        version_update = WorkflowUpdate(
+            git_commit_hash=git_commit_hash,
+            version=random_lower_string(8),
+            delete_modes=[str(random_workflow_mode.mode_id)],
+            append_modes=[
+                WorkflowModeIn(
+                    name=random_lower_string(10), entrypoint=random_lower_string(16), schema_path=random_lower_string()
+                )
+            ],
+        ).model_dump_json()
+        response = await client.post(
+            "/".join([self.base_path, str(random_workflow.workflow_id), "update"]),
+            data=version_update,  # type: ignore[arg-type]
+            headers=random_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_201_CREATED
+        created_version = response.json()
+        assert created_version["git_commit_hash"] == git_commit_hash
+        assert created_version["status"] == WorkflowVersion.Status.CREATED
+        assert created_version["icon_url"] == str(random_workflow.versions[0].icon_url)
+        assert created_version["modes"] is not None
+        assert len(created_version["modes"]) == 1
+        assert created_version["modes"][0] != str(random_workflow_mode.mode_id)
+
+        stmt = select(WorkflowVersion).where(WorkflowVersion.git_commit_hash == git_commit_hash)
+        db_version = await db.scalar(stmt)
+        assert db_version is not None
+        assert db_version.status == WorkflowVersion.Status.CREATED
+
+        mode_id = UUID(created_version["modes"][0])
+        assert (
+            f"{git_commit_hash}-{mode_id.hex}.json"
+            in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+        )
+        assert (
+            f"{git_commit_hash}-{random_workflow_mode.mode_id.hex}.json"
+            not in mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).objects.all_keys()
+        )
+
+        # Clean up after test
+        await db.execute(delete(WorkflowMode).where(WorkflowMode._mode_id == mode_id.bytes))
+        await db.commit()
+        mock_s3_service.Bucket(settings.WORKFLOW_BUCKET).Object(f"{git_commit_hash}-{mode_id.hex}.json").delete()
+
     @pytest.mark.asyncio
     async def test_update_workflow_with_error(
         self, db: AsyncSession, client: AsyncClient, random_user: UserWithAuthHeader, random_workflow: WorkflowOut
@@ -714,6 +1028,8 @@ class TestWorkflowRoutesUpdate(_TestWorkflowRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
         """
         version_update = WorkflowUpdate(
             git_commit_hash=random_hex_string(),
@@ -774,6 +1090,8 @@ class TestWorkflowRoutesUpdate(_TestWorkflowRoutes):
             HTTP Client to perform the request on.
         random_second_user : app.tests.utils.user.UserWithAuthHeader
             Random second user for testing.
+        random_workflow : app.schemas.workflow.WorkflowOut
+            Random workflow for testing.
         """
         version_update = WorkflowUpdate(
             git_commit_hash=random_hex_string(),
diff --git a/app/tests/api/test_workflow_execution.py b/app/tests/api/test_workflow_execution.py
index c66ebc7ac089ac24e3871b2b670b2b0fd089542b..b310215c8bbb5a7c6e6387971acff87934936ad6 100644
--- a/app/tests/api/test_workflow_execution.py
+++ b/app/tests/api/test_workflow_execution.py
@@ -11,6 +11,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
 from app.core.config import settings
 from app.schemas.workflow import WorkflowOut
 from app.schemas.workflow_execution import DevWorkflowExecutionIn, WorkflowExecutionIn
+from app.schemas.workflow_mode import WorkflowModeIn
 from app.scm import SCM
 from app.tests.mocks import MockS3ServiceResource, MockSlurmCluster
 from app.tests.utils.bucket import add_permission_for_bucket
@@ -34,7 +35,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         mock_slurm_cluster: MockSlurmCluster,
     ) -> None:
         """
-        Test for starting a workflow execution.
+        Test for starting a workflow execution from a public GitHub repository.
 
         Parameters
         ----------
@@ -148,11 +149,12 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         mock_slurm_cluster: MockSlurmCluster,
     ) -> None:
         """
-        Test for starting a workflow execution.
+        Test for starting a workflow execution from a public GitLab repository.
 
         Parameters
         ----------
-        db :
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
         client : httpx.AsyncClient
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
@@ -262,7 +264,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         random_workflow_version: WorkflowVersion,
     ) -> None:
         """
-        Test for starting a workflow execution with an unknown workflow version.
+        Test for starting a workflow execution with a deprecated workflow version.
 
         Parameters
         ----------
@@ -296,7 +298,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         random_workflow_version: WorkflowVersion,
     ) -> None:
         """
-        Test for starting a workflow execution with a non-existing bucket.
+        Test for starting a workflow execution with a non-existing bucket in the parameters.
 
         Parameters
         ----------
@@ -323,7 +325,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         random_workflow_version: WorkflowVersion,
     ) -> None:
         """
-        Test for starting a workflow execution with an existing bucket.
+        Test for starting a workflow execution with an existing bucket in the parameters.
 
         Parameters
         ----------
@@ -353,7 +355,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         random_workflow_version: WorkflowVersion,
     ) -> None:
         """
-        Test for starting a workflow execution with a permission for the reference bucket.
+        Test for starting a workflow execution with a permission for the referenced bucket.
 
         Parameters
         ----------
@@ -387,7 +389,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         random_workflow_version: WorkflowVersion,
     ) -> None:
         """
-        Test for starting a workflow execution without a permission for the reference bucket.
+        Test for starting a workflow execution without a permission for the referenced bucket.
 
         Parameters
         ----------
@@ -489,7 +491,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         mock_slurm_cluster: MockSlurmCluster,
     ) -> None:
         """
-        Test for starting a workflow execution where the report output bucket is a non-existing bucket.
+        Test for starting a workflow execution with an workflow mode
 
         Parameters
         ----------
@@ -529,7 +531,7 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
         mock_slurm_cluster: MockSlurmCluster,
     ) -> None:
         """
-        Test for starting a workflow execution where the report output bucket is a non-existing bucket.
+        Test for starting a workflow execution with a non-existing workflow mode
 
         Parameters
         ----------
@@ -552,6 +554,62 @@ class TestWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
 
 
 class TestDevWorkflowExecutionRoutesCreate(_TestWorkflowExecutionRoutes):
+    @pytest.mark.asyncio
+    async def test_start_dev_workflow_execution_from_github_with_mode(
+        self,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        mock_s3_service: MockS3ServiceResource,
+        mock_slurm_cluster: MockSlurmCluster,
+    ) -> None:
+        """
+        Test for starting a workflow execution with an arbitrary GitHub repository and a workflow mode.
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        mock_slurm_cluster : app.tests.mocks.mock_slurm_cluster.MockSlurmCluster
+            Mock Slurm cluster to inspect submitted jobs.
+        """
+        mode = WorkflowModeIn(
+            name=random_lower_string(10), entrypoint=random_lower_string(16), schema_path=random_lower_string(16)
+        )
+        execution_in = DevWorkflowExecutionIn(
+            git_commit_hash=random_hex_string(),
+            repository_url="https://github.com/example-user/example",
+            parameters={},
+            mode=mode,
+        )
+        response = await client.post(
+            f"{self.base_path}/arbitrary", headers=random_user.auth_headers, json=execution_in.model_dump()
+        )
+        assert response.status_code == status.HTTP_201_CREATED
+        execution_response = response.json()
+        assert execution_response["user_id"] == random_user.user.uid
+        assert execution_response["status"] == WorkflowExecution.WorkflowExecutionStatus.PENDING
+
+        assert (
+            f"params-{UUID(hex=execution_response['execution_id']).hex }.json"
+            in mock_s3_service.Bucket(settings.PARAMS_BUCKET).objects.all_keys()
+        )
+
+        execution_id = UUID(execution_response["execution_id"])
+        job = mock_slurm_cluster.get_job_by_name(str(execution_id))
+        assert job is not None
+        assert job["job"]["environment"]["TOWER_WORKSPACE_ID"] == execution_id.hex[:16]
+        assert "NXF_SCM_FILE" not in job["job"]["environment"].keys()
+
+        nextflow_script = job["script"]
+        assert "-hub github" in nextflow_script
+        assert f"-entry {mode.entrypoint}" in nextflow_script
+        assert f"-revision {execution_in.git_commit_hash}" in nextflow_script
+        assert f"run {execution_in.repository_url}" in nextflow_script
+
     @pytest.mark.asyncio
     async def test_start_dev_workflow_execution_from_github(
         self,
diff --git a/app/tests/api/test_workflow_mode.py b/app/tests/api/test_workflow_mode.py
index 4b98d5ee0e69047eb879c655f7a76dbac5b0b369..be506d55e25106de8d9cbe1086b212d9508e502d 100644
--- a/app/tests/api/test_workflow_mode.py
+++ b/app/tests/api/test_workflow_mode.py
@@ -9,13 +9,15 @@ from app.tests.utils.user import UserWithAuthHeader
 
 
 class TestWorkflowModeRoutesGet:
+    _base_path = "workflow_modes"
+
     @pytest.mark.asyncio
     async def test_get_non_existing_workflow_mode(
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
     ) -> None:
-        response = await client.get(f"/{uuid4()}", headers=random_user.auth_headers)
+        response = await client.get(f"{self._base_path}/{uuid4()}", headers=random_user.auth_headers)
         assert response.status_code == status.HTTP_404_NOT_FOUND
 
     @pytest.mark.asyncio
@@ -26,7 +28,7 @@ class TestWorkflowModeRoutesGet:
         random_workflow_mode: WorkflowMode,
     ) -> None:
         response = await client.get(
-            f"workflow_modes/{str(random_workflow_mode.mode_id)}", headers=random_user.auth_headers
+            f"{self._base_path}/{str(random_workflow_mode.mode_id)}", headers=random_user.auth_headers
         )
         assert response.status_code == status.HTTP_200_OK
         mode = response.json()
diff --git a/app/tests/api/test_workflow_version.py b/app/tests/api/test_workflow_version.py
index c403effd5fc91985116cd8bc8b54a94dc12cb77b..c601d70d1bbe9523b3aa669625c4408acff60d10 100644
--- a/app/tests/api/test_workflow_version.py
+++ b/app/tests/api/test_workflow_version.py
@@ -1,10 +1,10 @@
 from io import BytesIO
+from uuid import uuid4
 
 import pytest
-from clowmdb.models import WorkflowVersion
+from clowmdb.models import WorkflowMode, WorkflowVersion
 from fastapi import status
 from httpx import AsyncClient
-from mocks.mock_s3_resource import MockS3ServiceResource
 from sqlalchemy import select
 from sqlalchemy.ext.asyncio import AsyncSession
 
@@ -12,6 +12,7 @@ from app.api.endpoints.workflow_version import DocumentationEnum
 from app.core.config import settings
 from app.schemas.workflow import WorkflowOut
 from app.schemas.workflow_version import WorkflowVersionStatus
+from app.tests.mocks.mock_s3_resource import MockS3ServiceResource
 from app.tests.utils.user import UserWithAuthHeader
 from app.tests.utils.utils import random_hex_string
 
@@ -227,7 +228,10 @@ class TestWorkflowVersionRoutesUpdate(_TestWorkflowVersionRoutes):
 class TestWorkflowVersionRoutesGetDocumentation(_TestWorkflowVersionRoutes):
     @pytest.mark.asyncio
     async def test_download_workflow_version_documentation(
-        self, client: AsyncClient, random_user: UserWithAuthHeader, random_workflow: WorkflowOut
+        self,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow_version: WorkflowVersion,
     ) -> None:
         """
         Test downloading all the different documentation file for a workflow version.
@@ -238,17 +242,17 @@ class TestWorkflowVersionRoutesGetDocumentation(_TestWorkflowVersionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow : app.schemas.workflow.WorkflowOut
-            Random workflow for testing.
+        random_workflow_version : clowmdb.models.WorkflowVersion
+            Random workflow version for testing.
         """
         for document in DocumentationEnum:
             response = await client.get(
                 "/".join(
                     [
                         self.base_path,
-                        str(random_workflow.workflow_id),
+                        str(random_workflow_version.workflow_id),
                         "versions",
-                        random_workflow.versions[0].git_commit_hash,
+                        random_workflow_version.git_commit_hash,
                         "documentation",
                     ]
                 ),
@@ -257,6 +261,79 @@ class TestWorkflowVersionRoutesGetDocumentation(_TestWorkflowVersionRoutes):
             )
             assert response.status_code == status.HTTP_200_OK
 
+    @pytest.mark.asyncio
+    async def test_download_workflow_version_documentation_with_non_existing_mode(
+        self,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow_version: WorkflowVersion,
+    ) -> None:
+        """
+        Test downloading all the different documentation file for a workflow version with a non-existing workflow mode.
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow_version : clowmdb.models.WorkflowVersion
+            Random workflow version for testing.
+        """
+        for document in DocumentationEnum:
+            response = await client.get(
+                "/".join(
+                    [
+                        self.base_path,
+                        str(random_workflow_version.workflow_id),
+                        "versions",
+                        random_workflow_version.git_commit_hash,
+                        "documentation",
+                    ]
+                ),
+                headers=random_user.auth_headers,
+                params={"document": document.value, "mode_id": str(uuid4())},
+            )
+            assert response.status_code == status.HTTP_404_NOT_FOUND
+
+    @pytest.mark.asyncio
+    async def test_download_workflow_version_documentation_with_existing_mode(
+        self,
+        client: AsyncClient,
+        random_user: UserWithAuthHeader,
+        random_workflow_version: WorkflowVersion,
+        random_workflow_mode: WorkflowMode,
+    ) -> None:
+        """
+        Test downloading all the different documentation file for a workflow version with a workflow mode.
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow_version : clowmdb.models.WorkflowVersion
+            Random workflow version for testing.
+        random_workflow_mode : clowmdb.models.WorkflowMode
+            Random workflow mode for testing.
+        """
+        for document in DocumentationEnum:
+            response = await client.get(
+                "/".join(
+                    [
+                        self.base_path,
+                        str(random_workflow_version.workflow_id),
+                        "versions",
+                        random_workflow_version.git_commit_hash,
+                        "documentation",
+                    ]
+                ),
+                headers=random_user.auth_headers,
+                params={"document": document.value, "mode_id": str(random_workflow_mode.mode_id)},
+            )
+            assert response.status_code == status.HTTP_200_OK
+
 
 class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
     @pytest.mark.asyncio
@@ -264,7 +341,7 @@ class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow: WorkflowOut,
+        random_workflow_version: WorkflowVersion,
         mock_s3_service: MockS3ServiceResource,
         db: AsyncSession,
     ) -> None:
@@ -277,22 +354,21 @@ class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow : app.schemas.workflow.WorkflowOut
-            Random workflow for testing.
+        random_workflow_version : clowmdb.models.WorkflowVersion
+            Random workflow version for testing.
         mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
             Mock S3 Service to manipulate objects.
         db : sqlalchemy.ext.asyncio.AsyncSession.
             Async database session to perform query on.
         """
         files = {"icon": ("RickRoll.txt", BytesIO(b"Never gonna give you up"), "plain/text")}
-        version_hash = random_workflow.versions[0].git_commit_hash
         response = await client.post(
             "/".join(
                 [
                     self.base_path,
-                    str(random_workflow.workflow_id),
+                    str(random_workflow_version.workflow_id),
                     "versions",
-                    version_hash,
+                    random_workflow_version.git_commit_hash,
                     "icon",
                 ]
             ),
@@ -302,19 +378,55 @@ class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
         assert response.status_code == status.HTTP_201_CREATED
         icon_slug = response.json()
         assert icon_slug in mock_s3_service.Bucket(settings.ICON_BUCKET).objects.all_keys()
-        db_version = await db.scalar(select(WorkflowVersion).where(WorkflowVersion.git_commit_hash == version_hash))
+        db_version = await db.scalar(
+            select(WorkflowVersion).where(WorkflowVersion.git_commit_hash == random_workflow_version.git_commit_hash)
+        )
         assert db_version is not None
         assert db_version.icon_slug == icon_slug
 
         # Clean up
         mock_s3_service.Bucket(settings.ICON_BUCKET).Object(icon_slug).delete()
 
+    @pytest.mark.asyncio
+    async def test_upload_new_icon_as_non_developer(
+        self,
+        client: AsyncClient,
+        random_second_user: UserWithAuthHeader,
+        random_workflow_version: WorkflowVersion,
+    ) -> None:
+        """
+        Test for uploading a new icon for a workflow version
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_second_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow_version : clowmdb.models.WorkflowVersion
+            Random workflow version for testing.
+        """
+        files = {"icon": ("RickRoll.txt", BytesIO(b"Never gonna give you up"), "plain/text")}
+        response = await client.post(
+            "/".join(
+                [
+                    self.base_path,
+                    str(random_workflow_version.workflow_id),
+                    "versions",
+                    random_workflow_version.git_commit_hash,
+                    "icon",
+                ]
+            ),
+            headers=random_second_user.auth_headers,
+            files=files,
+        )
+        assert response.status_code == status.HTTP_403_FORBIDDEN
+
     @pytest.mark.asyncio
     async def test_delete_icon(
         self,
         client: AsyncClient,
         random_user: UserWithAuthHeader,
-        random_workflow: WorkflowOut,
         random_workflow_version: WorkflowVersion,
         mock_s3_service: MockS3ServiceResource,
         db: AsyncSession,
@@ -328,8 +440,6 @@ class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
             HTTP Client to perform the request on.
         random_user : app.tests.utils.user.UserWithAuthHeader
             Random user for testing.
-        random_workflow : app.schemas.workflow.WorkflowOut
-            Random workflow for testing.
         random_workflow_version : clowmdb.models.WorkflowVersion
             Random workflow version for testing.
         mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
@@ -342,7 +452,7 @@ class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
             "/".join(
                 [
                     self.base_path,
-                    str(random_workflow.workflow_id),
+                    str(random_workflow_version.workflow_id),
                     "versions",
                     random_workflow_version.git_commit_hash,
                     "icon",
@@ -357,3 +467,42 @@ class TestWorkflowVersionIconRoutes(_TestWorkflowVersionRoutes):
         )
         assert db_version is not None
         assert db_version.icon_slug is None
+
+    @pytest.mark.asyncio
+    async def test_delete_icon_as_non_developer(
+        self,
+        client: AsyncClient,
+        random_second_user: UserWithAuthHeader,
+        random_workflow_version: WorkflowVersion,
+        mock_s3_service: MockS3ServiceResource,
+        db: AsyncSession,
+    ) -> None:
+        """
+        Test for deleting a workflow version icon
+
+        Parameters
+        ----------
+        client : httpx.AsyncClient
+            HTTP Client to perform the request on.
+        random_second_user : app.tests.utils.user.UserWithAuthHeader
+            Random user for testing.
+        random_workflow_version : clowmdb.models.WorkflowVersion
+            Random workflow version for testing.
+        mock_s3_service : app.tests.mocks.mock_s3_resource.MockS3ServiceResource
+            Mock S3 Service to manipulate objects.
+        db : sqlalchemy.ext.asyncio.AsyncSession.
+            Async database session to perform query on.
+        """
+        response = await client.delete(
+            "/".join(
+                [
+                    self.base_path,
+                    str(random_workflow_version.workflow_id),
+                    "versions",
+                    random_workflow_version.git_commit_hash,
+                    "icon",
+                ]
+            ),
+            headers=random_second_user.auth_headers,
+        )
+        assert response.status_code == status.HTTP_403_FORBIDDEN