From 12c97f42aaa667e4234d7076cf5fdb264cee277a Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sat, 29 Nov 2025 21:56:21 +0300 Subject: [PATCH 1/2] feat(hip): add HIP for OCI Artifact Selection and Referrers Support This HIP proposes enabling Helm to: 1. Select chart manifests from OCI Image Index by artifactType 2. Set artifactType field when pushing charts 3. Support Referrers API via --subject flag Addresses helm/helm#31582 Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- hips/hip-9999.md | 270 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 hips/hip-9999.md diff --git a/hips/hip-9999.md b/hips/hip-9999.md new file mode 100644 index 00000000..6b881d23 --- /dev/null +++ b/hips/hip-9999.md @@ -0,0 +1,270 @@ +--- +hip: "9999" +title: "OCI Artifact Selection and Referrers Support" +authors: ["Aleksei Sviridkin "] +created: "2025-11-29" +type: "feature" +status: "draft" +--- + +## Abstract + +This proposal enables Helm to select chart manifests from OCI Image Index manifests and adds support for the OCI Referrers API. Currently, `helm pull` fails when encountering an OCI Image Index containing multiple artifacts. This HIP introduces artifact selection logic based on the `artifactType` field (with fallback to `config.mediaType`), sets `artifactType` during `helm push`, and optionally allows charts to be associated with container images via the `subject` field and Referrers API. + +## Motivation + +The OCI Image and Distribution specifications v1.1 (released February 2024) introduced native support for artifacts and the Referrers API. These features enable bundling multiple artifacts under a single OCI reference and establishing relationships between them. + +Currently, users who want to publish both a Helm chart and a container image for the same application version must use workarounds: + +- Tag suffixes (e.g., `:v1.0.0` for image, `:v1.0.0-helm` for chart) +- Separate repository paths (e.g., `registry/app` for image, `registry/app-chart` for chart) +- Completely separate registries + +These workarounds introduce unnecessary complexity in CI/CD pipelines, break atomic versioning guarantees, and require additional tooling to keep artifacts synchronized. Tools like ArtifactHub, ArgoCD, and GitOps workflows would benefit from a single source of truth for versioned artifacts. + +The OCI 1.1 specifications provide a standard solution: an Image Index can contain multiple manifests with different `artifactType` values, and the Referrers API allows querying artifacts associated with a specific image. Helm should leverage these capabilities. + +## Rationale + +### Why `artifactType` first, then `config.mediaType` fallback? + +The OCI Image Specification explicitly states that "artifacts have historically been created without an `artifactType` field, and tooling to work with artifacts should fallback to the `config.mediaType` value." Following this guidance ensures compatibility with: + +1. Charts pushed by current Helm versions (which don't set `artifactType`) +2. Charts pushed by third-party tools that may not set `artifactType` +3. Registries that strip or don't preserve `artifactType` + +### Why skip descriptors with `platform` field? + +Descriptors with a `platform` field are container images targeted at specific architectures. A Helm chart is not platform-specific and should never have a `platform` field. Skipping these descriptors avoids unnecessary manifest fetches. + +### Why use first match? + +The OCI Image Index specification states: "If multiple manifests match a client or runtime's requirements, the first matching entry SHOULD be used." This behavior is consistent with multi-architecture image selection. + +### Why add Referrers API support? + +The Referrers API enables discovering all artifacts (charts, SBOMs, signatures) associated with a specific container image. For Helm, this allows: + +- Finding the chart that deploys a specific image version +- Ensuring chart and image are always used together +- Enabling security scanning workflows that link vulnerabilities to deployment configurations + +## Specification + +This HIP introduces three related changes: + +### 1. Artifact Selection from Image Index + +When `helm pull`, `helm install`, or `helm dependency update` encounters an OCI reference that resolves to an Image Index (`application/vnd.oci.image.index.v1+json`), Helm MUST select a chart manifest using the following algorithm: + +1. **First pass**: Iterate through descriptors in `manifests[]` and check for `artifactType: application/vnd.cncf.helm.config.v1+json` + - If exactly one descriptor matches, select it + - If multiple descriptors match, select the first one (per OCI spec) + +2. **Second pass** (fallback): If no match in first pass, iterate through descriptors WITHOUT a `platform` field: + - Fetch the referenced manifest + - Check if `config.mediaType` equals `application/vnd.cncf.helm.config.v1+json` + - If exactly one manifest matches, select it + - If multiple manifests match, select the first one + +3. **Skip**: Descriptors with a `platform` field SHOULD be skipped as they represent container images + +4. **Error**: If no matching chart manifest is found, return an error indicating no Helm chart was found in the Image Index + +Example Image Index with multiple artifacts: + +```json +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.index.v1+json", + "manifests": [ + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:abc123...", + "size": 1234, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:def456...", + "size": 567, + "artifactType": "application/vnd.cncf.helm.config.v1+json" + } + ] +} +``` + +In this example, Helm would select the second descriptor (digest `sha256:def456...`) because it has the matching `artifactType`. + +### 2. Set `artifactType` on Push + +When `helm push` creates a manifest, it MUST set the `artifactType` field to `application/vnd.cncf.helm.config.v1+json`. + +Current manifest structure: + +```json +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": { + "mediaType": "application/vnd.cncf.helm.config.v1+json", + "digest": "sha256:...", + "size": 137 + }, + "layers": [...] +} +``` + +Proposed manifest structure: + +```json +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.cncf.helm.config.v1+json", + "config": { + "mediaType": "application/vnd.cncf.helm.config.v1+json", + "digest": "sha256:...", + "size": 137 + }, + "layers": [...] +} +``` + +This enables efficient selection from Image Index without fetching manifest content. + +### 3. Referrers API Support + +A new optional flag `--subject` is added to `helm push`: + +```bash +helm push mychart-1.0.0.tgz oci://registry.example.com/myapp --subject sha256:abc123... +``` + +When `--subject` is specified, Helm MUST: + +1. Set the `subject` field in the chart manifest to reference the specified digest: + +```json +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.cncf.helm.config.v1+json", + "subject": { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:abc123...", + "size": 1234 + }, + "config": {...}, + "layers": [...] +} +``` + +2. Handle the registry response according to OCI Distribution Spec 1.1: + - If registry returns `OCI-Subject` header, the referrer is tracked automatically + - If registry does not return `OCI-Subject` header, fall back to Referrers Tag Schema + +The `--subject` flag accepts: +- A digest (e.g., `sha256:abc123...`) +- An OCI reference that will be resolved to a digest (e.g., `oci://registry.example.com/myapp:v1.0.0`) + +## Backwards Compatibility + +This proposal is fully backwards compatible: + +1. **Single manifests**: Charts stored as single manifests (not Image Index) continue to work unchanged +2. **Existing charts**: Charts without `artifactType` are still selectable via `config.mediaType` fallback +3. **Registry compatibility**: `artifactType` is an optional field per OCI spec; registries MUST NOT error on unknown fields +4. **Optional Referrers**: The `--subject` flag is optional; existing `helm push` workflows are unchanged + +## Security Implications + +1. **No new attack vectors**: Artifact selection uses the same validation logic applied after manifest fetch +2. **Referrers association is weak**: The `subject` field creates an association, not a cryptographic binding. Chart integrity still depends on digest verification +3. **Registry trust model unchanged**: Users must still trust the registry to serve correct manifests + +## How to Teach This + +### Documentation Updates + +1. Update the OCI registry documentation on helm.sh to explain Image Index support +2. Add examples showing how to create multi-artifact Image Index using tools like `crane` or `oras` +3. Document the `--subject` flag and Referrers API integration + +### Example: Creating Multi-Artifact Image Index + +```bash +# Push container image +docker push registry.example.com/myapp:v1.0.0 + +# Push Helm chart +helm push myapp-1.0.0.tgz oci://registry.example.com/myapp + +# Create Image Index combining both +crane index append \ + --manifest registry.example.com/myapp:v1.0.0 \ + --manifest registry.example.com/myapp:v1.0.0-helm \ + --tag registry.example.com/myapp:v1.0.0 + +# Now helm pull works on the combined reference +helm pull oci://registry.example.com/myapp --version 1.0.0 +``` + +### Example: Associating Chart with Image + +```bash +# Get image digest +IMAGE_DIGEST=$(crane digest registry.example.com/myapp:v1.0.0) + +# Push chart with subject reference +helm push myapp-1.0.0.tgz oci://registry.example.com/myapp --subject $IMAGE_DIGEST + +# Query referrers (using oras) +oras discover registry.example.com/myapp@$IMAGE_DIGEST +``` + +## Reference Implementation + +A reference implementation is available at [helm/helm#31583](https://github.com/helm/helm/pull/31583). + +## Rejected Ideas + +### Requiring explicit `--artifact-type` flag + +Rejected because it adds unnecessary verbosity to common operations. The artifact type is always `application/vnd.cncf.helm.config.v1+json` for Helm charts. + +### Only supporting `artifactType` without `config.mediaType` fallback + +Rejected because it would break compatibility with existing charts and third-party tooling that doesn't set `artifactType`. + +### Making `--subject` mandatory + +Rejected because most users don't need Referrers API integration. The feature should be opt-in. + +### Automatic subject detection + +Considered automatically detecting the "main" image in an Image Index and setting it as subject. Rejected because: +- Ambiguous when multiple images exist +- May not match user intent +- Explicit is better than implicit + +## Open Issues + +1. **Fetching chart via Referrers API**: Should `helm pull` support fetching a chart by image digest using the Referrers API? For example: `helm pull --referrer-of oci://registry.example.com/myapp@sha256:abc123...` + +2. **Multiple charts per image**: What should happen when multiple charts reference the same image via Referrers API? Current proposal: return all, let user select. + +## References + +- [OCI Image Specification v1.1](https://github.com/opencontainers/image-spec/releases/tag/v1.1.0) +- [OCI Distribution Specification v1.1](https://github.com/opencontainers/distribution-spec/releases/tag/v1.1.0) +- [OCI Image Index Specification](https://github.com/opencontainers/image-spec/blob/main/image-index.md) +- [OCI Descriptor Specification](https://github.com/opencontainers/image-spec/blob/main/descriptor.md) +- [HIP-0006: OCI Support](https://github.com/helm/community/blob/main/hips/hip-0006.md) +- [helm/helm#31582: Support for OCI Image Index](https://github.com/helm/helm/issues/31582) +- [helm/helm#31583: Reference Implementation](https://github.com/helm/helm/pull/31583) From 97c33acd6ad05208856856197c38c3f7921be6ec Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Tue, 2 Dec 2025 03:46:41 +0300 Subject: [PATCH 2/2] docs(hip): clarify artifactType and layer mediaType rationale Address review feedback from TerryHowe: - Explain why artifactType equals config.mediaType (per OCI spec) - Explain why layer mediaType cannot be used for selection Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- hips/hip-9999.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hips/hip-9999.md b/hips/hip-9999.md index 6b881d23..1854d026 100644 --- a/hips/hip-9999.md +++ b/hips/hip-9999.md @@ -35,6 +35,14 @@ The OCI Image Specification explicitly states that "artifacts have historically 2. Charts pushed by third-party tools that may not set `artifactType` 3. Registries that strip or don't preserve `artifactType` +### Why `artifactType` equals `config.mediaType` + +The OCI Image Spec (descriptor.md) explicitly defines `artifactType` in Index descriptors as "the value of the config descriptor `mediaType` when the descriptor references an image manifest." This equality is intentional — it exposes the artifact identifier at the Index level for efficient selection without fetching manifests. Using `application/vnd.cncf.helm.config.v1+json` for both fields is correct per OCI spec, not a naming collision. + +### Why not use layer mediaType for selection + +Layer mediaTypes (e.g., `application/vnd.cncf.helm.chart.content.v1.tar+gzip`) are not exposed in Image Index descriptors — only `mediaType`, `digest`, `size`, `platform`, `artifactType`, and `annotations` are available. To check layers, Helm would need to fetch every manifest in the Index first, defeating the purpose of efficient artifact selection. The `artifactType`/`config.mediaType` approach provides artifact identification at the Index level without additional round-trips. + ### Why skip descriptors with `platform` field? Descriptors with a `platform` field are container images targeted at specific architectures. A Helm chart is not platform-specific and should never have a `platform` field. Skipping these descriptors avoids unnecessary manifest fetches.