Publishing
Manifest schema, version lifecycle, OCI integration, and yank semantics for bundle versions.
Publish Requirements
To publish a bundle version, two conditions must be met:
- At least one asset — you'll receive an error if the bundle has no assets.
Add at least one asset to your
musher.yamlbefore publishing. - Unique version string — you'll receive an error if that version already
exists for this bundle. Bump the version in your
musher.yamlto publish a new release.
Publishing freezes the manifest and creates an immutable version record. If an OCI registry is configured, assets are also pushed to the registry.
Manifest Schema
Top-Level Object
| Field | Type | Required | Description |
|---|---|---|---|
namespace | string | Yes | Namespace that owns the bundle |
bundle_slug | string | Yes | Bundle slug at publish time |
version | string | Yes | Published version string |
assets | array<object> | Yes | Snapshot of every asset in the published version |
Asset Entry
Each item in the assets array has the following shape:
| Field | Type | Required | Description |
|---|---|---|---|
asset_id | string | Yes | UUID of the asset (used for download) |
logical_path | string | Yes | Bundle-relative path, e.g. prompts/review.md |
asset_type | string | Yes | Asset classification label |
content_sha256 | string | Yes | SHA-256 hash of the asset content |
size_bytes | integer | Yes | Byte length of the asset content at publish time |
Manifest Example
{
"namespace": "acme",
"bundle_slug": "code-review",
"version": "1.2.0",
"assets": [
{
"asset_id": "550e8400-e29b-41d4-a716-446655440000",
"logical_path": "prompts/review.md",
"asset_type": "prompt",
"content_sha256": "9e8c4b9f1b8d6d52f1c4dd9ab8f6b0fd...",
"size_bytes": 2048
},
{
"asset_id": "a4b1ac0c-a0db-4ea5-a7d8-c6b4ff4b8c2f",
"logical_path": "agents/reviewer.yaml",
"asset_type": "agent_spec",
"content_sha256": "4f31d7a3fd6f0fca0d66ef7dd3c738fc...",
"size_bytes": 1187
}
]
}API Responses
The manifest data appears in two response shapes depending on the endpoint.
The version detail endpoint returns the full manifest with namespace, slug, and version at the top level:
{
"namespace": "acme",
"bundleSlug": "code-review",
"version": "1.2.0",
"assets": [
{
"assetId": "550e8400-e29b-41d4-a716-446655440000",
"logicalPath": "prompts/review.md",
"assetType": "prompt",
"contentSha256": "9e8c4b9f...",
"sizeBytes": 2048
}
]
}Each asset includes assetId, logicalPath, assetType, contentSha256, and sizeBytes.
OCI Integration
When a registry is configured, the publish flow pushes bundle assets to an OCI-compatible registry using the ORAS protocol.
Media Types
| Media Type | Purpose |
|---|---|
application/vnd.musher.bundle.v1.asset | Individual asset file layer |
application/vnd.musher.bundle.v1.config | Config blob with asset metadata (paths, types, hashes) |
Reference Format
OCI references follow the pattern {registry}/{namespace}/{bundle_slug}:{version}.
Error Handling
| Scenario | HTTP Status | What to Do |
|---|---|---|
| Registry authentication failed | 503 Service Unavailable | Re-authenticate with musher login or check your API key |
| Registry unreachable (connection timeout, DNS failure) | 503 Service Unavailable | Check your network connection and retry; run musher doctor to diagnose |
| Other push failures | 500 Internal Server Error | Retry the publish; if the error persists, contact support |
Version States
A published version has exactly one allowed state transition:
published ──yank──▶ yanked ──unyank──▶ publishedYank Semantics
Yanking soft-withdraws a published version from resolution:
- The version's state changes to
yanked, and the reason, timestamp, and actor are recorded. - Yanked versions are excluded from resolve queries but remain accessible via the detail endpoint for audit purposes.
- Idempotent — yanking an already-yanked version is a no-op.
- Reversible — use
musher unyankto restore a yanked version. - Audit trail preserved — you can always see what was withdrawn, by whom, when, and why.