diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/Sarif.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/Sarif.kt
index dfc4a8a7706884ee98ff4b411fd3dcf1709aca0e..7768af1419bef7d5f1dd0cb430652a3df76e5096 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/Sarif.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/Sarif.kt
@@ -89,25 +89,25 @@ data class Tool(
 @Serializable
 data class Driver(
     @SerialName("downloadUri")
-    val downloadUri: String,
+    val downloadUri: String? = null,
     @SerialName("fullName")
-    val fullName: String,
+    val fullName: String? = null,
     @SerialName("guid")
-    val guid: String,
+    val guid: String? = null,
     @SerialName("informationUri")
-    val informationUri: String,
+    val informationUri: String? = null,
     @SerialName("language")
-    val language: String,
+    val language: String? = null,
     @SerialName("name")
-    val name: String,
+    val name: String? = null,
     @SerialName("organization")
-    val organization: String,
+    val organization: String? = null,
     @SerialName("rules")
     val rules: List<Rule>,
     @SerialName("semanticVersion")
-    val semanticVersion: String,
+    val semanticVersion: String? = null,
     @SerialName("version")
-    val version: String
+    val version: String? = null
 )
 
 @Serializable
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/SarifExtensions.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/SarifExtensions.kt
index bf90606284b159bcb5d01d5cb6cdec6868a3b90a..b535c2e3c286bd0bf89226200130319ac14cc9d8 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/SarifExtensions.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/sarif/SarifExtensions.kt
@@ -22,7 +22,8 @@ fun de.fraunhofer.iem.dataprovider.sarif.Rule.asDbObject(): Rule {
 fun de.fraunhofer.iem.dataprovider.sarif.Tool.asDbObject(): Tool {
     val tool = Tool()
     tool.addRules(this.driver.rules.map { it.asDbObject() })
-    tool.name = this.driver.fullName
+    tool.fullName = this.driver.fullName
+    tool.name = this.driver.name
     tool.version = this.driver.version
     return tool
 }
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt
index c6488980bf5f51bf85325a6779cdebbe2c598b30..d2fda8fab65e3ee16c162e38024284fe3da534fd 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt
@@ -4,10 +4,7 @@ import de.fraunhofer.iem.dataprovider.gitlab.GitConfiguration
 import de.fraunhofer.iem.dataprovider.gitlab.RepositoryRepository
 import de.fraunhofer.iem.dataprovider.logger.getLogger
 import de.fraunhofer.iem.dataprovider.sarif.Sarif
-import de.fraunhofer.iem.dataprovider.taskManager.tasks.CloneGitTask
-import de.fraunhofer.iem.dataprovider.taskManager.tasks.DetektTask
-import de.fraunhofer.iem.dataprovider.taskManager.tasks.GetGitlabProjectTask
-import de.fraunhofer.iem.dataprovider.taskManager.tasks.GitRepository
+import de.fraunhofer.iem.dataprovider.taskManager.tasks.*
 import de.fraunhofer.iem.dataprovider.toolResult.ToolRunRepository
 import jakarta.annotation.PreDestroy
 import kotlinx.coroutines.CoroutineScope
@@ -29,7 +26,10 @@ sealed class TaskDone : Event() {
 
 class GitCloneDone(override val taskId: UUID, val repoId: UUID, val outputDirectory: String) : TaskDone()
 class GetGitlabProjectDone(override val taskId: UUID, val repoId: UUID, val gitRepository: GitRepository) : TaskDone()
-class ProcessTaskDone(override val taskId: UUID, val message: String) : TaskDone()
+
+class SarifProcessDone(override val taskId: UUID, val repoId: UUID, val sarif: Sarif) : TaskDone()
+class SarifProcessGroupDone(override val taskId: UUID, val repoId: UUID, val groupId: UUID, val sarif: Sarif) :
+    TaskDone()
 
 class DetektDone(override val taskId: UUID, val sarif: Sarif) : TaskDone()
 
@@ -89,7 +89,7 @@ class TaskManager(
     private inner class MyActor {
 
         private val logger = getLogger(javaClass)
-
+        private val dependentEvents: MutableMap<UUID, MutableSet<UUID>> = mutableMapOf()
         suspend fun onReceive(event: Event) {
             logger.info("[${Thread.currentThread().name}] add task called in Task Manager $event")
 
@@ -118,19 +118,49 @@ class TaskManager(
                 }
 
                 is GitCloneDone -> {
+                    val taskIds = mutableSetOf<UUID>()
+                    val groupId = UUID.randomUUID()
                     // TODO: analysis results path should be unique or best not placed in the git folder
                     val analysisResultsPath = Paths.get(event.outputDirectory, "tool-results").toString()
-//                    worker.addTask(OdcTask(event.outputDirectory, analysisResultsPath, ::addEvent))
-                    worker.addTask(
-                        DetektTask(
-                            event.outputDirectory,
-                            analysisResultsPath,
-                            ::addEvent,
-                            event.repoId,
-                            repositoryRepository,
-                            toolRunRepository
-                        )
+
+                    val odcTask = OdcTask(
+                        event.outputDirectory,
+                        analysisResultsPath,
+                        ::addEvent,
+                        event.repoId,
+                        repositoryRepository,
+                        toolRunRepository, groupId
+                    )
+
+                    val detektTask = DetektTask(
+                        event.outputDirectory,
+                        analysisResultsPath,
+                        ::addEvent,
+                        event.repoId,
+                        repositoryRepository,
+                        toolRunRepository,
+                        groupID = groupId
                     )
+
+                    taskIds.add(odcTask.taskID)
+                    taskIds.add(detektTask.taskID)
+
+                    dependentEvents[groupId] = taskIds
+
+                    worker.addTask(odcTask)
+                    worker.addTask(detektTask)
+                }
+
+                is SarifProcessGroupDone -> {
+                    val eventGroup = dependentEvents[event.groupId]
+
+                    if (eventGroup != null) {
+                        eventGroup.remove(event.taskId)
+                        if (eventGroup.isEmpty()) {
+                            // TODO: Start metrics calculation
+                            worker.addTask(MetricsTask(event.repoId, repositoryRepository, ::addEvent))
+                        }
+                    }
                 }
 
 
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/DetektTask.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/DetektTask.kt
index 18d46f475692b94bf787c7a36b30bafa89c504ea..af6ec9ae60b0d581b0d0c09cfe4b2cd7953cb70d 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/DetektTask.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/DetektTask.kt
@@ -2,8 +2,6 @@ package de.fraunhofer.iem.dataprovider.taskManager.tasks
 
 
 import de.fraunhofer.iem.dataprovider.gitlab.RepositoryRepository
-import de.fraunhofer.iem.dataprovider.sarif.Sarif
-import de.fraunhofer.iem.dataprovider.taskManager.DetektDone
 import de.fraunhofer.iem.dataprovider.taskManager.Event
 import de.fraunhofer.iem.dataprovider.toolResult.ToolRunRepository
 import org.springframework.core.io.ClassPathResource
@@ -14,19 +12,16 @@ import java.util.*
 
 
 class DetektTask(
-    projectPath: String, outputPath: String, override val responseChannel: suspend (task: Event) -> Unit,
+    projectPath: String, outputPath: String,
+    override val responseChannel: suspend (task: Event) -> Unit,
     override val repoId: UUID,
     override val repository: RepositoryRepository,
-    override val toolRunRepository: ToolRunRepository
+    override val toolRunRepository: ToolRunRepository,
+    override val groupID: UUID? = null
 ) : SarifTask() {
 
     private val resource: Resource = ClassPathResource("scripts/detekt.sh")
     override val flags: Array<String> = arrayOf(resource.file.absolutePath, projectPath, outputPath)
     override val execPath: String = "/bin/sh"
     override val resultPath: Path = Paths.get(outputPath, "detekt", "report.sarif")
-
-
-    override suspend fun sendResult(sarif: Sarif) {
-        responseChannel(DetektDone(this.taskID, sarif))
-    }
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/MetricsTask.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/MetricsTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1d07ca14618185d9f56eaf110595c9827572f0da
--- /dev/null
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/MetricsTask.kt
@@ -0,0 +1,18 @@
+package de.fraunhofer.iem.dataprovider.taskManager.tasks
+
+import de.fraunhofer.iem.dataprovider.gitlab.RepositoryRepository
+import de.fraunhofer.iem.dataprovider.taskManager.Event
+import java.util.*
+
+class MetricsTask(
+    val repoId: UUID,
+    val repository: RepositoryRepository,
+    override val responseChannel: suspend (task: Event) -> Unit
+) : Task() {
+    override suspend fun execute() {
+//        val repo = repository.findById(repoId).get()
+//        repo.toolRuns.forEach {tr ->
+//
+//        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/OdcTask.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/OdcTask.kt
index 36e1994ffbb9c35238ccc418ffaae18101aba7b1..12c653c5607210680322c0eba7f1cc6c0792e22d 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/OdcTask.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/OdcTask.kt
@@ -1,25 +1,27 @@
 package de.fraunhofer.iem.dataprovider.taskManager.tasks
 
+import de.fraunhofer.iem.dataprovider.gitlab.RepositoryRepository
 import de.fraunhofer.iem.dataprovider.taskManager.Event
-import de.fraunhofer.iem.dataprovider.taskManager.ProcessTaskDone
+import de.fraunhofer.iem.dataprovider.toolResult.ToolRunRepository
 import org.springframework.core.io.ClassPathResource
 import org.springframework.core.io.Resource
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.*
 
 // TODO: extend the existing odc setup to have an external db with cve lists.
 //  Else every docker run will load all indixes for a couple of minutes..
-class OdcTask(projectPath: String, outputPath: String, override val responseChannel: suspend (task: Event) -> Unit) :
-    ProcessTask() {
+class OdcTask(
+    projectPath: String, outputPath: String,
+    override val responseChannel: suspend (task: Event) -> Unit,
+    override val repoId: UUID,
+    override val repository: RepositoryRepository,
+    override val toolRunRepository: ToolRunRepository,
+    override val groupID: UUID? = null
+) : SarifTask() {
 
     private val resource: Resource = ClassPathResource("scripts/odc.sh")
     override val flags: Array<String> = arrayOf(resource.file.absolutePath, outputPath, projectPath)
-
     override val execPath: String = "/bin/sh"
-
-    override suspend fun handleProcessReturn(p: Process) {
-        logger.info(resource.toString())
-        val returnMessage = "Odc finished with exit code ${p.exitValue()}"
-        val output = String(p.inputStream.readAllBytes())
-        logger.info("Process output $output")
-        responseChannel(ProcessTaskDone(taskID, returnMessage))
-    }
+    override val resultPath: Path = Paths.get(outputPath, "odc", "dependency-check-report.sarif")
 }
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/ProcessTask.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/ProcessTask.kt
index b9fe3691b0d954200e131faa1e01cdea0969c338..f1793de1f065d90848bb39b5362d9a139fa34b75 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/ProcessTask.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/ProcessTask.kt
@@ -4,11 +4,12 @@ import de.fraunhofer.iem.dataprovider.gitlab.RepositoryRepository
 import de.fraunhofer.iem.dataprovider.sarif.Sarif
 import de.fraunhofer.iem.dataprovider.sarif.asDbObject
 import de.fraunhofer.iem.dataprovider.sarif.getSarifFromFilePath
+import de.fraunhofer.iem.dataprovider.taskManager.SarifProcessDone
+import de.fraunhofer.iem.dataprovider.taskManager.SarifProcessGroupDone
 import de.fraunhofer.iem.dataprovider.toolResult.ToolRunRepository
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
-import org.springframework.transaction.annotation.Transactional
 import java.nio.file.Files
 import java.nio.file.Path
 import java.nio.file.Paths
@@ -41,9 +42,10 @@ sealed class ProcessTask : Task() {
     }
 
     abstract suspend fun handleProcessReturn(p: Process)
+    abstract suspend fun sendResult(sarif: Sarif)
 
 }
-@Transactional
+
 sealed class SarifTask : ProcessTask() {
     protected abstract val repoId: UUID
     protected abstract val repository: RepositoryRepository
@@ -63,13 +65,20 @@ sealed class SarifTask : ProcessTask() {
         val results = toolRunRepository.saveAll(sarifDb)
 
         repo.ifPresent {
-//            Hibernate.initialize(it.toolRuns) // TODO: this fails because the session seems to be closed and add won't work because toolRuns are loaded lazily
             it.addToolResults(results)
             repository.save(it)
         }
         sendResult(sarifResult)
     }
 
-    abstract suspend fun sendResult(sarif: Sarif)
+    override suspend fun sendResult(sarif: Sarif) {
 
+        val event = if (groupID != null) {
+            SarifProcessGroupDone(this.taskID, repoId, groupID!!, sarif)
+        } else {
+            SarifProcessDone(this.taskID, repoId, sarif)
+        }
+
+        responseChannel(event)
+    }
 }
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/Task.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/Task.kt
index 04bf166262c17622be570881010a6f899a2efc10..c029c4961bb9d885f976ffc1738bfe1a437c3209 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/Task.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/Task.kt
@@ -11,6 +11,8 @@ interface ITask {
 
 sealed class Task : ITask {
     override val taskID: UUID = UUID.randomUUID()
+    protected open val groupID: UUID? = null
+
     protected val logger = getLogger(javaClass)
     protected abstract val responseChannel: suspend (task: Event) -> Unit
 }
diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/toolResult/ToolRun.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/toolResult/ToolRun.kt
index ed71bb931b55d70852c927aecc7ea62325be1338..7b947239769dc9c0ea0d9f26d514828c15322926 100644
--- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/toolResult/ToolRun.kt
+++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/toolResult/ToolRun.kt
@@ -13,7 +13,7 @@ enum class Level {
 }
 
 enum class Kind {
-    pass, open, informational, notApplicable
+    Pass, Open, Informational, NotApplicable
 }
 
 @Entity
@@ -59,6 +59,8 @@ class Tool {
     @Column(name = "id", nullable = false)
     var id: UUID? = null
 
+    @Column(name = "full_name", length = 500)
+    var fullName: String? = null
 
     @Column(name = "name", length = 500)
     var name: String? = null
diff --git a/src/main/resources/scripts/odc.sh b/src/main/resources/scripts/odc.sh
index 9c41229169bd4c8beaae262273e02c0ee6f6e318..46c5c5d54ed286dab4b3a199e29b20cf38fc4109 100755
--- a/src/main/resources/scripts/odc.sh
+++ b/src/main/resources/scripts/odc.sh
@@ -1,10 +1,10 @@
 #!/bin/sh
 
 DC_VERSION="latest"
-DC_DIRECTORY=${1}/OWASP-Dependency-Check
+DC_DIRECTORY=${1}/odc
 DC_PROJECT="dependency-check scan: ${2}"
-DATA_DIRECTORY="$DC_DIRECTORY/data"
-CACHE_DIRECTORY="$DC_DIRECTORY/data/cache"
+DATA_DIRECTORY="/tmp/opencode/data"
+CACHE_DIRECTORY="/tmp/opencode/data/cache"
 
 if [ ! -d "$DATA_DIRECTORY" ]; then
     echo "Initially creating persistent directory: $DATA_DIRECTORY"
@@ -21,11 +21,12 @@ fi
 docker run --rm \
     --volume "${2}":/src:z \
     --volume "$DATA_DIRECTORY":/usr/share/dependency-check/data:z \
-    --volume "$DC_DIRECTORY"/odc-reports:/report:z \
+    --volume "$DC_DIRECTORY":/odc:z \
     odc \
     --scan /src \
     --format "ALL" \
     --project "$DC_PROJECT" \
-    --out /report
+    --data /usr/share/dependency-check/data \
+    --out /odc
     # Use suppression like this: (where /src == $pwd)
     # --suppression "/src/security/dependency-check-suppression.xml"
\ No newline at end of file