Conflict Detection
The conflict detection engine identifies every artifact in the package that would conflict with an existing artifact in the target tenant, before any installation begins.
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.typeANDA.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 Type | Merge Supported | Reason |
|---|---|---|
| ProcessDefinition | No | Complex nested graph — automated merge unreliable |
| ThreadDefinition | No | Same as ProcessDefinition |
| AtlasForm | No | Field ordering and action dependencies make merge ambiguous |
| RuleSet | Yes | Simple array of rules — append/update is well-defined |
| EntitySchema | Yes | Additive field changes merge cleanly |
| AppDefinition | Yes | Configuration values can be merged safely |