diff --git a/openbas-api/src/main/java/io/openbas/migration/V3_46__Add_table_inject_dependencies.java b/openbas-api/src/main/java/io/openbas/migration/V3_46__Add_table_inject_dependencies.java
new file mode 100644
index 0000000000..21ca0f6e99
--- /dev/null
+++ b/openbas-api/src/main/java/io/openbas/migration/V3_46__Add_table_inject_dependencies.java
@@ -0,0 +1,58 @@
+package io.openbas.migration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.openbas.database.model.InjectDependencyConditions;
+import org.flywaydb.core.api.migration.BaseJavaMigration;
+import org.flywaydb.core.api.migration.Context;
+import org.springframework.stereotype.Component;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.List;
+
+@Component
+public class V3_46__Add_table_inject_dependencies extends BaseJavaMigration {
+
+    @Override
+    public void migrate(Context context) throws Exception {
+        ObjectMapper mapper = new ObjectMapper();
+        Statement select = context.getConnection().createStatement();
+        select.execute("""
+                        CREATE TABLE injects_dependencies (
+                            inject_parent_id VARCHAR(255) NOT NULL REFERENCES injects(inject_id) ON DELETE CASCADE,
+                            inject_children_id VARCHAR(255) NOT NULL REFERENCES injects(inject_id) ON DELETE CASCADE,
+                            dependency_condition JSONB,
+                            dependency_created_at TIMESTAMP DEFAULT now(),
+                            dependency_updated_at TIMESTAMP DEFAULT now(),
+                            PRIMARY KEY(inject_parent_id, inject_children_id)
+                          );
+                          CREATE INDEX idx_injects_dependencies ON injects_dependencies(inject_children_id);
+                """);
+
+        // Migration datas
+        ResultSet results = select.executeQuery("SELECT * FROM injects WHERE inject_depends_from_another IS NOT NULL");
+        PreparedStatement statement = context.getConnection().prepareStatement(
+            """
+                INSERT INTO injects_dependencies(inject_parent_id, inject_children_id, dependency_condition) 
+                VALUES (?, ?, to_json(?::json))
+                """
+        );
+        while (results.next()) {
+            String injectId = results.getString("inject_id");
+            String parentId = results.getString("inject_depends_from_another");
+            InjectDependencyConditions.InjectDependencyCondition injectDependencyCondition = new InjectDependencyConditions.InjectDependencyCondition();
+            injectDependencyCondition.setMode(InjectDependencyConditions.DependencyMode.and);
+            InjectDependencyConditions.Condition condition = new InjectDependencyConditions.Condition();
+            condition.setKey("Execution");
+            condition.setOperator(InjectDependencyConditions.DependencyOperator.eq);
+            condition.setValue(true);
+            injectDependencyCondition.setConditions(List.of(condition));
+            statement.setString(1, parentId);
+            statement.setString(2, injectId);
+            statement.setString(3, mapper.writeValueAsString(injectDependencyCondition));
+            statement.addBatch();
+        }
+        statement.executeBatch();
+    }
+}
diff --git a/openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java b/openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java
index 690e765168..ef1acdf524 100644
--- a/openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java
+++ b/openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java
@@ -41,6 +41,7 @@
 
 import java.time.Duration;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -297,7 +298,20 @@ public Inject createInjectForExercise(@PathVariable String exerciseId, @Valid @R
     inject.setUser(userRepository.findById(currentUser().getId()).orElseThrow(ElementNotFoundException::new));
     inject.setExercise(exercise);
     // Set dependencies
-    inject.setDependsOn(resolveOptionalRelation(input.getDependsOn(), injectRepository));
+    if(input.getDependsOn() != null) {
+      inject.getDependsOn().addAll(
+        input.getDependsOn()
+          .stream()
+          .map(injectDependencyInput -> {
+            InjectDependency dependency = new InjectDependency();
+            dependency.setInjectDependencyCondition(injectDependencyInput.getConditions());
+            dependency.setCompositeId(new InjectDependencyId());
+            dependency.getCompositeId().setInjectChildren(inject);
+            dependency.getCompositeId().setInjectParent(injectRepository.findById(injectDependencyInput.getRelationship().getInjectParentId()).orElse(null));
+            return dependency;
+          }).toList()
+      );
+    }
     inject.setTeams(fromIterable(teamRepository.findAllById(input.getTeams())));
     inject.setAssets(fromIterable(assetService.assets(input.getAssets())));
     inject.setAssetGroups(fromIterable(assetGroupService.assetGroups(input.getAssetGroups())));
@@ -467,7 +481,20 @@ public Inject createInjectForScenario(
     inject.setUser(this.userRepository.findById(currentUser().getId()).orElseThrow(ElementNotFoundException::new));
     inject.setScenario(scenario);
     // Set dependencies
-    inject.setDependsOn(resolveOptionalRelation(input.getDependsOn(), this.injectRepository));
+    if(input.getDependsOn() != null) {
+      inject.getDependsOn().addAll(
+        input.getDependsOn()
+          .stream()
+          .map(injectDependencyInput -> {
+            InjectDependency dependency = new InjectDependency();
+            dependency.setInjectDependencyCondition(injectDependencyInput.getConditions());
+            dependency.setCompositeId(new InjectDependencyId());
+            dependency.getCompositeId().setInjectChildren(inject);
+            dependency.getCompositeId().setInjectParent(injectRepository.findById(injectDependencyInput.getRelationship().getInjectParentId()).orElse(null));
+            return dependency;
+          }).toList()
+      );
+    }
     inject.setTeams(fromIterable(teamRepository.findAllById(input.getTeams())));
     inject.setAssets(fromIterable(assetService.assets(input.getAssets())));
     inject.setAssetGroups(fromIterable(assetGroupService.assetGroups(input.getAssetGroups())));
@@ -575,7 +602,42 @@ private Inject updateInject(@NotBlank final String injectId, @NotNull InjectInpu
     inject.setUpdateAttributes(input);
 
     // Set dependencies
-    inject.setDependsOn(updateRelation(input.getDependsOn(), inject.getDependsOn(), this.injectRepository));
+    if(input.getDependsOn() != null) {
+      input.getDependsOn().forEach(entry -> {
+        Optional<InjectDependency> existingDependency = inject.getDependsOn().stream()
+                .filter(injectDependency -> injectDependency.getCompositeId().getInjectParent().getId().equals(entry.getRelationship().getInjectParentId()))
+                .findFirst();
+        if(existingDependency.isPresent()) {
+          existingDependency.get().getInjectDependencyCondition().setConditions(entry.getConditions().getConditions());
+          existingDependency.get().getInjectDependencyCondition().setMode(entry.getConditions().getMode());
+        } else {
+          InjectDependency injectDependency = new InjectDependency();
+          injectDependency.getCompositeId().setInjectChildren(inject);
+          injectDependency.getCompositeId().setInjectParent(injectRepository.findById(entry.getRelationship().getInjectParentId()).orElse(null));
+          injectDependency.setInjectDependencyCondition(new InjectDependencyConditions.InjectDependencyCondition());
+          injectDependency.getInjectDependencyCondition().setConditions(entry.getConditions().getConditions());
+          injectDependency.getInjectDependencyCondition().setMode(entry.getConditions().getMode());
+          inject.getDependsOn().add(injectDependency);
+        }
+      });
+    }
+
+    List<InjectDependency> injectDepencyToRemove = new ArrayList<>();
+    if(inject.getDependsOn() != null && !inject.getDependsOn().isEmpty()) {
+      if (input.getDependsOn() != null && !input.getDependsOn().isEmpty()) {
+        inject.getDependsOn().forEach(
+          injectDependency -> {
+            if (!input.getDependsOn().stream().map((injectDependencyInput -> injectDependencyInput.getRelationship().getInjectParentId())).toList().contains(injectDependency.getCompositeId().getInjectParent().getId())) {
+              injectDepencyToRemove.add(injectDependency);
+            }
+          }
+        );
+      } else {
+        injectDepencyToRemove.addAll(inject.getDependsOn());
+      }
+      inject.getDependsOn().removeAll(injectDepencyToRemove);
+    }
+
     inject.setTeams(fromIterable(this.teamRepository.findAllById(input.getTeams())));
     inject.setAssets(fromIterable(this.assetService.assets(input.getAssets())));
     inject.setAssetGroups(fromIterable(this.assetGroupService.assetGroups(input.getAssetGroups())));
diff --git a/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectDependencyIdInput.java b/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectDependencyIdInput.java
new file mode 100644
index 0000000000..3103102bc3
--- /dev/null
+++ b/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectDependencyIdInput.java
@@ -0,0 +1,25 @@
+package io.openbas.rest.inject.form;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import io.openbas.database.model.Inject;
+import io.openbas.database.model.InjectDependencyConditions;
+import io.openbas.database.model.InjectDependencyId;
+import io.openbas.helper.MonoIdDeserializer;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class InjectDependencyIdInput {
+
+    @JsonProperty("inject_parent_id")
+    private String injectParentId;
+
+    @JsonProperty("inject_children_id")
+    private String injectChildrenId;
+
+}
diff --git a/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectDependencyInput.java b/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectDependencyInput.java
new file mode 100644
index 0000000000..8ce475cb98
--- /dev/null
+++ b/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectDependencyInput.java
@@ -0,0 +1,22 @@
+package io.openbas.rest.inject.form;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.openbas.database.model.*;
+import jakarta.persistence.EmbeddedId;
+import jakarta.validation.constraints.NotNull;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Setter
+@Getter
+public class InjectDependencyInput {
+
+    @JsonProperty("dependency_relationship")
+    private InjectDependencyIdInput relationship;
+
+    @JsonProperty("dependency_condition")
+    private InjectDependencyConditions.InjectDependencyCondition conditions;
+
+}
diff --git a/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectInput.java b/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectInput.java
index 8571fc4003..ad663f90f1 100644
--- a/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectInput.java
+++ b/openbas-api/src/main/java/io/openbas/rest/inject/form/InjectInput.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import io.openbas.database.model.Inject;
+import io.openbas.database.model.InjectDependency;
 import io.openbas.database.model.InjectorContract;
 import jakarta.validation.constraints.NotNull;
 import lombok.Getter;
@@ -10,6 +11,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @Setter
 @Getter
@@ -28,7 +30,7 @@ public class InjectInput {
     private ObjectNode content;
 
     @JsonProperty("inject_depends_on")
-    private String dependsOn;
+    private List<InjectDependencyInput> dependsOn = new ArrayList<>();
 
     @JsonProperty("inject_depends_duration")
     private Long dependsDuration;
diff --git a/openbas-api/src/main/java/io/openbas/rest/inject/output/InjectOutput.java b/openbas-api/src/main/java/io/openbas/rest/inject/output/InjectOutput.java
index 38278ae5df..8f02397141 100644
--- a/openbas-api/src/main/java/io/openbas/rest/inject/output/InjectOutput.java
+++ b/openbas-api/src/main/java/io/openbas/rest/inject/output/InjectOutput.java
@@ -2,6 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.openbas.database.model.InjectDependency;
 import io.openbas.database.model.InjectorContract;
 import io.openbas.helper.InjectModelHelper;
 import io.openbas.injectors.email.EmailContract;
@@ -12,6 +13,8 @@
 import lombok.Data;
 
 import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @Data
 public class InjectOutput {
@@ -39,7 +42,7 @@ public class InjectOutput {
   private Long dependsDuration;
 
   @JsonProperty("inject_depends_on")
-  private String dependsOn;
+  private List<InjectDependency> dependsOn;
 
   @JsonProperty("inject_injector_contract")
   private InjectorContract injectorContract;
@@ -79,20 +82,19 @@ public InjectOutput(
       String exerciseId,
       String scenarioId,
       Long dependsDuration,
-      String dependsOn,
       InjectorContract injectorContract,
       String[] tags,
       String[] teams,
       String[] assets,
       String[] assetGroups,
-      String injectType) {
+      String injectType,
+      InjectDependency injectDependency) {
     this.id = id;
     this.title = title;
     this.enabled = enabled;
     this.exercise = exerciseId;
     this.scenario = scenarioId;
     this.dependsDuration = dependsDuration;
-    this.dependsOn = dependsOn;
     this.injectorContract = injectorContract;
     this.tags = tags != null ? new HashSet<>(Arrays.asList(tags)) : new HashSet<>();
 
@@ -111,5 +113,10 @@ public InjectOutput(
     this.injectType = injectType;
     this.teams = teams != null ? new ArrayList<>(Arrays.asList(teams)) : new ArrayList<>();
     this.content = content;
+
+    if (injectDependency != null) {
+      this.dependsOn = List.of(injectDependency);
+    }
+
   }
 }
diff --git a/openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java b/openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java
index 784c17e599..30a7d8c6fc 100644
--- a/openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java
+++ b/openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java
@@ -12,17 +12,21 @@
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
 import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.Job;
 import org.quartz.JobExecutionContext;
 import org.quartz.JobExecutionException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.stereotype.Component;
 
 import java.time.Instant;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -47,10 +51,14 @@ public class InjectsExecutionJob implements Job {
     private final QueueService queueService;
     private final ExecutionExecutorService executionExecutorService;
     private final AtomicTestingService atomicTestingService;
+    private final InjectDependenciesRepository injectDependenciesRepository;
+    private final InjectExpectationRepository injectExpectationRepository;
 
     private final List<ExecutionStatus> executionStatusesNotReady =
             List.of(ExecutionStatus.QUEUING, ExecutionStatus.DRAFT, ExecutionStatus.EXECUTING, ExecutionStatus.PENDING);
 
+    private final List<InjectExpectation.EXPECTATION_STATUS> expectationStatusesSuccess = List.of(InjectExpectation.EXPECTATION_STATUS.SUCCESS);
+
     @Resource
     protected ObjectMapper mapper;
 
@@ -148,24 +156,26 @@ private void executeInject(ExecutableInject executableInject) {
         Inject inject = executableInject.getInjection().getInject();
 
         // We are now checking if we depend on another inject and if it did not failed
-        if (inject.getDependsOn() != null
-                && inject.getDependsOn().getStatus().isPresent()
-                && ( inject.getDependsOn().getStatus().get().getName().equals(ExecutionStatus.ERROR)
-                    || executionStatusesNotReady.contains(inject.getDependsOn().getStatus().get().getName()))) {
+        Optional<List<String>> errorMessages = null;
+        if(executableInject.getExercise() != null) {
+            errorMessages = getErrorMessagesPreExecution(executableInject.getExercise().getId(), inject);
+        }
+        if (errorMessages != null && errorMessages.isPresent()) {
             InjectStatus status = new InjectStatus();
             if (inject.getStatus().isEmpty()) {
                 status.setInject(inject);
             } else {
                 status = inject.getStatus().get();
             }
-            String errorMsg = inject.getDependsOn().getStatus().get().getName().equals(ExecutionStatus.ERROR) ?
-                    "The inject is depending on another inject that failed"
-                    : "The inject is depending on another inject that is not executed yet";
-            status.getTraces().add(InjectStatusExecution.traceError(errorMsg));
-            status.setName(ExecutionStatus.ERROR);
-            status.setTrackingSentDate(Instant.now());
-            status.setCommandsLines(atomicTestingService.getCommandsLinesFromInject(inject));
-            injectStatusRepository.save(status);
+
+            InjectStatus finalStatus = status;
+            errorMessages.get().forEach(
+                    errorMsg -> finalStatus.getTraces().add(InjectStatusExecution.traceError(errorMsg))
+            );
+            finalStatus.setName(ExecutionStatus.ERROR);
+            finalStatus.setTrackingSentDate(Instant.now());
+            finalStatus.setCommandsLines(atomicTestingService.getCommandsLinesFromInject(inject));
+            injectStatusRepository.save(finalStatus);
         } else {
             inject.getInjectorContract().ifPresent(injectorContract -> {
 
@@ -225,6 +235,94 @@ private void executeInject(ExecutableInject executableInject) {
         }
     }
 
+    /**
+     * Get error messages if pre execution conditions are not met
+     * @param exerciseId the id of the exercise
+     * @param inject the inject to check
+     * @return an optional of list of error message
+     */
+    private Optional<List<String>> getErrorMessagesPreExecution(String exerciseId, Inject inject) {
+        List<InjectDependency> injectDependencies = injectDependenciesRepository.findParents(List.of(inject.getId()));
+        if (!injectDependencies.isEmpty()) {
+            List<Inject> parents = injectDependencies.stream()
+                    .map(injectDependency -> injectDependency.getCompositeId().getInjectParent()).toList();
+
+            Map<String, Boolean> mapCondition = getStringBooleanMap(parents, exerciseId, injectDependencies);
+
+            List<String> results = null;
+
+            for (InjectDependency injectDependency : injectDependencies) {
+                String expressionToEvaluate = injectDependency.getInjectDependencyCondition().toString();
+                List<String> conditions = injectDependency.getInjectDependencyCondition().getConditions().stream().map(InjectDependencyConditions.Condition::toString).toList();
+                for(String condition : conditions) {
+                    expressionToEvaluate = expressionToEvaluate.replaceAll(condition.split("==")[0].trim(), String.format("#this['%s']", condition.split("==")[0].trim()));
+                }
+
+                ExpressionParser parser = new SpelExpressionParser();
+                Expression exp = parser.parseExpression(expressionToEvaluate);
+                boolean canBeExecuted = Boolean.TRUE.equals(exp.getValue(mapCondition, Boolean.class));
+                if (!canBeExecuted) {
+                    if (results == null) {
+                        results = new ArrayList<>();
+                        results.add("This inject depends on other injects expectations that are not met. The following conditions were not as expected : ");
+                    }
+                    results.addAll(labelFromCondition(injectDependency.getCompositeId().getInjectParent(), injectDependency.getInjectDependencyCondition()));
+                }
+            }
+            return results == null ? Optional.empty() : Optional.of(results);
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Get a map containing the expectations and if they are met or not
+     * @param parents the parents injects
+     * @param exerciseId the id of the exercise
+     * @param injectDependencies the list of dependencies
+     * @return a map of expectations and their value
+     */
+    private @NotNull Map<String, Boolean> getStringBooleanMap(List<Inject> parents, String exerciseId, List<InjectDependency> injectDependencies) {
+        Map<String, Boolean> mapCondition = new HashMap<>();
+
+        injectDependencies.forEach(injectDependency -> {
+            injectDependency.getInjectDependencyCondition().getConditions().stream().forEach(condition ->  {
+                mapCondition.put(condition.getKey(), false);
+            });
+        });
+
+        parents.forEach(parent -> {
+            mapCondition.put("Execution",
+                    parent.getStatus().isPresent()
+                            && !parent.getStatus().get().getName().equals(ExecutionStatus.ERROR)
+                            && !executionStatusesNotReady.contains(parent.getStatus().get().getName()));
+
+            List<InjectExpectation> expectations = injectExpectationRepository.findAllForExerciseAndInject(exerciseId, parent.getId());
+            expectations.forEach(injectExpectation -> {
+                String name = StringUtils.capitalize(injectExpectation.getType().toString().toLowerCase());
+                if(injectExpectation.getType().equals(InjectExpectation.EXPECTATION_TYPE.MANUAL)) {
+                    name = injectExpectation.getName();
+                }
+                if(InjectExpectation.EXPECTATION_TYPE.CHALLENGE.equals(injectExpectation.getType())
+                || InjectExpectation.EXPECTATION_TYPE.ARTICLE.equals(injectExpectation.getType())) {
+                    if(injectExpectation.getUser() == null && injectExpectation.getScore() != null) {
+                        mapCondition.put(name, injectExpectation.getScore() >= injectExpectation.getExpectedScore());
+                    }
+                } else {
+                    mapCondition.put(name, expectationStatusesSuccess.contains(injectExpectation.getResponse()));
+                }
+            });
+        });
+        return mapCondition;
+    }
+
+    private List<String> labelFromCondition(Inject injectParent, InjectDependencyConditions.InjectDependencyCondition condition) {
+        List<String> result = new ArrayList<>();
+        for (InjectDependencyConditions.Condition conditionElement : condition.getConditions()) {
+            result.add(String.format("Inject '%s' - %s is %s", injectParent.getTitle(), conditionElement.getKey(), conditionElement.isValue()));
+        }
+        return result;
+    }
+
     public void updateExercise(String exerciseId) {
         Exercise exercise = exerciseRepository.findById(exerciseId).orElseThrow();
         exercise.setUpdatedAt(now());
diff --git a/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java b/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java
index f947391e3c..8aca82e63e 100644
--- a/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java
+++ b/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java
@@ -228,7 +228,9 @@ public Inject copyInject(@NotNull Inject injectOrigin, boolean isAtomic) {
         injectDuplicate.setTeams(injectOrigin.getTeams().stream().toList());
         injectDuplicate.setEnabled(injectOrigin.isEnabled());
         injectDuplicate.setDependsDuration(injectOrigin.getDependsDuration());
-        injectDuplicate.setDependsOn(injectOrigin.getDependsOn());
+        if(injectOrigin.getDependsOn() != null) {
+            injectDuplicate.setDependsOn(injectOrigin.getDependsOn().stream().toList());
+        }
         injectDuplicate.setCountry(injectOrigin.getCountry());
         injectDuplicate.setCity(injectOrigin.getCity());
         injectDuplicate.setInjectorContract(injectOrigin.getInjectorContract().orElse(null));
diff --git a/openbas-api/src/main/java/io/openbas/service/InjectService.java b/openbas-api/src/main/java/io/openbas/service/InjectService.java
index d1c6c905fc..c6e825984a 100644
--- a/openbas-api/src/main/java/io/openbas/service/InjectService.java
+++ b/openbas-api/src/main/java/io/openbas/service/InjectService.java
@@ -1199,7 +1199,8 @@ private void selectForInject(CriteriaBuilder cb, CriteriaQuery<Tuple> cq, Root<I
         Join<Inject, Scenario> injectScenarioJoin = createLeftJoin(injectRoot, "scenario");
         Join<Inject, InjectorContract> injectorContractJoin = createLeftJoin(injectRoot, "injectorContract");
         Join<InjectorContract, Injector> injectorJoin = injectorContractJoin.join("injector", JoinType.LEFT);
-        Join<Inject, Inject> injectDependsJoin = createLeftJoin(injectRoot, "dependsOn");
+        Join<Inject, InjectDependency> injectDependency = createLeftJoin(injectRoot, "dependsOn");
+
         // Array aggregations
         Expression<String[]> tagIdsExpression = createJoinArrayAggOnId(cb, injectRoot, "tags");
         Expression<String[]> teamIdsExpression = createJoinArrayAggOnId(cb, injectRoot, "teams");
@@ -1216,13 +1217,13 @@ private void selectForInject(CriteriaBuilder cb, CriteriaQuery<Tuple> cq, Root<I
                 injectExerciseJoin.get("id").alias("inject_exercise"),
                 injectScenarioJoin.get("id").alias("inject_scenario"),
                 injectRoot.get("dependsDuration").alias("inject_depends_duration"),
-                injectDependsJoin.get("id").alias("inject_depends_from_another"),
                 injectorContractJoin.alias("inject_injector_contract"),
                 tagIdsExpression.alias("inject_tags"),
                 teamIdsExpression.alias("inject_teams"),
                 assetIdsExpression.alias("inject_assets"),
                 assetGroupIdsExpression.alias("inject_asset_groups"),
-                injectorJoin.get("type").alias("inject_type")
+                injectorJoin.get("type").alias("inject_type"),
+                injectDependency.alias("inject_depends_on")
         ).distinct(true);
 
         // GROUP BY
@@ -1231,7 +1232,8 @@ private void selectForInject(CriteriaBuilder cb, CriteriaQuery<Tuple> cq, Root<I
                 injectExerciseJoin.get("id"),
                 injectScenarioJoin.get("id"),
                 injectorContractJoin.get("id"),
-                injectorJoin.get("id")
+                injectorJoin.get("id"),
+                injectDependency.get("id")
         ));
     }
 
@@ -1247,13 +1249,13 @@ private List<InjectOutput> execInject(TypedQuery<Tuple> query) {
                         tuple.get("inject_exercise", String.class),
                         tuple.get("inject_scenario", String.class),
                         tuple.get("inject_depends_duration", Long.class),
-                        tuple.get("inject_depends_from_another", String.class),
                         tuple.get("inject_injector_contract", InjectorContract.class),
                         tuple.get("inject_tags", String[].class),
                         tuple.get("inject_teams", String[].class),
                         tuple.get("inject_assets", String[].class),
                         tuple.get("inject_asset_groups", String[].class),
-                        tuple.get("inject_type", String.class)
+                        tuple.get("inject_type", String.class),
+                        tuple.get("inject_depends_on", InjectDependency.class)
                 ))
                 .toList();
     }
diff --git a/openbas-api/src/main/java/io/openbas/service/ScenarioToExerciseService.java b/openbas-api/src/main/java/io/openbas/service/ScenarioToExerciseService.java
index 7669482a2c..c933c5b67a 100644
--- a/openbas-api/src/main/java/io/openbas/service/ScenarioToExerciseService.java
+++ b/openbas-api/src/main/java/io/openbas/service/ScenarioToExerciseService.java
@@ -247,7 +247,15 @@ public Exercise toExercise(
     scenarioInjects.forEach(scenarioInject -> {
       if(scenarioInject.getDependsOn() != null) {
         Inject injectToUpdate = mapExerciseInjectsByScenarioInject.get(scenarioInject.getId());
-        injectToUpdate.setDependsOn(mapExerciseInjectsByScenarioInject.get(scenarioInject.getDependsOn().getId()));
+        injectToUpdate.getDependsOn().clear();
+        injectToUpdate.getDependsOn().addAll(scenarioInject.getDependsOn().stream().map((injectDependency -> {
+            InjectDependency dep = new InjectDependency();
+            dep.setCompositeId(injectDependency.getCompositeId());
+            dep.setInjectDependencyCondition(injectDependency.getInjectDependencyCondition());
+            dep.getCompositeId().setInjectParent(mapExerciseInjectsByScenarioInject.get(dep.getCompositeId().getInjectParent().getId()));
+            dep.getCompositeId().setInjectChildren(injectToUpdate);
+            return dep;
+        })).toList());
         this.injectRepository.save(injectToUpdate);
       }
     });
diff --git a/openbas-front/src/actions/injects/Inject.d.ts b/openbas-front/src/actions/injects/Inject.d.ts
index 9d70a9a315..f1b3154851 100644
--- a/openbas-front/src/actions/injects/Inject.d.ts
+++ b/openbas-front/src/actions/injects/Inject.d.ts
@@ -39,3 +39,40 @@ export type InjectExpectationStore = Omit<InjectExpectation, 'inject_expectation
   inject_expectation_team: string | undefined;
   inject_expectation_inject: string | undefined;
 };
+
+export interface ConditionElement {
+  name: string,
+  value: boolean,
+  key: string,
+  index: number,
+}
+
+export interface ConditionType {
+  parentId?: string,
+  childrenId?: string,
+  mode?: string,
+  conditionElement?: ConditionElement[],
+}
+
+export interface Dependency {
+  inject?: InjectOutputType,
+  index: number,
+}
+
+export interface Content {
+  expectations: {
+    expectation_type: string,
+    expectation_name: string,
+  }[]
+}
+
+export interface ConvertedContentType {
+  fields: {
+    key: string
+    value: string,
+    predefinedExpectations: {
+      expectation_type: string,
+      expectation_name: string,
+    }[]
+  }[],
+}
diff --git a/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx b/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx
index 352f69fc23..3c1530e947 100644
--- a/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx
+++ b/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx
@@ -25,7 +25,7 @@ import ExportButton from '../../../../components/common/ExportButton';
 import { useQueryableWithLocalStorage } from '../../../../components/common/queryable/useQueryableWithLocalStorage';
 import SortHeadersComponentV2 from '../../../../components/common/queryable/sort/SortHeadersComponentV2';
 import { Header } from '../../../../components/common/SortHeadersList';
-import FilterModeChip from '../../../../components/common/queryable/filter/FilterModeChip';
+import ClickableModeChip from '../../../../components/common/chips/ClickableModeChip';
 import FilterChipValues from '../../../../components/common/queryable/filter/FilterChipValues';
 
 const useStyles = makeStyles(() => ({
@@ -77,7 +77,7 @@ const computeRuleValues = (assetGroup: AssetGroupOutput, t: (value: string) => s
         <>
           {assetGroup.asset_group_dynamic_filter.filters.map((filter, idx) => (
             <React.Fragment key={filter.key}>
-              {idx !== 0 && <FilterModeChip mode={assetGroup.asset_group_dynamic_filter?.mode} />}
+              {idx !== 0 && <ClickableModeChip mode={assetGroup.asset_group_dynamic_filter?.mode} />}
               <Chip
                 key={filter.key}
                 variant={'filled'}
diff --git a/openbas-front/src/admin/components/common/injects/InjectChainsForm.js b/openbas-front/src/admin/components/common/injects/InjectChainsForm.js
deleted file mode 100644
index 90ee59112e..0000000000
--- a/openbas-front/src/admin/components/common/injects/InjectChainsForm.js
+++ /dev/null
@@ -1,280 +0,0 @@
-import React, { useState } from 'react';
-import { makeStyles } from '@mui/styles';
-import { Accordion, AccordionDetails, AccordionSummary, FormControl, IconButton, InputLabel, MenuItem, Select, Tooltip, Typography } from '@mui/material';
-import { Add, DeleteOutlined, ExpandMore } from '@mui/icons-material';
-import { useFormatter } from '../../../../components/i18n';
-
-const useStyles = makeStyles(() => ({
-  container: {
-    display: 'inline-flex',
-    alignItems: 'center',
-  },
-  importerStyle: {
-    display: 'flex',
-    alignItems: 'center',
-    marginTop: 20,
-  },
-}));
-
-const InjectForm = ({
-  values,
-  form,
-  injects,
-}) => {
-  const classes = useStyles();
-  const { t } = useFormatter();
-
-  const [parents, setParents] = useState(
-    injects.filter((currentInject) => currentInject.inject_id === values.inject_depends_on)
-      .map((inject, index) => {
-        return { inject, index };
-      }),
-  );
-  const [childrens, setChildrens] = useState(
-    injects.filter((currentInject) => currentInject.inject_depends_on === values.inject_id)
-      .map((inject, index) => {
-        return { inject, index };
-      }),
-  );
-
-  const handleChangeParent = (_event, parent) => {
-    const rx = /\.\$select-parent-(.*)-inject-(.*)/g;
-    const arr = rx.exec(parent.key);
-
-    const newParents = parents
-      .map((element) => {
-        if (element.index === parseInt(arr[1], 10)) {
-          return {
-            inject: injects.find((currentInject) => currentInject.inject_id === arr[2]),
-            index: element.index,
-          };
-        }
-        return element;
-      });
-
-    setParents(newParents);
-
-    // We take any parent that is not undefined or undefined (since there is only one parent for now, this'll
-    // be changed when we allow for multiple parents)
-    const anyParent = newParents.find((inject) => inject !== undefined);
-
-    form.mutators.setValue(
-      'inject_depends_on',
-      anyParent?.inject.inject_id || null,
-    );
-  };
-
-  const addParent = () => {
-    setParents([...parents, { inject: undefined, index: parents.length }]);
-  };
-
-  const handleChangeChildren = (_event, child) => {
-    const rx = /\.\$select-children-(.*)-inject-(.*)/g;
-    const arr = rx.exec(child.key);
-
-    const newChildrens = childrens
-      .map((element) => {
-        if (element.index === parseInt(arr[1], 10)) {
-          return {
-            inject: injects.find((currentInject) => currentInject.inject_id === arr[2]),
-            index: element.index,
-          };
-        }
-        return element;
-      });
-
-    setChildrens(newChildrens);
-
-    form.mutators.setValue('inject_depends_to', newChildrens.map((inject) => inject.inject?.inject_id));
-  };
-
-  const addChildren = () => {
-    setChildrens([...childrens, { inject: undefined, index: childrens.length }]);
-  };
-
-  const deleteParent = (parent) => {
-    const parentIndexInArray = parents.findIndex((currentParent) => currentParent.index === parent.index);
-
-    if (parentIndexInArray > -1) {
-      const newParents = [
-        ...parents.slice(0, parentIndexInArray),
-        ...parents.slice(parentIndexInArray + 1),
-      ];
-      setParents(newParents);
-      const anyParent = newParents.find((inject) => inject !== undefined);
-
-      form.mutators.setValue(
-        'inject_depends_on',
-        anyParent?.inject.inject_id || null,
-      );
-    }
-  };
-
-  const deleteChildren = (children) => {
-    const childrenIndexInArray = childrens.findIndex((currentChildren) => currentChildren.index === children.index);
-
-    if (childrenIndexInArray > -1) {
-      const newChildrens = [
-        ...childrens.slice(0, childrenIndexInArray),
-        ...childrens.slice(childrenIndexInArray + 1),
-      ];
-      setChildrens(newChildrens);
-
-      form.mutators.setValue('inject_depends_to', newChildrens.map((inject) => inject.inject?.inject_id));
-    }
-  };
-
-  return (
-    <>
-      <div className={classes.importerStyle}>
-        <Typography variant="h2" sx={{ m: 0 }}>
-          {t('Parent')}
-        </Typography>
-        <IconButton
-          color="secondary"
-          aria-label="Add"
-          size="large"
-          disabled={parents.length > 0}
-          onClick={addParent}
-        >
-          <Add fontSize="small"/>
-        </IconButton>
-      </div>
-
-      {parents.map((parent, index) => {
-        return (
-          <Accordion
-            key={`accordion-parent-${parent.index}`}
-            variant="outlined"
-            style={{ width: '100%', marginBottom: '10px' }}
-          >
-            <AccordionSummary
-              expandIcon={<ExpandMore/>}
-            >
-              <div className={classes.container}>
-                <Typography>
-                  #{index + 1} {parent.inject?.inject_title}
-                </Typography>
-                <Tooltip title={t('Delete')}>
-                  <IconButton color="error"
-                    onClick={() => { deleteParent(parent); }}
-                  >
-                    <DeleteOutlined fontSize="small"/>
-                  </IconButton>
-                </Tooltip>
-              </div>
-            </AccordionSummary>
-            <AccordionDetails>
-              <FormControl style={{ width: '100%' }}>
-                <InputLabel id="inject_id">{t('Inject')}</InputLabel>
-                <Select
-                  labelId="condition"
-                  fullWidth={true}
-                  value={parents[parent.index].inject ? parents[parent.index].inject.inject_id : ''}
-                  onChange={handleChangeParent}
-                >
-                  {injects
-                    .filter((currentInject) => currentInject.inject_depends_duration < values.inject_depends_duration
-                      && (parents.find((parentSearch) => currentInject.inject_id === parentSearch.inject?.inject_id) === undefined
-                        || parents[parent.index].inject?.inject_id === currentInject.inject_id))
-                    .map((currentInject) => {
-                      return (<MenuItem key={`select-parent-${index}-inject-${currentInject.inject_id}`}
-                        value={currentInject.inject_id}
-                              >{currentInject.inject_title}</MenuItem>);
-                    })}
-                </Select>
-              </FormControl>
-              <FormControl style={{ width: '100%', marginTop: '15px' }}>
-                <InputLabel id="condition">{t('Condition')}</InputLabel>
-                <Select
-                  labelId="condition"
-                  value={'Success'}
-                  fullWidth={true}
-                  disabled
-                >
-                  <MenuItem value="Success">{t('Execution successful')}</MenuItem>
-                </Select>
-              </FormControl>
-            </AccordionDetails>
-          </Accordion>
-        );
-      })}
-
-      <div className={classes.importerStyle}>
-        <Typography variant="h2" sx={{ m: 0 }}>
-          {t('Childrens')}
-        </Typography>
-        <IconButton
-          color="secondary"
-          aria-label="Add"
-          size="large"
-          onClick={addChildren}
-        >
-          <Add fontSize="small"/>
-        </IconButton>
-      </div>
-      {childrens.map((children, index) => {
-        return (
-          <Accordion
-            key={`accordion-children-${children.index}`}
-            variant="outlined"
-            style={{ width: '100%', marginBottom: '10px' }}
-          >
-            <AccordionSummary
-              expandIcon={<ExpandMore/>}
-            >
-              <div className={classes.container}>
-                <Typography>
-                  #{index + 1} {children.inject?.inject_title}
-                </Typography>
-                <Tooltip title={t('Delete')}>
-                  <IconButton color="error"
-                    onClick={() => { deleteChildren(children); }}
-                  >
-                    <DeleteOutlined fontSize="small"/>
-                  </IconButton>
-                </Tooltip>
-              </div>
-            </AccordionSummary>
-            <AccordionDetails>
-              <FormControl style={{ width: '100%' }}>
-                <InputLabel id="inject_id">{t('Inject')}</InputLabel>
-                <Select
-                  labelId="condition"
-                  fullWidth={true}
-                  value={childrens.find((childrenSearch) => children.index === childrenSearch.index).inject
-                    ? childrens.find((childrenSearch) => children.index === childrenSearch.index).inject.inject_id : ''}
-                  onChange={handleChangeChildren}
-                >
-                  {injects
-                    .filter((currentInject) => currentInject.inject_depends_duration > values.inject_depends_duration
-                        && (childrens.find((childrenSearch) => currentInject.inject_id === childrenSearch.inject?.inject_id) === undefined
-                            || childrens.find((childrenSearch) => children.index === childrenSearch.index).inject?.inject_id === currentInject.inject_id))
-                    .map((currentInject) => {
-                      return (
-                        <MenuItem key={`select-children-${children.index}-inject-${currentInject.inject_id}`}
-                          value={currentInject.inject_id}
-                        >{currentInject.inject_title}</MenuItem>);
-                    })}
-                </Select>
-              </FormControl>
-              <FormControl style={{ width: '100%', marginTop: '15px' }}>
-                <InputLabel id="condition">{t('Condition')}</InputLabel>
-                <Select
-                  labelId="condition"
-                  value={'Success'}
-                  fullWidth={true}
-                  disabled
-                >
-                  <MenuItem value="Success">{t('Execution successful')}</MenuItem>
-                </Select>
-              </FormControl>
-            </AccordionDetails>
-          </Accordion>
-        );
-      })}
-    </>
-  );
-};
-
-export default InjectForm;
diff --git a/openbas-front/src/admin/components/common/injects/InjectChainsForm.tsx b/openbas-front/src/admin/components/common/injects/InjectChainsForm.tsx
new file mode 100644
index 0000000000..accc9804fa
--- /dev/null
+++ b/openbas-front/src/admin/components/common/injects/InjectChainsForm.tsx
@@ -0,0 +1,993 @@
+import React, { ReactElement, ReactNode, useEffect, useState } from 'react';
+import { makeStyles } from '@mui/styles';
+import {
+  Accordion,
+  AccordionDetails,
+  AccordionSummary,
+  Box,
+  Button,
+  FormControl,
+  IconButton,
+  InputLabel,
+  MenuItem,
+  Select,
+  SelectChangeEvent,
+  Tooltip,
+  Typography,
+} from '@mui/material';
+import { Add, DeleteOutlined, ExpandMore } from '@mui/icons-material';
+import { FormApi } from 'final-form';
+import { Value } from 'classnames';
+import { useFormatter } from '../../../../components/i18n';
+import ClickableModeChip from '../../../../components/common/chips/ClickableModeChip';
+import ClickableChip from '../../../../components/common/chips/ClickableChip';
+import { capitalize } from '../../../../utils/String';
+import type { Inject, InjectDependency, InjectDependencyCondition, InjectOutput } from '../../../../utils/api-types';
+import type { ConditionElement, ConditionType, Content, ConvertedContentType, Dependency, InjectOutputType } from '../../../../actions/injects/Inject';
+import type { Element } from '../../../../components/common/chips/ClickableChip';
+
+const useStyles = makeStyles(() => ({
+  container: {
+    display: 'inline-flex',
+    alignItems: 'center',
+  },
+  importerStyle: {
+    display: 'flex',
+    alignItems: 'center',
+    marginTop: 20,
+  },
+  labelExecutionCondition: {
+    color: '#7c8088',
+  },
+}));
+
+interface Props {
+  values: Inject & { inject_depends_to: InjectDependency[]; },
+  form: FormApi<Inject & { inject_depends_to: InjectDependency[]; }, Partial<Inject & { inject_depends_to: InjectDependency[]; }>>,
+  injects?: InjectOutputType[],
+}
+
+const InjectForm: React.FC<Props> = ({ values, form, injects }) => {
+  const classes = useStyles();
+  const { t } = useFormatter();
+
+  // List of parents
+  const [parents, setParents] = useState<Dependency[]>(
+    () => {
+      if (values.inject_depends_on) {
+        return values.inject_depends_on?.filter((searchInject) => searchInject.dependency_relationship?.inject_children_id === values.inject_id)
+          .map((inject, index) => {
+            return {
+              inject: injects?.find((currentInject) => currentInject.inject_id === inject.dependency_relationship?.inject_parent_id),
+              index,
+            };
+          });
+      }
+      return [];
+    },
+
+  );
+
+  // List of childrens
+  const [childrens, setChildrens] = useState<Dependency[]>(
+    () => {
+      if (injects !== undefined) {
+        return injects?.filter(
+          (searchInject) => searchInject.inject_depends_on?.find(
+            (dependsOnSearch) => dependsOnSearch.dependency_relationship?.inject_parent_id === values.inject_id,
+          ) !== undefined,
+        )
+          .map((inject, index) => {
+            return {
+              inject,
+              index,
+            };
+          });
+      }
+      return [];
+    },
+  );
+
+  // Property to deactivate the add children button if there are no children available anymore
+  const [addChildrenButtonDisabled, setAddChildrenButtonDisabled] = useState(false);
+  useEffect(() => {
+    const availableChildrensNumber = injects ? injects.filter((currentInject) => currentInject.inject_depends_duration > values.inject_depends_duration).length : 0;
+    setAddChildrenButtonDisabled(childrens ? childrens.length >= availableChildrensNumber : true);
+  }, [childrens]);
+
+  /**
+   * Transform an inject dependency into ConditionElement
+   * @param injectDependsOn an array of injectDependency
+   */
+  const getConditionContentParent = (injectDependsOn: (InjectDependency | undefined)[]) => {
+    const conditions: ConditionType[] = [];
+    if (injectDependsOn) {
+      injectDependsOn.forEach((parent) => {
+        if (parent !== undefined) {
+          conditions.push({
+            parentId: parent.dependency_relationship?.inject_parent_id,
+            childrenId: parent.dependency_relationship?.inject_children_id,
+            mode: parent.dependency_condition?.mode,
+            conditionElement: parent.dependency_condition?.conditions?.map((dependencyCondition, indexCondition) => {
+              return {
+                name: dependencyCondition.key,
+                value: dependencyCondition.value!,
+                key: dependencyCondition.key,
+                index: indexCondition,
+              };
+            }),
+          });
+        }
+      });
+    }
+    return conditions;
+  };
+
+  /**
+   * Transform an inject dependency into ConditionElement
+   * @param injectDependsTo an array of injectDependency
+   */
+  const getConditionContentChildren = (injectDependsTo: (InjectDependency | undefined)[]) => {
+    const conditions: ConditionType[] = [];
+    injectDependsTo.forEach((children) => {
+      if (children !== undefined) {
+        conditions.push({
+          parentId: values.inject_id,
+          childrenId: children.dependency_relationship?.inject_children_id,
+          mode: children.dependency_condition?.mode,
+          conditionElement: children.dependency_condition?.conditions?.map((dependencyCondition, indexCondition) => {
+            return {
+              name: dependencyCondition.key,
+              value: dependencyCondition.value!,
+              key: dependencyCondition.key,
+              index: indexCondition,
+            };
+          }),
+        });
+      }
+    });
+    return conditions;
+  };
+
+  const [parentConditions, setParentConditions] = useState(getConditionContentParent(values.inject_depends_on ? values.inject_depends_on : []));
+  const [childrenConditions, setChildrenConditions] = useState(getConditionContentChildren(values.inject_depends_to));
+
+  /**
+   * Get the inject dependency object from dependency ones
+   * @param deps the inject depencies
+   */
+  const injectDependencyFromDependency = (deps: Dependency[]) => {
+    return deps.flatMap((dependency) => (dependency.inject?.inject_depends_on !== null ? dependency.inject?.inject_depends_on : []));
+  };
+
+  /**
+   * Handle the change of the parent
+   * @param _event the event
+   * @param parent the parent key
+   */
+  const handleChangeParent = (_event: SelectChangeEvent<Value>, parent: ReactNode) => {
+    const rx = /\.\$select-parent-(.*)-inject-(.*)/g;
+    if (!parent) return;
+    let key = '';
+    const parentElement = parent as ReactElement;
+    if ('key' in parentElement && parentElement.key !== null) {
+      key = parentElement.key;
+    }
+    if (key === null) {
+      return;
+    }
+    const arr = rx.exec(key);
+
+    if (parents === undefined || arr === null || injects === undefined) return;
+    const newInject = injects.find((currentInject) => currentInject.inject_id === arr[2]);
+    const newParents = parents
+      .map((element) => {
+        if (element.index === parseInt(arr[1], 10)) {
+          const previousInject = injects.find((value) => value.inject_id === element.inject?.inject_id);
+          if (previousInject?.inject_depends_on !== undefined) {
+            previousInject!.inject_depends_on = previousInject!.inject_depends_on?.filter(
+              (dependsOn) => dependsOn.dependency_relationship?.inject_children_id !== values.inject_id,
+            );
+          }
+          return {
+            inject: newInject!,
+            index: element.index,
+          };
+        }
+        return element;
+      });
+
+    setParents(newParents);
+
+    const baseInjectDependency: InjectDependency = {
+      dependency_relationship: {
+        inject_parent_id: newInject?.inject_id,
+        inject_children_id: values.inject_id,
+      },
+      dependency_condition: {
+        conditions: [
+          {
+            key: 'Execution',
+            operator: 'eq',
+            value: true,
+          },
+        ],
+        mode: 'and',
+      },
+    };
+
+    form.mutators.setValue(
+      'inject_depends_on',
+      [baseInjectDependency],
+    );
+
+    if (newInject!.inject_depends_on !== null) {
+      setParentConditions(getConditionContentParent(injectDependencyFromDependency(newParents)));
+    }
+  };
+
+  /**
+   * Add a new parent inject
+   */
+  const addParent = () => {
+    setParents([...parents, { inject: undefined, index: parents.length }]);
+  };
+
+  /**
+   * Handle the change of a children
+   * @param _event
+   * @param child
+   */
+  const handleChangeChildren = (_event: SelectChangeEvent<string>, child: ReactNode) => {
+    const rx = /\.\$select-children-(.*)-inject-(.*)/g;
+    if (!child) return;
+    let key = '';
+    const childElement = (child as ReactElement);
+    if ('key' in (childElement as ReactElement) && childElement.key !== null) {
+      key = childElement.key;
+    }
+    if (key === null) {
+      return;
+    }
+    const arr = rx.exec(key);
+
+    if (childrens === undefined || arr === null || injects === undefined) return;
+    const newInject = injects.find((currentInject) => currentInject.inject_id === arr[2]);
+    const newChildrens = childrens
+      .map((element) => {
+        if (element.index === parseInt(arr[1], 10)) {
+          const baseInjectDependency: InjectDependency = {
+            dependency_relationship: {
+              inject_parent_id: values.inject_id,
+              inject_children_id: newInject?.inject_id,
+            },
+            dependency_condition: {
+              conditions: [
+                {
+                  key: 'Execution',
+                  operator: 'eq',
+                  value: true,
+                },
+              ],
+              mode: 'and',
+            },
+          };
+          newInject!.inject_depends_on = [baseInjectDependency];
+          return {
+            inject: newInject!,
+            index: element.index,
+          };
+        }
+        return element;
+      });
+
+    setChildrens(newChildrens);
+
+    const dependsTo = injectDependencyFromDependency(newChildrens);
+    form.mutators.setValue('inject_depends_to', dependsTo);
+
+    if (newInject!.inject_depends_on !== null) {
+      setChildrenConditions(getConditionContentChildren(dependsTo.filter((dep) => dep !== undefined)));
+    }
+  };
+
+  /**
+   * Add a new children inject
+   */
+  const addChildren = () => {
+    setChildrens([...childrens, { inject: undefined, index: childrens.length }]);
+  };
+
+  /**
+   * Delete a parent inject
+   * @param parent
+   */
+  const deleteParent = (parent: Dependency) => {
+    const parentIndexInArray = parents.findIndex((currentParent) => currentParent.index === parent.index);
+
+    if (parentIndexInArray > -1) {
+      const newParents = [
+        ...parents.slice(0, parentIndexInArray),
+        ...parents.slice(parentIndexInArray + 1),
+      ];
+      setParents(newParents);
+
+      form.mutators.setValue(
+        'inject_depends_on',
+        injectDependencyFromDependency(newParents),
+      );
+    }
+  };
+
+  /**
+   * Delete a children inject
+   * @param children
+   */
+  const deleteChildren = (children: Dependency) => {
+    const childrenIndexInArray = childrens.findIndex((currentChildren) => currentChildren.inject?.inject_id === children.inject?.inject_id);
+
+    if (childrenIndexInArray > -1) {
+      const newChildrens = [
+        ...childrens.slice(0, childrenIndexInArray),
+        ...childrens.slice(childrenIndexInArray + 1),
+      ];
+      setChildrens(newChildrens);
+
+      form.mutators.setValue('inject_depends_to', injectDependencyFromDependency(newChildrens));
+    }
+  };
+
+  /**
+   * Returns an updated depends on from a ConditionType
+   * @param conditions
+   * @param switchIds
+   */
+  const updateDependsCondition = (conditions: ConditionType) => {
+    const result: InjectDependencyCondition = {
+      mode: conditions.mode === 'and' ? 'and' : 'or',
+      conditions: conditions.conditionElement?.map((value) => {
+        return {
+          value: value.value,
+          key: value.key,
+          operator: 'eq',
+        };
+      }),
+    };
+    return result;
+  };
+
+  /**
+   * Returns an updated depends on from a ConditionType
+   * @param conditions
+   * @param switchIds
+   */
+  const updateDependsOn = (conditions: ConditionType) => {
+    const result: InjectDependency = {
+      dependency_relationship: {
+        inject_parent_id: conditions.parentId,
+        inject_children_id: conditions.childrenId,
+      },
+      dependency_condition: updateDependsCondition(conditions),
+    };
+    return result;
+  };
+
+  /**
+   * Get the list of available expectations
+   * @param inject
+   */
+  const getAvailableExpectations = (inject: InjectOutputType | undefined) => {
+    if (inject?.inject_content !== null && inject?.inject_content !== undefined && (inject.inject_content as Content).expectations !== undefined) {
+      const expectations = (inject.inject_content as Content).expectations.map((expectation) => (expectation.expectation_type === 'MANUAL' ? expectation.expectation_name : capitalize(expectation.expectation_type)));
+      return ['Execution', ...expectations];
+    }
+    if (inject?.inject_injector_contract !== undefined
+        && (inject?.inject_injector_contract.convertedContent as unknown as ConvertedContentType).fields.find((field) => field.key === 'expectations')) {
+      const predefinedExpectations = (inject.inject_injector_contract.convertedContent as unknown as ConvertedContentType).fields?.find((field) => field.key === 'expectations')
+        ?.predefinedExpectations.map((expectation) => (expectation.expectation_type === 'MANUAL' ? expectation.expectation_name : capitalize(expectation.expectation_type)));
+      if (predefinedExpectations !== undefined) {
+        return ['Execution', ...predefinedExpectations];
+      }
+    }
+    return ['Execution'];
+  };
+
+  /**
+   * Add a new condition to a parent inject
+   * @param parent
+   */
+  const addConditionParent = (parent: Dependency) => {
+    const currentConditions = parentConditions.find((currentCondition) => parent.inject!.inject_id === currentCondition.parentId);
+
+    if (parent.inject !== undefined && currentConditions !== undefined) {
+      let expectationString = 'Execution';
+      if (currentConditions?.conditionElement !== undefined) {
+        expectationString = getAvailableExpectations(parent.inject)
+          .find((expectation) => !currentConditions?.conditionElement?.find((conditionElement) => conditionElement.key === expectation));
+      }
+      currentConditions.conditionElement?.push({
+        key: expectationString,
+        name: expectationString,
+        value: true,
+        index: currentConditions.conditionElement?.length,
+      });
+
+      setParentConditions(parentConditions);
+
+      const element = parentConditions.find((conditionElement) => conditionElement.childrenId === values.inject_id);
+
+      const dep: InjectDependency = {
+        dependency_relationship: {
+          inject_parent_id: element?.parentId,
+          inject_children_id: element?.childrenId,
+        },
+        dependency_condition: {
+          mode: element?.mode === '&&' ? 'and' : 'or',
+          conditions: element?.conditionElement ? element?.conditionElement.map((value) => {
+            return {
+              key: value.key,
+              value: value.value,
+              operator: 'eq',
+            };
+          }) : [],
+        },
+      };
+
+      form.mutators.setValue(
+        'inject_depends_on',
+        [dep],
+      );
+    }
+  };
+
+  /**
+   * Add a new condition to a children inject
+   * @param children
+   */
+  const addConditionChildren = (children: Dependency) => {
+    const currentConditions = childrenConditions.find((currentCondition) => children.inject!.inject_id === currentCondition.childrenId);
+
+    if (children.inject !== undefined && currentConditions !== undefined) {
+      const updatedChildren = childrens.find((currentChildren) => currentChildren.inject?.inject_id === children.inject?.inject_id);
+      let expectationString = 'Execution';
+      if (currentConditions?.conditionElement !== undefined) {
+        expectationString = getAvailableExpectations(values as InjectOutput as InjectOutputType)
+          .find((expectation) => !currentConditions?.conditionElement?.find((conditionElement) => conditionElement.key === expectation));
+      }
+      currentConditions.conditionElement?.push({
+        key: expectationString,
+        name: expectationString,
+        value: true,
+        index: currentConditions.conditionElement?.length,
+      });
+
+      if (updatedChildren?.inject?.inject_depends_on !== undefined) {
+        updatedChildren.inject.inject_depends_on = [updateDependsOn(currentConditions)];
+      }
+
+      setChildrenConditions(childrenConditions);
+      form.mutators.setValue(
+        'inject_depends_to',
+        injectDependencyFromDependency(childrens),
+      );
+    }
+  };
+
+  /**
+   * Handle a change in a condition of a parent element
+   * @param newElement
+   * @param conditions
+   * @param condition
+   * @param parent
+   */
+  const changeParentElement = (newElement: Element, conditions: ConditionType, condition: ConditionElement, parent: Dependency) => {
+    const newConditionElements = conditions.conditionElement?.map((newConditionElement) => {
+      if (newConditionElement.index === condition.index) {
+        return {
+          index: condition.index,
+          key: newElement.key,
+          name: `${conditions.parentId}-${newElement.key}-Success`,
+          value: newElement.value === 'Success',
+        };
+      }
+      return newConditionElement;
+    });
+    const newParentConditions = parentConditions.map((parentCondition) => {
+      if (parentCondition.parentId === parent.inject?.inject_id) {
+        return {
+          ...parentCondition,
+          conditionElement: newConditionElements,
+        };
+      }
+      return parentCondition;
+    });
+    setParentConditions(newParentConditions);
+
+    const element = newParentConditions?.find((conditionElement) => conditionElement.parentId === conditions.parentId);
+    const dep: InjectDependency = {
+      dependency_relationship: {
+        inject_parent_id: element?.parentId,
+        inject_children_id: element?.childrenId,
+      },
+      dependency_condition: {
+        mode: element?.mode === '&&' ? 'and' : 'or',
+        conditions: element?.conditionElement ? element?.conditionElement.map((value) => {
+          return {
+            key: value.key,
+            value: value.value,
+            operator: 'eq',
+          };
+        }) : [],
+      },
+    };
+
+    form.mutators.setValue(
+      'inject_depends_on',
+      [dep],
+    );
+  };
+
+  /**
+   * Handle a change in a condition of a children element
+   * @param newElement
+   * @param conditions
+   * @param condition
+   * @param children
+   */
+  const changeChildrenElement = (newElement: Element, conditions: ConditionType, condition: ConditionElement, children: Dependency) => {
+    const newConditionElements = conditions.conditionElement?.map((newConditionElement) => {
+      if (newConditionElement.index === condition.index) {
+        return {
+          index: condition.index,
+          key: newElement.key,
+          name: `${conditions.childrenId}-${newElement.key}-Success`,
+          value: newElement.value === 'Success',
+        };
+      }
+      return newConditionElement;
+    });
+    const newChildrenConditions = childrenConditions.map((childrenCondition) => {
+      if (childrenCondition.childrenId === children.inject?.inject_id) {
+        return {
+          ...childrenCondition,
+          conditionElement: newConditionElements,
+        };
+      }
+      return childrenCondition;
+    });
+    setChildrenConditions(newChildrenConditions);
+
+    const updatedChildren = childrens.find((currentChildren) => currentChildren.inject?.inject_id === children.inject?.inject_id);
+    const newCondition = newChildrenConditions.find((childrenCondition) => childrenCondition.childrenId === children.inject?.inject_id);
+    if (updatedChildren?.inject?.inject_depends_on !== undefined && newCondition !== undefined) {
+      updatedChildren.inject.inject_depends_on = [updateDependsOn(newCondition)];
+    }
+    form.mutators.setValue(
+      'inject_depends_to',
+      injectDependencyFromDependency(childrens),
+    );
+  };
+
+  /**
+   * Changes the mode (AND/OR) in a parent inject
+   * @param conditions
+   * @param condition
+   */
+  const changeModeParent = (conditions: ConditionType[] | undefined, condition: ConditionType) => {
+    const newConditionElements = conditions?.map((currentCondition) => {
+      if (currentCondition.parentId === condition.parentId) {
+        return {
+          ...currentCondition,
+          mode: currentCondition.mode === 'and' ? 'or' : 'and',
+        };
+      }
+      return currentCondition;
+    });
+    if (newConditionElements !== undefined) {
+      setParentConditions(newConditionElements);
+    }
+
+    const element = newConditionElements?.find((conditionElement) => conditionElement.parentId === condition.parentId);
+    const dep: InjectDependency = {
+      dependency_relationship: {
+        inject_parent_id: element?.parentId,
+        inject_children_id: element?.childrenId,
+      },
+      dependency_condition: {
+        mode: element?.mode === '&&' ? 'and' : 'or',
+        conditions: element?.conditionElement ? element?.conditionElement.map((value) => {
+          return {
+            key: value.key,
+            value: value.value,
+            operator: 'eq',
+          };
+        }) : [],
+      },
+    };
+
+    form.mutators.setValue(
+      'inject_depends_on',
+      [dep],
+    );
+  };
+
+  /**
+   * Changes the mode (AND/OR) in a children inject
+   * @param conditions
+   * @param condition
+   */
+  const changeModeChildren = (conditions: ConditionType[] | undefined, condition: ConditionType) => {
+    const newConditionElements = conditions?.map((currentCondition) => {
+      if (currentCondition.childrenId === condition.childrenId) {
+        return {
+          ...currentCondition,
+          mode: currentCondition.mode === 'and' ? 'or' : 'and',
+        };
+      }
+      return currentCondition;
+    });
+    if (newConditionElements !== undefined) {
+      setChildrenConditions(newConditionElements);
+    }
+
+    const newCurrentCondition = newConditionElements?.find((currentCondition) => currentCondition.childrenId === condition.childrenId);
+    const updatedChildren = childrens.find((currentChildren) => currentChildren.inject?.inject_id === newCurrentCondition?.childrenId);
+    if (updatedChildren?.inject?.inject_depends_on !== undefined && newCurrentCondition !== undefined) {
+      updatedChildren.inject.inject_depends_on = [updateDependsOn(newCurrentCondition)];
+    }
+    form.mutators.setValue(
+      'inject_depends_to',
+      injectDependencyFromDependency(childrens),
+    );
+  };
+
+  /**
+   * Delete a condition from a parent inject
+   * @param conditions
+   * @param condition
+   */
+  const deleteConditionParent = (conditions: ConditionType, condition: ConditionElement) => {
+    const newConditionElements = parentConditions.map((currentCondition) => {
+      if (currentCondition.parentId === conditions.parentId) {
+        return {
+          ...currentCondition,
+          conditionElement: currentCondition.conditionElement?.filter((element) => element.index !== condition.index),
+        };
+      }
+      return currentCondition;
+    });
+    setParentConditions(newConditionElements);
+
+    const element = newConditionElements.find((conditionElement) => conditionElement.parentId === conditions.parentId);
+    const dep: InjectDependency = {
+      dependency_relationship: {
+        inject_parent_id: element?.parentId,
+        inject_children_id: element?.childrenId,
+      },
+      dependency_condition: {
+        mode: element?.mode === '&&' ? 'and' : 'or',
+        conditions: element?.conditionElement ? element?.conditionElement.map((value) => {
+          return {
+            key: value.key,
+            value: value.value,
+            operator: 'eq',
+          };
+        }) : [],
+      },
+    };
+
+    form.mutators.setValue(
+      'inject_depends_on',
+      [dep],
+    );
+  };
+
+  /**
+   * Delete a condition from a children inject
+   * @param conditions
+   * @param condition
+   */
+  const deleteConditionChildren = (conditions: ConditionType, condition: ConditionElement) => {
+    const newConditionElements = childrenConditions.map((currentCondition) => {
+      if (currentCondition.childrenId === conditions.childrenId) {
+        return {
+          ...currentCondition,
+          conditionElement: currentCondition.conditionElement?.filter((element) => element.index !== condition.index),
+        };
+      }
+      return currentCondition;
+    });
+    setChildrenConditions(newConditionElements);
+
+    const updatedChildren = childrens.find((currentChildren) => currentChildren.inject?.inject_id === conditions.childrenId);
+    if (updatedChildren?.inject?.inject_depends_on !== undefined && conditions !== undefined) {
+      const newCondition = newConditionElements.find((currentCondition) => currentCondition.childrenId === conditions.childrenId);
+      if (newCondition !== undefined) updatedChildren.inject.inject_depends_on = [updateDependsOn(newCondition)];
+    }
+    form.mutators.setValue(
+      'inject_depends_to',
+      injectDependencyFromDependency(childrens),
+    );
+  };
+
+  /**
+   * Whether or not we can add a new condition
+   * @param inject
+   * @param conditions
+   */
+  const canAddConditions = (inject: InjectOutputType, conditions?: ConditionType) => {
+    const expectationsNumber = getAvailableExpectations(inject).length;
+    if (conditions === undefined || conditions.conditionElement === undefined) return true;
+
+    return conditions?.conditionElement.length < expectationsNumber;
+  };
+
+  /**
+   * Return a clickable parent chip
+   * @param parent
+   */
+  const getClickableParentChip = (parent: Dependency) => {
+    const parentChip = parentConditions.find((parentCondition) => parent.inject !== undefined && parentCondition.parentId === parent.inject.inject_id);
+    if (parentChip === undefined || parentChip.conditionElement === undefined) return (<></>);
+    return parentChip.conditionElement.map((condition, conditionIndex) => {
+      const conditions = parentConditions
+        .find((parentCondition) => parent.inject !== undefined && parentCondition.parentId === parent.inject.inject_id);
+      if (conditions?.conditionElement !== undefined) {
+        return (<div key={`${condition.name}-${condition.index}`} style={{ display: 'contents' }}>
+          <ClickableChip
+            selectedElement={{ key: condition.key, operator: 'is', value: condition.value ? 'Success' : 'Fail' }}
+            pristine={true}
+            availableKeys={getAvailableExpectations(parent.inject)}
+            availableOperators={['is']}
+            availableValues={['Success', 'Fail']}
+            onDelete={
+              conditions.conditionElement.length > 1 ? () => { deleteConditionParent(conditions, condition); } : undefined
+            }
+            onChange={(newElement) => {
+              changeParentElement(newElement, conditions, condition, parent);
+            }}
+          />
+          {conditionIndex < conditions.conditionElement.length - 1
+             && <ClickableModeChip
+               mode={conditions.mode}
+               onClick={() => { changeModeParent(parentConditions, conditions); }}
+                />
+          }</div>);
+      }
+      return (<></>);
+    });
+  };
+
+  /**
+   * Return a clickable children chip
+   * @param parent
+   */
+  const getClickableChildrenChip = (children: Dependency) => {
+    const childrenChip = childrenConditions.find((childrenCondition) => children.inject !== undefined && childrenCondition.childrenId === children.inject.inject_id);
+    if (childrenChip?.conditionElement === undefined) return (<></>);
+    return childrenChip
+      .conditionElement.map((condition, conditionIndex) => {
+        const conditions = childrenConditions
+          .find((childrenCondition) => childrenCondition.childrenId === children.inject?.inject_id);
+        if (conditions?.conditionElement !== undefined) {
+          return (<div key={`${condition.name}-${condition.index}`} style={{ display: 'contents' }}>
+            <ClickableChip
+              selectedElement={{ key: condition.key, operator: 'is', value: condition.value ? 'Success' : 'Fail' }}
+              pristine={true}
+              availableKeys={getAvailableExpectations(injects?.find((currentInject) => currentInject.inject_id === values.inject_id))}
+              availableOperators={['is']}
+              availableValues={['Success', 'Fail']}
+              onDelete={
+                  conditions.conditionElement.length > 1 ? () => { deleteConditionChildren(conditions, condition); } : undefined
+                }
+              onChange={(newElement) => {
+                changeChildrenElement(newElement, conditions, condition, children);
+              }}
+            />
+            {conditionIndex < conditions.conditionElement.length - 1
+                && <ClickableModeChip
+                  mode={conditions?.mode}
+                  onClick={() => { changeModeChildren(childrenConditions, conditions); }}
+                   />
+            }</div>);
+        }
+        return (<></>);
+      });
+  };
+
+  return (
+    <>
+      <div className={classes.importerStyle}>
+        <Typography variant="h2" sx={{ m: 0 }}>
+          {t('Parent')}
+        </Typography>
+        <IconButton
+          color="secondary"
+          aria-label="Add"
+          size="large"
+          disabled={parents.length > 0
+              || injects?.filter((currentInject) => currentInject.inject_depends_duration < values.inject_depends_duration).length === 0}
+          onClick={addParent}
+        >
+          <Add fontSize="small"/>
+        </IconButton>
+      </div>
+
+      {parents.map((parent, index) => {
+        return (
+          <Accordion
+            key={`accordion-parent-${parent.index}`}
+            variant="outlined"
+            style={{ width: '100%', marginBottom: '10px' }}
+          >
+            <AccordionSummary
+              expandIcon={<ExpandMore/>}
+            >
+              <div className={classes.container}>
+                <Typography>
+                  #{index + 1} {parent.inject?.inject_title}
+                </Typography>
+                <Tooltip title={t('Delete')}>
+                  <IconButton color="error"
+                    onClick={() => { deleteParent(parent); }}
+                  >
+                    <DeleteOutlined fontSize="small"/>
+                  </IconButton>
+                </Tooltip>
+              </div>
+            </AccordionSummary>
+            <AccordionDetails>
+              <FormControl style={{ width: '100%' }}>
+                <InputLabel id="inject_id">{t('Inject')}</InputLabel>
+                <Select
+                  labelId="condition"
+                  fullWidth={true}
+                  value={parents[parent.index].inject ? parents[parent.index].inject?.inject_id : ''}
+                  onChange={handleChangeParent}
+                >
+                  {injects?.filter((currentInject) => currentInject.inject_depends_duration < values.inject_depends_duration
+                      && (parents.find((parentSearch) => currentInject.inject_id === parentSearch.inject?.inject_id) === undefined
+                        || parents[parent.index].inject?.inject_id === currentInject.inject_id))
+                    .map((currentInject) => {
+                      return (<MenuItem key={`select-parent-${index}-inject-${currentInject.inject_id}`}
+                        value={currentInject.inject_id}
+                              >{currentInject.inject_title}</MenuItem>);
+                    })}
+                </Select>
+              </FormControl>
+              <FormControl style={{ width: '100%', marginTop: '15px' }}>
+                <label className={classes.labelExecutionCondition}>{t('Execution condition:')}</label>
+                <Box
+                  sx={{
+                    padding: '12px 4px',
+                    display: 'flex',
+                    flexWrap: 'wrap',
+                    gap: 1,
+                  }}
+                >
+                  {getClickableParentChip(parent)}
+                </Box>
+                <div style={{ justifyContent: 'left' }}>
+                  <Button
+                    color="secondary"
+                    aria-label="Add"
+                    size="large"
+                    onClick={() => {
+                      addConditionParent(parent);
+                    }}
+                    style={{ justifyContent: 'start' }}
+                    disabled={!canAddConditions(parent.inject!, parentConditions.find((parentCondition) => parentCondition.parentId === parent.inject?.inject_id))}
+                  >
+                    <Add fontSize="small"/>
+                    <Typography>
+                      {t('Add condition')}
+                    </Typography>
+                  </Button>
+                </div>
+              </FormControl>
+            </AccordionDetails>
+          </Accordion>
+        );
+      })}
+
+      <div className={classes.importerStyle}>
+        <Typography variant="h2" sx={{ m: 0 }}>
+          {t('Childrens')}
+        </Typography>
+        <IconButton
+          color="secondary"
+          aria-label="Add"
+          size="large"
+          disabled={addChildrenButtonDisabled}
+          onClick={addChildren}
+        >
+          <Add fontSize="small"/>
+        </IconButton>
+      </div>
+      {childrens.map((children, index) => {
+        return (
+          <Accordion
+            key={`accordion-children-${children.index}`}
+            variant="outlined"
+            style={{ width: '100%', marginBottom: '10px' }}
+          >
+            <AccordionSummary
+              expandIcon={<ExpandMore/>}
+            >
+              <div className={classes.container}>
+                <Typography>
+                  #{index + 1} {children.inject?.inject_title}
+                </Typography>
+                <Tooltip title={t('Delete')}>
+                  <IconButton color="error"
+                    onClick={() => { deleteChildren(children); }}
+                  >
+                    <DeleteOutlined fontSize="small"/>
+                  </IconButton>
+                </Tooltip>
+              </div>
+            </AccordionSummary>
+            <AccordionDetails>
+              <FormControl style={{ width: '100%' }}>
+                <InputLabel id="inject_id">{t('Inject')}</InputLabel>
+                <Select
+                  labelId="condition"
+                  fullWidth={true}
+                  value={childrens.find((childrenSearch) => children.index === childrenSearch.index)?.inject
+                    ? childrens.find((childrenSearch) => children.index === childrenSearch.index)?.inject?.inject_id : ''}
+                  onChange={handleChangeChildren}
+                >
+                  {injects?.filter((currentInject) => currentInject.inject_depends_duration > values.inject_depends_duration
+                        && (childrens.find((childrenSearch) => currentInject.inject_id === childrenSearch.inject?.inject_id) === undefined
+                            || childrens.find((childrenSearch) => children.index === childrenSearch.index)?.inject?.inject_id === currentInject.inject_id))
+                    .map((currentInject) => {
+                      return (
+                        <MenuItem key={`select-children-${children.index}-inject-${currentInject.inject_id}`}
+                          value={currentInject.inject_id}
+                        >{currentInject.inject_title}</MenuItem>);
+                    })}
+                </Select>
+              </FormControl>
+              <FormControl style={{ width: '100%', marginTop: '15px' }}>
+                <label className={classes.labelExecutionCondition}>{t('Execution condition:')}</label>
+
+                <Box
+                  sx={{
+                    padding: '12px 4px',
+                    display: 'flex',
+                    flexWrap: 'wrap',
+                    gap: 1,
+                  }}
+                >
+                  {getClickableChildrenChip(children)}
+                </Box>
+                <div style={{ justifyContent: 'left' }}>
+                  <Button
+                    color="secondary"
+                    aria-label="Add"
+                    size="large"
+                    onClick={() => {
+                      addConditionChildren(children);
+                    }}
+                    disabled={!canAddConditions(
+                      values as InjectOutput as InjectOutputType,
+                      childrenConditions.find((childrenCondition) => childrenCondition.childrenId === children.inject?.inject_id),
+                    )}
+                    style={{ justifyContent: 'start' }}
+                  >
+                    <Add fontSize="small"/>
+                    <Typography>
+                      {t('Add condition')}
+                    </Typography>
+                  </Button>
+                </div>
+              </FormControl>
+            </AccordionDetails>
+          </Accordion>
+        );
+      })}
+    </>
+  );
+};
+
+export default InjectForm;
diff --git a/openbas-front/src/admin/components/common/injects/Injects.tsx b/openbas-front/src/admin/components/common/injects/Injects.tsx
index 31618b2f48..4a0d359c65 100644
--- a/openbas-front/src/admin/components/common/injects/Injects.tsx
+++ b/openbas-front/src/admin/components/common/injects/Injects.tsx
@@ -49,7 +49,6 @@ const useStyles = makeStyles(() => ({
     color: '#00b1ff',
     border: '1px solid #00b1ff',
   },
-
   itemHead: {
     textTransform: 'uppercase',
   },
@@ -216,10 +215,13 @@ const Injects: FunctionComponent<Props> = ({
       setInjects([created as InjectOutputType, ...injects]);
     }
   };
+
   const onUpdate = (result: { result: string, entities: { injects: Record<string, InjectStore> } }) => {
     if (result.entities) {
       const updated = result.entities.injects[result.result];
-      setInjects(injects.map((i) => (i.inject_id !== updated.inject_id ? i as InjectOutputType : (updated as InjectOutputType))));
+      setInjects(injects.map((i) => {
+        return (i.inject_id !== updated.inject_id ? i as InjectOutputType : (updated as InjectOutputType));
+      }));
     }
   };
 
@@ -240,10 +242,12 @@ const Injects: FunctionComponent<Props> = ({
       onCreate(result);
     });
   };
+
   const onUpdateInject = async (data: Inject) => {
     if (selectedInjectId) {
       await injectContext.onUpdateInject(selectedInjectId, data).then((result: { result: string, entities: { injects: Record<string, InjectStore> } }) => {
         onUpdate(result);
+        return result;
       });
     }
   };
@@ -379,7 +383,7 @@ const Injects: FunctionComponent<Props> = ({
       'inject_description',
       'inject_injector_contract',
       'inject_content',
-      'inject_depends_from_another',
+      'inject_depends_on',
       'inject_depends_duration',
       'inject_teams',
       'inject_assets',
diff --git a/openbas-front/src/admin/components/common/injects/UpdateInjectDetails.js b/openbas-front/src/admin/components/common/injects/UpdateInjectDetails.js
index ecf2905511..55813d8758 100644
--- a/openbas-front/src/admin/components/common/injects/UpdateInjectDetails.js
+++ b/openbas-front/src/admin/components/common/injects/UpdateInjectDetails.js
@@ -209,7 +209,7 @@ const UpdateInjectDetails = ({
         inject_asset_groups: assetGroupIds,
         inject_documents: documents,
         inject_depends_duration,
-        inject_depends_on: data.inject_depends_on,
+        inject_depends_on: data.inject_depends_on ? data.inject_depends_on : [],
       };
       await onUpdateInject(values);
     }
@@ -324,7 +324,7 @@ const UpdateInjectDetails = ({
           </div>}
         />
         <CardContent classes={{ root: classes.injectorContractContent }}>
-          {tPick(contractContent.label)}
+          {contractContent !== null ? tPick(contractContent.label) : ''}
         </CardContent>
       </Card>
       <Form
diff --git a/openbas-front/src/admin/components/common/injects/UpdateInjectLogicalChains.js b/openbas-front/src/admin/components/common/injects/UpdateInjectLogicalChains.tsx
similarity index 59%
rename from openbas-front/src/admin/components/common/injects/UpdateInjectLogicalChains.js
rename to openbas-front/src/admin/components/common/injects/UpdateInjectLogicalChains.tsx
index 43ac86e834..f3e5845eaa 100644
--- a/openbas-front/src/admin/components/common/injects/UpdateInjectLogicalChains.js
+++ b/openbas-front/src/admin/components/common/injects/UpdateInjectLogicalChains.tsx
@@ -7,8 +7,13 @@ import { HelpOutlined } from '@mui/icons-material';
 import { useFormatter } from '../../../../components/i18n';
 import PlatformIcon from '../../../../components/PlatformIcon';
 import InjectChainsForm from './InjectChainsForm';
+import type { Theme } from '../../../../components/Theme';
+import type { Inject, InjectDependency } from '../../../../utils/api-types';
+import type { InjectOutputType } from '../../../../actions/injects/Inject';
+import { useHelper } from '../../../../store';
+import type { InjectHelper } from '../../../../actions/injects/inject-helper';
 
-const useStyles = makeStyles((theme) => ({
+const useStyles = makeStyles<Theme>((theme) => ({
   injectorContract: {
     margin: '10px 0 20px 0',
     width: '100%',
@@ -24,66 +29,85 @@ const useStyles = makeStyles((theme) => ({
   },
 }));
 
-const UpdateInjectLogicalChains = ({
-  inject,
-  handleClose,
-  onUpdateInject,
-  injects,
-}) => {
+interface Props {
+  inject: Inject,
+  handleClose: () => void;
+  onUpdateInject?: (data: Inject[]) => Promise<void>;
+  injects?: InjectOutputType[],
+}
+
+const UpdateInjectLogicalChains: React.FC<Props> = ({ inject, handleClose, onUpdateInject, injects }) => {
   const { t, tPick } = useFormatter();
   const classes = useStyles();
 
+  const { injectsMap } = useHelper((helper: InjectHelper) => ({
+    injectsMap: helper.getInjectsMap(),
+  }));
+
   const initialValues = {
     ...inject,
-    inject_depends_to: injects
-      .filter((currentInject) => currentInject.inject_depends_on === inject.inject_id)
-      .map((currentInject) => currentInject.inject_id),
+    inject_depends_to: injects !== undefined ? injects
+      .filter((currentInject) => currentInject.inject_depends_on !== undefined
+          && currentInject.inject_depends_on !== null
+          && currentInject.inject_depends_on
+            .find((searchInject) => searchInject.dependency_relationship?.inject_parent_id === inject.inject_id)
+          !== undefined)
+      .flatMap((currentInject) => {
+        return currentInject.inject_depends_on;
+      }) : undefined,
+    inject_depends_on: inject.inject_depends_on,
   };
 
-  const onSubmit = async (data) => {
+  const onSubmit = async (data: Inject & { inject_depends_to: InjectDependency[] }) => {
     const injectUpdate = {
       ...data,
       inject_id: data.inject_id,
-      inject_injector_contract: data.inject_injector_contract.injector_contract_id,
+      inject_injector_contract: data.inject_injector_contract?.injector_contract_id,
       inject_depends_on: data.inject_depends_on,
     };
 
-    const injectsToUpdate = [];
+    const injectsToUpdate: Inject[] = [];
 
-    const childrenIds = data.inject_depends_to;
+    const childrenIds = data.inject_depends_to.map((childrenInject: InjectDependency) => childrenInject.dependency_relationship?.inject_children_id);
 
-    const injectsWithoutDependencies = injects
-      .filter((currentInject) => currentInject.inject_depends_on === data.inject_id
+    const injectsWithoutDependencies = injects ? injects
+      .filter((currentInject) => currentInject.inject_depends_on !== null
+        && currentInject.inject_depends_on?.find((searchInject) => searchInject.dependency_relationship?.inject_parent_id === data.inject_id) !== undefined
         && !childrenIds.includes(currentInject.inject_id))
       .map((currentInject) => {
         return {
-          ...currentInject,
+          ...injectsMap[currentInject.inject_id],
           inject_id: currentInject.inject_id,
           inject_injector_contract: currentInject.inject_injector_contract.injector_contract_id,
           inject_depends_on: undefined,
-        };
-      });
+        } as unknown as Inject;
+      }) : [];
 
     injectsToUpdate.push(...injectsWithoutDependencies);
 
     childrenIds.forEach((childrenId) => {
+      if (injects === undefined || childrenId === undefined) return;
       const children = injects.find((currentInject) => currentInject.inject_id === childrenId);
       if (children !== undefined) {
-        const injectChildrenUpdate = {
-          ...children,
+        const injectDependsOnUpdate = data.inject_depends_to
+          .find((dependsTo) => dependsTo.dependency_relationship?.inject_children_id === childrenId);
+
+        const injectChildrenUpdate: Inject = {
+          ...injectsMap[children.inject_id],
           inject_id: children.inject_id,
           inject_injector_contract: children.inject_injector_contract.injector_contract_id,
-          inject_depends_on: inject.inject_id,
+          inject_depends_on: injectDependsOnUpdate ? [injectDependsOnUpdate] : [],
         };
         injectsToUpdate.push(injectChildrenUpdate);
       }
     });
-
-    await onUpdateInject([injectUpdate, ...injectsToUpdate]);
+    if (onUpdateInject) {
+      await onUpdateInject([injectUpdate as Inject, ...injectsToUpdate]);
+    }
 
     handleClose();
   };
-  const injectorContractContent = JSON.parse(inject.inject_injector_contract.injector_contract_content);
+  const injectorContractContent = inject.inject_injector_contract?.injector_contract_content ? JSON.parse(inject.inject_injector_contract?.injector_contract_content) : undefined;
   return (
     <>
       <Card elevation={0} classes={{ root: classes.injectorContract }}>
@@ -91,7 +115,7 @@ const UpdateInjectLogicalChains = ({
           classes={{ root: classes.injectorContractHeader }}
           avatar={injectorContractContent?.config?.type ? <Avatar sx={{ width: 24, height: 24 }} src={`/api/images/injectors/${injectorContractContent.config.type}`} />
             : <Avatar sx={{ width: 24, height: 24 }}><HelpOutlined /></Avatar>}
-          title={inject?.contract_attack_patterns_external_ids?.join(', ')}
+          title={inject?.inject_attack_patterns?.map((value) => value.attack_pattern_external_id)?.join(', ')}
           action={<div style={{ display: 'flex', alignItems: 'center' }}>
             {inject?.inject_injector_contract?.injector_contract_platforms?.map(
               (platform) => <PlatformIcon key={platform} width={20} platform={platform} marginRight={10} />,
@@ -133,7 +157,7 @@ const UpdateInjectLogicalChains = ({
                   variant="contained"
                   color="secondary"
                   type="submit"
-                  disabled={Object.keys(errors).length > 0 }
+                  disabled={errors !== undefined && Object.keys(errors).length > 0 }
                 >
                   {t('Update')}
                 </Button>
diff --git a/openbas-front/src/components/ChainedTimeline.tsx b/openbas-front/src/components/ChainedTimeline.tsx
index d159b3a7ed..5236a084f6 100644
--- a/openbas-front/src/components/ChainedTimeline.tsx
+++ b/openbas-front/src/components/ChainedTimeline.tsx
@@ -36,7 +36,8 @@ import NodePhantom from './nodes/NodePhantom';
 import { useFormatter } from './i18n';
 import type { AssetGroupsHelper } from '../actions/asset_groups/assetgroup-helper';
 import type { EndpointHelper } from '../actions/assets/asset-helper';
-import type { Inject } from '../utils/api-types';
+import type { Inject, InjectDependency } from '../utils/api-types';
+import ChainingUtils from './common/chaining/ChainingUtils';
 
 const useStyles = makeStyles(() => ({
   container: {
@@ -121,6 +122,8 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
   ];
   const gapSize = 125;
   const newNodeSize = 50;
+  const nodeHeightClearance = 220;
+  const nodeWidthClearance = 350;
 
   let startDate: string | undefined;
 
@@ -147,48 +150,128 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
     return Math.round(((position.x) / (gapSize / minutesPerGapAllowed[minutesPerGapIndex])) * 60);
   };
 
+  /**
+   * Move item from an index to another one
+   * @param array the array to update
+   * @param to the target index
+   * @param from the origin index
+   */
+  const moveItem = (array: NodeInject[], to: number, from: number) => {
+    const item = array[from];
+    array.splice(from, 1);
+    array.splice(to, 0, item);
+    return array;
+  };
+
+  /**
+   * Calculate a bounding box for an index
+   * @param currentNode the node to calculate the bounding box for
+   * @param nodesAvailable the nodes
+   */
+  const calculateBoundingBox = (currentNode: NodeInject, nodesAvailable: NodeInject[]) => {
+    if (currentNode.data.inject?.inject_depends_on) {
+      const nodesId = currentNode.data.inject?.inject_depends_on.map((value) => value.dependency_relationship?.inject_parent_id);
+      const dependencies = nodesAvailable.filter((dependencyNode) => nodesId.includes(dependencyNode.id));
+      const minX = Math.min(currentNode.position.x, ...dependencies.map((value) => value.data.boundingBox!.topLeft.x));
+      const minY = Math.min(currentNode.position.y, ...dependencies.map((value) => value.data.boundingBox!.topLeft.y));
+      const maxX = Math.max(currentNode.position.x + nodeWidthClearance, ...dependencies.map((value) => value.data.boundingBox!.bottomRight.x));
+      const maxY = Math.max(currentNode.position.y + nodeHeightClearance, ...dependencies.map((value) => value.data.boundingBox!.bottomRight.y));
+      return {
+        topLeft: { x: minX, y: minY },
+        bottomRight: { x: maxX, y: maxY },
+      };
+    }
+    return {
+      topLeft: currentNode.position,
+      bottomRight: { x: currentNode.position.x + nodeWidthClearance, y: currentNode.position.y + nodeHeightClearance },
+    };
+  };
+
   /**
    * Calculate injects position when dragging stopped
    * @param nodeInjects the list of injects
    */
   const calculateInjectPosition = (nodeInjects: NodeInject[]) => {
-    nodeInjects.forEach((nodeInject, index) => {
-      let row = 0;
-      let rowFound = true;
+    let reorganizedInjects = nodeInjects;
+
+    nodeInjects.forEach((node, i) => {
+      let childrens = reorganizedInjects.slice(i).filter((nextNode) => nextNode.id !== node.id
+          && nextNode.data.inject?.inject_depends_on !== undefined
+          && nextNode.data.inject?.inject_depends_on !== null
+          && nextNode.data.inject!.inject_depends_on
+            .find((dependsOn) => dependsOn.dependency_relationship?.inject_parent_id === node.id) !== undefined);
+
+      childrens = childrens.sort((a, b) => a.data.inject!.inject_depends_duration - b.data.inject!.inject_depends_duration);
+
+      childrens.forEach((children, j) => {
+        reorganizedInjects = moveItem(reorganizedInjects, i + j + 1, reorganizedInjects.indexOf(children, i));
+      });
+    });
+
+    reorganizedInjects.forEach((nodeInject, index) => {
       const nodeInjectPosition = nodeInject.position;
       const nodeInjectData = nodeInject.data;
-      do {
-        const previousNodes = nodeInjects.slice(0, index)
-          .filter((previousNode) => nodeInject.position.x >= previousNode.position.x && nodeInject.position.x < previousNode.position.x + 250);
-
-        for (let i = 0; i < previousNodes.length; i += 1) {
-          const previousNode = previousNodes[i];
-          if (previousNode.position.y + 150 > row * 150 && previousNode.position.y <= row * 150) {
-            row += 1;
-            rowFound = false;
-          } else {
-            nodeInjectPosition.y = 150 * row;
-            nodeInjectData.fixedY = nodeInject.position.y;
-            rowFound = true;
-          }
+
+      const previousNodes = reorganizedInjects.slice(0, index)
+        .filter((previousNode) => previousNode.data.boundingBox !== undefined
+            && nodeInjectData.boundingBox !== undefined
+            && nodeInjectData.boundingBox?.topLeft.x >= previousNode.data.boundingBox.topLeft.x
+            && nodeInjectData.boundingBox?.topLeft.x < previousNode.data.boundingBox.bottomRight.x);
+
+      const arrayOfY = previousNodes
+        .map((previousNode) => (previousNode.data.boundingBox?.bottomRight.y ? previousNode.data.boundingBox?.bottomRight.y : 0));
+      const maxY = Math.max(0, ...arrayOfY);
+
+      nodeInjectPosition.y = 0;
+      let rowFound = false;
+      for (let row = 1; row <= (maxY / nodeHeightClearance) + 1; row += 1) {
+        if (!arrayOfY.includes(row * nodeHeightClearance)) {
+          nodeInjectPosition.y = (row - 1) * nodeHeightClearance;
+          rowFound = true;
+          break;
         }
-      } while (!rowFound);
+      }
+
+      if (!rowFound) {
+        nodeInjectPosition.y = previousNodes.length === 0 ? 0 : maxY;
+      }
+      if (nodeInject.data.inject?.inject_depends_on) {
+        const nodesId = nodeInject.data.inject?.inject_depends_on.map((value) => value.dependency_relationship?.inject_parent_id);
+        const dependencies = reorganizedInjects.filter((dependencyNode) => nodesId.includes(dependencyNode.id));
+        const minY = dependencies.length > 0 ? Math.min(...dependencies.map((value) => value.data.boundingBox!.topLeft.y)) : 0;
+
+        nodeInjectPosition.y = nodeInjectPosition.y < minY ? minY : nodeInjectPosition.y;
+      }
+
+      nodeInjectData.fixedY = nodeInjectPosition.y;
+      nodeInjectData.boundingBox = calculateBoundingBox(nodeInject, reorganizedInjects);
+      reorganizedInjects[index] = nodeInject;
     });
   };
 
   const updateEdges = () => {
-    const newEdges = injects.filter((inject) => inject.inject_depends_on != null).map((inject) => {
-      return ({
-        id: `${inject.inject_id}->${inject.inject_depends_on}`,
-        target: `${inject.inject_id}`,
-        targetHandle: `target-${inject.inject_id}`,
-        source: `${inject.inject_depends_on}`,
-        sourceHandle: `source-${inject.inject_depends_on}`,
-        label: '',
-        labelShowBg: false,
-        labelStyle: { fill: theme.palette.text?.primary, fontSize: 9 },
+    const newEdges = injects.filter((inject) => inject.inject_depends_on !== null && inject.inject_depends_on !== undefined)
+      .flatMap((inject) => {
+        const results = [];
+        if (inject.inject_depends_on !== undefined) {
+          for (let i = 0; i < inject.inject_depends_on.length; i += 1) {
+            if (inject.inject_depends_on[i].dependency_relationship?.inject_children_id === inject.inject_id) {
+              results.push({
+                id: `${inject.inject_depends_on[i].dependency_relationship?.inject_parent_id}->${inject.inject_depends_on[i].dependency_relationship?.inject_children_id}`,
+                target: `${inject.inject_depends_on[i].dependency_relationship?.inject_children_id}`,
+                targetHandle: `target-${inject.inject_depends_on[i].dependency_relationship?.inject_children_id}`,
+                source: `${inject.inject_depends_on[i].dependency_relationship?.inject_parent_id}`,
+                sourceHandle: `source-${inject.inject_depends_on[i].dependency_relationship?.inject_parent_id}`,
+                label: ChainingUtils.fromInjectDependencyToLabel(inject.inject_depends_on[i]),
+                labelShowBg: false,
+                labelStyle: { fill: theme.palette.text?.primary, fontSize: 14 },
+              });
+            }
+          }
+        }
+        return results;
       });
-    });
+
     setEdges(newEdges);
   };
 
@@ -216,6 +299,10 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
             fixedY: 0,
             startDate,
             onSelectedInject,
+            boundingBox: {
+              topLeft: { x: (inject.inject_depends_duration / 60) * (gapSize / minutesPerGapAllowed[minutesPerGapIndex]), y: 0 },
+              bottomRight: { x: (inject.inject_depends_duration / 60) * (gapSize / minutesPerGapAllowed[minutesPerGapIndex]) + nodeWidthClearance, y: nodeHeightClearance },
+            },
             targets: inject.inject_assets!.map((asset) => assets[asset]?.asset_name)
               .concat(inject.inject_asset_groups!.map((assetGroup) => assetGroups[assetGroup]?.asset_group_name))
               .concat(inject.inject_teams!.map((team) => teams[team]?.team_name)),
@@ -279,6 +366,8 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
         inject_injector_contract: injectFromMap.inject_injector_contract.injector_contract_id,
         inject_id: node.id,
         inject_depends_duration: convertCoordinatesToTime(node.position),
+        inject_depends_on: injectFromMap.inject_depends_on !== null
+          ? injectFromMap.inject_depends_on : null,
       };
       onUpdateInject([inject]);
       setCurrentUpdatedNode(node);
@@ -316,11 +405,27 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
     const inject = injects.find((currentInject) => currentInject.inject_id === connection.target);
     const injectParent = injects.find((currentInject) => currentInject.inject_id === connection.source);
     if (inject !== undefined && injectParent !== undefined && inject.inject_depends_duration > injectParent.inject_depends_duration) {
+      const newDependsOn: InjectDependency = {
+        dependency_relationship: {
+          inject_children_id: inject.inject_id,
+          inject_parent_id: injectParent.inject_id,
+        },
+        dependency_condition:
+          {
+            mode: 'and',
+            conditions: [
+              {
+                key: 'Execution', operator: 'eq', value: true,
+              },
+            ],
+          },
+      };
+
       const injectToUpdate = {
         ...injectsMap[inject.inject_id],
         inject_injector_contract: inject.inject_injector_contract.injector_contract_id,
         inject_id: inject.inject_id,
-        inject_depends_on: injectParent?.inject_id,
+        inject_depends_on: [newDependsOn],
       };
       onUpdateInject([injectToUpdate]);
     }
@@ -335,8 +440,12 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
     setDraggingOnGoing(true);
     const { position } = node;
     const { data } = node;
-    const dependsOn = nodes.find((currentNode) => (currentNode.id === data.inject?.inject_depends_on));
-    const dependsTo = nodes.filter((currentNode) => (currentNode.data.inject?.inject_depends_on === node.id))
+    const dependsOn = nodes.find((currentNode) => (data.inject?.inject_depends_on !== null
+      && data.inject?.inject_depends_on!.find((value) => value.dependency_relationship?.inject_parent_id === currentNode.id)));
+    const dependsTo = nodes
+      .filter((currentNode) => (currentNode.data.inject?.inject_depends_on !== undefined
+          && currentNode.data.inject?.inject_depends_on !== null
+          && currentNode.data.inject?.inject_depends_on.find((value) => value.dependency_relationship?.inject_parent_id === node.id) !== undefined))
       .sort((a, b) => a.data.inject!.inject_depends_duration - b.data.inject!.inject_depends_duration)[0];
     const aSecond = gapSize / (minutesPerGapAllowed[minutesPerGapIndex] * 60);
     if (dependsOn?.position && position.x <= dependsOn?.position.x) {
@@ -462,11 +571,26 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
           inject_depends_on: undefined,
         };
         updates.push(injectToRemoveEdge);
+        const newDependsOn: InjectDependency = {
+          dependency_relationship: {
+            inject_children_id: injectToUpdate.inject_id,
+            inject_parent_id: edge.source,
+          },
+          dependency_condition:
+              {
+                mode: 'and',
+                conditions: [
+                  {
+                    key: 'Execution', operator: 'eq', value: true,
+                  },
+                ],
+              },
+        };
         const injectToUpdateEdge = {
           ...injectsMap[injectToUpdate.inject_id],
           inject_injector_contract: injectToUpdate.inject_injector_contract.injector_contract_id,
           inject_id: injectToUpdate.inject_id,
-          inject_depends_on: edge.source,
+          inject_depends_on: [newDependsOn],
         };
         updates.push(injectToUpdateEdge);
         onUpdateInject(updates);
@@ -475,11 +599,26 @@ const ChainedTimelineFlow: FunctionComponent<Props> = ({
       const inject = injects.find((currentInject) => currentInject.inject_id === edge.target);
       const parent = injects.find((currentInject) => currentInject.inject_id === connectionState.toNode?.id);
       if (inject !== undefined && parent !== undefined && parent.inject_depends_duration < inject.inject_depends_duration) {
+        const newDependsOn: InjectDependency = {
+          dependency_relationship: {
+            inject_children_id: inject.inject_id,
+            inject_parent_id: connectionState.toNode?.id,
+          },
+          dependency_condition:
+              {
+                mode: 'and',
+                conditions: [
+                  {
+                    key: 'Execution', operator: 'eq', value: true,
+                  },
+                ],
+              },
+        };
         const injectToUpdate = {
           ...injectsMap[inject.inject_id],
           inject_injector_contract: inject.inject_injector_contract.injector_contract_id,
           inject_id: inject.inject_id,
-          inject_depends_on: connectionState.toNode?.id,
+          inject_depends_on: [newDependsOn],
         };
         onUpdateInject([injectToUpdate]);
       }
diff --git a/openbas-front/src/components/common/chaining/ChainingUtils.tsx b/openbas-front/src/components/common/chaining/ChainingUtils.tsx
new file mode 100644
index 0000000000..6946df710e
--- /dev/null
+++ b/openbas-front/src/components/common/chaining/ChainingUtils.tsx
@@ -0,0 +1,14 @@
+import type { InjectDependency } from '../../../utils/api-types';
+
+const fromInjectDependencyToLabel = (dependency: InjectDependency) => {
+  let label = '';
+  if (dependency.dependency_condition?.conditions !== undefined) {
+    label = dependency.dependency_condition.conditions
+      .map((value) => `${value.key} is ${value.value ? 'Success' : 'Failure'}`)
+      .join(dependency.dependency_condition.mode === 'and' ? ' AND ' : ' OR ');
+  }
+
+  return label;
+};
+
+export default { fromInjectDependencyToLabel };
diff --git a/openbas-front/src/components/common/chips/ChipUtils.tsx b/openbas-front/src/components/common/chips/ChipUtils.tsx
new file mode 100644
index 0000000000..67dc6a6970
--- /dev/null
+++ b/openbas-front/src/components/common/chips/ChipUtils.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+
+// -- OPERATOR --
+
+const convertOperatorToIcon = (t: (text: string) => string, operator?: string) => {
+  switch (operator) {
+    case 'is':
+      return <>&nbsp;{t('is')}</>;
+    default:
+      return null;
+  }
+};
+
+export default convertOperatorToIcon;
diff --git a/openbas-front/src/components/common/chips/ClickableChip.tsx b/openbas-front/src/components/common/chips/ClickableChip.tsx
new file mode 100644
index 0000000000..8cdd60f489
--- /dev/null
+++ b/openbas-front/src/components/common/chips/ClickableChip.tsx
@@ -0,0 +1,181 @@
+import React, { FunctionComponent, useRef, useState } from 'react';
+import { Box, Chip, SelectChangeEvent, Tooltip } from '@mui/material';
+import { makeStyles } from '@mui/styles';
+import classNames from 'classnames';
+import type { Theme } from '../../Theme';
+import { useFormatter } from '../../i18n';
+import convertOperatorToIcon from './ChipUtils';
+import ClickableChipPopover from './ClickableChipPopover';
+
+const useStyles = makeStyles((theme: Theme) => ({
+  mode: {
+    display: 'inline-block',
+    height: '100%',
+    backgroundColor: theme.palette.action?.selected,
+    margin: '0 4px',
+    padding: '0 4px',
+  },
+  modeTooltip: {
+    margin: '0 4px',
+  },
+  container: {
+    gap: '4px',
+    display: 'flex',
+    overflow: 'hidden',
+    maxWidth: '400px',
+    alignItems: 'center',
+    lineHeight: '32px',
+    whiteSpace: 'nowrap',
+    textOverflow: 'ellipsis',
+  },
+  interactive: {
+    cursor: 'pointer',
+    '&:hover': {
+      textDecorationLine: 'underline',
+    },
+  },
+}));
+
+export interface Element {
+  key: string;
+  operator?: string;
+  value?: string;
+}
+
+interface Props {
+  onChange: (newElement: Element) => void;
+  pristine: boolean;
+  selectedElement: Element,
+  availableKeys: string[],
+  availableOperators: string[],
+  availableValues: string[],
+  onDelete?: () => void,
+}
+
+const ClickableChip: FunctionComponent<Props> = ({
+  onChange,
+  pristine,
+  selectedElement,
+  availableKeys,
+  availableOperators,
+  availableValues,
+  onDelete,
+}) => {
+  // Standard hooks
+  const { t } = useFormatter();
+  const classes = useStyles();
+
+  const chipRef = useRef<HTMLDivElement>(null);
+  const [open, setOpen] = useState(!pristine);
+  const [availableOptions, setAvailableOptions] = useState<string[]>([]);
+  const [selectedValue, setSelectedValue] = useState<string>();
+  const [propertyToChange, setPropertyToChange] = useState<string>('');
+  const handleOpen = () => setOpen(true);
+  const handleClose = () => setOpen(false);
+
+  const handleRemoveFilter = () => {
+    if (onDelete) onDelete();
+  };
+
+  const handleChange = (event: SelectChangeEvent) => {
+    const newValue = selectedElement;
+    switch (propertyToChange) {
+      case 'key': {
+        newValue.key = event.target.value;
+        break;
+      }
+      case 'operator': {
+        newValue.operator = event.target.value;
+        break;
+      }
+      case 'value': {
+        newValue.value = event.target.value;
+        break;
+      }
+      default:
+        break;
+    }
+    onChange(newValue);
+    setOpen(false);
+  };
+
+  const handleClickOpen = (options: string[], property: string, optionValue?: string) => {
+    setAvailableOptions(options);
+    if (optionValue) setSelectedValue(optionValue);
+    if (options.length > 1) handleOpen();
+    setPropertyToChange(property);
+  };
+
+  const toValues = (opts: string[] | undefined, isTooltip: boolean) => {
+    if (opts !== undefined) {
+      return opts.map((o, idx) => {
+        let or = <></>;
+        if (idx > 0) {
+          or = <div className={classNames({
+            [classes.mode]: !isTooltip,
+            [classes.modeTooltip]: isTooltip,
+          })}
+               >
+            {t('OR')}
+          </div>;
+        }
+        return (<div key={o}>{or}<span> {o}</span></div>);
+      });
+    }
+    return (<span key={'undefined'}> {t('undefined')}</span>);
+  };
+
+  const filterValues = (isTooltip: boolean) => {
+    return (
+      <span className={classes.container}>
+        <strong
+          className={availableKeys.length > 1 ? classes.interactive : undefined}
+          onClick={() => handleClickOpen(availableKeys, 'key', selectedElement.key)}
+        >
+          {t(selectedElement.key)}
+        </strong>
+        <Box sx={{ display: 'flex', flexDirection: 'row', overflow: 'hidden' }}
+          className={availableOperators.length > 1 ? classes.interactive : undefined}
+          onClick={() => handleClickOpen(availableOperators, 'operator', selectedElement.operator)}
+        >
+          {convertOperatorToIcon(t, selectedElement.operator)}
+        </Box>
+        <Box sx={{ display: 'flex', flexDirection: 'row', overflow: 'hidden' }}
+          className={availableValues.length > 1 ? classes.interactive : undefined}
+          onClick={() => handleClickOpen(availableValues, 'value', selectedElement.value)}
+        >
+          {toValues(selectedElement.value ? [selectedElement.value] : [], isTooltip)}
+        </Box>
+      </span>
+    );
+  };
+
+  const chipVariant = 'filled';
+
+  return (
+    <>
+      <Tooltip
+        title={filterValues(true)}
+      >
+        <Chip
+          variant={chipVariant}
+          label={filterValues(false)}
+          onDelete={onDelete ? handleRemoveFilter : undefined}
+          sx={{ borderRadius: 1 }}
+          ref={chipRef}
+        />
+      </Tooltip>
+      {chipRef?.current
+        && <ClickableChipPopover
+          handleChangeValue={handleChange}
+          open={open}
+          onClose={handleClose}
+          anchorEl={chipRef.current}
+          availableValues={availableOptions}
+          element={selectedValue}
+           />
+      }
+    </>
+  );
+};
+export default ClickableChip;
diff --git a/openbas-front/src/components/common/chips/ClickableChipPopover.tsx b/openbas-front/src/components/common/chips/ClickableChipPopover.tsx
new file mode 100644
index 0000000000..8ac0579da8
--- /dev/null
+++ b/openbas-front/src/components/common/chips/ClickableChipPopover.tsx
@@ -0,0 +1,69 @@
+import React, { FunctionComponent } from 'react';
+import { MenuItem, Popover, Select, SelectChangeEvent } from '@mui/material';
+
+interface Props {
+  handleChangeValue: (event: SelectChangeEvent) => void;
+  open: boolean;
+  onClose: () => void;
+  anchorEl?: HTMLElement;
+  availableValues: string[];
+  element?: string,
+}
+
+const ClickableChipPopover: FunctionComponent<Props> = ({
+  handleChangeValue,
+  open,
+  onClose,
+  anchorEl,
+  availableValues,
+  element,
+}) => {
+  // Standard hooks
+
+  const displayOperatorAndFilter = () => {
+    // Specific field
+
+    return (
+      <>
+        <Select
+          value={element || availableValues[0]}
+          label="Values"
+          variant="standard"
+          fullWidth
+          onChange={handleChangeValue}
+          style={{ marginBottom: 15 }}
+        >
+          {availableValues?.map((value) => (
+            <MenuItem key={value} value={value}>
+              {value}
+            </MenuItem>
+          ))}
+        </Select>
+      </>
+    );
+  };
+
+  return (
+    <Popover
+      open={open}
+      anchorEl={anchorEl}
+      onClose={onClose}
+      anchorOrigin={{
+        vertical: 'bottom',
+        horizontal: 'left',
+      }}
+      PaperProps={{ elevation: 1, style: { marginTop: 10 } }}
+    >
+      <div
+        style={{
+          width: 250,
+
+          padding: 8,
+        }}
+      >
+        {displayOperatorAndFilter()}
+      </div>
+    </Popover>
+  );
+};
+export default ClickableChipPopover;
diff --git a/openbas-front/src/components/common/queryable/filter/FilterModeChip.tsx b/openbas-front/src/components/common/chips/ClickableModeChip.tsx
similarity index 83%
rename from openbas-front/src/components/common/queryable/filter/FilterModeChip.tsx
rename to openbas-front/src/components/common/chips/ClickableModeChip.tsx
index cd6c8c2aa5..d0e3d5a79f 100644
--- a/openbas-front/src/components/common/queryable/filter/FilterModeChip.tsx
+++ b/openbas-front/src/components/common/chips/ClickableModeChip.tsx
@@ -1,8 +1,8 @@
 import React, { FunctionComponent } from 'react';
 import { makeStyles } from '@mui/styles';
 import classNames from 'classnames';
-import { useFormatter } from '../../../i18n';
-import type { Theme } from '../../../Theme';
+import { useFormatter } from '../../i18n';
+import type { Theme } from '../../Theme';
 
 const useStyles = makeStyles((theme: Theme) => ({
   mode: {
@@ -24,10 +24,10 @@ const useStyles = makeStyles((theme: Theme) => ({
 
 interface Props {
   onClick?: () => void;
-  mode?: 'and' | 'or';
+  mode?: string;
 }
 
-const FilterModeChip: FunctionComponent<Props> = ({
+const ClickableModeChip: FunctionComponent<Props> = ({
   onClick,
   mode,
 }) => {
@@ -52,4 +52,4 @@ const FilterModeChip: FunctionComponent<Props> = ({
   );
 };
 
-export default FilterModeChip;
+export default ClickableModeChip;
diff --git a/openbas-front/src/components/common/queryable/filter/FilterChips.tsx b/openbas-front/src/components/common/queryable/filter/FilterChips.tsx
index 51a23a6483..c601f33413 100644
--- a/openbas-front/src/components/common/queryable/filter/FilterChips.tsx
+++ b/openbas-front/src/components/common/queryable/filter/FilterChips.tsx
@@ -3,7 +3,7 @@ import { Box } from '@mui/material';
 import { FilterHelpers } from './FilterHelpers';
 import type { Filter, FilterGroup, PropertySchemaDTO } from '../../../../utils/api-types';
 import FilterChip from './FilterChip';
-import FilterModeChip from './FilterModeChip';
+import ClickableModeChip from '../../chips/ClickableModeChip';
 
 interface Props {
   propertySchemas: PropertySchemaDTO[];
@@ -48,7 +48,7 @@ const FilterChips: FunctionComponent<Props> = ({
         }
         return (
           <React.Fragment key={filter.key}>
-            {idx !== 0 && <FilterModeChip onClick={handleSwitchMode} mode={filterGroup?.mode} />}
+            {idx !== 0 && <ClickableModeChip onClick={handleSwitchMode} mode={filterGroup?.mode} />}
             <FilterChip
               filter={filter}
               helpers={helpers}
diff --git a/openbas-front/src/components/common/queryable/pagination/PaginationComponentV2.tsx b/openbas-front/src/components/common/queryable/pagination/PaginationComponentV2.tsx
index f73ce4edfa..c78dd20338 100644
--- a/openbas-front/src/components/common/queryable/pagination/PaginationComponentV2.tsx
+++ b/openbas-front/src/components/common/queryable/pagination/PaginationComponentV2.tsx
@@ -14,7 +14,7 @@ import TextSearchComponent from '../textSearch/TextSearchComponent';
 import FilterAutocomplete, { OptionPropertySchema } from '../filter/FilterAutocomplete';
 import useFilterableProperties from '../filter/useFilterableProperties';
 import FilterChips from '../filter/FilterChips';
-import FilterModeChip from '../filter/FilterModeChip';
+import ClickableModeChip from '../../chips/ClickableModeChip';
 import InjectorContractSwitchFilter from '../../../../admin/components/common/filters/InjectorContractSwitchFilter';
 import TablePaginationComponentV2 from './TablePaginationComponentV2';
 
@@ -184,7 +184,7 @@ const PaginationComponentV2 = <T extends object>({
                 onDelete={() => queryableHelpers.filterHelpers.handleRemoveFilterByKey(MITRE_FILTER_KEY)}
               />
               {(searchPaginationInput.filterGroup?.filters?.filter((f) => availableFilterNames?.filter((n) => n !== MITRE_FILTER_KEY).includes(f.key)).length ?? 0) > 0 && (
-                <FilterModeChip
+                <ClickableModeChip
                   onClick={queryableHelpers.filterHelpers.handleSwitchMode}
                   mode={searchPaginationInput.filterGroup.mode}
                 />
diff --git a/openbas-front/src/components/nodes/NodeInject.tsx b/openbas-front/src/components/nodes/NodeInject.tsx
index 48c38a65e3..46c23add77 100644
--- a/openbas-front/src/components/nodes/NodeInject.tsx
+++ b/openbas-front/src/components/nodes/NodeInject.tsx
@@ -1,5 +1,5 @@
 import React, { memo } from 'react';
-import { Handle, NodeProps, Position, Node, OnConnect } from '@xyflow/react';
+import { Handle, NodeProps, Position, Node, OnConnect, XYPosition } from '@xyflow/react';
 import { makeStyles, useTheme } from '@mui/styles';
 import { Tooltip } from '@mui/material';
 import moment from 'moment';
@@ -89,6 +89,10 @@ export type NodeInject = Node<{
   fixedY?: number,
   startDate?: string,
   targets: string[],
+  boundingBox?: {
+    topLeft: XYPosition,
+    bottomRight: XYPosition
+  },
   exerciseOrScenarioId: string,
   onSelectedInject(inject?: InjectOutputType): void,
   onCreate: (result: { result: string, entities: { injects: Record<string, InjectStore> } }) => void,
diff --git a/openbas-front/src/utils/Localization.js b/openbas-front/src/utils/Localization.js
index fe6f62b789..b055683651 100644
--- a/openbas-front/src/utils/Localization.js
+++ b/openbas-front/src/utils/Localization.js
@@ -1394,6 +1394,9 @@ const i18n = {
       'The element has been successfully updated': 'L\'élément a été mis à jour avec succès',
       'The element has been successfully deleted': 'L\'élément a été supprimé avec succès',
       'No data to display': 'Aucune donnée à afficher',
+      'Add condition': 'Ajouter une condition',
+      is: 'est',
+      undefined: 'non défini',
     },
     zh: {
       'Email address': 'email地址',
@@ -2734,6 +2737,9 @@ const i18n = {
       'The element has been successfully deleted': '元素已成功删除',
       'Internal error': '内部错误 ',
       'No data to display': '没有可显示的数据',
+      'Add condition': '添加条件',
+      is: '是',
+      undefined: '未定义',
     },
     en: {
       openbas_email: 'Email',
diff --git a/openbas-front/src/utils/String.js b/openbas-front/src/utils/String.js
index f1a589b5c5..a9ad73a527 100644
--- a/openbas-front/src/utils/String.js
+++ b/openbas-front/src/utils/String.js
@@ -68,6 +68,10 @@ export const computeLabel = (status) => {
   return 'Failed';
 };
 
+export const capitalize = (text) => {
+  return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
+};
+
 // compute color for status
 export const computeColorStyle = (status) => {
   if (status === 'PENDING') {
diff --git a/openbas-front/src/utils/api-types.d.ts b/openbas-front/src/utils/api-types.d.ts
index 2f7824239f..865bd00048 100644
--- a/openbas-front/src/utils/api-types.d.ts
+++ b/openbas-front/src/utils/api-types.d.ts
@@ -463,6 +463,12 @@ export interface Communication {
   listened?: boolean;
 }
 
+export interface Condition {
+  key: string;
+  operator: "eq";
+  value?: boolean;
+}
+
 export interface CreateUserInput {
   user_admin?: boolean;
   user_email: string;
@@ -1073,7 +1079,7 @@ export interface Inject {
    * @min 0
    */
   inject_depends_duration: number;
-  inject_depends_on?: Inject;
+  inject_depends_on?: InjectDependency[];
   inject_description?: string;
   inject_documents?: InjectDocument[];
   inject_enabled?: boolean;
@@ -1104,6 +1110,31 @@ export interface Inject {
   listened?: boolean;
 }
 
+export interface InjectDependency {
+  dependency_condition?: InjectDependencyCondition;
+  /** @format date-time */
+  dependency_created_at?: string;
+  dependency_relationship?: InjectDependencyId;
+  /** @format date-time */
+  dependency_updated_at?: string;
+}
+
+export interface InjectDependencyCondition {
+  conditions?: Condition[];
+  mode: "and" | "or";
+}
+
+export interface InjectDependencyId {
+  inject_children_id?: string;
+  inject_parent_id?: string;
+}
+
+export interface InjectDependencyInput {
+  dependency_conditions?: Condition[];
+  dependency_mode?: "&&" | "||";
+  dependency_parent?: string;
+}
+
 export interface InjectDocument {
   document_attached?: boolean;
   document_id?: Document;
@@ -1221,7 +1252,7 @@ export interface InjectInput {
   inject_country?: string;
   /** @format int64 */
   inject_depends_duration?: number;
-  inject_depends_on?: string;
+  inject_depends_on?: InjectDependencyInput[];
   inject_description?: string;
   inject_documents?: InjectDocumentInput[];
   inject_injector_contract?: string;
@@ -1239,7 +1270,7 @@ export interface InjectOutput {
    * @min 0
    */
   inject_depends_duration: number;
-  inject_depends_on?: string;
+  inject_depends_on?: InjectDependency[];
   inject_enabled?: boolean;
   inject_exercise?: string;
   inject_id: string;
diff --git a/openbas-model/src/main/java/io/openbas/database/model/Inject.java b/openbas-model/src/main/java/io/openbas/database/model/Inject.java
index e8b76fa11f..e3a93e53a6 100644
--- a/openbas-model/src/main/java/io/openbas/database/model/Inject.java
+++ b/openbas-model/src/main/java/io/openbas/database/model/Inject.java
@@ -123,11 +123,9 @@ public class Inject implements Base, Injection {
   private Scenario scenario;
 
   @Getter
-  @ManyToOne(fetch = FetchType.LAZY)
-  @JoinColumn(name = "inject_depends_from_another")
-  @JsonSerialize(using = MonoIdDeserializer.class)
+  @OneToMany(mappedBy = "compositeId.injectChildren", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
   @JsonProperty("inject_depends_on")
-  private Inject dependsOn;
+  private List<InjectDependency> dependsOn = new ArrayList<>();
 
   @Getter
   @Column(name = "inject_depends_duration")
@@ -279,7 +277,7 @@ public boolean isReady() {
 
   @JsonIgnore
   public Instant computeInjectDate(Instant source, int speed) {
-    return InjectModelHelper.computeInjectDate(source, speed, getDependsOn(), getDependsDuration(), getExercise());
+    return InjectModelHelper.computeInjectDate(source, speed, getDependsDuration(), getExercise());
   }
 
   @JsonProperty("inject_date")
@@ -291,7 +289,7 @@ public Optional<Instant> getDate() {
         return Optional.of(now().minusSeconds(60));
       }
     }
-    return InjectModelHelper.getDate(getExercise(), getScenario(), getDependsOn(), getDependsDuration());
+    return InjectModelHelper.getDate(getExercise(), getScenario(), getDependsDuration());
   }
 
   @JsonIgnore
diff --git a/openbas-model/src/main/java/io/openbas/database/model/InjectDependency.java b/openbas-model/src/main/java/io/openbas/database/model/InjectDependency.java
new file mode 100644
index 0000000000..d7dd0419ec
--- /dev/null
+++ b/openbas-model/src/main/java/io/openbas/database/model/InjectDependency.java
@@ -0,0 +1,55 @@
+package io.openbas.database.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import io.hypersistence.utils.hibernate.type.json.JsonType;
+import io.openbas.helper.MonoIdDeserializer;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import java.time.Instant;
+import java.util.Objects;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "injects_dependencies")
+public class InjectDependency {
+
+    @EmbeddedId
+    @JsonProperty("dependency_relationship")
+    private InjectDependencyId compositeId = new InjectDependencyId();
+
+    @Column(name = "dependency_condition")
+    @JsonProperty("dependency_condition")
+    @Type(JsonType.class)
+    private InjectDependencyConditions.InjectDependencyCondition injectDependencyCondition;
+
+    @CreationTimestamp
+    @Column(name = "dependency_created_at")
+    @JsonProperty("dependency_created_at")
+    private Instant creationDate;
+
+    @UpdateTimestamp
+    @Column(name = "dependency_updated_at")
+    @JsonProperty("dependency_updated_at")
+    private Instant updateDate;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        InjectDependency that = (InjectDependency) o;
+        return compositeId.equals(that.compositeId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(compositeId);
+    }
+}
diff --git a/openbas-model/src/main/java/io/openbas/database/model/InjectDependencyConditions.java b/openbas-model/src/main/java/io/openbas/database/model/InjectDependencyConditions.java
new file mode 100644
index 0000000000..4652a74f5f
--- /dev/null
+++ b/openbas-model/src/main/java/io/openbas/database/model/InjectDependencyConditions.java
@@ -0,0 +1,75 @@
+package io.openbas.database.model;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.util.Strings;
+
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Optional;
+
+public class InjectDependencyConditions {
+
+    public enum DependencyMode {
+        and{
+            @Override
+            public String toString() {
+                return "&&";
+            }
+        },
+        or{
+            @Override
+            public String toString() {
+                return "||";
+            }
+        };
+    }
+
+    public enum DependencyOperator {
+        eq {
+            @Override
+            public String toString() {
+                return "==";
+            }
+        };
+    }
+
+    @Data
+    public static class InjectDependencyCondition {
+
+        @NotNull
+        private DependencyMode mode; // Between filters
+        private List<Condition> conditions;
+
+        @Override
+        public String toString() {
+            StringBuilder result = new StringBuilder(Strings.EMPTY);
+            for (var i = 0 ; i < conditions.size() ; i++) {
+                if(i > 0) {
+                    result.append(mode.toString());
+                    result.append(StringUtils.SPACE);
+                }
+                result.append(conditions.get(i).toString());
+                result.append(StringUtils.SPACE);
+            }
+            return result.toString().trim();
+        }
+    }
+
+    @Data
+    public static class Condition {
+
+        @NotNull
+        private String key;
+        private boolean value;
+        @NotNull
+        private DependencyOperator operator;
+
+        @Override
+        public String toString() {
+            return String.format("%s %s %s", key, operator, value);
+        }
+    }
+}
diff --git a/openbas-model/src/main/java/io/openbas/database/model/InjectDependencyId.java b/openbas-model/src/main/java/io/openbas/database/model/InjectDependencyId.java
new file mode 100644
index 0000000000..8391832777
--- /dev/null
+++ b/openbas-model/src/main/java/io/openbas/database/model/InjectDependencyId.java
@@ -0,0 +1,54 @@
+package io.openbas.database.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import io.swagger.v3.oas.annotations.media.Schema;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import io.openbas.helper.MonoIdDeserializer;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Objects;
+
+@Embeddable
+@Getter
+@Setter
+@NoArgsConstructor
+public class InjectDependencyId implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @ManyToOne
+    @JsonProperty("inject_parent_id")
+    @JoinColumn(referencedColumnName="inject_id", name="inject_parent_id")
+    @JsonSerialize(using = MonoIdDeserializer.class)
+    @Schema(type = "string")
+    private Inject injectParent;
+
+    @ManyToOne
+    @JsonProperty("inject_children_id")
+    @JoinColumn(referencedColumnName="inject_id", name="inject_children_id")
+    @JsonSerialize(using = MonoIdDeserializer.class)
+    @Schema(type = "string")
+    private Inject injectChildren;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        InjectDependencyId that = (InjectDependencyId) o;
+        return injectParent.equals(that.injectParent) && injectChildren.equals(that.injectChildren);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(injectParent, injectChildren);
+    }
+}
diff --git a/openbas-model/src/main/java/io/openbas/database/repository/InjectDependenciesRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/InjectDependenciesRepository.java
new file mode 100644
index 0000000000..87d5ed77bc
--- /dev/null
+++ b/openbas-model/src/main/java/io/openbas/database/repository/InjectDependenciesRepository.java
@@ -0,0 +1,27 @@
+package io.openbas.database.repository;
+
+import io.openbas.database.model.InjectDependency;
+import io.openbas.database.model.InjectDependencyId;
+import io.openbas.database.model.Injector;
+import jakarta.validation.constraints.NotNull;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface InjectDependenciesRepository extends CrudRepository<InjectDependency, InjectDependencyId>, JpaSpecificationExecutor<Injector> {
+
+    @Query(value = "SELECT " +
+            "inject_parent_id, " +
+            "inject_children_id, " +
+            "dependency_condition, " +
+            "dependency_created_at, " +
+            "dependency_updated_at " +
+            "FROM injects_dependencies " +
+            "WHERE inject_children_id IN :childrens", nativeQuery = true)
+    List<InjectDependency> findParents(@NotNull List<String> childrens);
+}
diff --git a/openbas-model/src/main/java/io/openbas/helper/InjectModelHelper.java b/openbas-model/src/main/java/io/openbas/helper/InjectModelHelper.java
index fb39b73f27..c0ef540741 100644
--- a/openbas-model/src/main/java/io/openbas/helper/InjectModelHelper.java
+++ b/openbas-model/src/main/java/io/openbas/helper/InjectModelHelper.java
@@ -64,15 +64,11 @@ public static boolean isReady(
   public static Instant computeInjectDate(
       Instant source,
       int speed,
-      Inject dependsOn,
       Long dependsDuration,
       Exercise exercise) {
     // Compute origin execution date
-    Optional<Inject> dependsOnInject = ofNullable(dependsOn);
     long duration = ofNullable(dependsDuration).orElse(0L) / speed;
-    Instant dependingStart = dependsOnInject
-        .map(inject -> inject.computeInjectDate(source, speed))
-        .orElse(source);
+    Instant dependingStart = source;
     Instant standardExecutionDate = dependingStart.plusSeconds(duration);
     // Compute execution dates with previous terminated pauses
     long previousPauseDelay = 0L;
@@ -99,7 +95,6 @@ public static Instant computeInjectDate(
   public static Optional<Instant> getDate(
       Exercise exercise,
       Scenario scenario,
-      Inject dependsOn,
       Long dependsDuration
   ) {
     if (exercise == null && scenario == null) {
@@ -116,7 +111,7 @@ public static Optional<Instant> getDate(
       }
       return exercise
           .getStart()
-          .map(source -> computeInjectDate(source, SPEED_STANDARD, dependsOn, dependsDuration, exercise));
+          .map(source -> computeInjectDate(source, SPEED_STANDARD, dependsDuration, exercise));
     }
     return Optional.ofNullable(LocalDateTime.now().toInstant(ZoneOffset.UTC));
   }