Portal Community

What the Checksum Protects

The checksum detects:

What is Hashed

The bundle checksum is SHA-256 of all artifact file contents concatenated in install order. The manifest itself is not included in the hash (because the manifest contains the hash — a circular dependency).

// Install order from manifest: ["ent-44", "rule-305", "form-2005", "thread-2002", "proc-1001"]

// Checksum input = concatenation:
bytes(artifacts/entities/ent-44.json)
+ bytes(artifacts/rules/rule-305.json)
+ bytes(artifacts/forms/form-2005.json)
+ bytes(artifacts/workflows/thread-2002.json)
+ bytes(artifacts/workflows/proc-1001.json)

// Hash:
checksum = "sha256:" + hex(SHA256(concatenatedBytes))
Why In Install Order? Using install order ensures the hash is deterministic — the same artifacts always produce the same hash regardless of how they appear in the ZIP directory listing (which can vary by ZIP implementation). Install order is canonical because it is topologically sorted.

Per-Artifact Hashes

In addition to the bundle checksum, each artifact entry in the manifest includes its own hash field — the SHA-256 of that single artifact file's bytes:

{
  "artifacts": [
    {
      "id":   "proc-1001",
      "file": "artifacts/workflows/proc-1001.json",
      "hash": "sha256:abc123def456789..."   // SHA-256 of proc-1001.json bytes only
    }
  ]
}

On import, the engine verifies both:

  1. Each artifact file individually against its per-artifact hash
  2. The full bundle by recomputing the overall checksum

If an individual artifact hash fails but the bundle checksum matches, this indicates a manifest error. If the bundle checksum fails, at least one file was modified.

Verification Algorithm

// Import engine verification (pseudocode)
async VerifyChecksumAsync(zip, manifest):

    // Step 1: verify each artifact individually
    for artifact in manifest.artifacts:
        fileBytes = zip.ReadFile(artifact.file)
        actualHash = "sha256:" + hex(SHA256(fileBytes))
        if actualHash != artifact.hash:
            throw ChecksumMismatch(artifact.id, artifact.hash, actualHash)

    // Step 2: verify the full bundle
    concatenated = []
    for artifactId in manifest.installOrder:
        artifact = manifest.FindArtifact(artifactId)
        fileBytes = zip.ReadFile(artifact.file)
        concatenated.append(fileBytes)

    actualBundleChecksum = "sha256:" + hex(SHA256(concatenate(concatenated)))
    if actualBundleChecksum != manifest.checksum:
        throw BundleChecksumMismatch(manifest.checksum, actualBundleChecksum)

Checksum Format

"checksum": "sha256:3a9f1c4e8d2b7f6a1e5c9d3b0a4f8e2c7d1a6b9e3f5c8d2a0b7e4f1c9d3a6b0"
                ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                prefix 64 hex characters = 256 bits = SHA-256 output

The sha256: prefix is mandatory and allows future support for alternative hash algorithms (e.g., sha512:) without breaking parsers.

Computing the Checksum (C# Example)

public static string ComputeBundleChecksum(
    IReadOnlyList<SerializedArtifact> artifacts,
    IReadOnlyList<string>             installOrder)
{
    using var sha256 = SHA256.Create();
    using var combined = new MemoryStream();

    // Concatenate artifact bytes in install order
    foreach (var artifactId in installOrder)
    {
        var artifact = artifacts.First(a => a.Id == artifactId);
        combined.Write(artifact.Bytes);
    }

    combined.Position = 0;
    var hash = sha256.ComputeHash(combined);
    return "sha256:" + Convert.ToHexString(hash).ToLowerInvariant();
}

public static string ComputeArtifactHash(byte[] artifactBytes)
{
    using var sha256 = SHA256.Create();
    var hash = sha256.ComputeHash(artifactBytes);
    return "sha256:" + Convert.ToHexString(hash).ToLowerInvariant();
}

Checksum Failure Response

HTTP 400 Bad Request
{
  "error":   "ChecksumMismatch",
  "message": "The bundle checksum in the manifest does not match the computed checksum. The package may have been corrupted or tampered with.",
  "expected": "sha256:3a9f1c4e...",
  "actual":   "sha256:7b2c8d5f..."
}
Do Not Edit Bundle Contents Any change to an artifact file inside the ZIP after export will cause checksum verification to fail. Re-export from the source tenant if you need updated content.