Portal Community

Conflict Detection Rule

An artifact conflict is defined as:

An artifact A in the package conflicts with an artifact B in the target tenant if and only if A.type == B.type AND A.name == B.name (case-insensitive).

Note: The comparison is on name, not ID. IDs have already been remapped to avoid ID collisions. The name comparison is what catches genuine "same artifact, different version" scenarios.

Detection Algorithm

public async Task<ConflictReport> DetectConflictsAsync(
    IReadOnlyList<RemappedArtifact> packageArtifacts,
    string                          targetTenantId,
    CancellationToken               ct)
{
    var report = new ConflictReport();

    foreach (var artifact in packageArtifacts)
    {
        // Query target tenant for artifact with same type and name
        var existing = await _repository.FindByNameAsync(
            artifact.Type,
            artifact.Name,
            targetTenantId,
            ct);

        if (existing is not null)
        {
            report.AddConflict(new ConflictEntry
            {
                ArtifactType     = artifact.Type,
                ArtifactName     = artifact.Name,
                PackageArtifactId  = artifact.RemappedId,
                ExistingArtifactId = existing.Id,
                PackageVersion   = artifact.Version,
                ExistingVersion  = existing.Version,
                MergeSupported   = IsMergeSupported(artifact.Type)
            });
        }
    }

    return report;
}

When Detection Runs

Conflict detection runs after ID remapping and before the installation stage. If a defaultConflictStrategy is set, detection results are used to automatically assign strategies. If no default strategy is set and conflicts exist, the import pauses and returns the ConflictReport for administrator review.

Conflict Detection API Response (Paused for Review)

HTTP 202 Accepted
{
  "importId":        "imp-f9a2c1e8-...",
  "status":          "PendingConflictResolution",
  "message":         "2 conflicts found. Resolve them and resume the import.",
  "resumeUrl":       "/api/installhub/packages/import/imp-f9a2c1e8-/resume",
  "conflictReport": {
    "conflictsFound": 2,
    "conflicts": [
      {
        "conflictId":       "conf-001",
        "artifactType":     "AtlasForm",
        "artifactName":     "EmployeeForm",
        "packageVersion":   "1.3.0",
        "existingVersion":  "1.0.0",
        "mergeSupported":   false,
        "proposedStrategy": null
      },
      {
        "conflictId":       "conf-002",
        "artifactType":     "RuleSet",
        "artifactName":     "ApprovalRules",
        "packageVersion":   "1.2.0",
        "existingVersion":  "1.1.0",
        "mergeSupported":   true,
        "proposedStrategy": null
      }
    ]
  }
}

Resume with Conflict Resolutions

POST /api/installhub/packages/import/{importId}/resume
{
  "resolutions": [
    { "conflictId": "conf-001", "strategy": "Replace" },
    { "conflictId": "conf-002", "strategy": "Merge"   }
  ]
}

Merge Eligibility

Not all artifact types support automated merge. The mergeSupported flag in each conflict entry indicates whether Merge is a valid strategy for that conflict:

Artifact TypeMerge SupportedReason
ProcessDefinitionNoComplex nested graph — automated merge unreliable
ThreadDefinitionNoSame as ProcessDefinition
AtlasFormNoField ordering and action dependencies make merge ambiguous
RuleSetYesSimple array of rules — append/update is well-defined
EntitySchemaYesAdditive field changes merge cleanly
AppDefinitionYesConfiguration values can be merged safely