Offline Bundle Format (.stella.bundle.tgz)
Audience: engineers and operators who produce, transfer, or verify portable evidence packages for sealed Stella Ops deployments.
This guide describes the .stella.bundle.tgz format: a portable, signed, verifiable evidence package produced by the Export Center. For the image/chart/feed transport format, see Mirror Bundles; for staging bundles into a sealed install, see the Air-Gap Importer Guide.
Overview
The offline bundle is a self-contained archive containing all evidence and artifacts needed for offline triage of security findings. Bundles are:
- Portable: Single file that can be transferred to air-gapped environments
- Signed: DSSE-signed manifest for authenticity verification
- Verifiable: Content-addressable with SHA-256 hashes for integrity
- Complete: Contains all data needed for offline decision-making
File Format
{alert-id}.stella.bundle.tgz
├── manifest.json # Bundle manifest (DSSE-signed)
├── metadata/
│ ├── alert.json # Alert metadata snapshot
│ └── generation-info.json # Bundle generation metadata
├── evidence/
│ ├── reachability-proof.json # Call-graph reachability evidence
│ ├── callstack.json # Exploitability call stacks
│ └── provenance.json # Build provenance attestations
├── vex/
│ ├── decisions.ndjson # VEX decision history (NDJSON)
│ └── current-status.json # Current VEX status
├── sbom/
│ ├── current.cdx.json # Current SBOM slice (CycloneDX)
│ └── baseline.cdx.json # Baseline SBOM for diff
├── diff/
│ └── sbom-delta.json # SBOM delta changes
└── attestations/
├── bundle.dsse.json # DSSE envelope for bundle
└── evidence.dsse.json # Evidence attestation chain
Manifest Schema
The manifest.json file follows this schema:
{
"bundle_format_version": "1.0.0",
"bundle_id": "abc123def456...",
"alert_id": "alert-789",
"created_at": "2024-12-15T10:00:00Z",
"created_by": "user@example.com",
"stellaops_version": "1.5.0",
"entries": [
{
"path": "metadata/alert.json",
"hash": "sha256:...",
"size": 1234,
"content_type": "application/json"
}
],
"root_hash": "sha256:...",
"signature": {
"algorithm": "ES256",
"key_id": "signing-key-001",
"value": "..."
}
}
Manifest Fields
| Field | Type | Required | Description |
|---|---|---|---|
bundle_format_version | string | Yes | Format version (semver) |
bundle_id | string | Yes | Unique bundle identifier |
alert_id | string | Yes | Source alert identifier |
created_at | ISO 8601 | Yes | Bundle creation timestamp (UTC) |
created_by | string | Yes | Actor who created the bundle |
stellaops_version | string | Yes | StellaOps version that created bundle |
entries | array | Yes | List of content entries with hashes |
root_hash | string | Yes | Merkle root of all entry hashes |
signature | object | No | DSSE signature (if signed) |
Entry Schema
Each entry in the manifest:
{
"path": "evidence/reachability-proof.json",
"hash": "sha256:abc123...",
"size": 2048,
"content_type": "application/json",
"compression": null
}
DSSE Signing
Bundles support DSSE (Dead Simple Signing Envelope) signing:
Signing requires an operator-provided PEM private key whose public key is distributed through the receiving environment’s trust roots. The AirGap bundle writer fails closed when signing is enabled without a configured key; it does not mint ephemeral signatures for production bundles.
{
"payloadType": "application/vnd.stellaops.bundle.manifest+json",
"payload": "<base64-encoded manifest>",
"signatures": [
{
"keyid": "signing-key-001",
"sig": "<base64-encoded signature>"
}
]
}
Creation
API Endpoint
GET /v1/alerts/{alertId}/bundle
Authorization: Bearer <token>
Response: application/gzip
Content-Disposition: attachment; filename="alert-123.stella.bundle.tgz"
Programmatic
var packager = services.GetRequiredService<IOfflineBundlePackager>();
var result = await packager.CreateBundleAsync(new BundleRequest
{
AlertId = "alert-123",
ActorId = "user@example.com",
IncludeVexHistory = true,
IncludeSbomSlice = true
});
// result.Content contains the tarball stream
// result.ManifestHash contains the verification hash
Verification
API Endpoint
POST /v1/alerts/{alertId}/bundle/verify
Content-Type: application/json
{
"bundle_hash": "sha256:abc123...",
"signature": "<optional DSSE signature>"
}
Response:
{
"is_valid": true,
"hash_valid": true,
"chain_valid": true,
"signature_valid": true,
"verified_at": "2024-12-15T10:00:00Z"
}
Programmatic
var verification = await packager.VerifyBundleAsync(
bundlePath: "/path/to/bundle.stella.bundle.tgz",
expectedHash: "sha256:abc123...");
if (!verification.IsValid)
{
Console.WriteLine($"Verification failed: {string.Join(", ", verification.Errors)}");
}
CLI Usage
# Export bundle
stellaops alert bundle export --alert-id alert-123 --output ./bundles/
# Verify bundle
stellaops alert bundle verify --file ./bundles/alert-123.stella.bundle.tgz
# Import bundle (air-gapped instance)
stellaops alert bundle import --file ./bundles/alert-123.stella.bundle.tgz
OCI Referrer Artifacts
Mirror bundles automatically include OCI referrer artifacts (SBOMs, attestations, signatures) discovered from container registries. These artifacts are stored under a dedicated referrers/ directory keyed by subject image digest.
OCI Image-Layer Transport
Knowledge snapshot bundles produced by SnapshotBundleWriter can carry container image bytes for fully offline serving by the local deployment agent. Snapshot schema 2.1.0 adds ociImages[] to the manifest and stores image content in OCI image-layout form:
bundle.stella.bundle.tgz
├── manifest.json
└── oci/
├── oci-layout
├── index.json
└── blobs/
└── sha256/
└── <hex>
Each blob filename is its SHA-256 hex digest. ociImages[] records repo, subjectDigest, maskedRef, manifestDigest, configDigest, layerDigests[], referrerDigests[], and totalSizeBytes. Shared layers are deduplicated by digest across images. On pack, supplied layer and referrer digests must match the blob bytes or the writer fails closed. On import, run OciImageLayoutVerifier against the extracted oci/ directory to recompute blob hashes and ensure index.json descriptors resolve to present blobs. For deployment-agent serving, configure Agent:LocalRegistry:OciLayoutBundlePath with that extracted oci/ directory; the agent registry also verifies every blob and index.json descriptor before importing into its local content store. Deployment-decision referrer manifests are also listed in oci/index.json so a bundle-only agent can discover the signed verdict artifacts without external registry access.
Referrer Directory Structure
bundle.stella.bundle.tgz
├── ...existing structure...
├── referrers/
│ └── sha256-abc123.../ # Subject image digest
│ ├── sha256-def456.json # CycloneDX SBOM
│ ├── sha256-ghi789.json # in-toto attestation
│ └── sha256-jkl012.json # VEX statement
└── indexes/
├── referrers.index.json # Referrer artifact index
└── attestations.index.json # Attestation cross-reference
Manifest Referrers Section
The bundle manifest includes a referrers section documenting all discovered artifacts:
referrers:
subjects:
- subject: "sha256:abc123..."
artifacts:
- digest: "sha256:def456..."
artifactType: "application/vnd.cyclonedx+json"
mediaType: "application/vnd.oci.image.manifest.v1+json"
size: 12345
path: "referrers/sha256-abc123.../sha256-def456.json"
sha256: "def456789..."
category: "sbom"
annotations:
org.opencontainers.image.created: "2026-01-27T10:00:00Z"
- digest: "sha256:ghi789..."
artifactType: "application/vnd.in-toto+json"
mediaType: "application/vnd.oci.image.manifest.v1+json"
size: 8192
path: "referrers/sha256-abc123.../sha256-ghi789.json"
sha256: "ghi789abc..."
category: "attestation"
Referrer Validation
The ImportValidator verifies referrer artifacts during bundle import:
| Validation | Severity | Description |
|---|---|---|
ReferrerMissing | Error | Declared artifact not found in bundle |
ReferrerChecksumMismatch | Error | SHA-256 doesn’t match declared value |
ReferrerSizeMismatch | Error | Size doesn’t match declared value |
OrphanedReferrer | Warning | File exists in referrers/ but not declared |
Artifact Types
| Artifact Type | Category | Description |
|---|---|---|
application/vnd.cyclonedx+json | sbom | CycloneDX SBOM |
application/vnd.spdx+json | sbom | SPDX SBOM |
application/vnd.openvex+json | vex | OpenVEX statement |
application/vnd.csaf+json | vex | CSAF advisory |
application/vnd.in-toto+json | attestation | in-toto attestation |
application/vnd.dsse.envelope+json | attestation | DSSE envelope |
application/vnd.slsa.provenance+json | attestation | SLSA provenance |
application/vnd.stella.rva+json | attestation | RVA attestation |
Registry Compatibility
Referrer discovery supports both OCI 1.1 native API and fallback tag-based discovery:
- OCI 1.1+: Uses native
/v2/{repo}/referrers/{digest}endpoint - OCI 1.0 (fallback): Discovers via
sha256-{digest}.*tag pattern
See Registry Compatibility Matrix for per-registry details.
Function Map Artifacts
Bundles can include runtime linkage verification artifacts. These are stored in dedicated subdirectories:
bundle.stella.bundle.tgz
├── ...existing structure...
├── function-maps/
│ ├── {service}-function-map.json
│ └── {service}-function-map.dsse.json
├── observations/
│ └── {date-label}-observations.ndjson
└── verification/
├── verification-report.json
└── verification-report.dsse.json
Artifact Types
| Artifact Type | Media Type | Description |
|---|---|---|
function-map | application/vnd.stella.function-map+json | Function map predicate |
function-map.dsse | application/vnd.dsse+json | DSSE-signed function map |
observations | application/x-ndjson | Runtime observations (NDJSON) |
verification-report | application/vnd.stella.verification-report+json | Verification result |
verification-report.dsse | application/vnd.dsse+json | DSSE-signed verification report |
Offline Verification Workflow
In air-gapped environments:
- Export the bundle with function map and observations included
- Transfer to the air-gapped instance
- Run offline verification:
stella function-map verify \ --function-map ./function-maps/my-service-function-map.json \ --offline --observations ./observations/2026-01-23-observations.ndjson
See Function Map V1 Contract for the predicate schema specification.
Security Considerations
- Hash Verification: Always verify bundle hash before processing
- Signature Validation: Verify DSSE signature if present
- Content Validation: Validate JSON schemas after extraction
- Size Limits: Enforce maximum bundle size limits (default: 100MB)
- Path Traversal: Tarball extraction must prevent path traversal attacks
Versioning
| Format Version | Changes | Min StellaOps Version |
|---|---|---|
| 1.0.0 | Initial format | 1.0.0 |
Related documentation
- Mirror Bundles — image, chart, and feed transport format.
- Air-Gap Importer Guide — staging bundles into a sealed install.
- Offline Kit Guide — assembling and shipping the Offline Kit.
- Evidence Decision API — the OpenAPI reference for bundle export and verification endpoints.
