Portal Community
Phase 2 — PENDING The import system design is complete. Implementation has not started. The service interface is defined; all types described in this guide are accurate to the design specification.

What the Import System Does

The import system takes an InstallHub package ZIP and installs its artifacts into a target tenant. It handles every complexity automatically: verifying the bundle was not tampered with, scanning for security threats, translating artifact IDs to avoid collisions, resolving conflicts with existing artifacts, and committing everything in a single database transaction.

Import Pipeline

1

Upload

The caller POSTs the ZIP file to /api/installhub/packages/import. The engine reads the ZIP into memory and extracts the manifest.

2

Manifest Validation

Schema validation of manifest.json: required fields, SemVer format, artifact file presence, package dependency declarations.

3

Checksum Verification

Recompute SHA-256 over artifact files in install order. Compare to manifest checksum. Reject on mismatch.

4

Security Scan

Expression injection detection, SQL injection patterns, content policy check. FAIL result blocks import immediately. WARN allows import with administrator acknowledgment.

5

Package Dependency Check

Verify all packageDependencies are satisfied: correct packages are installed in the target tenant at compatible versions.

6

ID Remapping

Map every artifact ID from the source tenant to a new ID in the target tenant. Update all cross-references in artifact definitions to use new IDs.

7

Conflict Detection

Identify artifacts where the package contains an artifact with the same name and type as an existing artifact in the target tenant.

8

Conflict Resolution

Apply the configured strategy (Replace, Merge, or Skip) to each conflict. See Guide 5.

9

Transactional Install

Create or update artifacts in the target tenant in install order, within a database transaction. All artifacts are installed or none.

10

Post-Install Verification

Query each installed artifact to confirm it is accessible and functional. If verification fails, the transaction is rolled back.

ImportOptions

public class ImportOptions
{
    public string                   TargetTenantId     { get; init; }
    public ConflictResolutionStrategy DefaultConflictStrategy { get; init; }
        // Replace | Merge | Skip — applied to all conflicts
    public bool                     DryRun             { get; init; }
        // true = run full pipeline but do not commit — returns preview
    public bool                     AllowMajorVersionUpgrade { get; init; }
        // true = allow import when package major version > installed major version
    public bool                     AllowSecurityWarnings    { get; init; }
        // true = proceed with import even if security scan returns WARN
    public string                   ImportedBy         { get; init; }
        // User identity for audit log
}

Service Contract

public interface IImportService
{
    /// <summary>
    /// Imports a package bundle into the specified tenant.
    /// All stages run in sequence. On failure at any stage, all changes are rolled back.
    /// </summary>
    Task<ImportResult> ImportAsync(
        byte[]         zipBytes,
        ImportOptions  options,
        CancellationToken ct = default);

    /// <summary>
    /// Runs the full import pipeline but does not commit changes.
    /// Returns a preview of what would be installed and any conflicts or issues.
    /// </summary>
    Task<DryRunResult> DryRunAsync(
        byte[]         zipBytes,
        ImportOptions  options,
        CancellationToken ct = default);

    /// <summary>
    /// Returns the import history for a tenant, newest first.
    /// </summary>
    Task<IReadOnlyList<ImportHistoryRecord>> GetHistoryAsync(
        string         tenantId,
        int            pageSize = 50,
        CancellationToken ct = default);
}

Dry Run Mode

The dry-run mode is invaluable before committing to an import. It runs the full pipeline — validation, security scan, ID remapping, conflict detection — but does not write any data to the database. The response tells you exactly what would be installed and what conflicts exist:

POST /api/installhub/packages/import?dryRun=true
// or in ImportOptions: "dryRun": true

// Response:
{
  "isDryRun":         true,
  "wouldInstall":     ["EmployeeOnboarding", "EmployeeForm", "ApprovalRules", "EmployeeSchema"],
  "conflictsFound":   [
    { "artifactName": "EmployeeForm", "type": "AtlasForm", "resolution": "Replace" }
  ],
  "securityScanResult": "PASS",
  "estimatedInstallOrder": ["ent-44", "rule-305", "form-2005", "proc-1001"],
  "warnings": []
}