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

95 lines
3.7 KiB
Markdown

# 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`.
```json
{
"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. For replacement workflows, keep this stable for the logical source that should update the same managed destination artifact.
- `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:
```text
[{"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`](../consumers/pkg-bundle.md) for producer workflow guidance.
- `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`. See [Upstream Producer Integration](../consumers/api.md) and [HTTP Upload API Contract](http-upload.md).
CLI producers can use:
```sh
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:
```sh
go test ./pkg/bundle ./pkg/upload ./internal/bundle
```