Export History
Every export is recorded in the audit trail — who exported, which artifacts, when, and the resulting checksum. The history is immutable and queryable for compliance and debugging.
What is Logged
The ExportHistoryRepository records a history entry for every successful and failed export attempt. Each record captures:
| Field | Description |
|---|---|
exportId | Unique export event ID (different from packageId) |
packageId | The package created by this export (null if export failed) |
packageName | Package name as specified in the request |
version | Package version |
tenantId | Tenant from which artifacts were exported |
exportedBy | User identity (email or service account ID) |
exportedAt | UTC timestamp of the export operation |
artifactCount | Total number of artifacts in the bundle (including auto-resolved deps) |
rootArtifactIds | The artifact IDs specified in the export request |
checksum | SHA-256 checksum of the bundle (for integrity tracking) |
status | Success or Failure |
errorMessage | Error details if status is Failure |
bundleSize | ZIP file size in bytes |
Querying Export History
GET /api/installhub/packages/history
?tenantId={tenantId}
&pageSize=25
&page=1
&exportedBy=engineer@company.com // optional filter
&fromDate=2026-01-01 // optional filter
&toDate=2026-12-31 // optional filter
Authorization: Bearer {token}
Response
{
"totalCount": 47,
"page": 1,
"pageSize": 25,
"items": [
{
"exportId": "exp-f9a2c1e8-...",
"packageId": "pkg-a3f9c821-...",
"packageName": "Employee Onboarding Suite",
"version": "2.1.0",
"exportedBy": "engineer@company.com",
"exportedAt": "2026-05-25T09:00:00Z",
"artifactCount": 5,
"rootArtifactIds":["proc-1001"],
"checksum": "sha256:3a9f1c4e...",
"status": "Success",
"bundleSize": 87432
},
{
"exportId": "exp-b3d7f2a1-...",
"packageId": null,
"packageName": "Leave Approval",
"version": "1.0.0",
"exportedBy": "admin@company.com",
"exportedAt": "2026-05-24T14:30:00Z",
"artifactCount": 0,
"rootArtifactIds":["proc-9999"],
"checksum": null,
"status": "Failure",
"errorMessage": "ArtifactNotFound: proc-9999 does not exist in tenant",
"bundleSize": 0
}
]
}
Immutability
Export history records are immutable — they cannot be modified or deleted after creation. Even failed export attempts are permanently logged. This ensures a complete, tamper-evident audit trail for compliance purposes.
Retention Policy
Export history records are retained indefinitely by default. Tenants on Enterprise plans can configure a custom retention policy (minimum 90 days, maximum unlimited).
Bundle ZIP files stored in blob storage have a separate retention policy:
- Default: 365 days after last download
- Enterprise: configurable per-tenant
- If a bundle is expired, the history record remains but the download URL returns
HTTP 410 Gone
Re-Downloading a Previous Export
Use the packageId from a history record to download a previously created bundle:
GET /api/installhub/packages/{packageId}/download
Authorization: Bearer {token}
// If the bundle is still within retention:
HTTP 200 OK → ZIP bytes
// If the bundle has expired:
HTTP 410 Gone
{ "error": "BundleExpired", "message": "This bundle was created on 2025-01-01 and has expired per the 365-day retention policy. Please re-export from the source tenant." }
C# Entity
public class ExportHistoryRecord
{
public string ExportId { get; init; }
public string? PackageId { get; init; }
public string PackageName { get; init; }
public string Version { get; init; }
public string TenantId { get; init; }
public string ExportedBy { get; init; }
public DateTimeOffset ExportedAt { get; init; }
public int ArtifactCount { get; init; }
public string[] RootArtifactIds { get; init; }
public string? Checksum { get; init; }
public ExportStatus Status { get; init; }
public string? ErrorMessage { get; init; }
public long BundleSize { get; init; }
}
public enum ExportStatus { Success, Failure }