diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py
index dc4f639d8e8020613a9c6224bd53a5d96dc8459a..845fb9466ffe3d87a049f4eaf9307ebab95459c8 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py
@@ -5,7 +5,7 @@ This file contains permissions and filters that are used in the viewsets
 from rest_framework import permissions as drf_permissions, filters as drf_filters
 from .. import models
 from lofar.sas.tmss.tmss.exceptions import *
-from django.core.exceptions import ObjectDoesNotExist
+from django.core.exceptions import ObjectDoesNotExist, FieldError
 import logging
 logger = logging.getLogger(__name__)
 logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
@@ -40,20 +40,27 @@ def get_project_roles_for_user(user):
             # todo: remove these test users when not needed any more (required for local frontend testing where Keycloak is unavailable)
             if user == User.objects.get(username='tmss_friend'):
                 return ({'project': 'high', 'role': 'friend_of_project'},
-                        {'project': 'high', 'role': 'friend_of_project_primary'})
+                        {'project': 'high', 'role': 'friend_of_project_primary'},
+                        {'project': 'high', 'role': 'co_i'})
             if user == User.objects.get(username='tmss_friend2'):
-                return ({'project': 'high', 'role': 'friend_of_project'},)
+                return ({'project': 'high', 'role': 'friend_of_project'},
+                        {'project': 'high', 'role': 'co_i'})
             if user == User.objects.get(username='tmss_contact'):
-                return ({'project': 'high', 'role': 'contact'},)
+                return ({'project': 'high', 'role': 'contact'},
+                        {'project': 'high', 'role': 'co_i'})
             if user == User.objects.get(username='tmss_PI'):
-                return ({'project': 'high', 'role': 'pi'},)
+                return ({'project': 'high', 'role': 'pi'},
+                        {'project': 'high', 'role': 'co_i'})
             if user == User.objects.get(username='tmss_shared_support'):
                 return ({'project': 'high', 'role': 'shared_support'},
-                        {'project': 'high', 'role': 'shared_support_primary'})
+                        {'project': 'high', 'role': 'shared_support_primary'},
+                        {'project': 'high', 'role': 'co_i'})
             if user == User.objects.get(username='tmss_shared_support2'):
-                return ({'project': 'high', 'role': 'shared_support'},)
+                return ({'project': 'high', 'role': 'shared_support'},
+                        {'project': 'high', 'role': 'co_i'})
             if user == User.objects.get(username='scientist'):
-                return ({'project': 'high', 'role': 'co_i'},)
+                return ({'project': 'high', 'role': 'co_i'},
+                        {'project': 'high', 'role': 'co_i'})
 
         try:
             return tuple(user.project_roles)
@@ -146,7 +153,12 @@ class IsProjectMember(drf_permissions.DjangoObjectPermissions):
         # We need to check the project name before the object is created, but project is an object property.
         # Turning the path to the project into a (static) model attribute, allows us to use it both in the object
         # property as well as here (where we did not create an object yet).
-        if view.action == 'create' and request.data:
+        # Note: the Viewflow actions are currently create actions but they do not actually create anything
+        # (and do not contain the expected data to create an instance of the underlying model, but instead e.g. the
+        # data required to perform a workflow step). So we exclude the offending views here.
+        if view.action == 'create' and request.data \
+                and not 'SchedulingUnitTaskExecuteViewSet' in str(view) \
+                and not 'SchedulingUnitTaskAssignViewSet' in str(view):
             obj = None
             if view.serializer_class.Meta.model == models.Project:
                 return False  # project creation solely depends on system role
@@ -298,8 +310,18 @@ class IsProjectMemberFilterBackend(drf_filters.BaseFilterBackend):
                 return permitted_projects
             
             if hasattr(view.serializer_class.Meta.model, 'path_to_project'):
-                return queryset.filter(**{f"{view.serializer_class.Meta.model.path_to_project}__in": permitted_projects})
-            
+                path_to_project = view.serializer_class.Meta.model.path_to_project
+                try:
+                    return queryset.filter(**{f"{path_to_project}__in": permitted_projects})
+                except FieldError as e:
+                    # this is expected for models.schedulingunitflow.SchedulingUnitTask
+                    logger.warning('Cannot perform in-db filtering for project permissions on model=%s with path_to_project=%s: %s  -- applying slow filtering based on project property.' % (view.serializer_class.Meta.model, path_to_project, e))
+                    ids = []
+                    for candidate in queryset.all():
+                        if candidate.project in permitted_projects:
+                            ids.append(candidate.id)
+                    return queryset.filter(id__in=ids)
+
             if hasattr(view.serializer_class.Meta.model, 'project'):
                 return queryset.filter(project__in=permitted_projects)
 
diff --git a/SAS/TMSS/backend/src/tmss/urls.py b/SAS/TMSS/backend/src/tmss/urls.py
index d155c5f2b918443c525b0c98862fa0e0cc9c8793..d160af6ac6551cc1f17f52e62c9d99db7e09cde4 100644
--- a/SAS/TMSS/backend/src/tmss/urls.py
+++ b/SAS/TMSS/backend/src/tmss/urls.py
@@ -280,10 +280,10 @@ if isViewflowEnabled():
     viewflow_router.register('scheduling_unit_flow/qa_decide_acceptance', workflow_viewsets.DecideAcceptanceViewSet, basename='qa_decide_acceptance')
     viewflow_router.register('scheduling_unit_flow/qa_scheduling_unit_process', workflow_viewsets.SchedulingUnitProcessViewSet, basename='qa_scheduling_unit_process')
     viewflow_router.register('scheduling_unit_flow/qa_scheduling_unit_task', workflow_viewsets.SchedulingUnitTaskViewSet, basename='qa_scheduling_unit_task')
-    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_task/(?P<qa_scheduling_unit_task_id>\d+)/assign', workflow_viewsets.SchedulingUnitTaskAssignViewSet)
-    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_task/(?P<qa_scheduling_unit_task_id>\d+)/unassign', workflow_viewsets.SchedulingUnitTaskUnassignViewSet)
-    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_process/(?P<qa_scheduling_unit_process_id>\d+)/current_task', workflow_viewsets.SchedulingUnitGetActiveTasksViewSet)
-    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_process/(?P<qa_scheduling_unit_process_id>\d+)/perform', workflow_viewsets.SchedulingUnitTaskExecuteViewSet)
+    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_task/(?P<pk>\d+)/assign', workflow_viewsets.SchedulingUnitTaskAssignViewSet)
+    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_task/(?P<pk>\d+)/unassign', workflow_viewsets.SchedulingUnitTaskUnassignViewSet)
+    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_process/(?P<pk>\d+)/current_task', workflow_viewsets.SchedulingUnitGetActiveTasksViewSet)
+    viewflow_router.register(r'scheduling_unit_flow/qa_scheduling_unit_process/(?P<pk>\d+)/perform', workflow_viewsets.SchedulingUnitTaskExecuteViewSet)
 
     viewflow_urlpatterns.extend(viewflow_router.urls)
 
diff --git a/SAS/TMSS/backend/src/tmss/workflowapp/flows/schedulingunitflow.py b/SAS/TMSS/backend/src/tmss/workflowapp/flows/schedulingunitflow.py
index c523b539ce414cb1667c3aabe813228c3010d7cd..e344b40c39848d3562b7e34bfe9a0f04bf34ab36 100644
--- a/SAS/TMSS/backend/src/tmss/workflowapp/flows/schedulingunitflow.py
+++ b/SAS/TMSS/backend/src/tmss/workflowapp/flows/schedulingunitflow.py
@@ -323,10 +323,11 @@ class SchedulingUnitFlow(Flow):
     def signal_SUB_allow_ingest(self, activation):
 
         logger.info("granting ingest permission for scheduling unit blueprint id=%s", activation.process.su.id)
-        activation.process.su.ingest_permission_granted_since = round_to_second_precision(datetime.utcnow())
-        activation.process.su.ingest_permission_required = True
+        if activation.process.su.ingest_permission_granted_since is None:
+            activation.process.su.ingest_permission_granted_since = round_to_second_precision(datetime.utcnow())
+        else:
+            logger.warning("ingest permission on scheduling unit blueprint id=%s has already been granted on %s" % (activation.process.su.id, activation.process.su.ingest_permission_granted_since))
         activation.process.su.save()
-
         activation.process.save()
 
     def check_SchedulingUnitBlueprint_status_or_beyond(self, activation, scheduling_unit: models.SchedulingUnitBlueprint, expected_status):
diff --git a/SAS/TMSS/backend/src/tmss/workflowapp/models/schedulingunitflow.py b/SAS/TMSS/backend/src/tmss/workflowapp/models/schedulingunitflow.py
index 4c05a91512d7c67c0d418b22c88b9361ae500f20..c1e0217b976ee691c93e8c13b4f0727bcbfb0bf9 100644
--- a/SAS/TMSS/backend/src/tmss/workflowapp/models/schedulingunitflow.py
+++ b/SAS/TMSS/backend/src/tmss/workflowapp/models/schedulingunitflow.py
@@ -11,29 +11,29 @@ from lofar.sas.tmss.tmss.tmssapp.models.common import ProjectPropertyMixin
 class QAReportingTO(Model, ProjectPropertyMixin):
     operator_report = TextField()
     operator_accept = BooleanField(default=False)
-    path_to_project = 'flow_process__su__draft__scheduling_set__project'  # todo: currently not used, verify in TMSS-982 / TMSS-2054
+    path_to_project = 'flow_process__su__draft__scheduling_set__project'
 
 class QAReportingSOS(Model, ProjectPropertyMixin):
     sos_report = TextField()
     quality_within_policy = BooleanField(default=False)
     sos_accept_show_pi = BooleanField(default=False)
-    path_to_project = 'flow_process__su__draft__scheduling_set__project'  # todo: currently not used, verify in TMSS-982 / TMSS-2054
+    path_to_project = 'flow_process__su__draft__scheduling_set__project'
 
 class PIVerification(Model, ProjectPropertyMixin):
     pi_report = TextField()
     pi_accept = BooleanField(default=False)
-    path_to_project = 'flow_process__su__draft__scheduling_set__project'  # todo: currently not used, verify in TMSS-982 / TMSS-2054
+    path_to_project = 'flow_process__su__draft__scheduling_set__project'
 
 class DecideAcceptance(Model, ProjectPropertyMixin):
     sos_accept_after_pi = BooleanField(default=False)
-    path_to_project = 'flow_process__su__draft__scheduling_set__project'  # todo: currently not used, verify in TMSS-982 / TMSS-2054
+    path_to_project = 'flow_process__su__draft__scheduling_set__project'
 
 class UnpinData(Model, ProjectPropertyMixin):
     unpin_data = BooleanField(default=False)
-    path_to_project = 'flow_process__su__draft__scheduling_set__project'  # todo: currently not used, verify in TMSS-982 / TMSS-2054
+    path_to_project = 'flow_process__su__draft__scheduling_set__project'
 
 class SchedulingUnitTask(Task, ProjectPropertyMixin):
-    path_to_project ='flow_process__su__draft__scheduling_set__project'   # todo: currently not used, verify in TMSS-982 / TMSS-2054
+    path_to_project = 'flow_process__su__draft__scheduling_set__project'  # Note: flow_process is not a db field but a property here
 
 class SchedulingUnitProcess(Process, ProjectPropertyMixin):
     """
diff --git a/SAS/TMSS/backend/src/tmss/workflowapp/viewsets/schedulingunitflow.py b/SAS/TMSS/backend/src/tmss/workflowapp/viewsets/schedulingunitflow.py
index 5bafd25a3044382b6f4336092dd8b20e0d46b996..618f07a4d34de378833a15dbfcc80d3d9053f9c5 100644
--- a/SAS/TMSS/backend/src/tmss/workflowapp/viewsets/schedulingunitflow.py
+++ b/SAS/TMSS/backend/src/tmss/workflowapp/viewsets/schedulingunitflow.py
@@ -133,6 +133,7 @@ class SchedulingUnitTaskViewSet(PreventSaveByUnassignedUsersMixin, TMSSFilterAnd
 
 class TMSSPermissionView(generic.CreateView):
     # todo: comment in to marshal permissions on the viewflow-internal views, if required.
+    #  Or rather merge with TMSSPermissionGenericViewSet
     #  -> TMSS-982 / TMSS-2054
     # permission_classes = (TMSSPermissions,)
     pass
@@ -279,7 +280,7 @@ class SchedulingUnitTaskAssignViewSet(mixins.CreateModelMixin,
                                     422: 'error'},
                          operation_description="Assign a Scheduling Unit Task to an user")
   def create(self, request, *args, **kwargs):
-    if 'qa_scheduling_unit_task_id' in kwargs:
+    if 'pk' in kwargs:
       try:
         user_email = request.GET.get('user_email')
         if user_email:  # For some reason this is GET data, even though it's a POST action...
@@ -288,7 +289,7 @@ class SchedulingUnitTaskAssignViewSet(mixins.CreateModelMixin,
                 return Response(content, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
             user, _ = User.objects.get_or_create(email=user_email, defaults={'username': 'user_%s' % uuid.uuid4()})  # Users that log in via Keycloak are matched with Django users with same email address
         elif request.GET.get('project_role'):  # For some reason this is GET data, even though it's a POST action...
-            task = models.SchedulingUnitTask.objects.filter(id=self.kwargs['qa_scheduling_unit_task_id'])[0]
+            task = models.SchedulingUnitTask.objects.filter(id=self.kwargs['pk'])[0]
             scheduling_unit_blueprint = task.flow_process.su
             project = scheduling_unit_blueprint.project.name
             users = get_users_by_role_in_project(role=request.GET.get('project_role'), project=project)
@@ -304,7 +305,7 @@ class SchedulingUnitTaskAssignViewSet(mixins.CreateModelMixin,
             user, _ = User.objects.get_or_create(email=user_email, defaults={'username': 'user_%s' % uuid.uuid4()})
         else:
             user = self.request.user
-        models.SchedulingUnitTask.objects.filter(id=self.kwargs['qa_scheduling_unit_task_id'])[0].activate().assign(user)
+        models.SchedulingUnitTask.objects.filter(id=self.kwargs['pk'])[0].activate().assign(user)
         content = {'Assigned': 'Scheduling Unit Task assigned to user=%s' % user.email}
         return Response(content, status=status.HTTP_200_OK)
       except AttributeError:
@@ -329,9 +330,9 @@ class SchedulingUnitTaskUnassignViewSet(mixins.CreateModelMixin,
                                     422: 'error'},
                          operation_description="Unassign a Scheduling Unit Task")
   def create(self, request, *args, **kwargs):
-    if 'qa_scheduling_unit_task_id' in kwargs:
+    if 'pk' in kwargs:
       try:
-        models.SchedulingUnitTask.objects.filter(id=self.kwargs['qa_scheduling_unit_task_id'])[0].activate().unassign()
+        models.SchedulingUnitTask.objects.filter(id=self.kwargs['pk'])[0].activate().unassign()
         content = {'Unassign': 'Scheduling Unit Task unassigned'}
         return Response(content, status=status.HTTP_200_OK)
       except AttributeError:
@@ -354,10 +355,10 @@ class SchedulingUnitGetActiveTasksViewSet(mixins.CreateModelMixin,
                                     403: 'forbidden',
                                     422: 'error'},
                          operation_description="Get the list of active tasks.")
-  def create(self, request, *args, **kwargs):
-    if 'qa_scheduling_unit_process_id' in kwargs:
+  def create(self, request, *args, **kwargs):    # todo: should be 'get'
+    if 'pk' in kwargs:
       try:
-        tasks = models.SchedulingUnitProcess.objects.filter(id=self.kwargs['qa_scheduling_unit_process_id'])[0].active_tasks()
+        tasks = models.SchedulingUnitProcess.objects.filter(id=self.kwargs['pk'])[0].active_tasks()
         return JsonResponse(list(tasks.values()), safe=False)
       except IndexError:
         content = {'Get Active Task(s)': 'No Process with the specified id'}
@@ -377,14 +378,14 @@ class SchedulingUnitTaskExecuteViewSet(mixins.CreateModelMixin,
   @swagger_auto_schema(responses={200: '',
                                     403: 'forbidden',
                                     422: 'error'},
-                         operation_description="Unassign a Scheduling Unit Task")
+                         operation_description="Perform a Scheduling Unit Task")
 
   def create(self, request, *args, **kwargs):
-    if 'qa_scheduling_unit_process_id' in kwargs:
+    if 'pk' in kwargs:
 
       try:
-        process= models.SchedulingUnitProcess.objects.get(pk=self.kwargs['qa_scheduling_unit_process_id'])
-        task = models.SchedulingUnitProcess.objects.get(pk=self.kwargs['qa_scheduling_unit_process_id']).active_tasks()[0]
+        process= models.SchedulingUnitProcess.objects.get(pk=self.kwargs['pk'])
+        task = models.SchedulingUnitProcess.objects.get(pk=self.kwargs['pk']).active_tasks()[0]
         view =  task.flow_task._view_class.as_view()
 
         act=task.activate()