3.7 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 be1.id: non-empty bundle identifier. For replacement workflows, keep this stable for the logical source that should update the same managed destination artifact.digest: lowercasesha256:<64 hex>digest of the orderedfileslist.created: RFC3339 timestamp.files: non-empty ordered list of file records.
Required file fields:
path: bundle-relative slash-separated file path.sha256: lowercasesha256:<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. See pkg/bundle for producer workflow guidance.
BuildManifest: builds a manifest from explicit file paths or scan mode.WriteManifest: writesmanifest.json, optionally replacing an existing manifest.WriteBundle: copies source files into a complete bundle, validates it, and promotes it into place.LoadManifest,ParseManifest,ValidateManifest, andValidateBundle: parse and validate local bundles.FileDigest,BundleDigest, andValidateDigest: digest helpers.
Go producers that submit bundles to distributor serve can use gitea.maximumdirect.net/eric/distributor/pkg/upload. See Upstream Producer Integration and 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