Repository: kubernetes-sigs/security-profiles-operator
Pull request #1855 (2023-08-30 23:48:51)

build(deps): bump oras.land/oras-go/v2 from 2.2.1 to 2.3.0
Bumps [oras.land/oras-go/v2](https://github.com/oras-project/oras-go) from 2.2.1 to 2.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/oras-project/oras-go/releases">oras.land/oras-go/v2's releases</a>.</em></p>
<blockquote>
<h2>v2.3.0</h2>
<h2>New Features</h2>
<ul>
<li>Conform to <a href="https://github.com/opencontainers/image-spec/blob/v1.1.0-rc4/spec.md"><code>image-spec v1.1.0-rc4</code></a> and <a href="https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md"><code>distribution-spec v1.1.0-rc3</code></a>, while remaining compatible with <a href="https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/spec.md"><code>image-spec v1.1.0-rc2</code></a> and <a href="https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md"><code>distribution-spec v1.1.0-rc1</code></a> (see <a href="https://redirect.github.com/oras-project/oras-go/issues/494">#494</a> for more details)
<ul>
<li>Support handling <a href="https://github.com/opencontainers/image-spec/blob/v1.1.0-rc4/image-index.md">Image Index with a <code>subject</code></a></li>
<li>Add <code>oras.PackManifest</code> that supports packing Image Manifest version <code>1.0</code> and version <code>1.1.0-rc4</code>, as well as media type validation</li>
<li>Add <code>Repository.HandleWarning</code> that can be used to handle <a href="https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#warnings">warnings</a> returned by the remote registry</li>
<li>Update the implementation of Referrers API to support the &quot;OCI-Filters-Applied&quot; response header</li>
<li>Update the implementation of pushing manifests with <code>subject</code> to support the &quot;OCI-Subject&quot; response header</li>
</ul>
</li>
<li>Add <code>Repository.SkipReferrersGC</code> that allows skipping deleting dangling referrers index when referrers tag schema is utilized</li>
</ul>
<h2>Deprecation</h2>
<ul>
<li><code>oras.Pack</code> is deprecated and not recommended for future use. Use <code>oras.PackManifest</code> instead.</li>
</ul>
<h2>Other Changes</h2>
<ul>
<li>Improve documentation and examples</li>
</ul>
<h2>Detailed Commits</h2>
<ul>
<li>feat: add option to skip referrers GC by <a href="https://github.com/qweeah"><code>@​qweeah</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/515">oras-project/oras-go#515</a></li>
<li>feat: support Image Index with a subject by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/548">oras-project/oras-go#548</a></li>
<li>feat: add a PackOption to support packing image manifests that conform to image-spec v1.1.0-rc4 by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/550">oras-project/oras-go#550</a></li>
<li>feat: update Referrers API for distribution-spec v1.1.0-rc3 by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/553">oras-project/oras-go#553</a></li>
<li>feat: update the implementation of pushing manifest for distribution-spec v1.1.0-rc3 by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/557">oras-project/oras-go#557</a></li>
<li>feat: update the implementation of deleting manifest for distribution-spec v1.1.0-rc3 by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/558">oras-project/oras-go#558</a></li>
<li>docs: update links by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/563">oras-project/oras-go#563</a></li>
<li>feat: report warnings by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/560">oras-project/oras-go#560</a></li>
<li>docs: add e2e examples for oras-go by <a href="https://github.com/wangxiaoxuan273"><code>@​wangxiaoxuan273</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/561">oras-project/oras-go#561</a></li>
<li>docs: display larger example by <a href="https://github.com/wangxiaoxuan273"><code>@​wangxiaoxuan273</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/564">oras-project/oras-go#564</a></li>
<li>fix: pack should not set <code>artifactType</code> when config is specified by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/565">oras-project/oras-go#565</a></li>
<li>build(deps): bump apache/skywalking-eyes from 0.4.0 to 0.5.0 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/569">oras-project/oras-go#569</a></li>
<li>refactor: add <code>PackManifest</code> and deprecate <code>Pack</code>   by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/570">oras-project/oras-go#570</a></li>
<li>refactor: refactor unexported pack methods by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/573">oras-project/oras-go#573</a></li>
<li>feat: validate input media type for <code>oras.PackManifest </code> by <a href="https://github.com/Wwwsylvia"><code>@​Wwwsylvia</code></a> in <a href="https://redirect.github.com/oras-project/oras-go/pull/574">oras-project/oras-go#574</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/oras-project/oras-go/compare/v2.2.1...v2.3.0">https://github.com/oras-project/oras-go/compare/v2.2.1...v2.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/oras-project/oras-go/commit/47d028a52a21a2da888aa522543e99920d3f3ef7"><code>47d028a</code></a> feat: validate input media type for <code>oras.PackManifest </code> (<a href="https://redirect.github.com/oras-project/oras-go/issues/574">#574</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/60da91b7a0ba2fa555ee7a3df1fb23e51fe5fd9d"><code>60da91b</code></a> refactor: refactor unexported pack methods (<a href="https://redirect.github.com/oras-project/oras-go/issues/573">#573</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/e6d40b6ff29f6f36b4faedbc242ce9475751ab7f"><code>e6d40b6</code></a> refactor: add <code>PackManifest</code> and deprecate <code>Pack</code>   (<a href="https://redirect.github.com/oras-project/oras-go/issues/570">#570</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/ea07bf6b8c57a5f4db0c81f621afcc2f87198814"><code>ea07bf6</code></a> build(deps): bump apache/skywalking-eyes from 0.4.0 to 0.5.0 (<a href="https://redirect.github.com/oras-project/oras-go/issues/569">#569</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/bbe92af00542d87ab6feeef1be1be4c6dffcf121"><code>bbe92af</code></a> fix: pack should not set <code>artifactType</code> when config is specified (<a href="https://redirect.github.com/oras-project/oras-go/issues/565">#565</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/933ae417d4c76a639ad72378812aacc5ebe44fb2"><code>933ae41</code></a> docs: display larger example (<a href="https://redirect.github.com/oras-project/oras-go/issues/564">#564</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/d5cefe9c922384a6c4ea37c9a068f0add4c1d9b7"><code>d5cefe9</code></a> docs: add e2e examples for oras-go (<a href="https://redirect.github.com/oras-project/oras-go/issues/561">#561</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/b59a33e4d4e4881d07377aeb0d88d0b7f5980b77"><code>b59a33e</code></a> feat: report warnings (<a href="https://redirect.github.com/oras-project/oras-go/issues/560">#560</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/3a2e0c1c24493f07db90e3cda4fa610718a454b2"><code>3a2e0c1</code></a> docs: update links (<a href="https://redirect.github.com/oras-project/oras-go/issues/563">#563</a>)</li>
<li><a href="https://github.com/oras-project/oras-go/commit/6ec43e7d6241285bb0ec1bf131840cd3352c6ebb"><code>6ec43e7</code></a> feat: update the implementation of deleting manifest for distribution-spec v1...</li>
<li>Additional commits viewable in <a href="https://github.com/oras-project/oras-go/compare/v2.2.1...v2.3.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oras.land/oras-go/v2&package-manager=go_modules&previous-version=2.2.1&new-version=2.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>

k8s-ci-robot: Hi @dependabot[bot]. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/1855#" title="Author self-approved">dependabot[bot]</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign [jaormx](https://github.com/jaormx) for approval. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/security-profiles-operator/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["jaormx"]} -->
k8s-ci-robot: @dependabot[bot]: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-security-profiles-operator-verify | 59123c6ba7f113695058601a3dac3d0027c62fc1 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/1855/pull-security-profiles-operator-verify/1697033681232728064) | true | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=1855). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adependabot[bot]). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/security-profiles-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
codecov-commenter: ## [Codecov](https://app.codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/1855?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs) Report
> Merging [#1855](https://app.codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/1855?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs) (59123c6) into [main](https://app.codecov.io/gh/kubernetes-sigs/security-profiles-operator/commit/5715433d25ccdc16b34b96d14f829948ff8d3a39?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs) (5715433) will **not change** coverage.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #1855   +/-   ##
=======================================
  Coverage   49.18%   49.18%           
=======================================
  Files          72       72           
  Lines        7030     7030           
=======================================
  Hits         3458     3458           
  Misses       3438     3438           
  Partials      134      134           
```

</details>
saschagrunert: /retest
k8s-ci-robot: @dependabot[bot]: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-security-profiles-operator-test-e2e | 59123c6ba7f113695058601a3dac3d0027c62fc1 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/1855/pull-security-profiles-operator-test-e2e/1697033681442443264) | true | `/test pull-security-profiles-operator-test-e2e`
pull-security-profiles-operator-verify | 59123c6ba7f113695058601a3dac3d0027c62fc1 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/1855/pull-security-profiles-operator-verify/1698589473178128384) | true | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=1855). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adependabot[bot]). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/security-profiles-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @dependabot[bot]: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-security-profiles-operator-verify | 8376b65bac836235ef7c40b9f47668c12ee3deae | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/1855/pull-security-profiles-operator-verify/1698615565075091456) | true | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=1855). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adependabot[bot]). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/security-profiles-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0bce29174..44e16f16d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -49,7 +49,7 @@ jobs:
       contents: write  # required for updating the release
       id-token: write  # required for sigstore signing
     steps:
-      - uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 # v3.1.1
+      - uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
       - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.5.2
       - uses: cachix/install-nix-action@6ed004b9ccb68dbc28e7c85bee15fa93dbd214ac
         with:
diff --git a/go.mod b/go.mod
index 190248a39..23d9e3624 100644
--- a/go.mod
+++ b/go.mod
@@ -38,7 +38,7 @@ require (
 	k8s.io/cli-runtime v0.28.1
 	k8s.io/client-go v0.28.1
 	k8s.io/klog/v2 v2.100.1
-	oras.land/oras-go/v2 v2.2.1
+	oras.land/oras-go/v2 v2.3.0
 	sigs.k8s.io/controller-runtime v0.16.1
 	sigs.k8s.io/controller-tools v0.13.0
 	sigs.k8s.io/mdtoc v1.1.0
diff --git a/go.sum b/go.sum
index 470b35e5f..0d04a355a 100644
--- a/go.sum
+++ b/go.sum
@@ -1456,8 +1456,8 @@ k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5Ohx
 k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
 k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU=
 k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-oras.land/oras-go/v2 v2.2.1 h1:3VJTYqy5KfelEF9c2jo1MLSpr+TM3mX8K42wzZcd6qE=
-oras.land/oras-go/v2 v2.2.1/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ=
+oras.land/oras-go/v2 v2.3.0 h1:lqX1aXdN+DAmDTKjiDyvq85cIaI4RkIKp/PghWlAGIU=
+oras.land/oras-go/v2 v2.3.0/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/internal/pkg/artifact/artifact.go b/internal/pkg/artifact/artifact.go
index c89459a59..4d664a7b6 100644
--- a/internal/pkg/artifact/artifact.go
+++ b/internal/pkg/artifact/artifact.go
@@ -143,10 +143,14 @@ func (a *Artifact) Push(
 	}
 
 	a.logger.Info("Packing files")
-	manifestDescriptor, err := a.Pack(
-		ctx, store, "",
-		fileDescriptors,
-		oras.PackOptions{PackImageManifest: true},
+	manifestDescriptor, err := a.PackManifest(
+		ctx,
+		store,
+		oras.PackManifestVersion1_1_RC4,
+		oras.MediaTypeUnknownConfig,
+		oras.PackManifestOptions{
+			Layers: fileDescriptors,
+		},
 	)
 	if err != nil {
 		return fmt.Errorf("pack files: %w", err)
diff --git a/internal/pkg/artifact/artifactfakes/fake_impl.go b/internal/pkg/artifact/artifactfakes/fake_impl.go
index 75cddd403..07be2fb39 100644
--- a/internal/pkg/artifact/artifactfakes/fake_impl.go
+++ b/internal/pkg/artifact/artifactfakes/fake_impl.go
@@ -127,20 +127,20 @@ type FakeImpl struct {
 		result1 *remote.Repository
 		result2 error
 	}
-	PackStub        func(context.Context, content.Pusher, string, []v1.Descriptor, oras.PackOptions) (v1.Descriptor, error)
-	packMutex       sync.RWMutex
-	packArgsForCall []struct {
+	PackManifestStub        func(context.Context, content.Pusher, oras.PackManifestVersion, string, oras.PackManifestOptions) (v1.Descriptor, error)
+	packManifestMutex       sync.RWMutex
+	packManifestArgsForCall []struct {
 		arg1 context.Context
 		arg2 content.Pusher
-		arg3 string
-		arg4 []v1.Descriptor
-		arg5 oras.PackOptions
+		arg3 oras.PackManifestVersion
+		arg4 string
+		arg5 oras.PackManifestOptions
 	}
-	packReturns struct {
+	packManifestReturns struct {
 		result1 v1.Descriptor
 		result2 error
 	}
-	packReturnsOnCall map[int]struct {
+	packManifestReturnsOnCall map[int]struct {
 		result1 v1.Descriptor
 		result2 error
 	}
@@ -707,25 +707,20 @@ func (fake *FakeImpl) NewRepositoryReturnsOnCall(i int, result1 *remote.Reposito
 	}{result1, result2}
 }
 
-func (fake *FakeImpl) Pack(arg1 context.Context, arg2 content.Pusher, arg3 string, arg4 []v1.Descriptor, arg5 oras.PackOptions) (v1.Descriptor, error) {
-	var arg4Copy []v1.Descriptor
-	if arg4 != nil {
-		arg4Copy = make([]v1.Descriptor, len(arg4))
-		copy(arg4Copy, arg4)
-	}
-	fake.packMutex.Lock()
-	ret, specificReturn := fake.packReturnsOnCall[len(fake.packArgsForCall)]
-	fake.packArgsForCall = append(fake.packArgsForCall, struct {
+func (fake *FakeImpl) PackManifest(arg1 context.Context, arg2 content.Pusher, arg3 oras.PackManifestVersion, arg4 string, arg5 oras.PackManifestOptions) (v1.Descriptor, error) {
+	fake.packManifestMutex.Lock()
+	ret, specificReturn := fake.packManifestReturnsOnCall[len(fake.packManifestArgsForCall)]
+	fake.packManifestArgsForCall = append(fake.packManifestArgsForCall, struct {
 		arg1 context.Context
 		arg2 content.Pusher
-		arg3 string
-		arg4 []v1.Descriptor
-		arg5 oras.PackOptions
-	}{arg1, arg2, arg3, arg4Copy, arg5})
-	stub := fake.PackStub
-	fakeReturns := fake.packReturns
-	fake.recordInvocation("Pack", []interface{}{arg1, arg2, arg3, arg4Copy, arg5})
-	fake.packMutex.Unlock()
+		arg3 oras.PackManifestVersion
+		arg4 string
+		arg5 oras.PackManifestOptions
+	}{arg1, arg2, arg3, arg4, arg5})
+	stub := fake.PackManifestStub
+	fakeReturns := fake.packManifestReturns
+	fake.recordInvocation("PackManifest", []interface{}{arg1, arg2, arg3, arg4, arg5})
+	fake.packManifestMutex.Unlock()
 	if stub != nil {
 		return stub(arg1, arg2, arg3, arg4, arg5)
 	}
@@ -735,46 +730,46 @@ func (fake *FakeImpl) Pack(arg1 context.Context, arg2 content.Pusher, arg3 strin
 	return fakeReturns.result1, fakeReturns.result2
 }
 
-func (fake *FakeImpl) PackCallCount() int {
-	fake.packMutex.RLock()
-	defer fake.packMutex.RUnlock()
-	return len(fake.packArgsForCall)
+func (fake *FakeImpl) PackManifestCallCount() int {
+	fake.packManifestMutex.RLock()
+	defer fake.packManifestMutex.RUnlock()
+	return len(fake.packManifestArgsForCall)
 }
 
-func (fake *FakeImpl) PackCalls(stub func(context.Context, content.Pusher, string, []v1.Descriptor, oras.PackOptions) (v1.Descriptor, error)) {
-	fake.packMutex.Lock()
-	defer fake.packMutex.Unlock()
-	fake.PackStub = stub
+func (fake *FakeImpl) PackManifestCalls(stub func(context.Context, content.Pusher, oras.PackManifestVersion, string, oras.PackManifestOptions) (v1.Descriptor, error)) {
+	fake.packManifestMutex.Lock()
+	defer fake.packManifestMutex.Unlock()
+	fake.PackManifestStub = stub
 }
 
-func (fake *FakeImpl) PackArgsForCall(i int) (context.Context, content.Pusher, string, []v1.Descriptor, oras.PackOptions) {
-	fake.packMutex.RLock()
-	defer fake.packMutex.RUnlock()
-	argsForCall := fake.packArgsForCall[i]
+func (fake *FakeImpl) PackManifestArgsForCall(i int) (context.Context, content.Pusher, oras.PackManifestVersion, string, oras.PackManifestOptions) {
+	fake.packManifestMutex.RLock()
+	defer fake.packManifestMutex.RUnlock()
+	argsForCall := fake.packManifestArgsForCall[i]
 	return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5
 }
 
-func (fake *FakeImpl) PackReturns(result1 v1.Descriptor, result2 error) {
-	fake.packMutex.Lock()
-	defer fake.packMutex.Unlock()
-	fake.PackStub = nil
-	fake.packReturns = struct {
+func (fake *FakeImpl) PackManifestReturns(result1 v1.Descriptor, result2 error) {
+	fake.packManifestMutex.Lock()
+	defer fake.packManifestMutex.Unlock()
+	fake.PackManifestStub = nil
+	fake.packManifestReturns = struct {
 		result1 v1.Descriptor
 		result2 error
 	}{result1, result2}
 }
 
-func (fake *FakeImpl) PackReturnsOnCall(i int, result1 v1.Descriptor, result2 error) {
-	fake.packMutex.Lock()
-	defer fake.packMutex.Unlock()
-	fake.PackStub = nil
-	if fake.packReturnsOnCall == nil {
-		fake.packReturnsOnCall = make(map[int]struct {
+func (fake *FakeImpl) PackManifestReturnsOnCall(i int, result1 v1.Descriptor, result2 error) {
+	fake.packManifestMutex.Lock()
+	defer fake.packManifestMutex.Unlock()
+	fake.PackManifestStub = nil
+	if fake.packManifestReturnsOnCall == nil {
+		fake.packManifestReturnsOnCall = make(map[int]struct {
 			result1 v1.Descriptor
 			result2 error
 		})
 	}
-	fake.packReturnsOnCall[i] = struct {
+	fake.packManifestReturnsOnCall[i] = struct {
 		result1 v1.Descriptor
 		result2 error
 	}{result1, result2}
@@ -1318,8 +1313,8 @@ func (fake *FakeImpl) Invocations() map[string][][]interface{} {
 	defer fake.mkdirTempMutex.RUnlock()
 	fake.newRepositoryMutex.RLock()
 	defer fake.newRepositoryMutex.RUnlock()
-	fake.packMutex.RLock()
-	defer fake.packMutex.RUnlock()
+	fake.packManifestMutex.RLock()
+	defer fake.packManifestMutex.RUnlock()
 	fake.parseReferenceMutex.RLock()
 	defer fake.parseReferenceMutex.RUnlock()
 	fake.readFileMutex.RLock()
diff --git a/internal/pkg/artifact/impl.go b/internal/pkg/artifact/impl.go
index 9d6a8c516..a1ea1e757 100644
--- a/internal/pkg/artifact/impl.go
+++ b/internal/pkg/artifact/impl.go
@@ -50,7 +50,9 @@ type impl interface {
 	YamlUnmarshal([]byte, interface{}) error
 	StoreAdd(context.Context, *file.Store, string, string, string) (ocispec.Descriptor, error)
 	StoreTag(context.Context, *file.Store, ocispec.Descriptor, string) error
-	Pack(context.Context, content.Pusher, string, []ocispec.Descriptor, oras.PackOptions) (ocispec.Descriptor, error)
+	PackManifest(
+		context.Context, content.Pusher, oras.PackManifestVersion, string, oras.PackManifestOptions,
+	) (ocispec.Descriptor, error)
 	ClientSecret(options.OIDCOptions) (string, error)
 	SignCmd(*options.RootOptions, options.KeyOpts, options.SignOptions, []string) error
 	VerifyCmd(context.Context, verify.VerifyCommand, string) error
@@ -112,11 +114,12 @@ func (*defaultImpl) StoreTag(
 	return store.Tag(ctx, desc, ref)
 }
 
-func (*defaultImpl) Pack(
-	ctx context.Context, pusher content.Pusher, artifactType string,
-	blobs []ocispec.Descriptor, opts oras.PackOptions,
+func (*defaultImpl) PackManifest(
+	ctx context.Context, pusher content.Pusher,
+	packManifestVersion oras.PackManifestVersion,
+	artifactType string, opts oras.PackManifestOptions,
 ) (ocispec.Descriptor, error) {
-	return oras.Pack(ctx, pusher, artifactType, blobs, opts)
+	return oras.PackManifest(ctx, pusher, packManifestVersion, artifactType, opts)
 }
 
 //nolint:gocritic // intentional for the mock
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 6d8c5f9b4..13628900d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1859,7 +1859,7 @@ k8s.io/utils/net
 k8s.io/utils/pointer
 k8s.io/utils/strings/slices
 k8s.io/utils/trace
-# oras.land/oras-go/v2 v2.2.1
+# oras.land/oras-go/v2 v2.3.0
 ## explicit; go 1.19
 oras.land/oras-go/v2
 oras.land/oras-go/v2/content
@@ -1874,6 +1874,7 @@ oras.land/oras-go/v2/internal/graph
 oras.land/oras-go/v2/internal/httputil
 oras.land/oras-go/v2/internal/interfaces
 oras.land/oras-go/v2/internal/ioutil
+oras.land/oras-go/v2/internal/manifestutil
 oras.land/oras-go/v2/internal/platform
 oras.land/oras-go/v2/internal/registryutil
 oras.land/oras-go/v2/internal/resolver
diff --git a/vendor/oras.land/oras-go/v2/content/graph.go b/vendor/oras.land/oras-go/v2/content/graph.go
index fa2f9efe7..9ae837285 100644
--- a/vendor/oras.land/oras-go/v2/content/graph.go
+++ b/vendor/oras.land/oras-go/v2/content/graph.go
@@ -75,18 +75,33 @@ func Successors(ctx context.Context, fetcher Fetcher, node ocispec.Descriptor) (
 		}
 		nodes = append(nodes, manifest.Config)
 		return append(nodes, manifest.Layers...), nil
-	case docker.MediaTypeManifestList, ocispec.MediaTypeImageIndex:
+	case docker.MediaTypeManifestList:
 		content, err := FetchAll(ctx, fetcher, node)
 		if err != nil {
 			return nil, err
 		}
 
-		// docker manifest list and oci index are equivalent for successors.
+		// OCI manifest index schema can be used to marshal docker manifest list
 		var index ocispec.Index
 		if err := json.Unmarshal(content, &index); err != nil {
 			return nil, err
 		}
 		return index.Manifests, nil
+	case ocispec.MediaTypeImageIndex:
+		content, err := FetchAll(ctx, fetcher, node)
+		if err != nil {
+			return nil, err
+		}
+
+		var index ocispec.Index
+		if err := json.Unmarshal(content, &index); err != nil {
+			return nil, err
+		}
+		var nodes []ocispec.Descriptor
+		if index.Subject != nil {
+			nodes = append(nodes, *index.Subject)
+		}
+		return append(nodes, index.Manifests...), nil
 	case spec.MediaTypeArtifactManifest:
 		content, err := FetchAll(ctx, fetcher, node)
 		if err != nil {
diff --git a/vendor/oras.land/oras-go/v2/content/storage.go b/vendor/oras.land/oras-go/v2/content/storage.go
index 971142cbf..47c95d876 100644
--- a/vendor/oras.land/oras-go/v2/content/storage.go
+++ b/vendor/oras.land/oras-go/v2/content/storage.go
@@ -31,7 +31,7 @@ type Fetcher interface {
 // Pusher pushes content.
 type Pusher interface {
 	// Push pushes the content, matching the expected descriptor.
-	// Reader is perferred to Writer so that the suitable buffer size can be
+	// Reader is preferred to Writer so that the suitable buffer size can be
 	// chosen by the underlying implementation. Furthermore, the implementation
 	// can also do reflection on the Reader for more advanced I/O optimization.
 	Push(ctx context.Context, expected ocispec.Descriptor, content io.Reader) error
diff --git a/vendor/oras.land/oras-go/v2/errdef/errors.go b/vendor/oras.land/oras-go/v2/errdef/errors.go
index 030360edb..7adb44b17 100644
--- a/vendor/oras.land/oras-go/v2/errdef/errors.go
+++ b/vendor/oras.land/oras-go/v2/errdef/errors.go
@@ -22,6 +22,7 @@ var (
 	ErrAlreadyExists      = errors.New("already exists")
 	ErrInvalidDigest      = errors.New("invalid digest")
 	ErrInvalidReference   = errors.New("invalid reference")
+	ErrInvalidMediaType   = errors.New("invalid media type")
 	ErrMissingReference   = errors.New("missing reference")
 	ErrNotFound           = errors.New("not found")
 	ErrSizeExceedsLimit   = errors.New("size exceeds limit")
diff --git a/vendor/oras.land/oras-go/v2/internal/manifestutil/parser.go b/vendor/oras.land/oras-go/v2/internal/manifestutil/parser.go
new file mode 100644
index 000000000..c904dc690
--- /dev/null
+++ b/vendor/oras.land/oras-go/v2/internal/manifestutil/parser.go
@@ -0,0 +1,63 @@
+/*
+Copyright The ORAS Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package manifestutil
+
+import (
+	"context"
+	"encoding/json"
+
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"oras.land/oras-go/v2/content"
+	"oras.land/oras-go/v2/internal/docker"
+)
+
+// Config returns the config of desc, if present.
+func Config(ctx context.Context, fetcher content.Fetcher, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
+	switch desc.MediaType {
+	case docker.MediaTypeManifest, ocispec.MediaTypeImageManifest:
+		content, err := content.FetchAll(ctx, fetcher, desc)
+		if err != nil {
+			return nil, err
+		}
+		// OCI manifest schema can be used to marshal docker manifest
+		var manifest ocispec.Manifest
+		if err := json.Unmarshal(content, &manifest); err != nil {
+			return nil, err
+		}
+		return &manifest.Config, nil
+	default:
+		return nil, nil
+	}
+}
+
+// Manifest returns the manifests of desc, if present.
+func Manifests(ctx context.Context, fetcher content.Fetcher, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
+	switch desc.MediaType {
+	case docker.MediaTypeManifestList, ocispec.MediaTypeImageIndex:
+		content, err := content.FetchAll(ctx, fetcher, desc)
+		if err != nil {
+			return nil, err
+		}
+		// OCI manifest index schema can be used to marshal docker manifest list
+		var index ocispec.Index
+		if err := json.Unmarshal(content, &index); err != nil {
+			return nil, err
+		}
+		return index.Manifests, nil
+	default:
+		return nil, nil
+	}
+}
diff --git a/vendor/oras.land/oras-go/v2/internal/platform/platform.go b/vendor/oras.land/oras-go/v2/internal/platform/platform.go
index 38d8d47fd..e903fe3d5 100644
--- a/vendor/oras.land/oras-go/v2/internal/platform/platform.go
+++ b/vendor/oras.land/oras-go/v2/internal/platform/platform.go
@@ -25,6 +25,7 @@ import (
 	"oras.land/oras-go/v2/content"
 	"oras.land/oras-go/v2/errdef"
 	"oras.land/oras-go/v2/internal/docker"
+	"oras.land/oras-go/v2/internal/manifestutil"
 )
 
 // Match checks whether the current platform matches the target platform.
@@ -35,7 +36,7 @@ import (
 //     array of the current platform.
 //
 // Note: Variant, OSVersion and OSFeatures are optional fields, will skip
-// the comparison if the target platform does not provide specfic value.
+// the comparison if the target platform does not provide specific value.
 func Match(got *ocispec.Platform, want *ocispec.Platform) bool {
 	if got.Architecture != want.Architecture || got.OS != want.OS {
 		return false
@@ -77,7 +78,7 @@ func isSubset(a, b []string) bool {
 func SelectManifest(ctx context.Context, src content.ReadOnlyStorage, root ocispec.Descriptor, p *ocispec.Platform) (ocispec.Descriptor, error) {
 	switch root.MediaType {
 	case docker.MediaTypeManifestList, ocispec.MediaTypeImageIndex:
-		manifests, err := content.Successors(ctx, src, root)
+		manifests, err := manifestutil.Manifests(ctx, src, root)
 		if err != nil {
 			return ocispec.Descriptor{}, err
 		}
@@ -90,7 +91,8 @@ func SelectManifest(ctx context.Context, src content.ReadOnlyStorage, root ocisp
 		}
 		return ocispec.Descriptor{}, fmt.Errorf("%s: %w: no matching manifest was found in the manifest list", root.Digest, errdef.ErrNotFound)
 	case docker.MediaTypeManifest, ocispec.MediaTypeImageManifest:
-		descs, err := content.Successors(ctx, src, root)
+		// config will be non-nil for docker manifest and OCI image manifest
+		config, err := manifestutil.Config(ctx, src, root)
 		if err != nil {
 			return ocispec.Descriptor{}, err
 		}
@@ -99,8 +101,7 @@ func SelectManifest(ctx context.Context, src content.ReadOnlyStorage, root ocisp
 		if root.MediaType == ocispec.MediaTypeImageManifest {
 			configMediaType = ocispec.MediaTypeImageConfig
 		}
-
-		cfgPlatform, err := getPlatformFromConfig(ctx, src, descs[0], configMediaType)
+		cfgPlatform, err := getPlatformFromConfig(ctx, src, *config, configMediaType)
 		if err != nil {
 			return ocispec.Descriptor{}, err
 		}
diff --git a/vendor/oras.land/oras-go/v2/pack.go b/vendor/oras.land/oras-go/v2/pack.go
index 872afa518..08e14e195 100644
--- a/vendor/oras.land/oras-go/v2/pack.go
+++ b/vendor/oras.land/oras-go/v2/pack.go
@@ -21,6 +21,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"regexp"
 	"time"
 
 	specs "github.com/opencontainers/image-spec/specs-go"
@@ -31,38 +32,127 @@ import (
 )
 
 const (
-	// MediaTypeUnknownConfig is the default mediaType used when no
-	// config media type is specified.
+	// MediaTypeUnknownConfig is the default config mediaType used
+	//   - for [Pack] when PackOptions.PackImageManifest is true and
+	//     PackOptions.ConfigDescriptor is not specified.
+	//   - for [PackManifest] when packManifestVersion is PackManifestVersion1_0
+	//     and PackManifestOptions.ConfigDescriptor is not specified.
 	MediaTypeUnknownConfig = "application/vnd.unknown.config.v1+json"
-	// MediaTypeUnknownArtifact is the default artifactType used when no
-	// artifact type is specified.
+
+	// MediaTypeUnknownArtifact is the default artifactType used for [Pack]
+	// when PackOptions.PackImageManifest is false and artifactType is
+	// not specified.
 	MediaTypeUnknownArtifact = "application/vnd.unknown.artifact.v1"
 )
 
-// ErrInvalidDateTimeFormat is returned by Pack() when
-// AnnotationArtifactCreated or AnnotationCreated is provided, but its value
-// is not in RFC 3339 format.
-// Reference: https://www.rfc-editor.org/rfc/rfc3339#section-5.6
-var ErrInvalidDateTimeFormat = errors.New("invalid date and time format")
+var (
+	// ErrInvalidDateTimeFormat is returned by [Pack] and [PackManifest] when
+	// AnnotationArtifactCreated or AnnotationCreated is provided, but its value
+	// is not in RFC 3339 format.
+	// Reference: https://www.rfc-editor.org/rfc/rfc3339#section-5.6
+	ErrInvalidDateTimeFormat = errors.New("invalid date and time format")
+
+	// ErrMissingArtifactType is returned by [PackManifest] when
+	// packManifestVersion is PackManifestVersion1_1_RC4 and artifactType is
+	// empty and the config media type is set to
+	// "application/vnd.oci.empty.v1+json".
+	ErrMissingArtifactType = errors.New("missing artifact type")
+)
+
+// PackManifestVersion represents the manifest version used for [PackManifest].
+type PackManifestVersion int
+
+const (
+	// PackManifestVersion1_0 represents the OCI Image Manifest defined in
+	// image-spec v1.0.2.
+	// Reference: https://github.com/opencontainers/image-spec/blob/v1.0.2/manifest.md
+	PackManifestVersion1_0 PackManifestVersion = 1
+
+	// PackManifestVersion1_1_RC4 represents the OCI Image Manifest defined
+	// in image-spec v1.1.0-rc4.
+	// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc4/manifest.md
+	PackManifestVersion1_1_RC4 PackManifestVersion = 2
+)
+
+// PackManifestOptions contains optional parameters for [PackManifest].
+type PackManifestOptions struct {
+	// Subject is the subject of the manifest.
+	// This option is only valid when PackManifestVersion is
+	// NOT PackManifestVersion1_0.
+	Subject *ocispec.Descriptor
+
+	// Layers is the layers of the manifest.
+	Layers []ocispec.Descriptor
+
+	// ManifestAnnotations is the annotation map of the manifest.
+	ManifestAnnotations map[string]string
+
+	// ConfigDescriptor is a pointer to the descriptor of the config blob.
+	// If not nil, ConfigAnnotations will be ignored.
+	ConfigDescriptor *ocispec.Descriptor
+
+	// ConfigAnnotations is the annotation map of the config descriptor.
+	// This option is valid only when ConfigDescriptor is nil.
+	ConfigAnnotations map[string]string
+}
+
+// mediaTypeRegexp checks the format of media types.
+// References:
+//   - https://github.com/opencontainers/image-spec/blob/v1.1.0-rc4/schema/defs-descriptor.json#L7
+//   - https://datatracker.ietf.org/doc/html/rfc6838#section-4.2
+var mediaTypeRegexp = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9!#$&-^_.+]{0,126}/[A-Za-z0-9][A-Za-z0-9!#$&-^_.+]{0,126}$`)
 
-// PackOptions contains parameters for [oras.Pack].
+// PackManifest generates an OCI Image Manifest based on the given parameters
+// and pushes the packed manifest to a content storage using pusher. The version
+// of the manifest to be packed is determined by packManifestVersion
+// (Recommended value: PackManifestVersion1_1_RC4).
+//
+//   - If packManifestVersion is [PackManifestVersion1_1_RC4]:
+//     artifactType MUST NOT be empty unless opts.ConfigDescriptor is specified.
+//   - If packManifestVersion is [PackManifestVersion1_0]:
+//     if opts.ConfigDescriptor is nil, artifactType will be used as the
+//     config media type; if artifactType is empty,
+//     "application/vnd.unknown.config.v1+json" will be used.
+//     if opts.ConfigDescriptor is NOT nil, artifactType will be ignored.
+//
+// artifactType and opts.ConfigDescriptor.MediaType MUST comply with RFC 6838.
+//
+// If succeeded, returns a descriptor of the packed manifest.
+func PackManifest(ctx context.Context, pusher content.Pusher, packManifestVersion PackManifestVersion, artifactType string, opts PackManifestOptions) (ocispec.Descriptor, error) {
+	switch packManifestVersion {
+	case PackManifestVersion1_0:
+		return packManifestV1_0(ctx, pusher, artifactType, opts)
+	case PackManifestVersion1_1_RC4:
+		return packManifestV1_1_RC4(ctx, pusher, artifactType, opts)
+	default:
+		return ocispec.Descriptor{}, fmt.Errorf("PackManifestVersion(%v): %w", packManifestVersion, errdef.ErrUnsupported)
+	}
+}
+
+// PackOptions contains optional parameters for [Pack].
+//
+// Deprecated: This type is deprecated and not recommended for future use.
+// Use [PackManifestOptions] instead.
 type PackOptions struct {
 	// Subject is the subject of the manifest.
 	Subject *ocispec.Descriptor
+
 	// ManifestAnnotations is the annotation map of the manifest.
 	ManifestAnnotations map[string]string
 
-	// PackImageManifest controls whether to pack an image manifest or not.
-	//   - If true, pack an image manifest; artifactType will be used as the
-	// the config descriptor mediaType of the image manifest.
-	//   - If false, pack an artifact manifest.
-	// Default: false.
+	// PackImageManifest controls whether to pack an OCI Image Manifest or not.
+	//   - If true, pack an OCI Image Manifest.
+	//   - If false, pack an OCI Artifact Manifest (deprecated).
+	//
+	// Default value: false.
 	PackImageManifest bool
+
 	// ConfigDescriptor is a pointer to the descriptor of the config blob.
 	// If not nil, artifactType will be implied by the mediaType of the
 	// specified ConfigDescriptor, and ConfigAnnotations will be ignored.
 	// This option is valid only when PackImageManifest is true.
 	ConfigDescriptor *ocispec.Descriptor
+
 	// ConfigAnnotations is the annotation map of the config descriptor.
 	// This option is valid only when PackImageManifest is true
 	// and ConfigDescriptor is nil.
@@ -74,17 +164,20 @@ type PackOptions struct {
 //
 // When opts.PackImageManifest is true, artifactType will be used as the
 // the config descriptor mediaType of the image manifest.
+//
 // If succeeded, returns a descriptor of the manifest.
+//
+// Deprecated: This method is deprecated and not recommended for future use.
+// Use [PackManifest] instead.
 func Pack(ctx context.Context, pusher content.Pusher, artifactType string, blobs []ocispec.Descriptor, opts PackOptions) (ocispec.Descriptor, error) {
 	if opts.PackImageManifest {
-		return packImage(ctx, pusher, artifactType, blobs, opts)
+		return packManifestV1_1_RC2(ctx, pusher, artifactType, blobs, opts)
 	}
 	return packArtifact(ctx, pusher, artifactType, blobs, opts)
 }
 
-// packArtifact packs the given blobs, generates an artifact manifest for the
-// pack, and pushes it to a content storage.
-// If succeeded, returns a descriptor of the manifest.
+// packArtifact packs an Artifact manifest as defined in image-spec v1.1.0-rc2.
+// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/artifact.md
 func packArtifact(ctx context.Context, pusher content.Pusher, artifactType string, blobs []ocispec.Descriptor, opts PackOptions) (ocispec.Descriptor, error) {
 	if artifactType == "" {
 		artifactType = MediaTypeUnknownArtifact
@@ -101,46 +194,72 @@ func packArtifact(ctx context.Context, pusher content.Pusher, artifactType strin
 		Subject:      opts.Subject,
 		Annotations:  annotations,
 	}
-	manifestJSON, err := json.Marshal(manifest)
-	if err != nil {
-		return ocispec.Descriptor{}, fmt.Errorf("failed to marshal manifest: %w", err)
+	return pushManifest(ctx, pusher, manifest, manifest.MediaType, manifest.ArtifactType, manifest.Annotations)
+}
+
+// packManifestV1_0 packs an image manifest defined in image-spec v1.0.2.
+// Reference: https://github.com/opencontainers/image-spec/blob/v1.0.2/manifest.md
+func packManifestV1_0(ctx context.Context, pusher content.Pusher, artifactType string, opts PackManifestOptions) (ocispec.Descriptor, error) {
+	if opts.Subject != nil {
+		return ocispec.Descriptor{}, fmt.Errorf("subject is not supported for manifest version %v: %w", PackManifestVersion1_0, errdef.ErrUnsupported)
 	}
-	manifestDesc := content.NewDescriptorFromBytes(spec.MediaTypeArtifactManifest, manifestJSON)
-	// populate ArtifactType and Annotations of the manifest into manifestDesc
-	manifestDesc.ArtifactType = manifest.ArtifactType
-	manifestDesc.Annotations = manifest.Annotations
 
-	// push manifest
-	if err := pusher.Push(ctx, manifestDesc, bytes.NewReader(manifestJSON)); err != nil && !errors.Is(err, errdef.ErrAlreadyExists) {
-		return ocispec.Descriptor{}, fmt.Errorf("failed to push manifest: %w", err)
+	// prepare config
+	var configDesc ocispec.Descriptor
+	if opts.ConfigDescriptor != nil {
+		if err := validateMediaType(opts.ConfigDescriptor.MediaType); err != nil {
+			return ocispec.Descriptor{}, fmt.Errorf("invalid config mediaType format: %w", err)
+		}
+		configDesc = *opts.ConfigDescriptor
+	} else {
+		if artifactType == "" {
+			artifactType = MediaTypeUnknownConfig
+		} else if err := validateMediaType(artifactType); err != nil {
+			return ocispec.Descriptor{}, fmt.Errorf("invalid artifactType format: %w", err)
+		}
+		var err error
+		configDesc, err = pushCustomEmptyConfig(ctx, pusher, artifactType, opts.ConfigAnnotations)
+		if err != nil {
+			return ocispec.Descriptor{}, err
+		}
 	}
 
-	return manifestDesc, nil
+	annotations, err := ensureAnnotationCreated(opts.ManifestAnnotations, ocispec.AnnotationCreated)
+	if err != nil {
+		return ocispec.Descriptor{}, err
+	}
+	if opts.Layers == nil {
+		opts.Layers = []ocispec.Descriptor{} // make it an empty array to prevent potential server-side bugs
+	}
+	manifest := ocispec.Manifest{
+		Versioned: specs.Versioned{
+			SchemaVersion: 2, // historical value. does not pertain to OCI or docker version
+		},
+		Config:      configDesc,
+		MediaType:   ocispec.MediaTypeImageManifest,
+		Layers:      opts.Layers,
+		Annotations: annotations,
+	}
+	return pushManifest(ctx, pusher, manifest, manifest.MediaType, manifest.Config.MediaType, manifest.Annotations)
 }
 
-// packImage packs the given blobs, generates an image manifest for the pack,
-// and pushes it to a content storage. artifactType will be used as the config
-// descriptor mediaType of the image manifest.
-// If succeeded, returns a descriptor of the manifest.
-func packImage(ctx context.Context, pusher content.Pusher, configMediaType string, layers []ocispec.Descriptor, opts PackOptions) (ocispec.Descriptor, error) {
+// packManifestV1_1_RC2 packs an image manifest as defined in image-spec
+// v1.1.0-rc2.
+// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/manifest.md
+func packManifestV1_1_RC2(ctx context.Context, pusher content.Pusher, configMediaType string, layers []ocispec.Descriptor, opts PackOptions) (ocispec.Descriptor, error) {
 	if configMediaType == "" {
 		configMediaType = MediaTypeUnknownConfig
 	}
 
+	// prepare config
 	var configDesc ocispec.Descriptor
 	if opts.ConfigDescriptor != nil {
 		configDesc = *opts.ConfigDescriptor
 	} else {
-		// Use an empty JSON object here, because some registries may not accept
-		// empty config blob.
-		// As of September 2022, GAR is known to return 400 on empty blob upload.
-		// See https://github.com/oras-project/oras-go/issues/294 for details.
-		configBytes := []byte("{}")
-		configDesc = content.NewDescriptorFromBytes(configMediaType, configBytes)
-		configDesc.Annotations = opts.ConfigAnnotations
-		// push config
-		if err := pusher.Push(ctx, configDesc, bytes.NewReader(configBytes)); err != nil && !errors.Is(err, errdef.ErrAlreadyExists) {
-			return ocispec.Descriptor{}, fmt.Errorf("failed to push config: %w", err)
+		var err error
+		configDesc, err = pushCustomEmptyConfig(ctx, pusher, configMediaType, opts.ConfigAnnotations)
+		if err != nil {
+			return ocispec.Descriptor{}, err
 		}
 	}
 
@@ -161,23 +280,124 @@ func packImage(ctx context.Context, pusher content.Pusher, configMediaType strin
 		Subject:     opts.Subject,
 		Annotations: annotations,
 	}
+	return pushManifest(ctx, pusher, manifest, manifest.MediaType, manifest.Config.MediaType, manifest.Annotations)
+}
+
+// packManifestV1_1_RC4 packs an image manifest defined in image-spec v1.1.0-rc4.
+// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc4/manifest.md#guidelines-for-artifact-usage
+func packManifestV1_1_RC4(ctx context.Context, pusher content.Pusher, artifactType string, opts PackManifestOptions) (ocispec.Descriptor, error) {
+	if artifactType == "" && (opts.ConfigDescriptor == nil || opts.ConfigDescriptor.MediaType == ocispec.MediaTypeEmptyJSON) {
+		// artifactType MUST be set when config.mediaType is set to the empty value
+		return ocispec.Descriptor{}, ErrMissingArtifactType
+	}
+	if artifactType != "" {
+		if err := validateMediaType(artifactType); err != nil {
+			return ocispec.Descriptor{}, fmt.Errorf("invalid artifactType format: %w", err)
+		}
+	}
+
+	// prepare config
+	var emptyBlobExists bool
+	var configDesc ocispec.Descriptor
+	if opts.ConfigDescriptor != nil {
+		if err := validateMediaType(opts.ConfigDescriptor.MediaType); err != nil {
+			return ocispec.Descriptor{}, fmt.Errorf("invalid config mediaType format: %w", err)
+		}
+		configDesc = *opts.ConfigDescriptor
+	} else {
+		// use the empty descriptor for config
+		configDesc = ocispec.DescriptorEmptyJSON
+		configDesc.Annotations = opts.ConfigAnnotations
+		configBytes := ocispec.DescriptorEmptyJSON.Data
+		// push config
+		if err := pushIfNotExist(ctx, pusher, configDesc, configBytes); err != nil {
+			return ocispec.Descriptor{}, fmt.Errorf("failed to push config: %w", err)
+		}
+		emptyBlobExists = true
+	}
+
+	annotations, err := ensureAnnotationCreated(opts.ManifestAnnotations, ocispec.AnnotationCreated)
+	if err != nil {
+		return ocispec.Descriptor{}, err
+	}
+	if len(opts.Layers) == 0 {
+		// use the empty descriptor as the single layer
+		layerDesc := ocispec.DescriptorEmptyJSON
+		layerData := ocispec.DescriptorEmptyJSON.Data
+		if !emptyBlobExists {
+			if err := pushIfNotExist(ctx, pusher, layerDesc, layerData); err != nil {
+				return ocispec.Descriptor{}, fmt.Errorf("failed to push layer: %w", err)
+			}
+		}
+		opts.Layers = []ocispec.Descriptor{layerDesc}
+	}
+
+	manifest := ocispec.Manifest{
+		Versioned: specs.Versioned{
+			SchemaVersion: 2, // historical value. does not pertain to OCI or docker version
+		},
+		Config:       configDesc,
+		MediaType:    ocispec.MediaTypeImageManifest,
+		Layers:       opts.Layers,
+		Subject:      opts.Subject,
+		ArtifactType: artifactType,
+		Annotations:  annotations,
+	}
+	return pushManifest(ctx, pusher, manifest, manifest.MediaType, manifest.ArtifactType, manifest.Annotations)
+}
+
+// pushIfNotExist pushes data described by desc if it does not exist in the
+// target.
+func pushIfNotExist(ctx context.Context, pusher content.Pusher, desc ocispec.Descriptor, data []byte) error {
+	if ros, ok := pusher.(content.ReadOnlyStorage); ok {
+		exists, err := ros.Exists(ctx, desc)
+		if err != nil {
+			return fmt.Errorf("failed to check existence: %s: %s: %w", desc.Digest.String(), desc.MediaType, err)
+		}
+		if exists {
+			return nil
+		}
+	}
+
+	if err := pusher.Push(ctx, desc, bytes.NewReader(data)); err != nil && !errors.Is(err, errdef.ErrAlreadyExists) {
+		return fmt.Errorf("failed to push: %s: %s: %w", desc.Digest.String(), desc.MediaType, err)
+	}
+	return nil
+}
+
+// pushManifest marshals manifest into JSON bytes and pushes it.
+func pushManifest(ctx context.Context, pusher content.Pusher, manifest any, mediaType string, artifactType string, annotations map[string]string) (ocispec.Descriptor, error) {
 	manifestJSON, err := json.Marshal(manifest)
 	if err != nil {
 		return ocispec.Descriptor{}, fmt.Errorf("failed to marshal manifest: %w", err)
 	}
-	manifestDesc := content.NewDescriptorFromBytes(ocispec.MediaTypeImageManifest, manifestJSON)
+	manifestDesc := content.NewDescriptorFromBytes(mediaType, manifestJSON)
 	// populate ArtifactType and Annotations of the manifest into manifestDesc
-	manifestDesc.ArtifactType = manifest.Config.MediaType
-	manifestDesc.Annotations = manifest.Annotations
-
+	manifestDesc.ArtifactType = artifactType
+	manifestDesc.Annotations = annotations
 	// push manifest
 	if err := pusher.Push(ctx, manifestDesc, bytes.NewReader(manifestJSON)); err != nil && !errors.Is(err, errdef.ErrAlreadyExists) {
 		return ocispec.Descriptor{}, fmt.Errorf("failed to push manifest: %w", err)
 	}
-
 	return manifestDesc, nil
 }
 
+// pushCustomEmptyConfig generates and pushes an empty config blob.
+func pushCustomEmptyConfig(ctx context.Context, pusher content.Pusher, mediaType string, annotations map[string]string) (ocispec.Descriptor, error) {
+	// Use an empty JSON object here, because some registries may not accept
+	// empty config blob.
+	// As of September 2022, GAR is known to return 400 on empty blob upload.
+	// See https://github.com/oras-project/oras-go/issues/294 for details.
+	configBytes := []byte("{}")
+	configDesc := content.NewDescriptorFromBytes(mediaType, configBytes)
+	configDesc.Annotations = annotations
+	// push config
+	if err := pushIfNotExist(ctx, pusher, configDesc, configBytes); err != nil {
+		return ocispec.Descriptor{}, fmt.Errorf("failed to push config: %w", err)
+	}
+	return configDesc, nil
+}
+
 // ensureAnnotationCreated ensures that annotationCreatedKey is in annotations,
 // and that its value conforms to RFC 3339. Otherwise returns a new annotation
 // map with annotationCreatedKey created.
@@ -201,3 +421,11 @@ func ensureAnnotationCreated(annotations map[string]string, annotationCreatedKey
 	copied[annotationCreatedKey] = now.Format(time.RFC3339)
 	return copied, nil
 }
+
+// validateMediaType validates the format of mediaType.
+func validateMediaType(mediaType string) error {
+	if !mediaTypeRegexp.MatchString(mediaType) {
+		return fmt.Errorf("%s: %w", mediaType, errdef.ErrInvalidMediaType)
+	}
+	return nil
+}
diff --git a/vendor/oras.land/oras-go/v2/registry/reference.go b/vendor/oras.land/oras-go/v2/registry/reference.go
index cea579a14..7661a162b 100644
--- a/vendor/oras.land/oras-go/v2/registry/reference.go
+++ b/vendor/oras.land/oras-go/v2/registry/reference.go
@@ -31,14 +31,16 @@ var (
 	// repository name set under OCI distribution spec is a subset of the docker
 	// spec. For maximum compatability, the docker spec is verified client-side.
 	// Further checks are left to the server-side.
+	//
 	// References:
-	// - https://github.com/distribution/distribution/blob/v2.7.1/reference/regexp.go#L53
-	// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pulling-manifests
+	//   - https://github.com/distribution/distribution/blob/v2.7.1/reference/regexp.go#L53
+	//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pulling-manifests
 	repositoryRegexp = regexp.MustCompile(`^[a-z0-9]+(?:(?:[._]|__|[-]*)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]*)[a-z0-9]+)*)*$`)
 
 	// tagRegexp checks the tag name.
 	// The docker and OCI spec have the same regular expression.
-	// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pulling-manifests
+	//
+	// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pulling-manifests
 	tagRegexp = regexp.MustCompile(`^[\w][\w.-]{0,127}$`)
 )
 
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go b/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go
index cf0018a01..fb192aa8a 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go
@@ -24,7 +24,7 @@ import (
 )
 
 // References:
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#error-codes
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#error-codes
 //   - https://docs.docker.com/registry/spec/api/#errors-2
 const (
 	ErrorCodeBlobUnknown         = "BLOB_UNKNOWN"
@@ -45,7 +45,7 @@ const (
 // Error represents a response inner error returned by the remote
 // registry.
 // References:
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#error-codes
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#error-codes
 //   - https://docs.docker.com/registry/spec/api/#errors-2
 type Error struct {
 	Code    string `json:"code"`
@@ -73,7 +73,7 @@ func (e Error) Error() string {
 // Errors represents a list of response inner errors returned by the remote
 // server.
 // References:
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#error-codes
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#error-codes
 //   - https://docs.docker.com/registry/spec/api/#errors-2
 type Errors []Error
 
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/referrers.go b/vendor/oras.land/oras-go/v2/registry/remote/referrers.go
index a3ed08ca5..191db9d17 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/referrers.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/referrers.go
@@ -22,7 +22,6 @@ import (
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"oras.land/oras-go/v2/content"
 	"oras.land/oras-go/v2/internal/descriptor"
-	"oras.land/oras-go/v2/internal/spec"
 )
 
 // zeroDigest represents a digest that consists of zeros. zeroDigest is used
@@ -103,17 +102,15 @@ func (e *ReferrersError) IsReferrersIndexDelete() bool {
 
 // buildReferrersTag builds the referrers tag for the given manifest descriptor.
 // Format: <algorithm>-<digest>
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#unavailable-referrers-api
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#unavailable-referrers-api
 func buildReferrersTag(desc ocispec.Descriptor) string {
 	alg := desc.Digest.Algorithm().String()
 	encoded := desc.Digest.Encoded()
 	return alg + "-" + encoded
 }
 
-// isReferrersFilterApplied checks annotations to see if requested is in the
-// applied filter list.
-func isReferrersFilterApplied(annotations map[string]string, requested string) bool {
-	applied := annotations[spec.AnnotationReferrersFiltersApplied]
+// isReferrersFilterApplied checks if requsted is in the applied filter list.
+func isReferrersFilterApplied(applied, requested string) bool {
 	if applied == "" || requested == "" {
 		return false
 	}
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/registry.go b/vendor/oras.land/oras-go/v2/registry/remote/registry.go
index c8c414f17..8ae538d96 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/registry.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/registry.go
@@ -73,13 +73,28 @@ func (r *Registry) client() Client {
 	return r.Client
 }
 
+// do sends an HTTP request and returns an HTTP response using the HTTP client
+// returned by r.client().
+func (r *Registry) do(req *http.Request) (*http.Response, error) {
+	if r.HandleWarning == nil {
+		return r.client().Do(req)
+	}
+
+	resp, err := r.client().Do(req)
+	if err != nil {
+		return nil, err
+	}
+	handleWarningHeaders(resp.Header.Values(headerWarning), r.HandleWarning)
+	return resp, nil
+}
+
 // Ping checks whether or not the registry implement Docker Registry API V2 or
 // OCI Distribution Specification.
 // Ping can be used to check authentication when an auth client is configured.
 //
 // References:
 //   - https://docs.docker.com/registry/spec/api/#base
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#api
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#api
 func (r *Registry) Ping(ctx context.Context) error {
 	url := buildRegistryBaseURL(r.PlainHTTP, r.Reference)
 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
@@ -87,7 +102,7 @@ func (r *Registry) Ping(ctx context.Context) error {
 		return err
 	}
 
-	resp, err := r.client().Do(req)
+	resp, err := r.do(req)
 	if err != nil {
 		return err
 	}
@@ -142,7 +157,7 @@ func (r *Registry) repositories(ctx context.Context, last string, fn func(repos
 		}
 		req.URL.RawQuery = q.Encode()
 	}
-	resp, err := r.client().Do(req)
+	resp, err := r.do(req)
 	if err != nil {
 		return "", err
 	}
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/repository.go b/vendor/oras.land/oras-go/v2/registry/remote/repository.go
index 32ac347d6..0f8c6acd2 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/repository.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/repository.go
@@ -47,11 +47,37 @@ import (
 	"oras.land/oras-go/v2/registry/remote/internal/errutil"
 )
 
-// dockerContentDigestHeader - The Docker-Content-Digest header, if present
-// on the response, returns the canonical digest of the uploaded blob.
-// See https://docs.docker.com/registry/spec/api/#digest-header
-// See https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pull
-const dockerContentDigestHeader = "Docker-Content-Digest"
+const (
+	// headerDockerContentDigest is the "Docker-Content-Digest" header.
+	// If present on the response, it contains the canonical digest of the
+	// uploaded blob.
+	//
+	// References:
+	//   - https://docs.docker.com/registry/spec/api/#digest-header
+	//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pull
+	headerDockerContentDigest = "Docker-Content-Digest"
+
+	// headerOCIFiltersApplied is the "OCI-Filters-Applied" header.
+	// If present on the response, it contains a comma-separated list of the
+	// applied filters.
+	//
+	// Reference:
+	//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
+	headerOCIFiltersApplied = "OCI-Filters-Applied"
+
+	// headerOCISubject is the "OCI-Subject" header.
+	// If present on the response, it contains the digest of the subject,
+	// indicating that Referrers API is supported by the registry.
+	headerOCISubject = "OCI-Subject"
+)
+
+// filterTypeArtifactType is the "artifactType" filter applied on the list of
+// referrers.
+//
+// References:
+//   - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
+//   - Compatible spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+const filterTypeArtifactType = "artifactType"
 
 // Client is an interface for a HTTP client.
 type Client interface {
@@ -93,7 +119,7 @@ type Repository struct {
 	// ReferrerListPageSize specifies the page size when invoking the Referrers
 	// API.
 	// If zero, the page size is determined by the remote registry.
-	// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+	// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
 	ReferrerListPageSize int
 
 	// MaxMetadataBytes specifies a limit on how many response bytes are allowed
@@ -102,6 +128,25 @@ type Repository struct {
 	// If less than or equal to zero, a default (currently 4MiB) is used.
 	MaxMetadataBytes int64
 
+	// SkipReferrersGC specifies whether to delete the dangling referrers
+	// index when referrers tag schema is utilized.
+	//  - If false, the old referrers index will be deleted after the new one
+	//    is successfully uploaded.
+	//  - If true, the old referrers index is kept.
+	// By default, it is disabled (set to false). See also:
+	//  - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#referrers-tag-schema
+	//  - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pushing-manifests-with-subject
+	//  - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#deleting-manifests
+	SkipReferrersGC bool
+
+	// HandleWarning handles the warning returned by the remote server.
+	// Callers SHOULD deduplicate warnings from multiple associated responses.
+	//
+	// References:
+	//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#warnings
+	//   - https://www.rfc-editor.org/rfc/rfc7234#section-5.5
+	HandleWarning func(warning Warning)
+
 	// NOTE: Must keep fields in sync with newRepositoryWithOptions function.
 
 	// referrersState represents that if the repository supports Referrers API.
@@ -145,6 +190,7 @@ func newRepositoryWithOptions(ref registry.Reference, opts *RepositoryOptions) (
 		Client:               opts.Client,
 		Reference:            ref,
 		PlainHTTP:            opts.PlainHTTP,
+		SkipReferrersGC:      opts.SkipReferrersGC,
 		ManifestMediaTypes:   slices.Clone(opts.ManifestMediaTypes),
 		TagListPageSize:      opts.TagListPageSize,
 		ReferrerListPageSize: opts.ReferrerListPageSize,
@@ -159,9 +205,9 @@ func newRepositoryWithOptions(ref registry.Reference, opts *RepositoryOptions) (
 // SetReferrersCapability returns ErrReferrersCapabilityAlreadySet if the
 // Referrers API capability has been already set.
 //   - When the capability is set to true, the Referrers() function will always
-//     request the Referrers API. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+//     request the Referrers API. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
 //   - When the capability is set to false, the Referrers() function will always
-//     request the Referrers Tag. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema
+//     request the Referrers Tag. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#referrers-tag-schema
 //   - When the capability is not set, the Referrers() function will automatically
 //     determine which API to use.
 func (r *Repository) SetReferrersCapability(capable bool) error {
@@ -196,6 +242,21 @@ func (r *Repository) client() Client {
 	return r.Client
 }
 
+// do sends an HTTP request and returns an HTTP response using the HTTP client
+// returned by r.client().
+func (r *Repository) do(req *http.Request) (*http.Response, error) {
+	if r.HandleWarning == nil {
+		return r.client().Do(req)
+	}
+
+	resp, err := r.client().Do(req)
+	if err != nil {
+		return nil, err
+	}
+	handleWarningHeaders(resp.Header.Values(headerWarning), r.HandleWarning)
+	return resp, nil
+}
+
 // blobStore detects the blob store for the given descriptor.
 func (r *Repository) blobStore(desc ocispec.Descriptor) registry.BlobStore {
 	if isManifest(r.ManifestMediaTypes, desc) {
@@ -320,7 +381,7 @@ func (r *Repository) ParseReference(reference string) (registry.Reference, error
 // of the Tags list.
 //
 // References:
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#content-discovery
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#content-discovery
 //   - https://docs.docker.com/registry/spec/api/#tags
 func (r *Repository) Tags(ctx context.Context, last string, fn func(tags []string) error) error {
 	ctx = registryutil.WithScopeHint(ctx, r.Reference, auth.ActionPull)
@@ -353,7 +414,7 @@ func (r *Repository) tags(ctx context.Context, last string, fn func(tags []strin
 		}
 		req.URL.RawQuery = q.Encode()
 	}
-	resp, err := r.client().Do(req)
+	resp, err := r.do(req)
 	if err != nil {
 		return "", err
 	}
@@ -379,7 +440,7 @@ func (r *Repository) tags(ctx context.Context, last string, fn func(tags []strin
 // Predecessors returns the descriptors of image or artifact manifests directly
 // referencing the given manifest descriptor.
 // Predecessors internally leverages Referrers.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
 func (r *Repository) Predecessors(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
 	var res []ocispec.Descriptor
 	if err := r.Referrers(ctx, desc, "", func(referrers []ocispec.Descriptor) error {
@@ -398,7 +459,7 @@ func (r *Repository) Predecessors(ctx context.Context, desc ocispec.Descriptor)
 // If artifactType is not empty, only referrers of the same artifact type are
 // fed to fn.
 //
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
 func (r *Repository) Referrers(ctx context.Context, desc ocispec.Descriptor, artifactType string, fn func(referrers []ocispec.Descriptor) error) error {
 	state := r.loadReferrersState()
 	if state == referrersStateUnsupported {
@@ -470,7 +531,7 @@ func (r *Repository) referrersPageByAPI(ctx context.Context, artifactType string
 		req.URL.RawQuery = q.Encode()
 	}
 
-	resp, err := r.client().Do(req)
+	resp, err := r.do(req)
 	if err != nil {
 		return "", err
 	}
@@ -485,10 +546,19 @@ func (r *Repository) referrersPageByAPI(ctx context.Context, artifactType string
 	if err := json.NewDecoder(lr).Decode(&index); err != nil {
 		return "", fmt.Errorf("%s %q: failed to decode response: %w", resp.Request.Method, resp.Request.URL, err)
 	}
+
 	referrers := index.Manifests
-	if artifactType != "" && !isReferrersFilterApplied(index.Annotations, "artifactType") {
-		// perform client side filtering if the filter is not applied on the server side
-		referrers = filterReferrers(referrers, artifactType)
+	if artifactType != "" {
+		// check both filters header and filters annotations for compatibility
+		// latest spec for filters header: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
+		// older spec for filters annotations: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+		filtersHeader := resp.Header.Get(headerOCIFiltersApplied)
+		filtersAnnotation := index.Annotations[spec.AnnotationReferrersFiltersApplied]
+		if !isReferrersFilterApplied(filtersHeader, filterTypeArtifactType) &&
+			!isReferrersFilterApplied(filtersAnnotation, filterTypeArtifactType) {
+			// perform client side filtering if the filter is not applied on the server side
+			referrers = filterReferrers(referrers, artifactType)
+		}
 	}
 	if len(referrers) > 0 {
 		if err := fn(referrers); err != nil {
@@ -502,7 +572,7 @@ func (r *Repository) referrersPageByAPI(ctx context.Context, artifactType string
 // referencing the given manifest descriptor by requesting referrers tag.
 // fn is called for the referrers result. If artifactType is not empty,
 // only referrers of the same artifact type are fed to fn.
-// reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#backwards-compatibility
+// reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#backwards-compatibility
 func (r *Repository) referrersByTagSchema(ctx context.Context, desc ocispec.Descriptor, artifactType string, fn func(referrers []ocispec.Descriptor) error) error {
 	referrersTag := buildReferrersTag(desc)
 	_, referrers, err := r.referrersFromIndex(ctx, referrersTag)
@@ -572,7 +642,7 @@ func (r *Repository) pingReferrers(ctx context.Context) (bool, error) {
 	if err != nil {
 		return false, err
 	}
-	resp, err := r.client().Do(req)
+	resp, err := r.do(req)
 	if err != nil {
 		return false, err
 	}
@@ -610,7 +680,7 @@ func (r *Repository) delete(ctx context.Context, target ocispec.Descriptor, isMa
 		return err
 	}
 
-	resp, err := r.client().Do(req)
+	resp, err := r.do(req)
 	if err != nil {
 		return err
 	}
@@ -642,7 +712,7 @@ func (s *blobStore) Fetch(ctx context.Context, target ocispec.Descriptor) (rc io
 		return nil, err
 	}
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return nil, err
 	}
@@ -689,7 +759,7 @@ func (s *blobStore) Mount(ctx context.Context, desc ocispec.Descriptor, fromRepo
 	if err != nil {
 		return err
 	}
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return err
 	}
@@ -715,7 +785,7 @@ func (s *blobStore) Mount(ctx context.Context, desc ocispec.Descriptor, fromRepo
 	// push it. If the caller has provided a getContent function, we
 	// can use that, otherwise pull the content from the source repository.
 	//
-	// [spec]: https://github.com/opencontainers/distribution-spec/blob/main/spec.md#mounting-a-blob-from-another-repository
+	// [spec]: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#mounting-a-blob-from-another-repository
 
 	var r io.ReadCloser
 	if getContent != nil {
@@ -746,10 +816,11 @@ func (s *blobStore) sibling(otherRepoName string) *blobStore {
 // Push is done by conventional 2-step monolithic upload instead of a single
 // `POST` request for better overall performance. It also allows early fail on
 // authentication errors.
+//
 // References:
-// - https://docs.docker.com/registry/spec/api/#pushing-an-image
-// - https://docs.docker.com/registry/spec/api/#initiate-blob-upload
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pushing-a-blob-monolithically
+//   - https://docs.docker.com/registry/spec/api/#pushing-an-image
+//   - https://docs.docker.com/registry/spec/api/#initiate-blob-upload
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pushing-a-blob-monolithically
 func (s *blobStore) Push(ctx context.Context, expected ocispec.Descriptor, content io.Reader) error {
 	// start an upload
 	// pushing usually requires both pull and push actions.
@@ -761,7 +832,7 @@ func (s *blobStore) Push(ctx context.Context, expected ocispec.Descriptor, conte
 		return err
 	}
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return err
 	}
@@ -816,7 +887,7 @@ func (s *blobStore) completePushAfterInitialPost(ctx context.Context, req *http.
 	if auth := resp.Request.Header.Get("Authorization"); auth != "" {
 		req.Header.Set("Authorization", auth)
 	}
-	resp, err = s.repo.client().Do(req)
+	resp, err = s.repo.do(req)
 	if err != nil {
 		return err
 	}
@@ -862,7 +933,7 @@ func (s *blobStore) Resolve(ctx context.Context, reference string) (ocispec.Desc
 		return ocispec.Descriptor{}, err
 	}
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return ocispec.Descriptor{}, err
 	}
@@ -897,7 +968,7 @@ func (s *blobStore) FetchReference(ctx context.Context, reference string) (desc
 		return ocispec.Descriptor{}, nil, err
 	}
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return ocispec.Descriptor{}, nil, err
 	}
@@ -973,7 +1044,7 @@ func (s *manifestStore) Fetch(ctx context.Context, target ocispec.Descriptor) (r
 	}
 	req.Header.Set("Accept", target.MediaType)
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return nil, err
 	}
@@ -1032,7 +1103,8 @@ func (s *manifestStore) Delete(ctx context.Context, target ocispec.Descriptor) e
 // deleteWithIndexing removes the manifest content identified by the descriptor,
 // and indexes referrers for the manifest when needed.
 func (s *manifestStore) deleteWithIndexing(ctx context.Context, target ocispec.Descriptor) error {
-	if target.MediaType == spec.MediaTypeArtifactManifest || target.MediaType == ocispec.MediaTypeImageManifest {
+	switch target.MediaType {
+	case spec.MediaTypeArtifactManifest, ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
 		if state := s.repo.loadReferrersState(); state == referrersStateSupported {
 			// referrers API is available, no client-side indexing needed
 			return s.repo.delete(ctx, target, true)
@@ -1053,9 +1125,12 @@ func (s *manifestStore) deleteWithIndexing(ctx context.Context, target ocispec.D
 	return s.repo.delete(ctx, target, true)
 }
 
-// indexReferrersForDelete indexes referrers for image or artifact manifest with
-// the subject field on manifest delete.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#deleting-manifests
+// indexReferrersForDelete indexes referrers for manifests with a subject field
+// on manifest delete.
+//
+// References:
+//   - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#deleting-manifests
+//   - Compatible spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#deleting-manifests
 func (s *manifestStore) indexReferrersForDelete(ctx context.Context, desc ocispec.Descriptor, manifestJSON []byte) error {
 	var manifest struct {
 		Subject *ocispec.Descriptor `json:"subject"`
@@ -1095,7 +1170,7 @@ func (s *manifestStore) Resolve(ctx context.Context, reference string) (ocispec.
 	}
 	req.Header.Set("Accept", manifestAcceptHeader(s.repo.ManifestMediaTypes))
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return ocispec.Descriptor{}, err
 	}
@@ -1127,7 +1202,7 @@ func (s *manifestStore) FetchReference(ctx context.Context, reference string) (d
 	}
 	req.Header.Set("Accept", manifestAcceptHeader(s.repo.ManifestMediaTypes))
 
-	resp, err := s.repo.client().Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return ocispec.Descriptor{}, nil, err
 	}
@@ -1225,7 +1300,7 @@ func (s *manifestStore) push(ctx context.Context, expected ocispec.Descriptor, c
 			return err
 		}
 	}
-	resp, err := client.Do(req)
+	resp, err := s.repo.do(req)
 	if err != nil {
 		return err
 	}
@@ -1234,14 +1309,26 @@ func (s *manifestStore) push(ctx context.Context, expected ocispec.Descriptor, c
 	if resp.StatusCode != http.StatusCreated {
 		return errutil.ParseErrorResponse(resp)
 	}
+	s.checkOCISubjectHeader(resp)
 	return verifyContentDigest(resp, expected.Digest)
 }
 
+// checkOCISubjectHeader checks the "OCI-Subject" header in the response and
+// sets referrers capability accordingly.
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pushing-manifests-with-subject
+func (s *manifestStore) checkOCISubjectHeader(resp *http.Response) {
+	// Referrers capability is not set to false when the subject header is not
+	// present, as the server may still conform to an older version of the spec
+	if subjectHeader := resp.Header.Get(headerOCISubject); subjectHeader != "" {
+		s.repo.SetReferrersCapability(true)
+	}
+}
+
 // pushWithIndexing pushes the manifest content matching the expected descriptor,
 // and indexes referrers for the manifest when needed.
 func (s *manifestStore) pushWithIndexing(ctx context.Context, expected ocispec.Descriptor, r io.Reader, reference string) error {
 	switch expected.MediaType {
-	case spec.MediaTypeArtifactManifest, ocispec.MediaTypeImageManifest:
+	case spec.MediaTypeArtifactManifest, ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
 		if state := s.repo.loadReferrersState(); state == referrersStateSupported {
 			// referrers API is available, no client-side indexing needed
 			return s.push(ctx, expected, r, reference)
@@ -1257,15 +1344,22 @@ func (s *manifestStore) pushWithIndexing(ctx context.Context, expected ocispec.D
 		if err := s.push(ctx, expected, bytes.NewReader(manifestJSON), reference); err != nil {
 			return err
 		}
+		// check referrers API availability again after push
+		if state := s.repo.loadReferrersState(); state == referrersStateSupported {
+			return nil
+		}
 		return s.indexReferrersForPush(ctx, expected, manifestJSON)
 	default:
 		return s.push(ctx, expected, r, reference)
 	}
 }
 
-// indexReferrersForPush indexes referrers for image or artifact manifest with
-// the subject field on manifest push.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pushing-manifests-with-subject
+// indexReferrersForPush indexes referrers for manifests with a subject field
+// on manifest push.
+//
+// References:
+//   - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pushing-manifests-with-subject
+//   - Compatible spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pushing-manifests-with-subject
 func (s *manifestStore) indexReferrersForPush(ctx context.Context, desc ocispec.Descriptor, manifestJSON []byte) error {
 	var subject ocispec.Descriptor
 	switch desc.MediaType {
@@ -1291,7 +1385,22 @@ func (s *manifestStore) indexReferrersForPush(ctx context.Context, desc ocispec.
 			return nil
 		}
 		subject = *manifest.Subject
-		desc.ArtifactType = manifest.Config.MediaType
+		desc.ArtifactType = manifest.ArtifactType
+		if desc.ArtifactType == "" {
+			desc.ArtifactType = manifest.Config.MediaType
+		}
+		desc.Annotations = manifest.Annotations
+	case ocispec.MediaTypeImageIndex:
+		var manifest ocispec.Index
+		if err := json.Unmarshal(manifestJSON, &manifest); err != nil {
+			return fmt.Errorf("failed to decode manifest: %s: %s: %w", desc.Digest, desc.MediaType, err)
+		}
+		if manifest.Subject == nil {
+			// no subject, no indexing needed
+			return nil
+		}
+		subject = *manifest.Subject
+		desc.ArtifactType = manifest.ArtifactType
 		desc.Annotations = manifest.Annotations
 	default:
 		return nil
@@ -1311,12 +1420,12 @@ func (s *manifestStore) indexReferrersForPush(ctx context.Context, desc ocispec.
 // updateReferrersIndex updates the referrers index for desc referencing subject
 // on manifest push and manifest delete.
 // References:
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pushing-manifests-with-subject
-//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#deleting-manifests
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#pushing-manifests-with-subject
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#deleting-manifests
 func (s *manifestStore) updateReferrersIndex(ctx context.Context, subject ocispec.Descriptor, change referrerChange) (err error) {
 	referrersTag := buildReferrersTag(subject)
 
-	var skipDelete bool
+	skipDelete := s.repo.SkipReferrersGC
 	var oldIndexDesc ocispec.Descriptor
 	var referrers []ocispec.Descriptor
 	prepare := func() error {
@@ -1408,13 +1517,13 @@ func (s *manifestStore) generateDescriptor(resp *http.Response, ref registry.Ref
 
 	// 4. Validate Server Digest (if present)
 	var serverHeaderDigest digest.Digest
-	if serverHeaderDigestStr := resp.Header.Get(dockerContentDigestHeader); serverHeaderDigestStr != "" {
+	if serverHeaderDigestStr := resp.Header.Get(headerDockerContentDigest); serverHeaderDigestStr != "" {
 		if serverHeaderDigest, err = digest.Parse(serverHeaderDigestStr); err != nil {
 			return ocispec.Descriptor{}, fmt.Errorf(
 				"%s %q: invalid response header value: `%s: %s`; %w",
 				resp.Request.Method,
 				resp.Request.URL,
-				dockerContentDigestHeader,
+				headerDockerContentDigest,
 				serverHeaderDigestStr,
 				err,
 			)
@@ -1431,7 +1540,7 @@ func (s *manifestStore) generateDescriptor(resp *http.Response, ref registry.Ref
 				// immediate fail
 				return ocispec.Descriptor{}, fmt.Errorf(
 					"HTTP %s request missing required header %q",
-					httpMethod, dockerContentDigestHeader,
+					httpMethod, headerDockerContentDigest,
 				)
 			}
 			// Otherwise, just trust the client-supplied digest
@@ -1453,7 +1562,7 @@ func (s *manifestStore) generateDescriptor(resp *http.Response, ref registry.Ref
 		return ocispec.Descriptor{}, fmt.Errorf(
 			"%s %q: invalid response; digest mismatch in %s: received %q when expecting %q",
 			resp.Request.Method, resp.Request.URL,
-			dockerContentDigestHeader, contentDigest,
+			headerDockerContentDigest, contentDigest,
 			refDigest,
 		)
 	}
@@ -1485,7 +1594,7 @@ func calculateDigestFromResponse(resp *http.Response, maxMetadataBytes int64) (d
 // OCI distribution-spec states the Docker-Content-Digest header is optional.
 // Reference: https://github.com/opencontainers/distribution-spec/blob/v1.0.1/spec.md#legacy-docker-support-http-headers
 func verifyContentDigest(resp *http.Response, expected digest.Digest) error {
-	digestStr := resp.Header.Get(dockerContentDigestHeader)
+	digestStr := resp.Header.Get(headerDockerContentDigest)
 
 	if len(digestStr) == 0 {
 		return nil
@@ -1496,7 +1605,7 @@ func verifyContentDigest(resp *http.Response, expected digest.Digest) error {
 		return fmt.Errorf(
 			"%s %q: invalid response header: `%s: %s`",
 			resp.Request.Method, resp.Request.URL,
-			dockerContentDigestHeader, digestStr,
+			headerDockerContentDigest, digestStr,
 		)
 	}
 
@@ -1504,7 +1613,7 @@ func verifyContentDigest(resp *http.Response, expected digest.Digest) error {
 		return fmt.Errorf(
 			"%s %q: invalid response; digest mismatch in %s: received %q when expecting %q",
 			resp.Request.Method, resp.Request.URL,
-			dockerContentDigestHeader, contentDigest,
+			headerDockerContentDigest, contentDigest,
 			expected,
 		)
 	}
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/url.go b/vendor/oras.land/oras-go/v2/registry/remote/url.go
index d3eee3eea..74258de7a 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/url.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/url.go
@@ -101,7 +101,7 @@ func buildRepositoryBlobMountURL(plainHTTP bool, ref registry.Reference, d diges
 
 // buildReferrersURL builds the URL for querying the Referrers API.
 // Format: <scheme>://<registry>/v2/<repository>/referrers/<digest>?artifactType=<artifactType>
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
 func buildReferrersURL(plainHTTP bool, ref registry.Reference, artifactType string) string {
 	var query string
 	if artifactType != "" {
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/warning.go b/vendor/oras.land/oras-go/v2/registry/remote/warning.go
new file mode 100644
index 000000000..ff8f9c029
--- /dev/null
+++ b/vendor/oras.land/oras-go/v2/registry/remote/warning.go
@@ -0,0 +1,100 @@
+/*
+Copyright The ORAS Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package remote
+
+import (
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+const (
+	// headerWarning is the "Warning" header.
+	// Reference: https://www.rfc-editor.org/rfc/rfc7234#section-5.5
+	headerWarning = "Warning"
+
+	// warnCode299 is the 299 warn-code.
+	// Reference: https://www.rfc-editor.org/rfc/rfc7234#section-5.5
+	warnCode299 = 299
+
+	// warnAgentUnknown represents an unknown warn-agent.
+	// Reference: https://www.rfc-editor.org/rfc/rfc7234#section-5.5
+	warnAgentUnknown = "-"
+)
+
+// errUnexpectedWarningFormat is returned by parseWarningHeader when
+// an unexpected warning format is encountered.
+var errUnexpectedWarningFormat = errors.New("unexpected warning format")
+
+// WarningValue represents the value of the Warning header.
+//
+// References:
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#warnings
+//   - https://www.rfc-editor.org/rfc/rfc7234#section-5.5
+type WarningValue struct {
+	// Code is the warn-code.
+	Code int
+	// Agent is the warn-agent.
+	Agent string
+	// Text is the warn-text.
+	Text string
+}
+
+// Warning contains the value of the warning header and may contain
+// other information related to the warning.
+//
+// References:
+//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#warnings
+//   - https://www.rfc-editor.org/rfc/rfc7234#section-5.5
+type Warning struct {
+	// WarningValue is the value of the warning header.
+	WarningValue
+}
+
+// parseWarningHeader parses the warning header into WarningValue.
+func parseWarningHeader(header string) (WarningValue, error) {
+	if len(header) < 9 || !strings.HasPrefix(header, `299 - "`) || !strings.HasSuffix(header, `"`) {
+		// minimum header value: `299 - "x"`
+		return WarningValue{}, fmt.Errorf("%s: %w", header, errUnexpectedWarningFormat)
+	}
+
+	// validate text only as code and agent are fixed
+	quotedText := header[6:] // behind `299 - `, quoted by "
+	text, err := strconv.Unquote(quotedText)
+	if err != nil {
+		return WarningValue{}, fmt.Errorf("%s: unexpected text: %w: %v", header, errUnexpectedWarningFormat, err)
+	}
+
+	return WarningValue{
+		Code:  warnCode299,
+		Agent: warnAgentUnknown,
+		Text:  text,
+	}, nil
+}
+
+// handleWarningHeaders parses the warning headers and handles the parsed
+// warnings using handleWarning.
+func handleWarningHeaders(headers []string, handleWarning func(Warning)) {
+	for _, h := range headers {
+		if value, err := parseWarningHeader(h); err == nil {
+			// ignore warnings in unexpected formats
+			handleWarning(Warning{
+				WarningValue: value,
+			})
+		}
+	}
+}
diff --git a/vendor/oras.land/oras-go/v2/registry/repository.go b/vendor/oras.land/oras-go/v2/registry/repository.go
index 2dd7ff994..b75b7b8ea 100644
--- a/vendor/oras.land/oras-go/v2/registry/repository.go
+++ b/vendor/oras.land/oras-go/v2/registry/repository.go
@@ -82,7 +82,7 @@ type ReferenceFetcher interface {
 }
 
 // ReferrerLister provides the Referrers API.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#listing-referrers
 type ReferrerLister interface {
 	Referrers(ctx context.Context, desc ocispec.Descriptor, artifactType string, fn func(referrers []ocispec.Descriptor) error) error
 }
@@ -93,16 +93,19 @@ type TagLister interface {
 	// Since the returned tag list may be paginated by the underlying
 	// implementation, a function should be passed in to process the paginated
 	// tag list.
+	//
 	// `last` argument is the `last` parameter when invoking the tags API.
 	// If `last` is NOT empty, the entries in the response start after the
 	// tag specified by `last`. Otherwise, the response starts from the top
 	// of the Tags list.
+	//
 	// Note: When implemented by a remote registry, the tags API is called.
 	// However, not all registries supports pagination or conforms the
 	// specification.
+	//
 	// References:
-	// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#content-discovery
-	// - https://docs.docker.com/registry/spec/api/#tags
+	//   - https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc3/spec.md#content-discovery
+	//   - https://docs.docker.com/registry/spec/api/#tags
 	// See also `Tags()` in this package.
 	Tags(ctx context.Context, last string, fn func(tags []string) error) error
 }


Test patch:
diff --git a/internal/pkg/artifact/artifact_test.go b/internal/pkg/artifact/artifact_test.go
index 0fc652c22..2728b92f8 100644
--- a/internal/pkg/artifact/artifact_test.go
+++ b/internal/pkg/artifact/artifact_test.go
@@ -140,10 +140,10 @@ func TestPush(t *testing.T) {
 			},
 		},
 		{
-			name: "failure on Pack",
+			name: "failure on PackManifest",
 			prepare: func(mock *artifactfakes.FakeImpl) {
 				mock.StoreAddReturns(defaultDescriptor(), nil)
-				mock.PackReturns(defaultDescriptor(), errTest)
+				mock.PackManifestReturns(defaultDescriptor(), errTest)
 			},
 			assert: func(err error) {
 				require.ErrorIs(t, err, errTest)