Files
distributor/docs/integrations/source-bundle.md

3.6 KiB

Source Bundle Contract

Audience: producer developers, integrators, and maintainers who create or validate source bundles consumed by distributor.

A source bundle is a directory containing manifest.json and every regular file listed by that manifest. This is the producer-to-distributor file-format contract.

Manifest Schema

Current schema version: 1.

{
  "schema_version": 1,
  "id": "reports.example.2026-06-04",
  "digest": "sha256:...",
  "created": "2026-06-04T12:00:00Z",
  "files": [
    {
      "path": "report.md",
      "sha256": "sha256:...",
      "size": 1234
    }
  ]
}

Required manifest fields:

  • schema_version: must be 1.
  • id: non-empty bundle identifier.
  • digest: lowercase sha256:<64 hex> digest of the ordered files list.
  • created: RFC3339 timestamp.
  • files: non-empty ordered list of file records.

Required file fields:

  • path: bundle-relative slash-separated file path.
  • sha256: lowercase sha256:<64 hex> digest of the file bytes.
  • size: file size in bytes, zero or greater.

Path Rules

Manifest file paths must be clean relative slash-separated paths. They must not be empty, absolute, contain backslashes, contain . or .. segments, include empty path segments, or normalize to a different path.

Any basename of manifest.json or .distributor.json is reserved, including nested occurrences such as nested/manifest.json.

Listed files must be regular files. Symlinks and other special file types are rejected during local bundle validation and manifest building.

Digest Rules

File digests use SHA-256 over each file's raw bytes.

The bundle digest is SHA-256 over the canonical JSON-like payload for the ordered file records. The payload is constructed as:

[{"path":"<path>","sha256":"<sha256>","size":<size>},...]

File order is significant. Explicit file lists preserve caller order. Scan mode sorts paths in ascending slash-path order.

Producer APIs

Go producers can use gitea.maximumdirect.net/eric/distributor/pkg/bundle to build and validate this contract:

  • BuildManifest: builds a manifest from explicit file paths or scan mode.
  • WriteManifest: writes manifest.json, optionally replacing an existing manifest.
  • WriteBundle: copies source files into a complete bundle, validates it, and promotes it into place.
  • LoadManifest, ParseManifest, ValidateManifest, and ValidateBundle: parse and validate local bundles.
  • FileDigest, BundleDigest, and ValidateDigest: digest helpers.

Go producers that submit bundles to distributor serve can use gitea.maximumdirect.net/eric/distributor/pkg/upload. It builds on pkg/bundle, packages valid bundles as gzip-compressed tar uploads, sends bearer authentication, and includes idempotency keys for safe retry behavior. See HTTP Upload API Contract.

CLI producers can use:

go run ./cmd/distributor manifest create <bundle-path> --id <bundle-id>
go run ./cmd/distributor validate <bundle-path>

Scan Mode

Manifest scan mode walks the local bundle root recursively, includes regular files, includes dotfiles, skips files whose basename is manifest.json or .distributor.json, rejects symlinks, and sorts paths before building the manifest.

Boundaries

The source bundle manifest does not configure routing, destination selection, public URLs, credentials, transforms, notification behavior, or storage backends. Those concerns belong in distributor configuration and destination state.

Tests

Before changing this contract, inspect and run:

go test ./pkg/bundle ./pkg/upload ./internal/bundle