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:

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

FieldTypeRequiredDescription
bundle_format_versionstringYesFormat version (semver)
bundle_idstringYesUnique bundle identifier
alert_idstringYesSource alert identifier
created_atISO 8601YesBundle creation timestamp (UTC)
created_bystringYesActor who created the bundle
stellaops_versionstringYesStellaOps version that created bundle
entriesarrayYesList of content entries with hashes
root_hashstringYesMerkle root of all entry hashes
signatureobjectNoDSSE 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:

ValidationSeverityDescription
ReferrerMissingErrorDeclared artifact not found in bundle
ReferrerChecksumMismatchErrorSHA-256 doesn’t match declared value
ReferrerSizeMismatchErrorSize doesn’t match declared value
OrphanedReferrerWarningFile exists in referrers/ but not declared

Artifact Types

Artifact TypeCategoryDescription
application/vnd.cyclonedx+jsonsbomCycloneDX SBOM
application/vnd.spdx+jsonsbomSPDX SBOM
application/vnd.openvex+jsonvexOpenVEX statement
application/vnd.csaf+jsonvexCSAF advisory
application/vnd.in-toto+jsonattestationin-toto attestation
application/vnd.dsse.envelope+jsonattestationDSSE envelope
application/vnd.slsa.provenance+jsonattestationSLSA provenance
application/vnd.stella.rva+jsonattestationRVA attestation

Registry Compatibility

Referrer discovery supports both OCI 1.1 native API and fallback tag-based discovery:

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 TypeMedia TypeDescription
function-mapapplication/vnd.stella.function-map+jsonFunction map predicate
function-map.dsseapplication/vnd.dsse+jsonDSSE-signed function map
observationsapplication/x-ndjsonRuntime observations (NDJSON)
verification-reportapplication/vnd.stella.verification-report+jsonVerification result
verification-report.dsseapplication/vnd.dsse+jsonDSSE-signed verification report

Offline Verification Workflow

In air-gapped environments:

  1. Export the bundle with function map and observations included
  2. Transfer to the air-gapped instance
  3. 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

  1. Hash Verification: Always verify bundle hash before processing
  2. Signature Validation: Verify DSSE signature if present
  3. Content Validation: Validate JSON schemas after extraction
  4. Size Limits: Enforce maximum bundle size limits (default: 100MB)
  5. Path Traversal: Tarball extraction must prevent path traversal attacks

Versioning

Format VersionChangesMin StellaOps Version
1.0.0Initial format1.0.0