Repository: containers/common

Issue:
feature request: Retry if Registry Returns 5xx HTTP Error
# Feature Request

Improve skopeo's "retry" logic to retry if the registry returns a 5xx HTTP error code. Such an error can be intermittent in a production environment, depending on how the container registry is configured/deployed.

## Use Case

On Red Hat's Konflux, skopeo is used to build the "source" container image/OCI artifact. This step in the build pipeline can fail if the upstream registry (such as `registry.redhat.io`) is having intermittent performance issues.


Discussion:
@adambkaplan: From a recent run log, it appears skopeo does not retry in this case:

```
2025-01-16 09:19:35,256:source-build:DEBUG:copy image: ['skopeo', 'copy', '--retry-times', '5', '--remove-signatures', 'docker://registry.access.redhat.com/ubi9-minimal:9.5-1731593028-source', 'oci:/var/workdir/source-build/parent_image_sources']
Copying blob sha256:dabcb493812b34ce7aea02e0f4ea5735cd7bb9d973389c9fed628d8166ea505f
Copying blob sha256:3298bbb4739d5a3e758c0e80fc69a77573a730c2f8427fcc719dc2dbeffdabc8
Copying blob sha256:b8d6db0209c1f7c3cc256a6ae2065afd105356fb0e49f71a2db4211037236dbe
...
...
Copying blob sha256:dcce78f78298cf49a96b44952bdd6ae67ab69a911253bd331c9320549592accd
time="2025-01-16T09:19:52Z" level=fatal msg="reading blob sha256:50031b8ea1fd30e7eb133ee62037adb5ff984ab77bac81883b9ab9880b488f01: fetching blob: received unexpected HTTP status: 502 Bad Gateway"
```@mtrmac: Thanks for your report.

This logic is centralized in https://github.com/containers/common/tree/main/pkg/retry, moving there.@dustymabe: As noted in https://github.com/containers/podman/issues/25109#issue-2807439155 this also causes intermediate `502 bad gateway` errors that we often get from `quay.io` to cause quadlets to not come up on initial system startup.@dustymabe: I assume retrying 502 would also be really useful for `podman push`. Hit this this morning:

```
[2025-01-27T12:20:50.106Z] 2025-01-27 12:20:50,052 INFO - Running command: ['podman', 'push', 'quay.io/coreos-assembler/staging:aarch64-69f5874']
[2025-01-27T12:20:50.361Z] Getting image source signatures
[2025-01-27T12:20:50.361Z] Copying blob sha256:3bb8e7714d4f7920a3723d2261381aa38597e9ae20b33e656ace2427c48276cb
[2025-01-27T12:21:05.814Z] Copying blob sha256:fc3fbed5ce15e1cdddbcec5a85b91091aeb9dd6b16951e764769ab32d3132327
[2025-01-27T12:21:52.408Z] Error: writing blob: uploading layer to https://quay.io/v2/coreos-assembler/staging/blobs/uploads/4e8204f9-867d-421b-b234-9965fe90967f?digest=sha256%3A47d9cf72e71e4f96c2efb4c8ba6cbaf204ea2331b6ef939719a82ddd92768273: received unexpected HTTP status: 502 Bad Gateway
```

@adambkaplan: I imagine 502 or 503 are the most common server-side HTTP errors that can come from a container registry. Personally I think it's safe to retry on any 5xx code since the default retry logic uses an exponential backoff. @Luap99: I can confirm that 502 from quay.io is one of the most common errors I see in our (podman) CI logs. It was so flaky we had to move to a local cache registry to solve move of these issues. However some pulls still hit the real quay.io and in other test env where we do not have the cache registry (e.g. gating test on distros) so I still see regular 502 in the logs.

So I totally agree here that retying 5XX codes should help many of our users.

That said I am not sure how pkg/retry can be used there without other changes. `IsErrorRetryable()` checks an error BUT the HTTP request was successful and the go std library does not return a known error type we could match for.
https://pkg.go.dev/net/http#Get
> A non-2xx response doesn't cause an error. 

c/image defines its own type `unexpectedHTTPStatusError` but that one is not exported. So to me it seems that must first be exported in c/image then we could update IsErrorRetryable() to match for that specific error type and then compare status code is in the 5xx range
cc @mtrmac @mtrmac: Sure. I probably wouldn’t want to make a c/image-wide new error type, it’s hard to promise that we can provide that information for various (current and hypothetical future) external dependencies (like a Fulcio/Rekor client) — but adding a new `c/image/v5/docker` error type for this purpose seems entirely reasonable.@dustymabe: This causes regular failures in our RHCOS pipelines that push to quay. Causing engineers to triage and retry these failures often.

Any chance to move forward on a solution?@Luap99: https://github.com/containers/common/pull/2378 should fix it though I have not tested it yet.

Solution patch:
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index 77901746..28b2413c 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -11,7 +11,7 @@ on:
 permissions: read-all
 
 env:
-  LINT_VERSION: v1.64.8
+  LINT_VERSION: v2.0
 
 jobs:
   codespell:
@@ -37,16 +37,15 @@ jobs:
         sudo apt-get -qq update
         sudo apt-get -qq install libseccomp-dev
     - name: lint
-      uses: golangci/golangci-lint-action@v6
+      uses: golangci/golangci-lint-action@v7
       with:
         version: "${{ env.LINT_VERSION }}"
         args: --verbose
     # Extra linters, only checking new code from a pull request.
-    - name: Extra golangci-lint config. switcharoo
-      run: mv .golangci-extra.yml golangci.yml
     - name: lint-extra
-      uses: golangci/golangci-lint-action@v6
+      uses: golangci/golangci-lint-action@v7
       with:
+        args: --config=.golangci-extra.yml
         version: "${{ env.LINT_VERSION }}"
         only-new-issues: true
 
diff --git a/.golangci-extra.yml b/.golangci-extra.yml
index bccd162b..f77d1811 100644
--- a/.golangci-extra.yml
+++ b/.golangci-extra.yml
@@ -6,7 +6,10 @@
 # The idea is to impose additional rules for newly added code only
 # (rules we can not realistically satisfy for existing code).
 
+version: "2"
+
 run:
+  timeout: 5m
   build-tags:
     - apparmor
     - seccomp
@@ -14,10 +17,13 @@ run:
     - systemd
     - exclude_graphdriver_btrfs
     - containers_image_openpgp
-  concurrency: 6
-  deadline: 5m
 
 linters:
-  disable-all: true
+  default: none
   enable:
     - godot
+    - staticcheck
+  settings:
+    staticcheck:
+      checks:
+        - all
diff --git a/.golangci.yml b/.golangci.yml
index d71b6b31..c5e98a99 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,5 +1,7 @@
----
+version: "2"
+
 run:
+  timeout: 5m
   build-tags:
     - apparmor
     - seccomp
@@ -8,81 +10,80 @@ run:
     - exclude_graphdriver_btrfs
     - containers_image_openpgp
     - cni
-  timeout: 5m
+
+formatters:
+  enable:
+    - gofumpt
+
 linters:
-  enable-all: true
-  disable:
-    # linters explicitly disabled for the below mentioned reasons ...
-    - funlen # too aggressive/wishful size/statement limit
-    - gochecknoinits # too many hard to fix init() funcs across the code
-    - gocognit # too aggressive default
-    - wsl # useful but too opinionated
-    # others to be re-enabled one-by-one ...
-    - goconst
-    - godox
-    - lll
-    - nestif
-    - cyclop
-    - depguard
-    - errchkjson
-    - errname
-    - errorlint
-    - exhaustive
-    - gochecknoglobals
-    - err113
-    - nolintlint
-    - wrapcheck
-    - varnamelen
-    - testpackage
-    - tenv
-    - tagliatelle
-    - stylecheck
-    - paralleltest
-    - nonamedreturns
-    - nlreturn
-    - nakedret
-    - musttag
-    - maintidx
-    - ireturn
-    - exhaustruct
-    - gosec
-    - godot
-    - gocyclo
-    - dogsled
-    - tparallel
-    - thelper
-    - mnd #way to many false positives
-    - nilnil
-    - nilerr
-    - interfacebloat
-    - forcetypeassert
-    - gomoddirectives
-    - testifylint # way to many issues to fix right now, however it is a great linter for better test errors
-    - inamedparam # opinionated style
-linters-settings:
-  errcheck:
-    check-type-assertions: true
-  gocyclo:
-    min-complexity: 35
-  gofmt:
-    rewrite-rules:
-      - pattern: 'interface{}'
-        replacement: 'any'
-  revive:
+  enable:
+    - asasalint
+    - asciicheck
+    - bidichk
+    - bodyclose
+    - canonicalheader
+    - containedctx
+    - contextcheck
+    - copyloopvar
+    - decorder
+    - dupl
+    - dupword
+    - durationcheck
+    - exptostd
+    - fatcontext
+    - forbidigo
+    - ginkgolinter
+    - gocheckcompilerdirectives
+    - gochecksumtype
+    - gocritic
+    - goprintffuncname
+    - gosmopolitan
+    - iface
+    - intrange
+    - makezero
+    - mirror
+    - misspell
+    - nilnesserr
+    - noctx
+    - nosprintfhostport
+    - perfsprint
+    - prealloc
+    - predeclared
+    - reassign
+    - recvcheck
+    - revive
+    - unconvert
+    - unparam
+    - usestdlibvars
+    - usetesting
+    - wastedassign
+    - whitespace
+  settings:
+    errcheck:
+      check-type-assertions: true
+    gocyclo:
+      min-complexity: 35
+    revive:
+      rules:
+        - name: dot-imports
+          disabled: true
+    staticcheck:
+      checks:
+        - all
+        - -ST1003 # https://staticcheck.dev/docs/checks/#ST1003 Poorly chosen identifier.
+        - -QF1008 # https://staticcheck.dev/docs/checks/#QF1008 Omit embedded fields from selector expression.
+  exclusions:
+    generated: strict
+    presets:
+      - comments
+      - common-false-positives
+      - std-error-handling
     rules:
-      - name: dot-imports
-        disabled: true
-
-issues:
-    # Excluding configuration per-path, per-linter, per-text and per-source
-  exclude-rules:
-    # Exclude some linters from running on tests files.
-    - path: _test\.go
-      linters:
-        - dupl
-        - perfsprint
-    # Exclude "should pass the context parameter" for libimage.LookupImage because of backward compatibility.
-    - path: "libimage"
-      text: "LookupImage"
-      linters:
-        - contextcheck
+      - linters:
+          - dupl
+          - perfsprint
+        path: _test\.go
+      - linters:
+          - contextcheck
+        path: libimage
+        text: LookupImage
diff --git a/docs/containers.conf.5.md b/docs/containers.conf.5.md
index f9ab7cef..8551cb92 100644
--- a/docs/containers.conf.5.md
+++ b/docs/containers.conf.5.md
@@ -199,7 +199,12 @@ container. The special value “none” can be specified to disable creation of
 **env**=["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
 
 Environment variable list for the container process, used for passing
-environment variables to the container.
+environment variables to the container. If a variable is listed without a value,
+the value is copied from the host environment.
+
+Note that this is only used when a container is created, not with subsequent
+commands like `podman exec`. This prevents variables in the config file from
+overwriting values specified on the command line when the container was created.
 
 **env_host**=false
 
diff --git a/go.mod b/go.mod
index 90aa9d10..48aa3e7e 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,7 @@ module github.com/containers/common
 
 // Warning: Ensure the "go" and "toolchain" versions match exactly to prevent unwanted auto-updates
 
-go 1.23.0
+go 1.23.3
 
 require (
 	github.com/BurntSushi/toml v1.5.0
@@ -11,7 +11,7 @@ require (
 	github.com/containerd/platforms v0.2.1
 	github.com/containernetworking/cni v1.2.3
 	github.com/containernetworking/plugins v1.6.2
-	github.com/containers/image/v5 v5.34.3-0.20250311194052-d84dbab374e7
+	github.com/containers/image/v5 v5.34.3-0.20250324170122-cfeba44147fc
 	github.com/containers/ocicrypt v1.2.1
 	github.com/containers/storage v1.57.3-0.20250310120440-ab85543c3c6a
 	github.com/coreos/go-systemd/v22 v22.5.0
@@ -35,7 +35,7 @@ require (
 	github.com/opencontainers/runtime-spec v1.2.1
 	github.com/opencontainers/runtime-tools v0.9.1-0.20241108202711-f7e3563b0271
 	github.com/opencontainers/selinux v1.12.0
-	github.com/pkg/sftp v1.13.8
+	github.com/pkg/sftp v1.13.9
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
 	github.com/seccomp/libseccomp-golang v0.10.0
 	github.com/sirupsen/logrus v1.9.3
@@ -70,8 +70,8 @@ require (
 	github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
 	github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
 	github.com/distribution/reference v0.6.0 // indirect
-	github.com/docker/docker v28.0.1+incompatible // indirect
-	github.com/docker/docker-credential-helpers v0.9.2 // indirect
+	github.com/docker/docker v28.0.2+incompatible // indirect
+	github.com/docker/docker-credential-helpers v0.9.3 // indirect
 	github.com/docker/go-connections v0.5.0 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/go-jose/go-jose/v4 v4.0.5 // indirect
@@ -92,7 +92,7 @@ require (
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/google/go-cmp v0.7.0 // indirect
-	github.com/google/go-containerregistry v0.20.2 // indirect
+	github.com/google/go-containerregistry v0.20.3 // indirect
 	github.com/google/go-intervals v0.0.2 // indirect
 	github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
 	github.com/google/uuid v1.6.0 // indirect
@@ -123,13 +123,13 @@ require (
 	github.com/proglottis/gpgme v0.1.4 // indirect
 	github.com/rivo/uniseg v0.4.7 // indirect
 	github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
-	github.com/sigstore/fulcio v1.6.4 // indirect
+	github.com/sigstore/fulcio v1.6.6 // indirect
 	github.com/sigstore/protobuf-specs v0.4.0 // indirect
 	github.com/sigstore/rekor v1.3.9 // indirect
-	github.com/sigstore/sigstore v1.8.15 // indirect
+	github.com/sigstore/sigstore v1.9.1 // indirect
 	github.com/smallstep/pkcs7 v0.1.1 // indirect
 	github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
-	github.com/sylabs/sif/v2 v2.20.2 // indirect
+	github.com/sylabs/sif/v2 v2.21.1 // indirect
 	github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
 	github.com/tchap/go-patricia/v2 v2.3.2 // indirect
 	github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
@@ -139,15 +139,16 @@ require (
 	github.com/vishvananda/netns v0.0.4 // indirect
 	go.mongodb.org/mongo-driver v1.14.0 // indirect
 	go.opencensus.io v0.24.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
-	go.opentelemetry.io/otel v1.32.0 // indirect
-	go.opentelemetry.io/otel/metric v1.32.0 // indirect
-	go.opentelemetry.io/otel/trace v1.32.0 // indirect
+	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
+	go.opentelemetry.io/otel v1.33.0 // indirect
+	go.opentelemetry.io/otel/metric v1.33.0 // indirect
+	go.opentelemetry.io/otel/trace v1.33.0 // indirect
 	golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 // indirect
 	golang.org/x/net v0.37.0 // indirect
 	golang.org/x/text v0.23.0 // indirect
 	golang.org/x/tools v0.30.0 // indirect
-	google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
 	google.golang.org/grpc v1.70.0 // indirect
 	google.golang.org/protobuf v1.36.5 // indirect
diff --git a/go.sum b/go.sum
index 02c2ace3..abf51568 100644
--- a/go.sum
+++ b/go.sum
@@ -61,8 +61,8 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F
 github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M=
 github.com/containernetworking/plugins v1.6.2 h1:pqP8Mq923TLyef5g97XfJ/xpDeVek4yF8A4mzy9Tc4U=
 github.com/containernetworking/plugins v1.6.2/go.mod h1:SP5UG3jDO9LtmfbBJdP+nl3A1atOtbj2MBOYsnaxy64=
-github.com/containers/image/v5 v5.34.3-0.20250311194052-d84dbab374e7 h1:DqNRPDES8oT32Fk2puucIsTnUbPkhKs8Ozo6nuzQjEM=
-github.com/containers/image/v5 v5.34.3-0.20250311194052-d84dbab374e7/go.mod h1:hq675fbWkn/bGJwXNXysDu1PQWMOL9P4i2yDvZlSRdA=
+github.com/containers/image/v5 v5.34.3-0.20250324170122-cfeba44147fc h1:BWIXSYcurWZSofN+3S4OayAiY8Q+5H7IbrD2lIqVQZ8=
+github.com/containers/image/v5 v5.34.3-0.20250324170122-cfeba44147fc/go.mod h1:aSFpjJABQnSOvpe9D+9nSEjCqrg3OzDZgl+BfCPPBq4=
 github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
 github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
 github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=
@@ -84,14 +84,14 @@ github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWh
 github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
 github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
 github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs=
-github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v28.0.2+incompatible h1:cRPZ77FK3/IXTAIQQj1vmhlxiLS5m+MIUDwS6f57lrE=
+github.com/docker/cli v28.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
 github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0=
-github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker-credential-helpers v0.9.2 h1:50JF7ADQiHdAVBRtg/vy883Y4U5+5GmPOBNtUU+X+6A=
-github.com/docker/docker-credential-helpers v0.9.2/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
+github.com/docker/docker v28.0.2+incompatible h1:9BILleFwug5FSSqWBgVevgL3ewDJfWWWyZVqlDMttE8=
+github.com/docker/docker v28.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
+github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
 github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
 github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
 github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
@@ -168,8 +168,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
-github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo=
-github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
+github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
+github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
 github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
 github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -181,8 +181,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
 github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -271,8 +271,8 @@ github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqw
 github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/sftp v1.13.8 h1:Xt7eJ/xqXv7s0VuzFw7JXhZj6Oc1zI6l4GK8KP9sFB0=
-github.com/pkg/sftp v1.13.8/go.mod h1:DmvEkvKE2lshEeuo2JMp06yqcx9HVnR7e3zqQl42F3U=
+github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
+github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -283,8 +283,8 @@ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/j
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
 github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY=
-github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI=
+github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
+github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
 github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
 github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -293,8 +293,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
 github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
-github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
 github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
 github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
 github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY=
@@ -303,14 +303,14 @@ github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3
 github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw=
 github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
 github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
-github.com/sigstore/fulcio v1.6.4 h1:d86obfxUAG3Y6CYwOx1pdwCZwKmROB6w6927pKOVIRY=
-github.com/sigstore/fulcio v1.6.4/go.mod h1:Y6bn3i3KGhXpaHsAtYP3Z4Np0+VzCo1fLv8Ci6mbPDs=
+github.com/sigstore/fulcio v1.6.6 h1:XaMYX6TNT+8n7Npe8D94nyZ7/ERjEsNGFC+REdi/wzw=
+github.com/sigstore/fulcio v1.6.6/go.mod h1:BhQ22lwaebDgIxVBEYOOqLRcN5+xOV+C9bh/GUXRhOk=
 github.com/sigstore/protobuf-specs v0.4.0 h1:yoZbdh0kZYKOSiVbYyA8J3f2wLh5aUk2SQB7LgAfIdU=
 github.com/sigstore/protobuf-specs v0.4.0/go.mod h1:FKW5NYhnnFQ/Vb9RKtQk91iYd0MKJ9AxyqInEwU6+OI=
 github.com/sigstore/rekor v1.3.9 h1:sUjRpKVh/hhgqGMs0t+TubgYsksArZ6poLEC3MsGAzU=
 github.com/sigstore/rekor v1.3.9/go.mod h1:xThNUhm6eNEmkJ/SiU/FVU7pLY2f380fSDZFsdDWlcM=
-github.com/sigstore/sigstore v1.8.15 h1:9HHnZmxjPQSTPXTCZc25HDxxSTWwsGMh/ZhWZZ39maU=
-github.com/sigstore/sigstore v1.8.15/go.mod h1:+Wa5mrG6A+Gss516YC9owy10q3IazqIRe0y1EoQRHHM=
+github.com/sigstore/sigstore v1.9.1 h1:bNMsfFATsMPaagcf+uppLk4C9rQZ2dh5ysmCxQBYWaw=
+github.com/sigstore/sigstore v1.9.1/go.mod h1:zUoATYzR1J3rLNp3jmp4fzIJtWdhC3ZM6MnpcBtnsE4=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
@@ -333,8 +333,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/sylabs/sif/v2 v2.20.2 h1:HGEPzauCHhIosw5o6xmT3jczuKEuaFzSfdjAsH33vYw=
-github.com/sylabs/sif/v2 v2.20.2/go.mod h1:WyYryGRaR4Wp21SAymm5pK0p45qzZCSRiZMFvUZiuhc=
+github.com/sylabs/sif/v2 v2.21.1 h1:GZ0b5//AFAqJEChd8wHV/uSKx/l1iuGYwjR8nx+4wPI=
+github.com/sylabs/sif/v2 v2.21.1/go.mod h1:YoqEGQnb5x/ItV653bawXHZJOXQaEWpGwHsSD3YePJI=
 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM=
@@ -366,24 +366,26 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd
 go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
 go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
-go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
-go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4=
-go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
-go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
-go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
-go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
+go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
+go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
+go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
+go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
+go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
+go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
 go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
 go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
-go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
-go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
-go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
-go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
+go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
+go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
+go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
+go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -508,8 +510,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
-google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
+google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb h1:B7GIB7sr443wZ/EAEl7VZjmh1V6qzkt5V+RYcUYtS1U=
+google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:E5//3O5ZIG2l71Xnt+P/CYUY8Bxs8E7WMoZ9tlcMbAY=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
diff --git a/libimage/copier.go b/libimage/copier.go
index 5a15c282..bac694fe 100644
--- a/libimage/copier.go
+++ b/libimage/copier.go
@@ -489,7 +489,7 @@ func (c *Copier) copyToStorage(ctx context.Context, source, destination types.Im
 	var resolvedReference types.ImageReference
 	_, err := c.copyInternal(ctx, source, destination, &resolvedReference)
 	if err != nil {
-		return nil, fmt.Errorf("internal error: unable to copy from source %s: %w", source, err)
+		return nil, fmt.Errorf("internal error: unable to copy from source %s: %w", transports.ImageName(source), err)
 	}
 	if resolvedReference == nil {
 		return nil, fmt.Errorf("internal error: After attempting to copy %s, resolvedReference is nil", source)
diff --git a/libimage/history.go b/libimage/history.go
index 845f4088..096280fc 100644
--- a/libimage/history.go
+++ b/libimage/history.go
@@ -25,7 +25,7 @@ func (i *Image) History(ctx context.Context) ([]ImageHistory, error) {
 		return nil, err
 	}
 
-	layerTree, err := i.runtime.newFreshLayerTree()
+	layerTree, err := i.runtime.newFreshLayerTree(ctx)
 	if err != nil {
 		return nil, err
 	}
diff --git a/libimage/image.go b/libimage/image.go
index d680537b..8f300e83 100644
--- a/libimage/image.go
+++ b/libimage/image.go
@@ -191,13 +191,21 @@ func (i *Image) IsReadOnly() bool {
 }
 
 // IsDangling returns true if the image is dangling, that is an untagged image
-// without children.
+// without children and not used in a manifest list.
 func (i *Image) IsDangling(ctx context.Context) (bool, error) {
-	return i.isDangling(ctx, nil)
+	images, layers, err := i.runtime.getImagesAndLayers()
+	if err != nil {
+		return false, err
+	}
+	tree, err := i.runtime.newLayerTreeFromData(ctx, images, layers, true)
+	if err != nil {
+		return false, err
+	}
+	return i.isDangling(ctx, tree)
 }
 
 // isDangling returns true if the image is dangling, that is an untagged image
-// without children.  If tree is nil, it will created for this invocation only.
+// without children and not used in a manifest list.  If tree is nil, it will created for this invocation only.
 func (i *Image) isDangling(ctx context.Context, tree *layerTree) (bool, error) {
 	if len(i.Names()) > 0 {
 		return false, nil
@@ -206,7 +214,8 @@ func (i *Image) isDangling(ctx context.Context, tree *layerTree) (bool, error) {
 	if err != nil {
 		return false, err
 	}
-	return len(children) == 0, nil
+	_, usedInManfiestList := tree.manifestListDigests[i.Digest()]
+	return (len(children) == 0 && !usedInManfiestList), nil
 }
 
 // IsIntermediate returns true if the image is an intermediate image, that is
@@ -258,7 +267,7 @@ func (i *Image) TopLayer() string {
 
 // Parent returns the parent image or nil if there is none
 func (i *Image) Parent(ctx context.Context) (*Image, error) {
-	tree, err := i.runtime.newFreshLayerTree()
+	tree, err := i.runtime.newFreshLayerTree(ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -292,7 +301,7 @@ func (i *Image) Children(ctx context.Context) ([]*Image, error) {
 // created for this invocation only.
 func (i *Image) getChildren(ctx context.Context, all bool, tree *layerTree) ([]*Image, error) {
 	if tree == nil {
-		t, err := i.runtime.newFreshLayerTree()
+		t, err := i.runtime.newFreshLayerTree(ctx)
 		if err != nil {
 			return nil, err
 		}
@@ -454,13 +463,13 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
 	skipRemove := false
 	numNames := len(i.Names())
 
-	// NOTE: the `numNames == 1` check is not only a performance
+	// NOTE: the `numNames != 1` check is not only a performance
 	// optimization but also preserves existing Podman/Docker behaviour.
 	// If image "foo" is used by a container and has only this tag/name,
 	// an `rmi foo` will not untag "foo" but instead attempt to remove the
 	// entire image.  If there's a container using "foo", we should get an
 	// error.
-	if !(referencedBy == "" || numNames == 1) {
+	if referencedBy != "" && numNames != 1 {
 		byID := strings.HasPrefix(i.ID(), referencedBy)
 		byDigest := strings.HasPrefix(referencedBy, "sha256:")
 		if !options.Force {
@@ -789,27 +798,25 @@ func (i *Image) Mount(_ context.Context, mountOptions []string, mountLabel strin
 // Mountpoint returns the path to image's mount point.  The path is empty if
 // the image is not mounted.
 func (i *Image) Mountpoint() (string, error) {
-	mountedTimes, err := i.runtime.store.Mounted(i.TopLayer())
-	if err != nil || mountedTimes == 0 {
-		if errors.Is(err, storage.ErrLayerUnknown) {
-			// Can happen, Podman did it, but there's no
-			// explanation why.
-			err = nil
+	for _, layerID := range append([]string{i.TopLayer()}, i.storageImage.MappedTopLayers...) {
+		mountedTimes, err := i.runtime.store.Mounted(layerID)
+		if err != nil {
+			if errors.Is(err, storage.ErrLayerUnknown) {
+				// Can happen, Podman did it, but there's no
+				// explanation why.
+				continue
+			}
+			return "", err
+		}
+		if mountedTimes > 0 {
+			layer, err := i.runtime.store.Layer(layerID)
+			if err != nil {
+				return "", err
+			}
+			return filepath.EvalSymlinks(layer.MountPoint)
 		}
-		return "", err
-	}
-
-	layer, err := i.runtime.store.Layer(i.TopLayer())
-	if err != nil {
-		return "", err
-	}
-
-	mountPoint, err := filepath.EvalSymlinks(layer.MountPoint)
-	if err != nil {
-		return "", err
 	}
-
-	return mountPoint, nil
+	return "", nil
 }
 
 // Unmount the image.  Use force to ignore the reference counter and forcefully
diff --git a/libimage/image_tree.go b/libimage/image_tree.go
index 9628a319..0c30b8a5 100644
--- a/libimage/image_tree.go
+++ b/libimage/image_tree.go
@@ -3,6 +3,7 @@
 package libimage
 
 import (
+	"context"
 	"fmt"
 	"strings"
 
@@ -13,7 +14,7 @@ import (
 // Tree generates a tree for the specified image and its layers.  Use
 // `traverseChildren` to traverse the layers of all children.  By default, only
 // layers of the image are printed.
-func (i *Image) Tree(traverseChildren bool) (string, error) {
+func (i *Image) Tree(ctx context.Context, traverseChildren bool) (string, error) {
 	// NOTE: a string builder prevents us from copying to much data around
 	// and compile the string when and where needed.
 	sb := &strings.Builder{}
@@ -37,7 +38,7 @@ func (i *Image) Tree(traverseChildren bool) (string, error) {
 		fmt.Fprintf(sb, "No Image Layers")
 	}
 
-	layerTree, err := i.runtime.newFreshLayerTree()
+	layerTree, err := i.runtime.newFreshLayerTree(ctx)
 	if err != nil {
 		return "", err
 	}
diff --git a/libimage/layer_tree.go b/libimage/layer_tree.go
index 33741bd0..2c548933 100644
--- a/libimage/layer_tree.go
+++ b/libimage/layer_tree.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/containers/storage"
 	storageTypes "github.com/containers/storage/types"
+	digest "github.com/opencontainers/go-digest"
 	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/sirupsen/logrus"
 )
@@ -22,6 +23,10 @@ type layerTree struct {
 	// emptyImages do not have any top-layer so we cannot create a
 	// *layerNode for them.
 	emptyImages []*Image
+	// manifestList keep track of images based on their digest.
+	// Library will use this map when checking if a image is dangling.
+	// If an image is used in a manifestList it is NOT dangling
+	manifestListDigests map[digest.Digest]struct{}
 }
 
 // node returns a layerNode for the specified layerID.
@@ -90,20 +95,21 @@ func (l *layerNode) repoTags() ([]string, error) {
 }
 
 // newFreshLayerTree extracts a layerTree from consistent layers and images in the local storage.
-func (r *Runtime) newFreshLayerTree() (*layerTree, error) {
+func (r *Runtime) newFreshLayerTree(ctx context.Context) (*layerTree, error) {
 	images, layers, err := r.getImagesAndLayers()
 	if err != nil {
 		return nil, err
 	}
-	return r.newLayerTreeFromData(images, layers)
+	return r.newLayerTreeFromData(ctx, images, layers, false)
 }
 
 // newLayerTreeFromData extracts a layerTree from the given the layers and images.
 // The caller is responsible for (layers, images) being consistent.
-func (r *Runtime) newLayerTreeFromData(images []*Image, layers []storage.Layer) (*layerTree, error) {
+func (r *Runtime) newLayerTreeFromData(ctx context.Context, images []*Image, layers []storage.Layer, generateManifestDigestList bool) (*layerTree, error) {
 	tree := layerTree{
-		nodes:    make(map[string]*layerNode),
-		ociCache: make(map[string]*ociv1.Image),
+		nodes:               make(map[string]*layerNode),
+		ociCache:            make(map[string]*ociv1.Image),
+		manifestListDigests: make(map[digest.Digest]struct{}),
 	}
 
 	// First build a tree purely based on layer information.
@@ -124,6 +130,21 @@ func (r *Runtime) newLayerTreeFromData(images []*Image, layers []storage.Layer)
 		topLayer := img.TopLayer()
 		if topLayer == "" {
 			tree.emptyImages = append(tree.emptyImages, img)
+			// When img is a manifest list, cache the lists of
+			// digests refereenced in manifest list. Digests can
+			// be used to check for dangling images.
+			if !generateManifestDigestList {
+				continue
+			}
+			if manifestList, _ := img.IsManifestList(ctx); manifestList {
+				mlist, err := img.ToManifestList()
+				if err != nil {
+					return nil, err
+				}
+				for _, digest := range mlist.list.Instances() {
+					tree.manifestListDigests[digest] = struct{}{}
+				}
+			}
 			continue
 		}
 		node, exists := tree.nodes[topLayer]
diff --git a/libimage/load.go b/libimage/load.go
index 48f255e8..2f69fd63 100644
--- a/libimage/load.go
+++ b/libimage/load.go
@@ -115,7 +115,7 @@ func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) (
 
 	// Give a decent error message if nothing above worked.
 	// we want the colon here for the multiline error
-	//nolint:revive
+	//nolint:revive,staticcheck
 	loadError := errors.New("payload does not match any of the supported image formats:")
 	for _, err := range loadErrors {
 		loadError = fmt.Errorf("%v\n * %v", loadError, err)
diff --git a/libimage/normalize.go b/libimage/normalize.go
index b00af66a..1dab82fe 100644
--- a/libimage/normalize.go
+++ b/libimage/normalize.go
@@ -30,7 +30,7 @@ func NormalizeName(name string) (reference.Named, error) {
 
 	// Enforce "localhost" if needed.
 	registry := reference.Domain(named)
-	if !(strings.ContainsAny(registry, ".:") || registry == "localhost") {
+	if !strings.ContainsAny(registry, ".:") && registry != "localhost" {
 		name = toLocalImageName(ref.String())
 	}
 
diff --git a/libimage/runtime.go b/libimage/runtime.go
index f7c9b2bf..1e01a5f0 100644
--- a/libimage/runtime.go
+++ b/libimage/runtime.go
@@ -634,7 +634,7 @@ func (r *Runtime) ListImages(ctx context.Context, options *ListImagesOptions) ([
 
 	var tree *layerTree
 	if needsLayerTree {
-		tree, err = r.newLayerTreeFromData(images, snapshot.Layers)
+		tree, err = r.newLayerTreeFromData(ctx, images, snapshot.Layers, true)
 		if err != nil {
 			return nil, err
 		}
diff --git a/libimage/search.go b/libimage/search.go
index 6ab016b3..2745b52b 100644
--- a/libimage/search.go
+++ b/libimage/search.go
@@ -217,7 +217,7 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri
 	paramsArr := []SearchResult{}
 	for i := range limit {
 		// Check whether query matches filters
-		if !(filterMatchesAutomatedFilter(&options.Filter, results[i]) && filterMatchesOfficialFilter(&options.Filter, results[i]) && filterMatchesStarFilter(&options.Filter, results[i])) {
+		if !filterMatchesAutomatedFilter(&options.Filter, results[i]) || !filterMatchesOfficialFilter(&options.Filter, results[i]) || !filterMatchesStarFilter(&options.Filter, results[i]) {
 			continue
 		}
 		official := ""
diff --git a/libnetwork/cni/network.go b/libnetwork/cni/network.go
index 7e001fab..ab3a05b5 100644
--- a/libnetwork/cni/network.go
+++ b/libnetwork/cni/network.go
@@ -191,7 +191,7 @@ func (n *cniNetwork) loadNetworks() error {
 		}
 
 		if !types.NameRegex.MatchString(conf.Name) {
-			logrus.Warnf("CNI config list %s has invalid name, skipping: %v", file, types.RegexError)
+			logrus.Warnf("CNI config list %s has invalid name, skipping: %v", file, types.ErrInvalidName)
 			continue
 		}
 
diff --git a/libnetwork/internal/util/bridge.go b/libnetwork/internal/util/bridge.go
index 44cd555c..e69c3882 100644
--- a/libnetwork/internal/util/bridge.go
+++ b/libnetwork/internal/util/bridge.go
@@ -19,7 +19,7 @@ func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet,
 			}
 		}
 		if !types.NameRegex.MatchString(network.NetworkInterface) {
-			return fmt.Errorf("bridge name %s invalid: %w", network.NetworkInterface, types.RegexError)
+			return fmt.Errorf("bridge name %s invalid: %w", network.NetworkInterface, types.ErrInvalidName)
 		}
 	} else {
 		var err error
diff --git a/libnetwork/internal/util/create.go b/libnetwork/internal/util/create.go
index 376a5731..42609d1b 100644
--- a/libnetwork/internal/util/create.go
+++ b/libnetwork/internal/util/create.go
@@ -23,7 +23,7 @@ func CommonNetworkCreate(n NetUtil, network *types.Network) error {
 	// validate the name when given
 	if network.Name != "" {
 		if !types.NameRegex.MatchString(network.Name) {
-			return fmt.Errorf("network name %s invalid: %w", network.Name, types.RegexError)
+			return fmt.Errorf("network name %s invalid: %w", network.Name, types.ErrInvalidName)
 		}
 		if _, err := n.Network(network.Name); err == nil {
 			return fmt.Errorf("network name %s already used: %w", network.Name, types.ErrNetworkExists)
diff --git a/libnetwork/netavark/config.go b/libnetwork/netavark/config.go
index 4916f725..6c17bd0a 100644
--- a/libnetwork/netavark/config.go
+++ b/libnetwork/netavark/config.go
@@ -294,10 +294,7 @@ func createIpvlanOrMacvlan(network *types.Network) error {
 	}
 
 	driver := network.Driver
-	isMacVlan := true
-	if driver == types.IPVLANNetworkDriver {
-		isMacVlan = false
-	}
+	isMacVlan := driver != types.IPVLANNetworkDriver
 
 	// always turn dns off with macvlan, it is not implemented in netavark
 	// and makes little sense to support with macvlan
diff --git a/libnetwork/netavark/network.go b/libnetwork/netavark/network.go
index 985d0db2..cf8b0d49 100644
--- a/libnetwork/netavark/network.go
+++ b/libnetwork/netavark/network.go
@@ -248,7 +248,7 @@ func (n *netavarkNetwork) loadNetworks() error {
 		}
 
 		if !types.NameRegex.MatchString(network.Name) {
-			logrus.Warnf("Network config %q has invalid name: %q, skipping: %v", path, network.Name, types.RegexError)
+			logrus.Warnf("Network config %q has invalid name: %q, skipping: %v", path, network.Name, types.ErrInvalidName)
 			continue
 		}
 
diff --git a/libnetwork/slirp4netns/slirp4netns.go b/libnetwork/slirp4netns/slirp4netns.go
index 524cabc4..afb54f60 100644
--- a/libnetwork/slirp4netns/slirp4netns.go
+++ b/libnetwork/slirp4netns/slirp4netns.go
@@ -682,7 +682,7 @@ func openSlirp4netnsPort(apiSocket, proto, hostip string, hostport, guestport ui
 	if err != nil {
 		return fmt.Errorf("cannot marshal JSON for slirp4netns: %w", err)
 	}
-	if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil {
+	if _, err := fmt.Fprintf(conn, "%s\n", data); err != nil {
 		return fmt.Errorf("cannot write to control socket %s: %w", apiSocket, err)
 	}
 	//nolint:errcheck // This cast should never fail, if it does we get a interface
diff --git a/libnetwork/types/define.go b/libnetwork/types/define.go
index 0bc68810..e5929c3e 100644
--- a/libnetwork/types/define.go
+++ b/libnetwork/types/define.go
@@ -24,8 +24,10 @@ var (
 	// NameRegex is a regular expression to validate names.
 	// This must NOT be changed.
 	NameRegex = regexp.Delayed("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$")
-	// RegexError is thrown in presence of an invalid name.
-	RegexError = fmt.Errorf("names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: %w", ErrInvalidArg) // nolint:revive // This lint is new and we do not want to break the API.
+	// ErrInvalidName is thrown in presence of an invalid name.
+	ErrInvalidName = fmt.Errorf("names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: %w", ErrInvalidArg)
+	// Deprecated: use [ErrInvalidName] instead.
+	RegexError = ErrInvalidName
 
 	// NotHexRegex is a regular expression to check if a string is
 	// a hexadecimal string.
diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go
index a3d333a9..4bcd490d 100644
--- a/pkg/auth/auth.go
+++ b/pkg/auth/auth.go
@@ -173,10 +173,10 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
 	if opts.StdinPassword {
 		var stdinPasswordStrBuilder strings.Builder
 		if opts.Password != "" {
-			return errors.New("Can't specify both --password-stdin and --password")
+			return errors.New("can't specify both --password-stdin and --password")
 		}
 		if opts.Username == "" {
-			return errors.New("Must provide --username with --password-stdin")
+			return errors.New("must provide --username with --password-stdin")
 		}
 		scanner := bufio.NewScanner(opts.Stdin)
 		for scanner.Scan() {
diff --git a/pkg/cgroups/utils_linux.go b/pkg/cgroups/utils_linux.go
index 848a59d2..505ac1b2 100644
--- a/pkg/cgroups/utils_linux.go
+++ b/pkg/cgroups/utils_linux.go
@@ -221,7 +221,7 @@ func MoveUnderCgroup(cgroup, subtree string, processes []uint32) error {
 		}
 
 		// root cgroup, skip it
-		if parts[2] == "/" && !(unifiedMode && parts[1] == "") {
+		if parts[2] == "/" && (!unifiedMode || parts[1] != "") {
 			continue
 		}
 
@@ -261,7 +261,7 @@ func MoveUnderCgroup(cgroup, subtree string, processes []uint32) error {
 
 		if len(processes) > 0 {
 			for _, pid := range processes {
-				if _, err := f.WriteString(fmt.Sprintf("%d\n", pid)); err != nil {
+				if _, err := fmt.Fprintf(f, "%d\n", pid); err != nil {
 					logrus.Debugf("Cannot move process %d to cgroup %q: %v", pid, newCgroup, err)
 				}
 			}
diff --git a/pkg/configmaps/configmaps.go b/pkg/configmaps/configmaps.go
index 092cb015..8fc831c8 100644
--- a/pkg/configmaps/configmaps.go
+++ b/pkg/configmaps/configmaps.go
@@ -132,7 +132,7 @@ func (s *ConfigMapManager) Store(name string, data []byte, driverType string, dr
 		return "", err
 	}
 
-	if !(len(data) > 0 && len(data) < maxConfigMapSize) {
+	if len(data) == 0 || len(data) >= maxConfigMapSize {
 		return "", errDataSize
 	}
 
diff --git a/pkg/parse/parse_unix.go b/pkg/parse/parse_unix.go
index 86563b3e..3e4e1d14 100644
--- a/pkg/parse/parse_unix.go
+++ b/pkg/parse/parse_unix.go
@@ -17,7 +17,7 @@ func DeviceFromPath(device string) ([]devices.Device, error) {
 		return nil, err
 	}
 	if unshare.IsRootless() && src != dst {
-		return nil, fmt.Errorf("Renaming device %s to %s is not supported in rootless containers", src, dst)
+		return nil, fmt.Errorf("renaming device %s to %s is not supported in rootless containers", src, dst)
 	}
 	srcInfo, err := os.Stat(src)
 	if err != nil {
diff --git a/pkg/retry/retry.go b/pkg/retry/retry.go
index d47e47e1..f4c6b135 100644
--- a/pkg/retry/retry.go
+++ b/pkg/retry/retry.go
@@ -5,10 +5,12 @@ import (
 	"io"
 	"math"
 	"net"
+	"net/http"
 	"net/url"
 	"syscall"
 	"time"
 
+	"github.com/containers/image/v5/docker"
 	"github.com/docker/distribution/registry/api/errcode"
 	errcodev2 "github.com/docker/distribution/registry/api/v2"
 	"github.com/hashicorp/go-multierror"
@@ -47,7 +49,7 @@ func IfNecessary(ctx context.Context, operation func() error, options *Options)
 		logrus.Warnf("Failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, options.MaxRetry, err)
 		select {
 		case <-time.After(delay):
-			break
+			// Do nothing.
 		case <-ctx.Done():
 			return err
 		}
@@ -81,6 +83,13 @@ func IsErrorRetryable(err error) bool {
 			return false
 		}
 		return true
+	case docker.UnexpectedHTTPStatusError:
+		// Retry on 502, 502 and 503 http server errors, they appear to be quite common in the field.
+		// https://github.com/containers/common/issues/2299
+		if e.StatusCode >= http.StatusBadGateway && e.StatusCode <= http.StatusGatewayTimeout {
+			return true
+		}
+		return false
 	case *net.OpError:
 		return IsErrorRetryable(e.Err)
 	case *url.Error: // This includes errors returned by the net/http client.
diff --git a/pkg/secrets/secrets.go b/pkg/secrets/secrets.go
index 113c6c43..7d8d33a1 100644
--- a/pkg/secrets/secrets.go
+++ b/pkg/secrets/secrets.go
@@ -166,7 +166,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
 		return "", err
 	}
 
-	if !(len(data) > 0 && len(data) < maxSecretSize) {
+	if len(data) == 0 || len(data) >= maxSecretSize {
 		return "", errDataSize
 	}
 	var secr *Secret
diff --git a/pkg/subscriptions/subscriptions.go b/pkg/subscriptions/subscriptions.go
index 2c78cf1e..202eb6d3 100644
--- a/pkg/subscriptions/subscriptions.go
+++ b/pkg/subscriptions/subscriptions.go
@@ -322,7 +322,7 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string
 func containerHasEtcSystemFips(subscriptionsDir, mountPoint string) (bool, error) {
 	containerEtc, err := securejoin.SecureJoin(mountPoint, "etc")
 	if err != nil {
-		return false, fmt.Errorf("Container /etc resolution error: %w", err)
+		return false, fmt.Errorf("container /etc resolution error: %w", err)
 	}
 	if fileutils.Lexists(filepath.Join(containerEtc, "system-fips")) != nil {
 		logrus.Debug("/etc/system-fips does not exist in the container, not creating /run/secrets/system-fips")
@@ -331,7 +331,7 @@ func containerHasEtcSystemFips(subscriptionsDir, mountPoint string) (bool, error
 
 	fipsFileTarget, err := securejoin.SecureJoin(mountPoint, "etc/system-fips")
 	if err != nil {
-		return false, fmt.Errorf("Container /etc/system-fips resolution error: %w", err)
+		return false, fmt.Errorf("container /etc/system-fips resolution error: %w", err)
 	}
 	if fipsFileTarget != filepath.Join(mountPoint, subscriptionsDir, "system-fips") {
 		logrus.Warnf("/etc/system-fips exists in the container, but is not a symlink to %[1]v/system-fips; not creating %[1]v/system-fips", subscriptionsDir)
@@ -448,24 +448,24 @@ func addFIPSMounts(mounts *[]rspec.Mount, containerRunDir, mountPoint, mountLabe
 	destPolicyConfig := "/etc/crypto-policies/config"
 	srcPolicyConfigOnHost, err := securejoin.SecureJoin(mountPoint, srcPolicyConfig)
 	if err != nil {
-		return fmt.Errorf("Could not expand %q in container: %w", srcPolicyConfig, err)
+		return fmt.Errorf("could not expand %q in container: %w", srcPolicyConfig, err)
 	}
 
 	if err = fileutils.Exists(srcPolicyConfigOnHost); err != nil {
 		if !errors.Is(err, os.ErrNotExist) {
-			return fmt.Errorf("Could not check whether %q exists in container: %w", srcPolicyConfig, err)
+			return fmt.Errorf("could not check whether %q exists in container: %w", srcPolicyConfig, err)
 		}
 
 		// /usr/share/crypto-policies/default-fips-config does not exist, let's create it ourselves
 		cryptoPoliciesConfigFile := filepath.Join(containerRunDir, "fips-config")
 		if err := os.WriteFile(cryptoPoliciesConfigFile, []byte("FIPS\n"), 0o644); err != nil {
-			return fmt.Errorf("Failed to write fips config file in container for FIPS mode: %w", err)
+			return fmt.Errorf("failed to write fips config file in container for FIPS mode: %w", err)
 		}
 		if err = label.Relabel(cryptoPoliciesConfigFile, mountLabel, false); err != nil {
-			return fmt.Errorf("Failed to apply correct labels on fips config file: %w", err)
+			return fmt.Errorf("failed to apply correct labels on fips config file: %w", err)
 		}
 		if err := os.Chown(cryptoPoliciesConfigFile, uid, gid); err != nil {
-			return fmt.Errorf("Failed to chown fips config file: %w", err)
+			return fmt.Errorf("failed to chown fips config file: %w", err)
 		}
 
 		srcPolicyConfigOnHost = cryptoPoliciesConfigFile
diff --git a/pkg/timetype/timestamp.go b/pkg/timetype/timestamp.go
index 519884c5..ce03c784 100644
--- a/pkg/timetype/timestamp.go
+++ b/pkg/timetype/timestamp.go
@@ -31,8 +31,9 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
 	}
 
 	var format string
-	// if the string has a Z or a + or three dashes use parse otherwise use parseinlocation
-	parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3)
+	// If the string has a Z, or a +, or three dashes,
+	// then use time.Parse, otherwise use time.ParseInLocation.
+	parseInLocation := !strings.ContainsAny(value, "zZ+") && strings.Count(value, "-") != 3
 
 	switch {
 	case strings.Contains(value, "."):
diff --git a/pkg/timezone/timezone.go b/pkg/timezone/timezone.go
index b82dc309..e6066145 100644
--- a/pkg/timezone/timezone.go
+++ b/pkg/timezone/timezone.go
@@ -20,10 +20,10 @@ import (
 // It returns the path of the created /etc/localtime file if needed.
 func ConfigureContainerTimeZone(timezone, containerRunDir, mountPoint, etcPath, containerID string) (localTimePath string, err error) {
 	var timezonePath string
-	switch {
-	case timezone == "":
+	switch timezone {
+	case "":
 		return "", nil
-	case timezone == "local":
+	case "local":
 		timezonePath, err = filepath.EvalSymlinks("/etc/localtime")
 		if err != nil {
 			return "", fmt.Errorf("finding local timezone for container %s: %w", containerID, err)
diff --git a/vendor/github.com/containers/image/v5/copy/multiple.go b/vendor/github.com/containers/image/v5/copy/multiple.go
index 009a067c..b0c107e8 100644
--- a/vendor/github.com/containers/image/v5/copy/multiple.go
+++ b/vendor/github.com/containers/image/v5/copy/multiple.go
@@ -83,7 +83,7 @@ func platformCompressionMap(list internalManifest.List, instanceDigests []digest
 			platformSet = set.New[string]()
 			res[platform] = platformSet
 		}
-		platformSet.AddSlice(instanceDetails.ReadOnly.CompressionAlgorithmNames)
+		platformSet.AddSeq(slices.Values(instanceDetails.ReadOnly.CompressionAlgorithmNames))
 	}
 	return res, nil
 }
diff --git a/vendor/github.com/containers/image/v5/copy/single.go b/vendor/github.com/containers/image/v5/copy/single.go
index 6aa4e760..f7aca838 100644
--- a/vendor/github.com/containers/image/v5/copy/single.go
+++ b/vendor/github.com/containers/image/v5/copy/single.go
@@ -6,6 +6,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"iter"
 	"maps"
 	"reflect"
 	"slices"
@@ -417,7 +418,7 @@ func (ic *imageCopier) compareImageDestinationManifestEqual(ctx context.Context,
 		}
 	}
 
-	algos, err := algorithmsByNames(compressionAlgos.Values())
+	algos, err := algorithmsByNames(compressionAlgos.All())
 	if err != nil {
 		return nil, err
 	}
@@ -552,7 +553,7 @@ func (ic *imageCopier) copyLayers(ctx context.Context) ([]compressiontypes.Algor
 	if srcInfosUpdated || layerDigestsDiffer(srcInfos, destInfos) {
 		ic.manifestUpdates.LayerInfos = destInfos
 	}
-	algos, err := algorithmsByNames(compressionAlgos.Values())
+	algos, err := algorithmsByNames(compressionAlgos.All())
 	if err != nil {
 		return nil, err
 	}
@@ -988,10 +989,10 @@ func computeDiffID(stream io.Reader, decompressor compressiontypes.DecompressorF
 	return digest.Canonical.FromReader(stream)
 }
 
-// algorithmsByNames returns slice of Algorithms from slice of Algorithm Names
-func algorithmsByNames(names []string) ([]compressiontypes.Algorithm, error) {
+// algorithmsByNames returns slice of Algorithms from a sequence of Algorithm Names
+func algorithmsByNames(names iter.Seq[string]) ([]compressiontypes.Algorithm, error) {
 	result := []compressiontypes.Algorithm{}
-	for _, name := range names {
+	for name := range names {
 		algo, err := compression.AlgorithmByName(name)
 		if err != nil {
 			return nil, err
diff --git a/vendor/github.com/containers/image/v5/docker/distribution_error.go b/vendor/github.com/containers/image/v5/docker/distribution_error.go
index 622d21fb..06a9593d 100644
--- a/vendor/github.com/containers/image/v5/docker/distribution_error.go
+++ b/vendor/github.com/containers/image/v5/docker/distribution_error.go
@@ -30,14 +30,25 @@ import (
 // errcode.Errors slice.
 var errNoErrorsInBody = errors.New("no error details found in HTTP response body")
 
-// unexpectedHTTPStatusError is returned when an unexpected HTTP status is
+// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
 // returned when making a registry api call.
-type unexpectedHTTPStatusError struct {
-	Status string
+type UnexpectedHTTPStatusError struct {
+	// StatusCode code as returned from the server, so callers can
+	// match the exact code to make certain decisions if needed.
+	StatusCode int
+	// status text as displayed in the error message, not exposed as callers should match the number.
+	status string
+}
+
+func (e UnexpectedHTTPStatusError) Error() string {
+	return fmt.Sprintf("received unexpected HTTP status: %s", e.status)
 }
 
-func (e *unexpectedHTTPStatusError) Error() string {
-	return fmt.Sprintf("received unexpected HTTP status: %s", e.Status)
+func newUnexpectedHTTPStatusError(resp *http.Response) UnexpectedHTTPStatusError {
+	return UnexpectedHTTPStatusError{
+		StatusCode: resp.StatusCode,
+		status:     resp.Status,
+	}
 }
 
 // unexpectedHTTPResponseError is returned when an expected HTTP status code
@@ -117,7 +128,7 @@ func handleErrorResponse(resp *http.Response) error {
 	case resp.StatusCode == http.StatusUnauthorized:
 		// Check for OAuth errors within the `WWW-Authenticate` header first
 		// See https://tools.ietf.org/html/rfc6750#section-3
-		for _, c := range parseAuthHeader(resp.Header) {
+		for c := range iterateAuthHeader(resp.Header) {
 			if c.Scheme == "bearer" {
 				var err errcode.Error
 				// codes defined at https://tools.ietf.org/html/rfc6750#section-3.1
@@ -146,5 +157,5 @@ func handleErrorResponse(resp *http.Response) error {
 		}
 		return err
 	}
-	return &unexpectedHTTPStatusError{Status: resp.Status}
+	return newUnexpectedHTTPStatusError(resp)
 }
diff --git a/vendor/github.com/containers/image/v5/docker/docker_client.go b/vendor/github.com/containers/image/v5/docker/docker_client.go
index 5da375a3..851d3e08 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_client.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_client.go
@@ -11,6 +11,7 @@ import (
 	"net/url"
 	"os"
 	"path/filepath"
+	"slices"
 	"strconv"
 	"strings"
 	"sync"
@@ -479,8 +480,7 @@ func (c *dockerClient) resolveRequestURL(path string) (*url.URL, error) {
 // returns the required scope to be used for fetching a new token.
 func needsRetryWithUpdatedScope(res *http.Response) (bool, *authScope) {
 	if res.StatusCode == http.StatusUnauthorized {
-		challenges := parseAuthHeader(res.Header)
-		for _, challenge := range challenges {
+		for challenge := range iterateAuthHeader(res.Header) {
 			if challenge.Scheme == "bearer" {
 				if errmsg, ok := challenge.Parameters["error"]; ok && errmsg == "insufficient_scope" {
 					if scope, ok := challenge.Parameters["scope"]; ok && scope != "" {
@@ -907,6 +907,10 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
 	}
 	tr := tlsclientconfig.NewTransport()
 	tr.TLSClientConfig = c.tlsClientConfig
+	// if set DockerProxyURL explicitly, use the DockerProxyURL instead of system proxy
+	if c.sys != nil && c.sys.DockerProxyURL != nil {
+		tr.Proxy = http.ProxyURL(c.sys.DockerProxyURL)
+	}
 	c.client = &http.Client{Transport: tr}
 
 	ping := func(scheme string) error {
@@ -924,7 +928,7 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
 		if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized {
 			return registryHTTPResponseToError(resp)
 		}
-		c.challenges = parseAuthHeader(resp.Header)
+		c.challenges = slices.Collect(iterateAuthHeader(resp.Header))
 		c.scheme = scheme
 		c.supportsSignatures = resp.Header.Get("X-Registry-Supports-Signatures") == "1"
 		return nil
@@ -992,7 +996,7 @@ func (c *dockerClient) getExternalBlob(ctx context.Context, urls []string) (io.R
 			continue
 		}
 		if resp.StatusCode != http.StatusOK {
-			err := fmt.Errorf("error fetching external blob from %q: %d (%s)", u, resp.StatusCode, http.StatusText(resp.StatusCode))
+			err := fmt.Errorf("error fetching external blob from %q: %w", u, newUnexpectedHTTPStatusError(resp))
 			remoteErrors = append(remoteErrors, err)
 			logrus.Debug(err)
 			resp.Body.Close()
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_src.go b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
index 41ab9bfd..4eb9cdfb 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_src.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
@@ -569,7 +569,7 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, sigURL *url.URL
 			logrus.Debugf("... got status 404, as expected = end of signatures")
 			return nil, true, nil
 		} else if res.StatusCode != http.StatusOK {
-			return nil, false, fmt.Errorf("reading signature from %s: status %d (%s)", sigURL.Redacted(), res.StatusCode, http.StatusText(res.StatusCode))
+			return nil, false, fmt.Errorf("reading signature from %s: %w", sigURL.Redacted(), newUnexpectedHTTPStatusError(res))
 		}
 
 		contentType := res.Header.Get("Content-Type")
diff --git a/vendor/github.com/containers/image/v5/docker/errors.go b/vendor/github.com/containers/image/v5/docker/errors.go
index e749b501..1ed40b87 100644
--- a/vendor/github.com/containers/image/v5/docker/errors.go
+++ b/vendor/github.com/containers/image/v5/docker/errors.go
@@ -40,10 +40,10 @@ func httpResponseToError(res *http.Response, context string) error {
 		err := registryHTTPResponseToError(res)
 		return ErrUnauthorizedForCredentials{Err: err}
 	default:
-		if context != "" {
-			context += ": "
+		if context == "" {
+			return newUnexpectedHTTPStatusError(res)
 		}
-		return fmt.Errorf("%sinvalid status code from registry %d (%s)", context, res.StatusCode, http.StatusText(res.StatusCode))
+		return fmt.Errorf("%s: %w", context, newUnexpectedHTTPStatusError(res))
 	}
 }
 
diff --git a/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go b/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go
index 883c0611..320a1780 100644
--- a/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go
+++ b/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go
@@ -242,9 +242,7 @@ func (w *Writer) ensureManifestItemLocked(layerDescriptors []manifest.Schema2Des
 	}
 
 	knownRepoTags := set.New[string]()
-	for _, repoTag := range item.RepoTags {
-		knownRepoTags.Add(repoTag)
-	}
+	knownRepoTags.AddSeq(slices.Values(item.RepoTags))
 	for _, tag := range repoTags {
 		// For github.com/docker/docker consumers, this works just as well as
 		//   refString := ref.String()
diff --git a/vendor/github.com/containers/image/v5/docker/paths_common.go b/vendor/github.com/containers/image/v5/docker/paths_common.go
index 862e8803..d9993630 100644
--- a/vendor/github.com/containers/image/v5/docker/paths_common.go
+++ b/vendor/github.com/containers/image/v5/docker/paths_common.go
@@ -1,5 +1,4 @@
 //go:build !freebsd
-// +build !freebsd
 
 package docker
 
diff --git a/vendor/github.com/containers/image/v5/docker/paths_freebsd.go b/vendor/github.com/containers/image/v5/docker/paths_freebsd.go
index 2bf27ac0..8f0f2eee 100644
--- a/vendor/github.com/containers/image/v5/docker/paths_freebsd.go
+++ b/vendor/github.com/containers/image/v5/docker/paths_freebsd.go
@@ -1,5 +1,4 @@
 //go:build freebsd
-// +build freebsd
 
 package docker
 
diff --git a/vendor/github.com/containers/image/v5/docker/wwwauthenticate.go b/vendor/github.com/containers/image/v5/docker/wwwauthenticate.go
index 6bcb835b..f5fed07b 100644
--- a/vendor/github.com/containers/image/v5/docker/wwwauthenticate.go
+++ b/vendor/github.com/containers/image/v5/docker/wwwauthenticate.go
@@ -4,6 +4,7 @@ package docker
 
 import (
 	"fmt"
+	"iter"
 	"net/http"
 	"strings"
 )
@@ -60,15 +61,17 @@ func init() {
 	}
 }
 
-func parseAuthHeader(header http.Header) []challenge {
-	challenges := []challenge{}
-	for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
-		v, p := parseValueAndParams(h)
-		if v != "" {
-			challenges = append(challenges, challenge{Scheme: v, Parameters: p})
+func iterateAuthHeader(header http.Header) iter.Seq[challenge] {
+	return func(yield func(challenge) bool) {
+		for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
+			v, p := parseValueAndParams(h)
+			if v != "" {
+				if !yield(challenge{Scheme: v, Parameters: p}) {
+					return
+				}
+			}
 		}
 	}
-	return challenges
 }
 
 // parseAuthScope parses an authentication scope string of the form `$resource:$remote:$actions`
diff --git a/vendor/github.com/containers/image/v5/internal/set/set.go b/vendor/github.com/containers/image/v5/internal/set/set.go
index acf30343..7716b12d 100644
--- a/vendor/github.com/containers/image/v5/internal/set/set.go
+++ b/vendor/github.com/containers/image/v5/internal/set/set.go
@@ -1,6 +1,9 @@
 package set
 
-import "golang.org/x/exp/maps"
+import (
+	"iter"
+	"maps"
+)
 
 // FIXME:
 // - Docstrings
@@ -28,8 +31,8 @@ func (s *Set[E]) Add(v E) {
 	s.m[v] = struct{}{} // Possibly writing the same struct{}{} presence marker again.
 }
 
-func (s *Set[E]) AddSlice(slice []E) {
-	for _, v := range slice {
+func (s *Set[E]) AddSeq(seq iter.Seq[E]) {
+	for v := range seq {
 		s.Add(v)
 	}
 }
@@ -47,6 +50,6 @@ func (s *Set[E]) Empty() bool {
 	return len(s.m) == 0
 }
 
-func (s *Set[E]) Values() []E {
+func (s *Set[E]) All() iter.Seq[E] {
 	return maps.Keys(s.m)
 }
diff --git a/vendor/github.com/containers/image/v5/manifest/docker_schema1.go b/vendor/github.com/containers/image/v5/manifest/docker_schema1.go
index b74a1e24..f4b1fc03 100644
--- a/vendor/github.com/containers/image/v5/manifest/docker_schema1.go
+++ b/vendor/github.com/containers/image/v5/manifest/docker_schema1.go
@@ -133,12 +133,12 @@ func (m *Schema1) ConfigInfo() types.BlobInfo {
 // The Digest field is guaranteed to be provided; Size may be -1.
 // WARNING: The list may contain duplicates, and they are semantically relevant.
 func (m *Schema1) LayerInfos() []LayerInfo {
-	layers := make([]LayerInfo, len(m.FSLayers))
-	for i, layer := range m.FSLayers { // NOTE: This includes empty layers (where m.History.V1Compatibility->ThrowAway)
-		layers[(len(m.FSLayers)-1)-i] = LayerInfo{
+	layers := make([]LayerInfo, 0, len(m.FSLayers))
+	for i, layer := range slices.Backward(m.FSLayers) { // NOTE: This includes empty layers (where m.History.V1Compatibility->ThrowAway)
+		layers = append(layers, LayerInfo{
 			BlobInfo:   types.BlobInfo{Digest: layer.BlobSum, Size: -1},
 			EmptyLayer: m.ExtractedV1Compatibility[i].ThrowAway,
-		}
+		})
 	}
 	return layers
 }
@@ -284,7 +284,7 @@ func (m *Schema1) ToSchema2Config(diffIDs []digest.Digest) ([]byte, error) {
 	}
 	// Build the history.
 	convertedHistory := []Schema2History{}
-	for _, compat := range m.ExtractedV1Compatibility {
+	for _, compat := range slices.Backward(m.ExtractedV1Compatibility) {
 		hitem := Schema2History{
 			Created:    compat.Created,
 			CreatedBy:  strings.Join(compat.ContainerConfig.Cmd, " "),
@@ -292,7 +292,7 @@ func (m *Schema1) ToSchema2Config(diffIDs []digest.Digest) ([]byte, error) {
 			Comment:    compat.Comment,
 			EmptyLayer: compat.ThrowAway,
 		}
-		convertedHistory = append([]Schema2History{hitem}, convertedHistory...)
+		convertedHistory = append(convertedHistory, hitem)
 	}
 	// Build the rootfs information.  We need the decompressed sums that we've been
 	// calculating to fill in the DiffIDs.  It's expected (but not enforced by us)
diff --git a/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go b/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go
index f32dd53d..7978229d 100644
--- a/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go
+++ b/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go
@@ -123,7 +123,7 @@ func (ref ociReference) getBlobsToDelete(blobsUsedByDescriptorToDelete map[diges
 //
 // So, NOTE: the blobPath() call below hard-codes "" even in calls where OCISharedBlobDirPath is set
 func (ref ociReference) deleteBlobs(blobsToDelete *set.Set[digest.Digest]) error {
-	for _, digest := range blobsToDelete.Values() {
+	for digest := range blobsToDelete.All() {
 		blobPath, err := ref.blobPath(digest, "") //Only delete in the local directory, see comment above
 		if err != nil {
 			return err
diff --git a/vendor/github.com/containers/image/v5/openshift/openshift-copies.go b/vendor/github.com/containers/image/v5/openshift/openshift-copies.go
index cef3dccc..7b83a886 100644
--- a/vendor/github.com/containers/image/v5/openshift/openshift-copies.go
+++ b/vendor/github.com/containers/image/v5/openshift/openshift-copies.go
@@ -571,8 +571,7 @@ func (rules *clientConfigLoadingRules) Load() (*clientcmdConfig, error) {
 	// merge all of the struct values in the reverse order so that priority is given correctly
 	// errors are not added to the list the second time
 	nonMapConfig := clientcmdNewConfig()
-	for i := len(kubeconfigs) - 1; i >= 0; i-- {
-		kubeconfig := kubeconfigs[i]
+	for _, kubeconfig := range slices.Backward(kubeconfigs) {
 		if err := mergo.MergeWithOverwrite(nonMapConfig, kubeconfig); err != nil {
 			return nil, err
 		}
diff --git a/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go b/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go
index 9d4125d6..8e513d41 100644
--- a/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go
+++ b/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go
@@ -240,7 +240,7 @@ func (mem *cache) candidateLocations(transport types.ImageTransport, scope types
 		if uncompressedDigest = mem.uncompressedDigestLocked(primaryDigest); uncompressedDigest != "" {
 			otherDigests := mem.digestsByUncompressed[uncompressedDigest] // nil if not present in the map
 			if otherDigests != nil {
-				for _, d := range otherDigests.Values() {
+				for d := range otherDigests.All() {
 					if d != primaryDigest && d != uncompressedDigest {
 						res = mem.appendReplacementCandidates(res, transport, scope, d, v2Options)
 					}
diff --git a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go
index da2238a0..243b13c8 100644
--- a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go
+++ b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go
@@ -6,6 +6,8 @@ import (
 	"errors"
 	"fmt"
 	"io/fs"
+	"iter"
+	"maps"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -93,9 +95,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
 				// Credential helpers in the auth file have a
 				// direct mapping to a registry, so we can just
 				// walk the map.
-				for registry := range fileContents.CredHelpers {
-					allKeys.Add(registry)
-				}
+				allKeys.AddSeq(maps.Keys(fileContents.CredHelpers))
 				for key := range fileContents.AuthConfigs {
 					key := normalizeAuthFileKey(key, path.legacyFormat)
 					if key == normalizedDockerIORegistry {
@@ -115,16 +115,14 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
 					return nil, err
 				}
 			}
-			for registry := range creds {
-				allKeys.Add(registry)
-			}
+			allKeys.AddSeq(maps.Keys(creds))
 		}
 	}
 
 	// Now use `GetCredentials` to the specific auth configs for each
 	// previously listed registry.
 	allCreds := make(map[string]types.DockerAuthConfig)
-	for _, key := range allKeys.Values() {
+	for key := range allKeys.All() {
 		creds, err := GetCredentials(sys, key)
 		if err != nil {
 			// Note: we rely on the logging in `GetCredentials`.
@@ -818,16 +816,10 @@ func findCredentialsInFile(key, registry string, path authPath) (types.DockerAut
 	// Support sub-registry namespaces in auth.
 	// (This is not a feature of ~/.docker/config.json; we support it even for
 	// those files as an extension.)
-	var keys []string
-	if !path.legacyFormat {
-		keys = authKeysForKey(key)
-	} else {
-		keys = []string{registry}
-	}
-
+	//
 	// Repo or namespace keys are only supported as exact matches. For registry
 	// keys we prefer exact matches as well.
-	for _, key := range keys {
+	for key := range authKeyLookupOrder(key, registry, path.legacyFormat) {
 		if val, exists := fileContents.AuthConfigs[key]; exists {
 			return decodeDockerAuth(path.path, key, val)
 		}
@@ -854,25 +846,33 @@ func findCredentialsInFile(key, registry string, path authPath) (types.DockerAut
 	return types.DockerAuthConfig{}, nil
 }
 
-// authKeysForKey returns the keys matching a provided auth file key, in order
-// from the best match to worst. For example,
+// authKeyLookupOrder returns a sequence for lookup keys matching (key or registry)
+// in file with legacyFormat, in order from the best match to worst.
+// For example, in a non-legacy file,
 // when given a repository key "quay.io/repo/ns/image", it returns
 // - quay.io/repo/ns/image
 // - quay.io/repo/ns
 // - quay.io/repo
 // - quay.io
-func authKeysForKey(key string) (res []string) {
-	for {
-		res = append(res, key)
+func authKeyLookupOrder(key, registry string, legacyFormat bool) iter.Seq[string] {
+	return func(yield func(string) bool) {
+		if legacyFormat {
+			_ = yield(registry) // We stop in any case
+			return
+		}
+
+		for {
+			if !yield(key) {
+				return
+			}
 
-		lastSlash := strings.LastIndex(key, "/")
-		if lastSlash == -1 {
-			break
+			lastSlash := strings.LastIndex(key, "/")
+			if lastSlash == -1 {
+				break
+			}
+			key = key[:lastSlash]
 		}
-		key = key[:lastSlash]
 	}
-
-	return res
 }
 
 // decodeDockerAuth decodes the username and password from conf,
diff --git a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_common.go b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_common.go
index 07fe5029..c9e8ac5c 100644
--- a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_common.go
+++ b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_common.go
@@ -1,5 +1,4 @@
 //go:build !freebsd
-// +build !freebsd
 
 package sysregistriesv2
 
diff --git a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_freebsd.go b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_freebsd.go
index 741b99f8..7dada4b7 100644
--- a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_freebsd.go
+++ b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/paths_freebsd.go
@@ -1,5 +1,4 @@
 //go:build freebsd
-// +build freebsd
 
 package sysregistriesv2
 
diff --git a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
index 2d47a4f2..318988f0 100644
--- a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
+++ b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
@@ -4,9 +4,11 @@ import (
 	"errors"
 	"fmt"
 	"io/fs"
+	"maps"
 	"os"
 	"path/filepath"
 	"reflect"
+	"slices"
 	"sort"
 	"strings"
 	"sync"
@@ -18,7 +20,6 @@ import (
 	"github.com/containers/storage/pkg/homedir"
 	"github.com/containers/storage/pkg/regexp"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/exp/maps"
 )
 
 // systemRegistriesConfPath is the path to the system-wide registry
@@ -1041,12 +1042,10 @@ func (c *parsedConfig) updateWithConfigurationFrom(updates *parsedConfig) {
 	}
 
 	// Go maps have a non-deterministic order when iterating the keys, so
-	// we dump them in a slice and sort it to enforce some order in
-	// Registries slice.  Some consumers of c/image (e.g., CRI-O) log the
-	// configuration where a non-deterministic order could easily cause
-	// confusion.
-	prefixes := maps.Keys(registryMap)
-	sort.Strings(prefixes)
+	// we sort the keys to enforce some order in Registries slice.
+	// Some consumers of c/image (e.g., CRI-O) log the configuration
+	// and a non-deterministic order could easily cause confusion.
+	prefixes := slices.Sorted(maps.Keys(registryMap))
 
 	c.partialV2.Registries = []Registry{}
 	for _, prefix := range prefixes {
diff --git a/vendor/github.com/containers/image/v5/signature/fulcio_cert.go b/vendor/github.com/containers/image/v5/signature/fulcio_cert.go
index a3c20480..cce46774 100644
--- a/vendor/github.com/containers/image/v5/signature/fulcio_cert.go
+++ b/vendor/github.com/containers/image/v5/signature/fulcio_cert.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_fulcio_stub
-// +build !containers_image_fulcio_stub
 
 package signature
 
diff --git a/vendor/github.com/containers/image/v5/signature/fulcio_cert_stub.go b/vendor/github.com/containers/image/v5/signature/fulcio_cert_stub.go
index c0dc7b23..da8e13c1 100644
--- a/vendor/github.com/containers/image/v5/signature/fulcio_cert_stub.go
+++ b/vendor/github.com/containers/image/v5/signature/fulcio_cert_stub.go
@@ -1,5 +1,4 @@
 //go:build containers_image_fulcio_stub
-// +build containers_image_fulcio_stub
 
 package signature
 
diff --git a/vendor/github.com/containers/image/v5/signature/internal/rekor_set.go b/vendor/github.com/containers/image/v5/signature/internal/rekor_set.go
index 2b024af6..f26a9787 100644
--- a/vendor/github.com/containers/image/v5/signature/internal/rekor_set.go
+++ b/vendor/github.com/containers/image/v5/signature/internal/rekor_set.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_rekor_stub
-// +build !containers_image_rekor_stub
 
 package internal
 
diff --git a/vendor/github.com/containers/image/v5/signature/internal/rekor_set_stub.go b/vendor/github.com/containers/image/v5/signature/internal/rekor_set_stub.go
index 2b20bbed..4ff3da7e 100644
--- a/vendor/github.com/containers/image/v5/signature/internal/rekor_set_stub.go
+++ b/vendor/github.com/containers/image/v5/signature/internal/rekor_set_stub.go
@@ -1,5 +1,4 @@
 //go:build containers_image_rekor_stub
-// +build containers_image_rekor_stub
 
 package internal
 
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
index 2b2a7ad8..8a8c5878 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_openpgp
-// +build !containers_image_openpgp
 
 package signature
 
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
index bd1979ae..fea8590e 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
@@ -1,5 +1,4 @@
 //go:build containers_image_openpgp
-// +build containers_image_openpgp
 
 package signature
 
diff --git a/vendor/github.com/containers/image/v5/signature/policy_paths_common.go b/vendor/github.com/containers/image/v5/signature/policy_paths_common.go
index 290fc245..038351cb 100644
--- a/vendor/github.com/containers/image/v5/signature/policy_paths_common.go
+++ b/vendor/github.com/containers/image/v5/signature/policy_paths_common.go
@@ -1,5 +1,4 @@
 //go:build !freebsd
-// +build !freebsd
 
 package signature
 
diff --git a/vendor/github.com/containers/image/v5/signature/policy_paths_freebsd.go b/vendor/github.com/containers/image/v5/signature/policy_paths_freebsd.go
index 702b7171..6a45a78f 100644
--- a/vendor/github.com/containers/image/v5/signature/policy_paths_freebsd.go
+++ b/vendor/github.com/containers/image/v5/signature/policy_paths_freebsd.go
@@ -1,5 +1,4 @@
 //go:build freebsd
-// +build freebsd
 
 package signature
 
diff --git a/vendor/github.com/containers/image/v5/storage/storage_dest.go b/vendor/github.com/containers/image/v5/storage/storage_dest.go
index c750da93..d1c5acef 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_dest.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_dest.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_storage_stub
-// +build !containers_image_storage_stub
 
 package storage
 
diff --git a/vendor/github.com/containers/image/v5/storage/storage_image.go b/vendor/github.com/containers/image/v5/storage/storage_image.go
index 7e368857..e7ba1dd2 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_image.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_image.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_storage_stub
-// +build !containers_image_storage_stub
 
 package storage
 
diff --git a/vendor/github.com/containers/image/v5/storage/storage_reference.go b/vendor/github.com/containers/image/v5/storage/storage_reference.go
index 5775c4ac..5e3ff9e6 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_reference.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_reference.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_storage_stub
-// +build !containers_image_storage_stub
 
 package storage
 
diff --git a/vendor/github.com/containers/image/v5/storage/storage_src.go b/vendor/github.com/containers/image/v5/storage/storage_src.go
index ff76b206..7cedf1d8 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_src.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_src.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_storage_stub
-// +build !containers_image_storage_stub
 
 package storage
 
diff --git a/vendor/github.com/containers/image/v5/storage/storage_transport.go b/vendor/github.com/containers/image/v5/storage/storage_transport.go
index c26f4e38..a66a1d19 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_transport.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_transport.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_storage_stub
-// +build !containers_image_storage_stub
 
 package storage
 
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon.go b/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon.go
index ffac6e0b..3a8caeeb 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_docker_daemon_stub
-// +build !containers_image_docker_daemon_stub
 
 package alltransports
 
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon_stub.go b/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon_stub.go
index ddc347bf..8e470c80 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon_stub.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/docker_daemon_stub.go
@@ -1,5 +1,4 @@
 //go:build containers_image_docker_daemon_stub
-// +build containers_image_docker_daemon_stub
 
 package alltransports
 
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/ostree.go b/vendor/github.com/containers/image/v5/transports/alltransports/ostree.go
index 2340702b..c5b2ddde 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/ostree.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/ostree.go
@@ -1,5 +1,4 @@
 //go:build containers_image_ostree && linux
-// +build containers_image_ostree,linux
 
 package alltransports
 
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/ostree_stub.go b/vendor/github.com/containers/image/v5/transports/alltransports/ostree_stub.go
index 8c417518..c9b989e0 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/ostree_stub.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/ostree_stub.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_ostree || !linux
-// +build !containers_image_ostree !linux
 
 package alltransports
 
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/storage.go b/vendor/github.com/containers/image/v5/transports/alltransports/storage.go
index 1e399cdb..4b27e059 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/storage.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/storage.go
@@ -1,5 +1,4 @@
 //go:build !containers_image_storage_stub
-// +build !containers_image_storage_stub
 
 package alltransports
 
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/storage_stub.go b/vendor/github.com/containers/image/v5/transports/alltransports/storage_stub.go
index 30802661..b021c1b5 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/storage_stub.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/storage_stub.go
@@ -1,5 +1,4 @@
 //go:build containers_image_storage_stub
-// +build containers_image_storage_stub
 
 package alltransports
 
diff --git a/vendor/github.com/containers/image/v5/types/types.go b/vendor/github.com/containers/image/v5/types/types.go
index 9a7a0da2..25d33c63 100644
--- a/vendor/github.com/containers/image/v5/types/types.go
+++ b/vendor/github.com/containers/image/v5/types/types.go
@@ -3,6 +3,7 @@ package types
 import (
 	"context"
 	"io"
+	"net/url"
 	"time"
 
 	"github.com/containers/image/v5/docker/reference"
@@ -655,6 +656,8 @@ type SystemContext struct {
 	// Note that this requires writing blobs to temporary files, and takes more time than the default behavior,
 	// when the digest for a blob is unknown.
 	DockerRegistryPushPrecomputeDigests bool
+	// DockerProxyURL specifies proxy configuration schema (like socks5://username:password@ip:port)
+	DockerProxyURL *url.URL
 
 	// === docker/daemon.Transport overrides ===
 	// A directory containing a CA certificate (ending with ".crt"),
diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml
index a4881f95..646032d6 100644
--- a/vendor/github.com/docker/docker/api/swagger.yaml
+++ b/vendor/github.com/docker/docker/api/swagger.yaml
@@ -5508,8 +5508,11 @@ definitions:
           com.example.some-other-label: "some-other-value"
       Data:
         description: |
-          Base64-url-safe-encoded ([RFC 4648](https://tools.ietf.org/html/rfc4648#section-5))
-          data to store as secret.
+          Data is the data to store as a secret, formatted as a Base64-url-safe-encoded
+          ([RFC 4648](https://tools.ietf.org/html/rfc4648#section-5)) string.
+          It must be empty if the Driver field is set, in which case the data is
+          loaded from an external secret store. The maximum allowed size is 500KB,
+          as defined in [MaxSecretSize](https://pkg.go.dev/github.com/moby/swarmkit/v2@v2.0.0-20250103191802-8c1959736554/api/validation#MaxSecretSize).
 
           This field is only used to _create_ a secret, and is not returned by
           other endpoints.
@@ -5560,8 +5563,9 @@ definitions:
           type: "string"
       Data:
         description: |
-          Base64-url-safe-encoded ([RFC 4648](https://tools.ietf.org/html/rfc4648#section-5))
-          config data.
+          Data is the data to store as a config, formatted as a Base64-url-safe-encoded
+          ([RFC 4648](https://tools.ietf.org/html/rfc4648#section-5)) string.
+          The maximum allowed size is 1000KB, as defined in [MaxConfigSize](https://pkg.go.dev/github.com/moby/swarmkit/v2@v2.0.0-20250103191802-8c1959736554/manager/controlapi#MaxConfigSize).
         type: "string"
       Templating:
         description: |
diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go
index b0a4d604..8117cb09 100644
--- a/vendor/github.com/docker/docker/api/types/registry/registry.go
+++ b/vendor/github.com/docker/docker/api/types/registry/registry.go
@@ -49,15 +49,17 @@ func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) {
 }
 
 // UnmarshalJSON sets the IPNet from a byte array of JSON
-func (ipnet *NetIPNet) UnmarshalJSON(b []byte) (err error) {
+func (ipnet *NetIPNet) UnmarshalJSON(b []byte) error {
 	var ipnetStr string
-	if err = json.Unmarshal(b, &ipnetStr); err == nil {
-		var cidr *net.IPNet
-		if _, cidr, err = net.ParseCIDR(ipnetStr); err == nil {
-			*ipnet = NetIPNet(*cidr)
-		}
+	if err := json.Unmarshal(b, &ipnetStr); err != nil {
+		return err
 	}
-	return
+	_, cidr, err := net.ParseCIDR(ipnetStr)
+	if err != nil {
+		return err
+	}
+	*ipnet = NetIPNet(*cidr)
+	return nil
 }
 
 // IndexInfo contains information about a registry
diff --git a/vendor/github.com/docker/docker/api/types/swarm/config.go b/vendor/github.com/docker/docker/api/types/swarm/config.go
index 16202ccc..f9a65187 100644
--- a/vendor/github.com/docker/docker/api/types/swarm/config.go
+++ b/vendor/github.com/docker/docker/api/types/swarm/config.go
@@ -12,6 +12,12 @@ type Config struct {
 // ConfigSpec represents a config specification from a config in swarm
 type ConfigSpec struct {
 	Annotations
+
+	// Data is the data to store as a config.
+	//
+	// The maximum allowed size is 1000KB, as defined in [MaxConfigSize].
+	//
+	// [MaxConfigSize]: https://pkg.go.dev/github.com/moby/swarmkit/v2@v2.0.0-20250103191802-8c1959736554/manager/controlapi#MaxConfigSize
 	Data []byte `json:",omitempty"`
 
 	// Templating controls whether and how to evaluate the config payload as
diff --git a/vendor/github.com/docker/docker/api/types/swarm/secret.go b/vendor/github.com/docker/docker/api/types/swarm/secret.go
index d5213ec9..aeb5bb54 100644
--- a/vendor/github.com/docker/docker/api/types/swarm/secret.go
+++ b/vendor/github.com/docker/docker/api/types/swarm/secret.go
@@ -12,8 +12,22 @@ type Secret struct {
 // SecretSpec represents a secret specification from a secret in swarm
 type SecretSpec struct {
 	Annotations
-	Data   []byte  `json:",omitempty"`
-	Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store
+
+	// Data is the data to store as a secret. It must be empty if a
+	// [Driver] is used, in which case the data is loaded from an external
+	// secret store. The maximum allowed size is 500KB, as defined in
+	// [MaxSecretSize].
+	//
+	// This field is only used to create the secret, and is not returned
+	// by other endpoints.
+	//
+	// [MaxSecretSize]: https://pkg.go.dev/github.com/moby/swarmkit/v2@v2.0.0-20250103191802-8c1959736554/api/validation#MaxSecretSize
+	Data []byte `json:",omitempty"`
+
+	// Driver is the name of the secrets driver used to fetch the secret's
+	// value from an external secret store. If not set, the default built-in
+	// store is used.
+	Driver *Driver `json:",omitempty"`
 
 	// Templating controls whether and how to evaluate the secret payload as
 	// a template. If it is not set, no templating is used.
diff --git a/vendor/github.com/docker/docker/client/container_create.go b/vendor/github.com/docker/docker/client/container_create.go
index 9b8616f7..9bb106f7 100644
--- a/vendor/github.com/docker/docker/client/container_create.go
+++ b/vendor/github.com/docker/docker/client/container_create.go
@@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"net/url"
 	"path"
 	"sort"
@@ -54,6 +55,19 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
 			// When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize
 			hostConfig.ConsoleSize = [2]uint{0, 0}
 		}
+		if versions.LessThan(cli.ClientVersion(), "1.44") {
+			for _, m := range hostConfig.Mounts {
+				if m.BindOptions != nil {
+					// ReadOnlyNonRecursive can be safely ignored when API < 1.44
+					if m.BindOptions.ReadOnlyForceRecursive {
+						return response, errors.New("bind-recursive=readonly requires API v1.44 or later")
+					}
+					if m.BindOptions.NonRecursive && versions.LessThan(cli.ClientVersion(), "1.40") {
+						return response, errors.New("bind-recursive=disabled requires API v1.40 or later")
+					}
+				}
+			}
+		}
 
 		hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd)
 		hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop)
diff --git a/vendor/github.com/docker/docker/client/service_create.go b/vendor/github.com/docker/docker/client/service_create.go
index fb12dd5b..54c03b13 100644
--- a/vendor/github.com/docker/docker/client/service_create.go
+++ b/vendor/github.com/docker/docker/client/service_create.go
@@ -37,6 +37,11 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
 	if err := validateServiceSpec(service); err != nil {
 		return response, err
 	}
+	if versions.LessThan(cli.version, "1.30") {
+		if err := validateAPIVersion(service, cli.version); err != nil {
+			return response, err
+		}
+	}
 
 	// ensure that the image is tagged
 	var resolveWarning string
@@ -191,3 +196,18 @@ func validateServiceSpec(s swarm.ServiceSpec) error {
 	}
 	return nil
 }
+
+func validateAPIVersion(c swarm.ServiceSpec, apiVersion string) error {
+	for _, m := range c.TaskTemplate.ContainerSpec.Mounts {
+		if m.BindOptions != nil {
+			if m.BindOptions.NonRecursive && versions.LessThan(apiVersion, "1.40") {
+				return errors.Errorf("bind-recursive=disabled requires API v1.40 or later")
+			}
+			// ReadOnlyNonRecursive can be safely ignored when API < 1.44
+			if m.BindOptions.ReadOnlyForceRecursive && versions.LessThan(apiVersion, "1.44") {
+				return errors.Errorf("bind-recursive=readonly requires API v1.44 or later")
+			}
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/google/go-containerregistry/pkg/name/ref.go b/vendor/github.com/google/go-containerregistry/pkg/name/ref.go
index 912ab330..0a048677 100644
--- a/vendor/github.com/google/go-containerregistry/pkg/name/ref.go
+++ b/vendor/github.com/google/go-containerregistry/pkg/name/ref.go
@@ -44,7 +44,7 @@ func ParseReference(s string, opts ...Option) (Reference, error) {
 	if d, err := NewDigest(s, opts...); err == nil {
 		return d, nil
 	}
-	return nil, newErrBadName("could not parse reference: " + s)
+	return nil, newErrBadName("could not parse reference: %s", s)
 }
 
 type stringConst string
diff --git a/vendor/github.com/pkg/sftp/client.go b/vendor/github.com/pkg/sftp/client.go
index 8c27fb18..0d4d9a91 100644
--- a/vendor/github.com/pkg/sftp/client.go
+++ b/vendor/github.com/pkg/sftp/client.go
@@ -17,6 +17,8 @@ import (
 
 	"github.com/kr/fs"
 	"golang.org/x/crypto/ssh"
+
+	"github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh"
 )
 
 var (
@@ -758,20 +760,39 @@ func (c *Client) Join(elem ...string) string { return path.Join(elem...) }
 // file or directory with the specified path exists, or if the specified directory
 // is not empty.
 func (c *Client) Remove(path string) error {
-	err := c.removeFile(path)
-	// some servers, *cough* osx *cough*, return EPERM, not ENODIR.
-	// serv-u returns ssh_FX_FILE_IS_A_DIRECTORY
-	// EPERM is converted to os.ErrPermission so it is not a StatusError
-	if err, ok := err.(*StatusError); ok {
-		switch err.Code {
-		case sshFxFailure, sshFxFileIsADirectory:
-			return c.RemoveDirectory(path)
+	errF := c.removeFile(path)
+	if errF == nil {
+		return nil
+	}
+
+	errD := c.RemoveDirectory(path)
+	if errD == nil {
+		return nil
+	}
+
+	// Both failed: figure out which error to return.
+
+	if errF, ok := errF.(*os.PathError); ok {
+		// The only time it makes sense to compare errors, is when both are `*os.PathError`.
+		// We cannot test these directly with errF == errD, as that would be a pointer comparison.
+
+		if errD, ok := errD.(*os.PathError); ok && errors.Is(errF.Err, errD.Err) {
+			// If they are both pointers to PathError,
+			// and the same underlying error, then return that.
+			return errF
 		}
 	}
-	if os.IsPermission(err) {
-		return c.RemoveDirectory(path)
+
+	fi, err := c.Stat(path)
+	if err != nil {
+		return err
+	}
+
+	if fi.IsDir() {
+		return errD
 	}
-	return err
+
+	return errF
 }
 
 func (c *Client) removeFile(path string) error {
@@ -785,7 +806,15 @@ func (c *Client) removeFile(path string) error {
 	}
 	switch typ {
 	case sshFxpStatus:
-		return normaliseError(unmarshalStatus(id, data))
+		err = normaliseError(unmarshalStatus(id, data))
+		if err == nil {
+			return nil
+		}
+		return &os.PathError{
+			Op:   "remove",
+			Path: path,
+			Err:  err,
+		}
 	default:
 		return unimplementedPacketErr(typ)
 	}
@@ -803,7 +832,15 @@ func (c *Client) RemoveDirectory(path string) error {
 	}
 	switch typ {
 	case sshFxpStatus:
-		return normaliseError(unmarshalStatus(id, data))
+		err = normaliseError(unmarshalStatus(id, data))
+		if err == nil {
+			return nil
+		}
+		return &os.PathError{
+			Op:   "remove",
+			Path: path,
+			Err:  err,
+		}
 	default:
 		return unimplementedPacketErr(typ)
 	}
@@ -1805,7 +1842,8 @@ func (f *File) readFromWithConcurrency(r io.Reader, concurrency int) (read int64
 		off := f.offset
 
 		for {
-			n, err := r.Read(b)
+			// Fill the entire buffer.
+			n, err := io.ReadFull(r, b)
 
 			if n > 0 {
 				read += int64(n)
@@ -1831,7 +1869,7 @@ func (f *File) readFromWithConcurrency(r io.Reader, concurrency int) (read int64
 			}
 
 			if err != nil {
-				if err != io.EOF {
+				if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) {
 					errCh <- rwErr{off, err}
 				}
 				return
@@ -1985,7 +2023,8 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
 
 	var read int64
 	for {
-		n, err := r.Read(b)
+		// Fill the entire buffer.
+		n, err := io.ReadFull(r, b)
 		if n < 0 {
 			panic("sftp.File: reader returned negative count from Read")
 		}
@@ -2002,7 +2041,7 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
 		}
 
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
 				return read, nil // return nil explicitly.
 			}
 
@@ -2122,6 +2161,13 @@ func (f *File) Sync() error {
 		return os.ErrClosed
 	}
 
+	if data, ok := f.c.HasExtension(openssh.ExtensionFSync().Name); !ok || data != "1" {
+		return &StatusError{
+			Code: sshFxOPUnsupported,
+			msg:  "fsync not supported",
+		}
+	}
+
 	id := f.c.nextID()
 	typ, data, err := f.c.sendPacket(context.Background(), nil, &sshFxpFsyncPacket{
 		ID:     id,
diff --git a/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/fsync.go b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/fsync.go
new file mode 100644
index 00000000..708a4ba7
--- /dev/null
+++ b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/fsync.go
@@ -0,0 +1,73 @@
+package openssh
+
+import (
+	sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer"
+)
+
+const extensionFSync = "fsync@openssh.com"
+
+// RegisterExtensionFSync registers the "fsync@openssh.com" extended packet with the encoding/ssh/filexfer package.
+func RegisterExtensionFSync() {
+	sshfx.RegisterExtendedPacketType(extensionFSync, func() sshfx.ExtendedData {
+		return new(FSyncExtendedPacket)
+	})
+}
+
+// ExtensionFSync returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
+func ExtensionFSync() *sshfx.ExtensionPair {
+	return &sshfx.ExtensionPair{
+		Name: extensionFSync,
+		Data: "1",
+	}
+}
+
+// FSyncExtendedPacket defines the fsync@openssh.com extend packet.
+type FSyncExtendedPacket struct {
+	Handle string
+}
+
+// Type returns the SSH_FXP_EXTENDED packet type.
+func (ep *FSyncExtendedPacket) Type() sshfx.PacketType {
+	return sshfx.PacketTypeExtended
+}
+
+// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
+func (ep *FSyncExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
+	p := &sshfx.ExtendedPacket{
+		ExtendedRequest: extensionFSync,
+
+		Data: ep,
+	}
+	return p.MarshalPacket(reqid, b)
+}
+
+// MarshalInto encodes ep into the binary encoding of the fsync@openssh.com extended packet-specific data.
+func (ep *FSyncExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
+	buf.AppendString(ep.Handle)
+}
+
+// MarshalBinary encodes ep into the binary encoding of the fsync@openssh.com extended packet-specific data.
+//
+// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
+func (ep *FSyncExtendedPacket) MarshalBinary() ([]byte, error) {
+	// string(handle)
+	size := 4 + len(ep.Handle)
+
+	buf := sshfx.NewBuffer(make([]byte, 0, size))
+	ep.MarshalInto(buf)
+	return buf.Bytes(), nil
+}
+
+// UnmarshalFrom decodes the fsync@openssh.com extended packet-specific data from buf.
+func (ep *FSyncExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
+	*ep = FSyncExtendedPacket{
+		Handle: buf.ConsumeString(),
+	}
+
+	return buf.Err
+}
+
+// UnmarshalBinary decodes the fsync@openssh.com extended packet-specific data into ep.
+func (ep *FSyncExtendedPacket) UnmarshalBinary(data []byte) (err error) {
+	return ep.UnmarshalFrom(sshfx.NewBuffer(data))
+}
diff --git a/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/hardlink.go b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/hardlink.go
new file mode 100644
index 00000000..f48d25a2
--- /dev/null
+++ b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/hardlink.go
@@ -0,0 +1,76 @@
+package openssh
+
+import (
+	sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer"
+)
+
+const extensionHardlink = "hardlink@openssh.com"
+
+// RegisterExtensionHardlink registers the "hardlink@openssh.com" extended packet with the encoding/ssh/filexfer package.
+func RegisterExtensionHardlink() {
+	sshfx.RegisterExtendedPacketType(extensionHardlink, func() sshfx.ExtendedData {
+		return new(HardlinkExtendedPacket)
+	})
+}
+
+// ExtensionHardlink returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
+func ExtensionHardlink() *sshfx.ExtensionPair {
+	return &sshfx.ExtensionPair{
+		Name: extensionHardlink,
+		Data: "1",
+	}
+}
+
+// HardlinkExtendedPacket defines the hardlink@openssh.com extend packet.
+type HardlinkExtendedPacket struct {
+	OldPath string
+	NewPath string
+}
+
+// Type returns the SSH_FXP_EXTENDED packet type.
+func (ep *HardlinkExtendedPacket) Type() sshfx.PacketType {
+	return sshfx.PacketTypeExtended
+}
+
+// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
+func (ep *HardlinkExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
+	p := &sshfx.ExtendedPacket{
+		ExtendedRequest: extensionHardlink,
+
+		Data: ep,
+	}
+	return p.MarshalPacket(reqid, b)
+}
+
+// MarshalInto encodes ep into the binary encoding of the hardlink@openssh.com extended packet-specific data.
+func (ep *HardlinkExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
+	buf.AppendString(ep.OldPath)
+	buf.AppendString(ep.NewPath)
+}
+
+// MarshalBinary encodes ep into the binary encoding of the hardlink@openssh.com extended packet-specific data.
+//
+// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
+func (ep *HardlinkExtendedPacket) MarshalBinary() ([]byte, error) {
+	// string(oldpath) + string(newpath)
+	size := 4 + len(ep.OldPath) + 4 + len(ep.NewPath)
+
+	buf := sshfx.NewBuffer(make([]byte, 0, size))
+	ep.MarshalInto(buf)
+	return buf.Bytes(), nil
+}
+
+// UnmarshalFrom decodes the hardlink@openssh.com extended packet-specific data from buf.
+func (ep *HardlinkExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
+	*ep = HardlinkExtendedPacket{
+		OldPath: buf.ConsumeString(),
+		NewPath: buf.ConsumeString(),
+	}
+
+	return buf.Err
+}
+
+// UnmarshalBinary decodes the hardlink@openssh.com extended packet-specific data into ep.
+func (ep *HardlinkExtendedPacket) UnmarshalBinary(data []byte) (err error) {
+	return ep.UnmarshalFrom(sshfx.NewBuffer(data))
+}
diff --git a/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/openssh.go b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/openssh.go
new file mode 100644
index 00000000..f93ff177
--- /dev/null
+++ b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/openssh.go
@@ -0,0 +1,2 @@
+// Package openssh implements the openssh secsh-filexfer extensions as described in https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
+package openssh
diff --git a/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/posix-rename.go b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/posix-rename.go
new file mode 100644
index 00000000..5166489c
--- /dev/null
+++ b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/posix-rename.go
@@ -0,0 +1,76 @@
+package openssh
+
+import (
+	sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer"
+)
+
+const extensionPOSIXRename = "posix-rename@openssh.com"
+
+// RegisterExtensionPOSIXRename registers the "posix-rename@openssh.com" extended packet with the encoding/ssh/filexfer package.
+func RegisterExtensionPOSIXRename() {
+	sshfx.RegisterExtendedPacketType(extensionPOSIXRename, func() sshfx.ExtendedData {
+		return new(POSIXRenameExtendedPacket)
+	})
+}
+
+// ExtensionPOSIXRename returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
+func ExtensionPOSIXRename() *sshfx.ExtensionPair {
+	return &sshfx.ExtensionPair{
+		Name: extensionPOSIXRename,
+		Data: "1",
+	}
+}
+
+// POSIXRenameExtendedPacket defines the posix-rename@openssh.com extend packet.
+type POSIXRenameExtendedPacket struct {
+	OldPath string
+	NewPath string
+}
+
+// Type returns the SSH_FXP_EXTENDED packet type.
+func (ep *POSIXRenameExtendedPacket) Type() sshfx.PacketType {
+	return sshfx.PacketTypeExtended
+}
+
+// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
+func (ep *POSIXRenameExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
+	p := &sshfx.ExtendedPacket{
+		ExtendedRequest: extensionPOSIXRename,
+
+		Data: ep,
+	}
+	return p.MarshalPacket(reqid, b)
+}
+
+// MarshalInto encodes ep into the binary encoding of the hardlink@openssh.com extended packet-specific data.
+func (ep *POSIXRenameExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
+	buf.AppendString(ep.OldPath)
+	buf.AppendString(ep.NewPath)
+}
+
+// MarshalBinary encodes ep into the binary encoding of the hardlink@openssh.com extended packet-specific data.
+//
+// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
+func (ep *POSIXRenameExtendedPacket) MarshalBinary() ([]byte, error) {
+	// string(oldpath) + string(newpath)
+	size := 4 + len(ep.OldPath) + 4 + len(ep.NewPath)
+
+	buf := sshfx.NewBuffer(make([]byte, 0, size))
+	ep.MarshalInto(buf)
+	return buf.Bytes(), nil
+}
+
+// UnmarshalFrom decodes the hardlink@openssh.com extended packet-specific data from buf.
+func (ep *POSIXRenameExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
+	*ep = POSIXRenameExtendedPacket{
+		OldPath: buf.ConsumeString(),
+		NewPath: buf.ConsumeString(),
+	}
+
+	return buf.Err
+}
+
+// UnmarshalBinary decodes the hardlink@openssh.com extended packet-specific data into ep.
+func (ep *POSIXRenameExtendedPacket) UnmarshalBinary(data []byte) (err error) {
+	return ep.UnmarshalFrom(sshfx.NewBuffer(data))
+}
diff --git a/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/statvfs.go b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/statvfs.go
new file mode 100644
index 00000000..51029ca0
--- /dev/null
+++ b/vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh/statvfs.go
@@ -0,0 +1,236 @@
+package openssh
+
+import (
+	sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer"
+)
+
+const extensionStatVFS = "statvfs@openssh.com"
+
+// RegisterExtensionStatVFS registers the "statvfs@openssh.com" extended packet with the encoding/ssh/filexfer package.
+func RegisterExtensionStatVFS() {
+	sshfx.RegisterExtendedPacketType(extensionStatVFS, func() sshfx.ExtendedData {
+		return new(StatVFSExtendedPacket)
+	})
+}
+
+// ExtensionStatVFS returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
+func ExtensionStatVFS() *sshfx.ExtensionPair {
+	return &sshfx.ExtensionPair{
+		Name: extensionStatVFS,
+		Data: "2",
+	}
+}
+
+// StatVFSExtendedPacket defines the statvfs@openssh.com extend packet.
+type StatVFSExtendedPacket struct {
+	Path string
+}
+
+// Type returns the SSH_FXP_EXTENDED packet type.
+func (ep *StatVFSExtendedPacket) Type() sshfx.PacketType {
+	return sshfx.PacketTypeExtended
+}
+
+// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
+func (ep *StatVFSExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
+	p := &sshfx.ExtendedPacket{
+		ExtendedRequest: extensionStatVFS,
+
+		Data: ep,
+	}
+	return p.MarshalPacket(reqid, b)
+}
+
+// MarshalInto encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
+func (ep *StatVFSExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
+	buf.AppendString(ep.Path)
+}
+
+// MarshalBinary encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
+//
+// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
+func (ep *StatVFSExtendedPacket) MarshalBinary() ([]byte, error) {
+	size := 4 + len(ep.Path) // string(path)
+
+	buf := sshfx.NewBuffer(make([]byte, 0, size))
+
+	ep.MarshalInto(buf)
+
+	return buf.Bytes(), nil
+}
+
+// UnmarshalFrom decodes the statvfs@openssh.com extended packet-specific data into ep.
+func (ep *StatVFSExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
+	*ep = StatVFSExtendedPacket{
+		Path: buf.ConsumeString(),
+	}
+
+	return buf.Err
+}
+
+// UnmarshalBinary decodes the statvfs@openssh.com extended packet-specific data into ep.
+func (ep *StatVFSExtendedPacket) UnmarshalBinary(data []byte) (err error) {
+	return ep.UnmarshalFrom(sshfx.NewBuffer(data))
+}
+
+const extensionFStatVFS = "fstatvfs@openssh.com"
+
+// RegisterExtensionFStatVFS registers the "fstatvfs@openssh.com" extended packet with the encoding/ssh/filexfer package.
+func RegisterExtensionFStatVFS() {
+	sshfx.RegisterExtendedPacketType(extensionFStatVFS, func() sshfx.ExtendedData {
+		return new(FStatVFSExtendedPacket)
+	})
+}
+
+// ExtensionFStatVFS returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
+func ExtensionFStatVFS() *sshfx.ExtensionPair {
+	return &sshfx.ExtensionPair{
+		Name: extensionFStatVFS,
+		Data: "2",
+	}
+}
+
+// FStatVFSExtendedPacket defines the fstatvfs@openssh.com extend packet.
+type FStatVFSExtendedPacket struct {
+	Path string
+}
+
+// Type returns the SSH_FXP_EXTENDED packet type.
+func (ep *FStatVFSExtendedPacket) Type() sshfx.PacketType {
+	return sshfx.PacketTypeExtended
+}
+
+// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
+func (ep *FStatVFSExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
+	p := &sshfx.ExtendedPacket{
+		ExtendedRequest: extensionFStatVFS,
+
+		Data: ep,
+	}
+	return p.MarshalPacket(reqid, b)
+}
+
+// MarshalInto encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
+func (ep *FStatVFSExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
+	buf.AppendString(ep.Path)
+}
+
+// MarshalBinary encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
+//
+// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
+func (ep *FStatVFSExtendedPacket) MarshalBinary() ([]byte, error) {
+	size := 4 + len(ep.Path) // string(path)
+
+	buf := sshfx.NewBuffer(make([]byte, 0, size))
+
+	ep.MarshalInto(buf)
+
+	return buf.Bytes(), nil
+}
+
+// UnmarshalFrom decodes the statvfs@openssh.com extended packet-specific data into ep.
+func (ep *FStatVFSExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
+	*ep = FStatVFSExtendedPacket{
+		Path: buf.ConsumeString(),
+	}
+
+	return buf.Err
+}
+
+// UnmarshalBinary decodes the statvfs@openssh.com extended packet-specific data into ep.
+func (ep *FStatVFSExtendedPacket) UnmarshalBinary(data []byte) (err error) {
+	return ep.UnmarshalFrom(sshfx.NewBuffer(data))
+}
+
+// The values for the MountFlags field.
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
+const (
+	MountFlagsReadOnly = 0x1 // SSH_FXE_STATVFS_ST_RDONLY
+	MountFlagsNoSUID   = 0x2 // SSH_FXE_STATVFS_ST_NOSUID
+)
+
+// StatVFSExtendedReplyPacket defines the extended reply packet for statvfs@openssh.com and fstatvfs@openssh.com requests.
+type StatVFSExtendedReplyPacket struct {
+	BlockSize     uint64 /* f_bsize:   file system block size */
+	FragmentSize  uint64 /* f_frsize:  fundamental fs block size / fagment size */
+	Blocks        uint64 /* f_blocks:  number of blocks (unit f_frsize) */
+	BlocksFree    uint64 /* f_bfree:   free blocks in filesystem */
+	BlocksAvail   uint64 /* f_bavail:  free blocks for non-root */
+	Files         uint64 /* f_files:   total file inodes */
+	FilesFree     uint64 /* f_ffree:   free file inodes */
+	FilesAvail    uint64 /* f_favail:  free file inodes for to non-root */
+	FilesystemID  uint64 /* f_fsid:    file system id */
+	MountFlags    uint64 /* f_flag:    bit mask of mount flag values */
+	MaxNameLength uint64 /* f_namemax: maximum filename length */
+}
+
+// Type returns the SSH_FXP_EXTENDED_REPLY packet type.
+func (ep *StatVFSExtendedReplyPacket) Type() sshfx.PacketType {
+	return sshfx.PacketTypeExtendedReply
+}
+
+// MarshalPacket returns ep as a two-part binary encoding of the full extended reply packet.
+func (ep *StatVFSExtendedReplyPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
+	p := &sshfx.ExtendedReplyPacket{
+		Data: ep,
+	}
+	return p.MarshalPacket(reqid, b)
+}
+
+// UnmarshalPacketBody returns ep as a two-part binary encoding of the full extended reply packet.
+func (ep *StatVFSExtendedReplyPacket) UnmarshalPacketBody(buf *sshfx.Buffer) (err error) {
+	p := &sshfx.ExtendedReplyPacket{
+		Data: ep,
+	}
+	return p.UnmarshalPacketBody(buf)
+}
+
+// MarshalInto encodes ep into the binary encoding of the (f)statvfs@openssh.com extended reply packet-specific data.
+func (ep *StatVFSExtendedReplyPacket) MarshalInto(buf *sshfx.Buffer) {
+	buf.AppendUint64(ep.BlockSize)
+	buf.AppendUint64(ep.FragmentSize)
+	buf.AppendUint64(ep.Blocks)
+	buf.AppendUint64(ep.BlocksFree)
+	buf.AppendUint64(ep.BlocksAvail)
+	buf.AppendUint64(ep.Files)
+	buf.AppendUint64(ep.FilesFree)
+	buf.AppendUint64(ep.FilesAvail)
+	buf.AppendUint64(ep.FilesystemID)
+	buf.AppendUint64(ep.MountFlags)
+	buf.AppendUint64(ep.MaxNameLength)
+}
+
+// MarshalBinary encodes ep into the binary encoding of the (f)statvfs@openssh.com extended reply packet-specific data.
+//
+// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended reply packet.
+func (ep *StatVFSExtendedReplyPacket) MarshalBinary() ([]byte, error) {
+	size := 11 * 8 // 11 × uint64(various)
+
+	b := sshfx.NewBuffer(make([]byte, 0, size))
+	ep.MarshalInto(b)
+	return b.Bytes(), nil
+}
+
+// UnmarshalFrom decodes the fstatvfs@openssh.com extended reply packet-specific data into ep.
+func (ep *StatVFSExtendedReplyPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
+	*ep = StatVFSExtendedReplyPacket{
+		BlockSize:     buf.ConsumeUint64(),
+		FragmentSize:  buf.ConsumeUint64(),
+		Blocks:        buf.ConsumeUint64(),
+		BlocksFree:    buf.ConsumeUint64(),
+		BlocksAvail:   buf.ConsumeUint64(),
+		Files:         buf.ConsumeUint64(),
+		FilesFree:     buf.ConsumeUint64(),
+		FilesAvail:    buf.ConsumeUint64(),
+		FilesystemID:  buf.ConsumeUint64(),
+		MountFlags:    buf.ConsumeUint64(),
+		MaxNameLength: buf.ConsumeUint64(),
+	}
+
+	return buf.Err
+}
+
+// UnmarshalBinary decodes the fstatvfs@openssh.com extended reply packet-specific data into ep.
+func (ep *StatVFSExtendedReplyPacket) UnmarshalBinary(data []byte) (err error) {
+	return ep.UnmarshalFrom(sshfx.NewBuffer(data))
+}
diff --git a/vendor/github.com/sigstore/sigstore/pkg/signature/algorithm_registry.go b/vendor/github.com/sigstore/sigstore/pkg/signature/algorithm_registry.go
index 0612d8f7..349926c7 100644
--- a/vendor/github.com/sigstore/sigstore/pkg/signature/algorithm_registry.go
+++ b/vendor/github.com/sigstore/sigstore/pkg/signature/algorithm_registry.go
@@ -21,6 +21,7 @@ import (
 	"crypto/ed25519"
 	"crypto/elliptic"
 	"crypto/rsa"
+	"errors"
 	"fmt"
 
 	v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
@@ -41,7 +42,8 @@ const (
 // RSAKeySize represents the size of an RSA public key in bits.
 type RSAKeySize int
 
-type algorithmDetails struct {
+// AlgorithmDetails exposes relevant information for a given signature algorithm.
+type AlgorithmDetails struct {
 	// knownAlgorithm is the signature algorithm that the following details refer to.
 	knownAlgorithm v1.PublicKeyDetails
 
@@ -63,7 +65,23 @@ type algorithmDetails struct {
 	flagValue string
 }
 
-func (a algorithmDetails) GetRSAKeySize() (RSAKeySize, error) {
+// GetSignatureAlgorithm returns the PublicKeyDetails associated with the algorithm details.
+func (a AlgorithmDetails) GetSignatureAlgorithm() v1.PublicKeyDetails {
+	return a.knownAlgorithm
+}
+
+// GetKeyType returns the PublicKeyType for the algorithm details.
+func (a AlgorithmDetails) GetKeyType() PublicKeyType {
+	return a.keyType
+}
+
+// GetHashType returns the hash algorithm that should be used with this algorithm
+func (a AlgorithmDetails) GetHashType() crypto.Hash {
+	return a.hashType
+}
+
+// GetRSAKeySize returns the RSA key size for the algorithm details, if the key type is RSA.
+func (a AlgorithmDetails) GetRSAKeySize() (RSAKeySize, error) {
 	if a.keyType != RSA {
 		return 0, fmt.Errorf("unable to retrieve RSA key size for key type: %T", a.keyType)
 	}
@@ -75,7 +93,8 @@ func (a algorithmDetails) GetRSAKeySize() (RSAKeySize, error) {
 	return rsaKeySize, nil
 }
 
-func (a algorithmDetails) GetECDSACurve() (*elliptic.Curve, error) {
+// GetECDSACurve returns the elliptic curve for the algorithm details, if the key type is ECDSA.
+func (a AlgorithmDetails) GetECDSACurve() (*elliptic.Curve, error) {
 	if a.keyType != ECDSA {
 		return nil, fmt.Errorf("unable to retrieve ECDSA curve for key type: %T", a.keyType)
 	}
@@ -87,7 +106,7 @@ func (a algorithmDetails) GetECDSACurve() (*elliptic.Curve, error) {
 	return &ecdsaCurve, nil
 }
 
-func (a algorithmDetails) checkKey(pubKey crypto.PublicKey) (bool, error) {
+func (a AlgorithmDetails) checkKey(pubKey crypto.PublicKey) (bool, error) {
 	switch a.keyType {
 	case RSA:
 		rsaKey, ok := pubKey.(*rsa.PublicKey)
@@ -116,14 +135,14 @@ func (a algorithmDetails) checkKey(pubKey crypto.PublicKey) (bool, error) {
 	return false, fmt.Errorf("unrecognized key type: %T", a.keyType)
 }
 
-func (a algorithmDetails) checkHash(hashType crypto.Hash) bool {
+func (a AlgorithmDetails) checkHash(hashType crypto.Hash) bool {
 	return a.hashType == hashType
 }
 
 // Note that deprecated options in PublicKeyDetails are not included in this
 // list, including PKCS1v1.5 encoded RSA. Refer to the v1.PublicKeyDetails enum
 // for more details.
-var supportedAlgorithms = []algorithmDetails{
+var supportedAlgorithms = []AlgorithmDetails{
 	{v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_2048_SHA256, RSA, crypto.SHA256, RSAKeySize(2048), "rsa-sign-pkcs1-2048-sha256"},
 	{v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_3072_SHA256, RSA, crypto.SHA256, RSAKeySize(3072), "rsa-sign-pkcs1-3072-sha256"},
 	{v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_4096_SHA256, RSA, crypto.SHA256, RSAKeySize(4096), "rsa-sign-pkcs1-4096-sha256"},
@@ -142,29 +161,29 @@ var supportedAlgorithms = []algorithmDetails{
 // Individual services may wish to restrict what algorithms are allowed to a subset of what is covered in the algorithm
 // registry (represented by v1.PublicKeyDetails).
 type AlgorithmRegistryConfig struct {
-	permittedAlgorithms []algorithmDetails
+	permittedAlgorithms []AlgorithmDetails
 }
 
-// getAlgorithmDetails retrieves a set of details for a given v1.PublicKeyDetails flag that allows users to
+// GetAlgorithmDetails retrieves a set of details for a given v1.PublicKeyDetails flag that allows users to
 // introspect the public key algorithm, hash algorithm and more.
-func getAlgorithmDetails(knownSignatureAlgorithm v1.PublicKeyDetails) (*algorithmDetails, error) {
+func GetAlgorithmDetails(knownSignatureAlgorithm v1.PublicKeyDetails) (AlgorithmDetails, error) {
 	for _, detail := range supportedAlgorithms {
 		if detail.knownAlgorithm == knownSignatureAlgorithm {
-			return &detail, nil
+			return detail, nil
 		}
 	}
-	return nil, fmt.Errorf("could not find algorithm details for known signature algorithm: %s", knownSignatureAlgorithm)
+	return AlgorithmDetails{}, fmt.Errorf("could not find algorithm details for known signature algorithm: %s", knownSignatureAlgorithm)
 }
 
 // NewAlgorithmRegistryConfig creates a new AlgorithmRegistryConfig for a set of permitted signature algorithms.
 func NewAlgorithmRegistryConfig(algorithmConfig []v1.PublicKeyDetails) (*AlgorithmRegistryConfig, error) {
-	permittedAlgorithms := make([]algorithmDetails, 0, len(supportedAlgorithms))
+	permittedAlgorithms := make([]AlgorithmDetails, 0, len(supportedAlgorithms))
 	for _, algorithm := range algorithmConfig {
-		a, err := getAlgorithmDetails(algorithm)
+		a, err := GetAlgorithmDetails(algorithm)
 		if err != nil {
 			return nil, err
 		}
-		permittedAlgorithms = append(permittedAlgorithms, *a)
+		permittedAlgorithms = append(permittedAlgorithms, a)
 	}
 	return &AlgorithmRegistryConfig{permittedAlgorithms: permittedAlgorithms}, nil
 }
@@ -204,3 +223,81 @@ func ParseSignatureAlgorithmFlag(flag string) (v1.PublicKeyDetails, error) {
 	}
 	return v1.PublicKeyDetails_PUBLIC_KEY_DETAILS_UNSPECIFIED, fmt.Errorf("could not find matching signature algorithm for flag: %s", flag)
 }
+
+// GetDefaultPublicKeyDetails returns the default public key details for a given key.
+//
+// RSA 2048 => v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_2048_SHA256
+// RSA 3072 => v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_3072_SHA256
+// RSA 4096 => v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_4096_SHA256
+// ECDSA P256 => v1.PublicKeyDetails_PKIX_ECDSA_P256_SHA_256
+// ECDSA P384 => v1.PublicKeyDetails_PKIX_ECDSA_P384_SHA_384
+// ECDSA P521 => v1.PublicKeyDetails_PKIX_ECDSA_P521_SHA_512
+// ED25519 => v1.PublicKeyDetails_PKIX_ED25519_PH
+//
+// This function accepts LoadOptions, which are used to determine the default
+// public key details when there may be ambiguities. For example, RSA keys may
+// be PSS or PKCS1v1.5 encoded, and ED25519 keys may be used with PureEd25519 or
+// with Ed25519ph. The Hash option is ignored if passed, because each of the
+// supported algorithms already has a default hash.
+func GetDefaultPublicKeyDetails(publicKey crypto.PublicKey, opts ...LoadOption) (v1.PublicKeyDetails, error) {
+	var rsaPSSOptions *rsa.PSSOptions
+	var useED25519ph bool
+	for _, o := range opts {
+		o.ApplyED25519ph(&useED25519ph)
+		o.ApplyRSAPSS(&rsaPSSOptions)
+	}
+
+	switch pk := publicKey.(type) {
+	case *rsa.PublicKey:
+		if rsaPSSOptions != nil {
+			switch pk.Size() * 8 {
+			case 2048:
+				return v1.PublicKeyDetails_PKIX_RSA_PSS_2048_SHA256, nil
+			case 3072:
+				return v1.PublicKeyDetails_PKIX_RSA_PSS_3072_SHA256, nil
+			case 4096:
+				return v1.PublicKeyDetails_PKIX_RSA_PSS_4096_SHA256, nil
+			}
+		} else {
+			switch pk.Size() * 8 {
+			case 2048:
+				return v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_2048_SHA256, nil
+			case 3072:
+				return v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_3072_SHA256, nil
+			case 4096:
+				return v1.PublicKeyDetails_PKIX_RSA_PKCS1V15_4096_SHA256, nil
+			}
+		}
+	case *ecdsa.PublicKey:
+		switch pk.Curve {
+		case elliptic.P256():
+			return v1.PublicKeyDetails_PKIX_ECDSA_P256_SHA_256, nil
+		case elliptic.P384():
+			return v1.PublicKeyDetails_PKIX_ECDSA_P384_SHA_384, nil
+		case elliptic.P521():
+			return v1.PublicKeyDetails_PKIX_ECDSA_P521_SHA_512, nil
+		}
+	case ed25519.PublicKey:
+		if useED25519ph {
+			return v1.PublicKeyDetails_PKIX_ED25519_PH, nil
+		}
+		return v1.PublicKeyDetails_PKIX_ED25519, nil
+	}
+	return v1.PublicKeyDetails_PUBLIC_KEY_DETAILS_UNSPECIFIED, errors.New("unsupported public key type")
+}
+
+// GetDefaultAlgorithmDetails returns the default algorithm details for a given
+// key, according to GetDefaultPublicKeyDetails.
+//
+// This function accepts LoadOptions, which are used to determine the default
+// algorithm details when there may be ambiguities. For example, RSA keys may be
+// PSS or PKCS1v1.5 encoded, and ED25519 keys may be used with PureEd25519 or
+// with Ed25519ph. The Hash option is ignored if passed, because each of the
+// supported algorithms already has a default hash.
+func GetDefaultAlgorithmDetails(publicKey crypto.PublicKey, opts ...LoadOption) (AlgorithmDetails, error) {
+	knownAlgorithm, err := GetDefaultPublicKeyDetails(publicKey, opts...)
+	if err != nil {
+		return AlgorithmDetails{}, err
+	}
+	return GetAlgorithmDetails(knownAlgorithm)
+}
diff --git a/vendor/github.com/sigstore/sigstore/pkg/signature/signer.go b/vendor/github.com/sigstore/sigstore/pkg/signature/signer.go
index e26def9f..7e402c42 100644
--- a/vendor/github.com/sigstore/sigstore/pkg/signature/signer.go
+++ b/vendor/github.com/sigstore/sigstore/pkg/signature/signer.go
@@ -123,3 +123,28 @@ func LoadSignerFromPEMFileWithOpts(path string, pf cryptoutils.PassFunc, opts ..
 	}
 	return LoadSignerWithOpts(priv, opts...)
 }
+
+// LoadDefaultSigner returns a signature.Signer based on the private key.
+// Each private key has a corresponding PublicKeyDetails associated in the
+// Sigstore ecosystem, see Algorithm Registry for more details.
+func LoadDefaultSigner(privateKey crypto.PrivateKey, opts ...LoadOption) (Signer, error) {
+	signer, ok := privateKey.(crypto.Signer)
+	if !ok {
+		return nil, errors.New("private key does not implement signature.Signer")
+	}
+	algorithmDetails, err := GetDefaultAlgorithmDetails(signer.Public(), opts...)
+	if err != nil {
+		return nil, err
+	}
+	filteredOpts := []LoadOption{options.WithHash(algorithmDetails.hashType)}
+	for _, opt := range opts {
+		var useED25519ph bool
+		var rsaPSSOptions *rsa.PSSOptions
+		opt.ApplyED25519ph(&useED25519ph)
+		opt.ApplyRSAPSS(&rsaPSSOptions)
+		if useED25519ph || rsaPSSOptions != nil {
+			filteredOpts = append(filteredOpts, opt)
+		}
+	}
+	return LoadSignerWithOpts(privateKey, filteredOpts...)
+}
diff --git a/vendor/github.com/sigstore/sigstore/pkg/signature/signerverifier.go b/vendor/github.com/sigstore/sigstore/pkg/signature/signerverifier.go
index 70253b12..f521f35f 100644
--- a/vendor/github.com/sigstore/sigstore/pkg/signature/signerverifier.go
+++ b/vendor/github.com/sigstore/sigstore/pkg/signature/signerverifier.go
@@ -103,3 +103,28 @@ func LoadSignerVerifierFromPEMFileWithOpts(path string, pf cryptoutils.PassFunc,
 	}
 	return LoadSignerVerifierWithOpts(priv, opts...)
 }
+
+// LoadDefaultSignerVerifier returns a signature.SignerVerifier based on
+// the private key. Each private key has a corresponding PublicKeyDetails
+// associated in the Sigstore ecosystem, see Algorithm Registry for more details.
+func LoadDefaultSignerVerifier(privateKey crypto.PrivateKey, opts ...LoadOption) (SignerVerifier, error) {
+	signer, ok := privateKey.(crypto.Signer)
+	if !ok {
+		return nil, errors.New("private key does not implement signature.Signer")
+	}
+	algorithmDetails, err := GetDefaultAlgorithmDetails(signer.Public(), opts...)
+	if err != nil {
+		return nil, err
+	}
+	filteredOpts := []LoadOption{options.WithHash(algorithmDetails.hashType)}
+	for _, opt := range opts {
+		var useED25519ph bool
+		var rsaPSSOptions *rsa.PSSOptions
+		opt.ApplyED25519ph(&useED25519ph)
+		opt.ApplyRSAPSS(&rsaPSSOptions)
+		if useED25519ph || rsaPSSOptions != nil {
+			filteredOpts = append(filteredOpts, opt)
+		}
+	}
+	return LoadSignerVerifierWithOpts(privateKey, filteredOpts...)
+}
diff --git a/vendor/github.com/sigstore/sigstore/pkg/signature/verifier.go b/vendor/github.com/sigstore/sigstore/pkg/signature/verifier.go
index cdde9fc5..fb1e1f5c 100644
--- a/vendor/github.com/sigstore/sigstore/pkg/signature/verifier.go
+++ b/vendor/github.com/sigstore/sigstore/pkg/signature/verifier.go
@@ -136,3 +136,24 @@ func LoadVerifierFromPEMFileWithOpts(path string, opts ...LoadOption) (Verifier,
 
 	return LoadVerifierWithOpts(pubKey, opts...)
 }
+
+// LoadDefaultVerifier returns a signature.Verifier based on the public key.
+// Each public key has a corresponding PublicKeyDetails associated in the
+// Sigstore ecosystem, see Algorithm Registry for more details.
+func LoadDefaultVerifier(publicKey crypto.PublicKey, opts ...LoadOption) (Verifier, error) {
+	algorithmDetails, err := GetDefaultAlgorithmDetails(publicKey, opts...)
+	if err != nil {
+		return nil, err
+	}
+	filteredOpts := []LoadOption{options.WithHash(algorithmDetails.hashType)}
+	for _, opt := range opts {
+		var useED25519ph bool
+		var rsaPSSOptions *rsa.PSSOptions
+		opt.ApplyED25519ph(&useED25519ph)
+		opt.ApplyRSAPSS(&rsaPSSOptions)
+		if useED25519ph || rsaPSSOptions != nil {
+			filteredOpts = append(filteredOpts, opt)
+		}
+	}
+	return LoadVerifierWithOpts(publicKey, filteredOpts...)
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/CONTRIBUTING.md b/vendor/go.opentelemetry.io/auto/sdk/CONTRIBUTING.md
new file mode 100644
index 00000000..773c9b64
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/CONTRIBUTING.md
@@ -0,0 +1,27 @@
+# Contributing to go.opentelemetry.io/auto/sdk
+
+The `go.opentelemetry.io/auto/sdk` module is a purpose built OpenTelemetry SDK.
+It is designed to be:
+
+0. An OpenTelemetry compliant SDK
+1. Instrumented by auto-instrumentation (serializable into OTLP JSON)
+2. Lightweight
+3. User-friendly
+
+These design choices are listed in the order of their importance.
+
+The primary design goal of this module is to be an OpenTelemetry SDK.
+This means that it needs to implement the Go APIs found in `go.opentelemetry.io/otel`.
+
+Having met the requirement of SDK compliance, this module needs to provide code that the `go.opentelemetry.io/auto` module can instrument.
+The chosen approach to meet this goal is to ensure the telemetry from the SDK is serializable into JSON encoded OTLP.
+This ensures then that the serialized form is compatible with other OpenTelemetry systems, and the auto-instrumentation can use these systems to deserialize any telemetry it is sent.
+
+Outside of these first two goals, the intended use becomes relevant.
+This package is intended to be used in the `go.opentelemetry.io/otel` global API as a default when the auto-instrumentation is running.
+Because of this, this package needs to not add unnecessary dependencies to that API.
+Ideally, it adds none.
+It also needs to operate efficiently.
+
+Finally, this module is designed to be user-friendly to Go development.
+It hides complexity in order to provide simpler APIs when the previous goals can all still be met.
diff --git a/vendor/go.opentelemetry.io/auto/sdk/LICENSE b/vendor/go.opentelemetry.io/auto/sdk/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/vendor/go.opentelemetry.io/auto/sdk/VERSIONING.md b/vendor/go.opentelemetry.io/auto/sdk/VERSIONING.md
new file mode 100644
index 00000000..088d19a6
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/VERSIONING.md
@@ -0,0 +1,15 @@
+# Versioning
+
+This document describes the versioning policy for this module.
+This policy is designed so the following goals can be achieved.
+
+**Users are provided a codebase of value that is stable and secure.**
+
+## Policy
+
+* Versioning of this module will be idiomatic of a Go project using [Go modules](https://github.com/golang/go/wiki/Modules).
+  * [Semantic import versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning) will be used.
+    * Versions will comply with [semver 2.0](https://semver.org/spec/v2.0.0.html).
+    * Any `v2` or higher version of this module will be included as a `/vN` at the end of the module path used in `go.mod` files and in the package import path.
+
+* GitHub releases will be made for all releases.
diff --git a/vendor/go.opentelemetry.io/auto/sdk/doc.go b/vendor/go.opentelemetry.io/auto/sdk/doc.go
new file mode 100644
index 00000000..ad73d8cb
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/doc.go
@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+Package sdk provides an auto-instrumentable OpenTelemetry SDK.
+
+An [go.opentelemetry.io/auto.Instrumentation] can be configured to target the
+process running this SDK. In that case, all telemetry the SDK produces will be
+processed and handled by that [go.opentelemetry.io/auto.Instrumentation].
+
+By default, if there is no [go.opentelemetry.io/auto.Instrumentation] set to
+auto-instrument the SDK, the SDK will not generate any telemetry.
+*/
+package sdk
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/attr.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/attr.go
new file mode 100644
index 00000000..af6ef171
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/attr.go
@@ -0,0 +1,58 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+// Attr is a key-value pair.
+type Attr struct {
+	Key   string `json:"key,omitempty"`
+	Value Value  `json:"value,omitempty"`
+}
+
+// String returns an Attr for a string value.
+func String(key, value string) Attr {
+	return Attr{key, StringValue(value)}
+}
+
+// Int64 returns an Attr for an int64 value.
+func Int64(key string, value int64) Attr {
+	return Attr{key, Int64Value(value)}
+}
+
+// Int returns an Attr for an int value.
+func Int(key string, value int) Attr {
+	return Int64(key, int64(value))
+}
+
+// Float64 returns an Attr for a float64 value.
+func Float64(key string, value float64) Attr {
+	return Attr{key, Float64Value(value)}
+}
+
+// Bool returns an Attr for a bool value.
+func Bool(key string, value bool) Attr {
+	return Attr{key, BoolValue(value)}
+}
+
+// Bytes returns an Attr for a []byte value.
+// The passed slice must not be changed after it is passed.
+func Bytes(key string, value []byte) Attr {
+	return Attr{key, BytesValue(value)}
+}
+
+// Slice returns an Attr for a []Value value.
+// The passed slice must not be changed after it is passed.
+func Slice(key string, value ...Value) Attr {
+	return Attr{key, SliceValue(value...)}
+}
+
+// Map returns an Attr for a map value.
+// The passed slice must not be changed after it is passed.
+func Map(key string, value ...Attr) Attr {
+	return Attr{key, MapValue(value...)}
+}
+
+// Equal returns if a is equal to b.
+func (a Attr) Equal(b Attr) bool {
+	return a.Key == b.Key && a.Value.Equal(b.Value)
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/doc.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/doc.go
new file mode 100644
index 00000000..949e2165
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/doc.go
@@ -0,0 +1,8 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+Package telemetry provides a lightweight representations of OpenTelemetry
+telemetry that is compatible with the OTLP JSON protobuf encoding.
+*/
+package telemetry
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/id.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/id.go
new file mode 100644
index 00000000..e854d7e8
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/id.go
@@ -0,0 +1,103 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+import (
+	"encoding/hex"
+	"errors"
+	"fmt"
+)
+
+const (
+	traceIDSize = 16
+	spanIDSize  = 8
+)
+
+// TraceID is a custom data type that is used for all trace IDs.
+type TraceID [traceIDSize]byte
+
+// String returns the hex string representation form of a TraceID.
+func (tid TraceID) String() string {
+	return hex.EncodeToString(tid[:])
+}
+
+// IsEmpty returns false if id contains at least one non-zero byte.
+func (tid TraceID) IsEmpty() bool {
+	return tid == [traceIDSize]byte{}
+}
+
+// MarshalJSON converts the trace ID into a hex string enclosed in quotes.
+func (tid TraceID) MarshalJSON() ([]byte, error) {
+	if tid.IsEmpty() {
+		return []byte(`""`), nil
+	}
+	return marshalJSON(tid[:])
+}
+
+// UnmarshalJSON inflates the trace ID from hex string, possibly enclosed in
+// quotes.
+func (tid *TraceID) UnmarshalJSON(data []byte) error {
+	*tid = [traceIDSize]byte{}
+	return unmarshalJSON(tid[:], data)
+}
+
+// SpanID is a custom data type that is used for all span IDs.
+type SpanID [spanIDSize]byte
+
+// String returns the hex string representation form of a SpanID.
+func (sid SpanID) String() string {
+	return hex.EncodeToString(sid[:])
+}
+
+// IsEmpty returns true if the span ID contains at least one non-zero byte.
+func (sid SpanID) IsEmpty() bool {
+	return sid == [spanIDSize]byte{}
+}
+
+// MarshalJSON converts span ID into a hex string enclosed in quotes.
+func (sid SpanID) MarshalJSON() ([]byte, error) {
+	if sid.IsEmpty() {
+		return []byte(`""`), nil
+	}
+	return marshalJSON(sid[:])
+}
+
+// UnmarshalJSON decodes span ID from hex string, possibly enclosed in quotes.
+func (sid *SpanID) UnmarshalJSON(data []byte) error {
+	*sid = [spanIDSize]byte{}
+	return unmarshalJSON(sid[:], data)
+}
+
+// marshalJSON converts id into a hex string enclosed in quotes.
+func marshalJSON(id []byte) ([]byte, error) {
+	// Plus 2 quote chars at the start and end.
+	hexLen := hex.EncodedLen(len(id)) + 2
+
+	b := make([]byte, hexLen)
+	hex.Encode(b[1:hexLen-1], id)
+	b[0], b[hexLen-1] = '"', '"'
+
+	return b, nil
+}
+
+// unmarshalJSON inflates trace id from hex string, possibly enclosed in quotes.
+func unmarshalJSON(dst []byte, src []byte) error {
+	if l := len(src); l >= 2 && src[0] == '"' && src[l-1] == '"' {
+		src = src[1 : l-1]
+	}
+	nLen := len(src)
+	if nLen == 0 {
+		return nil
+	}
+
+	if len(dst) != hex.DecodedLen(nLen) {
+		return errors.New("invalid length for ID")
+	}
+
+	_, err := hex.Decode(dst, src)
+	if err != nil {
+		return fmt.Errorf("cannot unmarshal ID from string '%s': %w", string(src), err)
+	}
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/number.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/number.go
new file mode 100644
index 00000000..29e629d6
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/number.go
@@ -0,0 +1,67 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+import (
+	"encoding/json"
+	"strconv"
+)
+
+// protoInt64 represents the protobuf encoding of integers which can be either
+// strings or integers.
+type protoInt64 int64
+
+// Int64 returns the protoInt64 as an int64.
+func (i *protoInt64) Int64() int64 { return int64(*i) }
+
+// UnmarshalJSON decodes both strings and integers.
+func (i *protoInt64) UnmarshalJSON(data []byte) error {
+	if data[0] == '"' {
+		var str string
+		if err := json.Unmarshal(data, &str); err != nil {
+			return err
+		}
+		parsedInt, err := strconv.ParseInt(str, 10, 64)
+		if err != nil {
+			return err
+		}
+		*i = protoInt64(parsedInt)
+	} else {
+		var parsedInt int64
+		if err := json.Unmarshal(data, &parsedInt); err != nil {
+			return err
+		}
+		*i = protoInt64(parsedInt)
+	}
+	return nil
+}
+
+// protoUint64 represents the protobuf encoding of integers which can be either
+// strings or integers.
+type protoUint64 uint64
+
+// Int64 returns the protoUint64 as a uint64.
+func (i *protoUint64) Uint64() uint64 { return uint64(*i) }
+
+// UnmarshalJSON decodes both strings and integers.
+func (i *protoUint64) UnmarshalJSON(data []byte) error {
+	if data[0] == '"' {
+		var str string
+		if err := json.Unmarshal(data, &str); err != nil {
+			return err
+		}
+		parsedUint, err := strconv.ParseUint(str, 10, 64)
+		if err != nil {
+			return err
+		}
+		*i = protoUint64(parsedUint)
+	} else {
+		var parsedUint uint64
+		if err := json.Unmarshal(data, &parsedUint); err != nil {
+			return err
+		}
+		*i = protoUint64(parsedUint)
+	}
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/resource.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/resource.go
new file mode 100644
index 00000000..cecad8ba
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/resource.go
@@ -0,0 +1,66 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// Resource information.
+type Resource struct {
+	// Attrs are the set of attributes that describe the resource. Attribute
+	// keys MUST be unique (it is not allowed to have more than one attribute
+	// with the same key).
+	Attrs []Attr `json:"attributes,omitempty"`
+	// DroppedAttrs is the number of dropped attributes. If the value
+	// is 0, then no attributes were dropped.
+	DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"`
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into r.
+func (r *Resource) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid Resource type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid Resource field: %#v", keyIface)
+		}
+
+		switch key {
+		case "attributes":
+			err = decoder.Decode(&r.Attrs)
+		case "droppedAttributesCount", "dropped_attributes_count":
+			err = decoder.Decode(&r.DroppedAttrs)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/scope.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/scope.go
new file mode 100644
index 00000000..b6f2e28d
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/scope.go
@@ -0,0 +1,67 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// Scope is the identifying values of the instrumentation scope.
+type Scope struct {
+	Name         string `json:"name,omitempty"`
+	Version      string `json:"version,omitempty"`
+	Attrs        []Attr `json:"attributes,omitempty"`
+	DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"`
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into r.
+func (s *Scope) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid Scope type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid Scope field: %#v", keyIface)
+		}
+
+		switch key {
+		case "name":
+			err = decoder.Decode(&s.Name)
+		case "version":
+			err = decoder.Decode(&s.Version)
+		case "attributes":
+			err = decoder.Decode(&s.Attrs)
+		case "droppedAttributesCount", "dropped_attributes_count":
+			err = decoder.Decode(&s.DroppedAttrs)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/span.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/span.go
new file mode 100644
index 00000000..a13a6b73
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/span.go
@@ -0,0 +1,456 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+import (
+	"bytes"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"time"
+)
+
+// A Span represents a single operation performed by a single component of the
+// system.
+type Span struct {
+	// A unique identifier for a trace. All spans from the same trace share
+	// the same `trace_id`. The ID is a 16-byte array. An ID with all zeroes OR
+	// of length other than 16 bytes is considered invalid (empty string in OTLP/JSON
+	// is zero-length and thus is also invalid).
+	//
+	// This field is required.
+	TraceID TraceID `json:"traceId,omitempty"`
+	// A unique identifier for a span within a trace, assigned when the span
+	// is created. The ID is an 8-byte array. An ID with all zeroes OR of length
+	// other than 8 bytes is considered invalid (empty string in OTLP/JSON
+	// is zero-length and thus is also invalid).
+	//
+	// This field is required.
+	SpanID SpanID `json:"spanId,omitempty"`
+	// trace_state conveys information about request position in multiple distributed tracing graphs.
+	// It is a trace_state in w3c-trace-context format: https://www.w3.org/TR/trace-context/#tracestate-header
+	// See also https://github.com/w3c/distributed-tracing for more details about this field.
+	TraceState string `json:"traceState,omitempty"`
+	// The `span_id` of this span's parent span. If this is a root span, then this
+	// field must be empty. The ID is an 8-byte array.
+	ParentSpanID SpanID `json:"parentSpanId,omitempty"`
+	// Flags, a bit field.
+	//
+	// Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace
+	// Context specification. To read the 8-bit W3C trace flag, use
+	// `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`.
+	//
+	// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions.
+	//
+	// Bits 8 and 9 represent the 3 states of whether a span's parent
+	// is remote. The states are (unknown, is not remote, is remote).
+	// To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`.
+	// To read whether the span is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`.
+	//
+	// When creating span messages, if the message is logically forwarded from another source
+	// with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD
+	// be copied as-is. If creating from a source that does not have an equivalent flags field
+	// (such as a runtime representation of an OpenTelemetry span), the high 22 bits MUST
+	// be set to zero.
+	// Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero.
+	//
+	// [Optional].
+	Flags uint32 `json:"flags,omitempty"`
+	// A description of the span's operation.
+	//
+	// For example, the name can be a qualified method name or a file name
+	// and a line number where the operation is called. A best practice is to use
+	// the same display name at the same call point in an application.
+	// This makes it easier to correlate spans in different traces.
+	//
+	// This field is semantically required to be set to non-empty string.
+	// Empty value is equivalent to an unknown span name.
+	//
+	// This field is required.
+	Name string `json:"name"`
+	// Distinguishes between spans generated in a particular context. For example,
+	// two spans with the same name may be distinguished using `CLIENT` (caller)
+	// and `SERVER` (callee) to identify queueing latency associated with the span.
+	Kind SpanKind `json:"kind,omitempty"`
+	// start_time_unix_nano is the start time of the span. On the client side, this is the time
+	// kept by the local machine where the span execution starts. On the server side, this
+	// is the time when the server's application handler starts running.
+	// Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970.
+	//
+	// This field is semantically required and it is expected that end_time >= start_time.
+	StartTime time.Time `json:"startTimeUnixNano,omitempty"`
+	// end_time_unix_nano is the end time of the span. On the client side, this is the time
+	// kept by the local machine where the span execution ends. On the server side, this
+	// is the time when the server application handler stops running.
+	// Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970.
+	//
+	// This field is semantically required and it is expected that end_time >= start_time.
+	EndTime time.Time `json:"endTimeUnixNano,omitempty"`
+	// attributes is a collection of key/value pairs. Note, global attributes
+	// like server name can be set using the resource API. Examples of attributes:
+	//
+	//     "/http/user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
+	//     "/http/server_latency": 300
+	//     "example.com/myattribute": true
+	//     "example.com/score": 10.239
+	//
+	// The OpenTelemetry API specification further restricts the allowed value types:
+	// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/common/README.md#attribute
+	// Attribute keys MUST be unique (it is not allowed to have more than one
+	// attribute with the same key).
+	Attrs []Attr `json:"attributes,omitempty"`
+	// dropped_attributes_count is the number of attributes that were discarded. Attributes
+	// can be discarded because their keys are too long or because there are too many
+	// attributes. If this value is 0, then no attributes were dropped.
+	DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"`
+	// events is a collection of Event items.
+	Events []*SpanEvent `json:"events,omitempty"`
+	// dropped_events_count is the number of dropped events. If the value is 0, then no
+	// events were dropped.
+	DroppedEvents uint32 `json:"droppedEventsCount,omitempty"`
+	// links is a collection of Links, which are references from this span to a span
+	// in the same or different trace.
+	Links []*SpanLink `json:"links,omitempty"`
+	// dropped_links_count is the number of dropped links after the maximum size was
+	// enforced. If this value is 0, then no links were dropped.
+	DroppedLinks uint32 `json:"droppedLinksCount,omitempty"`
+	// An optional final status for this span. Semantically when Status isn't set, it means
+	// span's status code is unset, i.e. assume STATUS_CODE_UNSET (code = 0).
+	Status *Status `json:"status,omitempty"`
+}
+
+// MarshalJSON encodes s into OTLP formatted JSON.
+func (s Span) MarshalJSON() ([]byte, error) {
+	startT := s.StartTime.UnixNano()
+	if s.StartTime.IsZero() || startT < 0 {
+		startT = 0
+	}
+
+	endT := s.EndTime.UnixNano()
+	if s.EndTime.IsZero() || endT < 0 {
+		endT = 0
+	}
+
+	// Override non-empty default SpanID marshal and omitempty.
+	var parentSpanId string
+	if !s.ParentSpanID.IsEmpty() {
+		b := make([]byte, hex.EncodedLen(spanIDSize))
+		hex.Encode(b, s.ParentSpanID[:])
+		parentSpanId = string(b)
+	}
+
+	type Alias Span
+	return json.Marshal(struct {
+		Alias
+		ParentSpanID string `json:"parentSpanId,omitempty"`
+		StartTime    uint64 `json:"startTimeUnixNano,omitempty"`
+		EndTime      uint64 `json:"endTimeUnixNano,omitempty"`
+	}{
+		Alias:        Alias(s),
+		ParentSpanID: parentSpanId,
+		StartTime:    uint64(startT),
+		EndTime:      uint64(endT),
+	})
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into s.
+func (s *Span) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid Span type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid Span field: %#v", keyIface)
+		}
+
+		switch key {
+		case "traceId", "trace_id":
+			err = decoder.Decode(&s.TraceID)
+		case "spanId", "span_id":
+			err = decoder.Decode(&s.SpanID)
+		case "traceState", "trace_state":
+			err = decoder.Decode(&s.TraceState)
+		case "parentSpanId", "parent_span_id":
+			err = decoder.Decode(&s.ParentSpanID)
+		case "flags":
+			err = decoder.Decode(&s.Flags)
+		case "name":
+			err = decoder.Decode(&s.Name)
+		case "kind":
+			err = decoder.Decode(&s.Kind)
+		case "startTimeUnixNano", "start_time_unix_nano":
+			var val protoUint64
+			err = decoder.Decode(&val)
+			s.StartTime = time.Unix(0, int64(val.Uint64()))
+		case "endTimeUnixNano", "end_time_unix_nano":
+			var val protoUint64
+			err = decoder.Decode(&val)
+			s.EndTime = time.Unix(0, int64(val.Uint64()))
+		case "attributes":
+			err = decoder.Decode(&s.Attrs)
+		case "droppedAttributesCount", "dropped_attributes_count":
+			err = decoder.Decode(&s.DroppedAttrs)
+		case "events":
+			err = decoder.Decode(&s.Events)
+		case "droppedEventsCount", "dropped_events_count":
+			err = decoder.Decode(&s.DroppedEvents)
+		case "links":
+			err = decoder.Decode(&s.Links)
+		case "droppedLinksCount", "dropped_links_count":
+			err = decoder.Decode(&s.DroppedLinks)
+		case "status":
+			err = decoder.Decode(&s.Status)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// SpanFlags represents constants used to interpret the
+// Span.flags field, which is protobuf 'fixed32' type and is to
+// be used as bit-fields. Each non-zero value defined in this enum is
+// a bit-mask.  To extract the bit-field, for example, use an
+// expression like:
+//
+//	(span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK)
+//
+// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions.
+//
+// Note that Span flags were introduced in version 1.1 of the
+// OpenTelemetry protocol.  Older Span producers do not set this
+// field, consequently consumers should not rely on the absence of a
+// particular flag bit to indicate the presence of a particular feature.
+type SpanFlags int32
+
+const (
+	// Bits 0-7 are used for trace flags.
+	SpanFlagsTraceFlagsMask SpanFlags = 255
+	// Bits 8 and 9 are used to indicate that the parent span or link span is remote.
+	// Bit 8 (`HAS_IS_REMOTE`) indicates whether the value is known.
+	// Bit 9 (`IS_REMOTE`) indicates whether the span or link is remote.
+	SpanFlagsContextHasIsRemoteMask SpanFlags = 256
+	// SpanFlagsContextHasIsRemoteMask indicates the Span is remote.
+	SpanFlagsContextIsRemoteMask SpanFlags = 512
+)
+
+// SpanKind is the type of span. Can be used to specify additional relationships between spans
+// in addition to a parent/child relationship.
+type SpanKind int32
+
+const (
+	// Indicates that the span represents an internal operation within an application,
+	// as opposed to an operation happening at the boundaries. Default value.
+	SpanKindInternal SpanKind = 1
+	// Indicates that the span covers server-side handling of an RPC or other
+	// remote network request.
+	SpanKindServer SpanKind = 2
+	// Indicates that the span describes a request to some remote service.
+	SpanKindClient SpanKind = 3
+	// Indicates that the span describes a producer sending a message to a broker.
+	// Unlike CLIENT and SERVER, there is often no direct critical path latency relationship
+	// between producer and consumer spans. A PRODUCER span ends when the message was accepted
+	// by the broker while the logical processing of the message might span a much longer time.
+	SpanKindProducer SpanKind = 4
+	// Indicates that the span describes consumer receiving a message from a broker.
+	// Like the PRODUCER kind, there is often no direct critical path latency relationship
+	// between producer and consumer spans.
+	SpanKindConsumer SpanKind = 5
+)
+
+// Event is a time-stamped annotation of the span, consisting of user-supplied
+// text description and key-value pairs.
+type SpanEvent struct {
+	// time_unix_nano is the time the event occurred.
+	Time time.Time `json:"timeUnixNano,omitempty"`
+	// name of the event.
+	// This field is semantically required to be set to non-empty string.
+	Name string `json:"name,omitempty"`
+	// attributes is a collection of attribute key/value pairs on the event.
+	// Attribute keys MUST be unique (it is not allowed to have more than one
+	// attribute with the same key).
+	Attrs []Attr `json:"attributes,omitempty"`
+	// dropped_attributes_count is the number of dropped attributes. If the value is 0,
+	// then no attributes were dropped.
+	DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"`
+}
+
+// MarshalJSON encodes e into OTLP formatted JSON.
+func (e SpanEvent) MarshalJSON() ([]byte, error) {
+	t := e.Time.UnixNano()
+	if e.Time.IsZero() || t < 0 {
+		t = 0
+	}
+
+	type Alias SpanEvent
+	return json.Marshal(struct {
+		Alias
+		Time uint64 `json:"timeUnixNano,omitempty"`
+	}{
+		Alias: Alias(e),
+		Time:  uint64(t),
+	})
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into se.
+func (se *SpanEvent) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid SpanEvent type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid SpanEvent field: %#v", keyIface)
+		}
+
+		switch key {
+		case "timeUnixNano", "time_unix_nano":
+			var val protoUint64
+			err = decoder.Decode(&val)
+			se.Time = time.Unix(0, int64(val.Uint64()))
+		case "name":
+			err = decoder.Decode(&se.Name)
+		case "attributes":
+			err = decoder.Decode(&se.Attrs)
+		case "droppedAttributesCount", "dropped_attributes_count":
+			err = decoder.Decode(&se.DroppedAttrs)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// A pointer from the current span to another span in the same trace or in a
+// different trace. For example, this can be used in batching operations,
+// where a single batch handler processes multiple requests from different
+// traces or when the handler receives a request from a different project.
+type SpanLink struct {
+	// A unique identifier of a trace that this linked span is part of. The ID is a
+	// 16-byte array.
+	TraceID TraceID `json:"traceId,omitempty"`
+	// A unique identifier for the linked span. The ID is an 8-byte array.
+	SpanID SpanID `json:"spanId,omitempty"`
+	// The trace_state associated with the link.
+	TraceState string `json:"traceState,omitempty"`
+	// attributes is a collection of attribute key/value pairs on the link.
+	// Attribute keys MUST be unique (it is not allowed to have more than one
+	// attribute with the same key).
+	Attrs []Attr `json:"attributes,omitempty"`
+	// dropped_attributes_count is the number of dropped attributes. If the value is 0,
+	// then no attributes were dropped.
+	DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"`
+	// Flags, a bit field.
+	//
+	// Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace
+	// Context specification. To read the 8-bit W3C trace flag, use
+	// `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`.
+	//
+	// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions.
+	//
+	// Bits 8 and 9 represent the 3 states of whether the link is remote.
+	// The states are (unknown, is not remote, is remote).
+	// To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`.
+	// To read whether the link is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`.
+	//
+	// Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero.
+	// When creating new spans, bits 10-31 (most-significant 22-bits) MUST be zero.
+	//
+	// [Optional].
+	Flags uint32 `json:"flags,omitempty"`
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into sl.
+func (sl *SpanLink) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid SpanLink type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid SpanLink field: %#v", keyIface)
+		}
+
+		switch key {
+		case "traceId", "trace_id":
+			err = decoder.Decode(&sl.TraceID)
+		case "spanId", "span_id":
+			err = decoder.Decode(&sl.SpanID)
+		case "traceState", "trace_state":
+			err = decoder.Decode(&sl.TraceState)
+		case "attributes":
+			err = decoder.Decode(&sl.Attrs)
+		case "droppedAttributesCount", "dropped_attributes_count":
+			err = decoder.Decode(&sl.DroppedAttrs)
+		case "flags":
+			err = decoder.Decode(&sl.Flags)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/status.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/status.go
new file mode 100644
index 00000000..1217776e
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/status.go
@@ -0,0 +1,40 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+// For the semantics of status codes see
+// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#set-status
+type StatusCode int32
+
+const (
+	// The default status.
+	StatusCodeUnset StatusCode = 0
+	// The Span has been validated by an Application developer or Operator to
+	// have completed successfully.
+	StatusCodeOK StatusCode = 1
+	// The Span contains an error.
+	StatusCodeError StatusCode = 2
+)
+
+var statusCodeStrings = []string{
+	"Unset",
+	"OK",
+	"Error",
+}
+
+func (s StatusCode) String() string {
+	if s >= 0 && int(s) < len(statusCodeStrings) {
+		return statusCodeStrings[s]
+	}
+	return "<unknown telemetry.StatusCode>"
+}
+
+// The Status type defines a logical error model that is suitable for different
+// programming environments, including REST APIs and RPC APIs.
+type Status struct {
+	// A developer-facing human readable error message.
+	Message string `json:"message,omitempty"`
+	// The status code.
+	Code StatusCode `json:"code,omitempty"`
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/traces.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/traces.go
new file mode 100644
index 00000000..69a348f0
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/traces.go
@@ -0,0 +1,189 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package telemetry
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// Traces represents the traces data that can be stored in a persistent storage,
+// OR can be embedded by other protocols that transfer OTLP traces data but do
+// not implement the OTLP protocol.
+//
+// The main difference between this message and collector protocol is that
+// in this message there will not be any "control" or "metadata" specific to
+// OTLP protocol.
+//
+// When new fields are added into this message, the OTLP request MUST be updated
+// as well.
+type Traces struct {
+	// An array of ResourceSpans.
+	// For data coming from a single resource this array will typically contain
+	// one element. Intermediary nodes that receive data from multiple origins
+	// typically batch the data before forwarding further and in that case this
+	// array will contain multiple elements.
+	ResourceSpans []*ResourceSpans `json:"resourceSpans,omitempty"`
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into td.
+func (td *Traces) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid TracesData type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid TracesData field: %#v", keyIface)
+		}
+
+		switch key {
+		case "resourceSpans", "resource_spans":
+			err = decoder.Decode(&td.ResourceSpans)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// A collection of ScopeSpans from a Resource.
+type ResourceSpans struct {
+	// The resource for the spans in this message.
+	// If this field is not set then no resource info is known.
+	Resource Resource `json:"resource"`
+	// A list of ScopeSpans that originate from a resource.
+	ScopeSpans []*ScopeSpans `json:"scopeSpans,omitempty"`
+	// This schema_url applies to the data in the "resource" field. It does not apply
+	// to the data in the "scope_spans" field which have their own schema_url field.
+	SchemaURL string `json:"schemaUrl,omitempty"`
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into rs.
+func (rs *ResourceSpans) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid ResourceSpans type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid ResourceSpans field: %#v", keyIface)
+		}
+
+		switch key {
+		case "resource":
+			err = decoder.Decode(&rs.Resource)
+		case "scopeSpans", "scope_spans":
+			err = decoder.Decode(&rs.ScopeSpans)
+		case "schemaUrl", "schema_url":
+			err = decoder.Decode(&rs.SchemaURL)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// A collection of Spans produced by an InstrumentationScope.
+type ScopeSpans struct {
+	// The instrumentation scope information for the spans in this message.
+	// Semantically when InstrumentationScope isn't set, it is equivalent with
+	// an empty instrumentation scope name (unknown).
+	Scope *Scope `json:"scope"`
+	// A list of Spans that originate from an instrumentation scope.
+	Spans []*Span `json:"spans,omitempty"`
+	// The Schema URL, if known. This is the identifier of the Schema that the span data
+	// is recorded in. To learn more about Schema URL see
+	// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url
+	// This schema_url applies to all spans and span events in the "spans" field.
+	SchemaURL string `json:"schemaUrl,omitempty"`
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into ss.
+func (ss *ScopeSpans) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid ScopeSpans type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid ScopeSpans field: %#v", keyIface)
+		}
+
+		switch key {
+		case "scope":
+			err = decoder.Decode(&ss.Scope)
+		case "spans":
+			err = decoder.Decode(&ss.Spans)
+		case "schemaUrl", "schema_url":
+			err = decoder.Decode(&ss.SchemaURL)
+		default:
+			// Skip unknown.
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/value.go b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/value.go
new file mode 100644
index 00000000..0dd01b06
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/value.go
@@ -0,0 +1,452 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+//go:generate stringer -type=ValueKind -trimprefix=ValueKind
+
+package telemetry
+
+import (
+	"bytes"
+	"cmp"
+	"encoding/base64"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"math"
+	"slices"
+	"strconv"
+	"unsafe"
+)
+
+// A Value represents a structured value.
+// A zero value is valid and represents an empty value.
+type Value struct {
+	// Ensure forward compatibility by explicitly making this not comparable.
+	noCmp [0]func() //nolint: unused  // This is indeed used.
+
+	// num holds the value for Int64, Float64, and Bool. It holds the length
+	// for String, Bytes, Slice, Map.
+	num uint64
+	// any holds either the KindBool, KindInt64, KindFloat64, stringptr,
+	// bytesptr, sliceptr, or mapptr. If KindBool, KindInt64, or KindFloat64
+	// then the value of Value is in num as described above. Otherwise, it
+	// contains the value wrapped in the appropriate type.
+	any any
+}
+
+type (
+	// sliceptr represents a value in Value.any for KindString Values.
+	stringptr *byte
+	// bytesptr represents a value in Value.any for KindBytes Values.
+	bytesptr *byte
+	// sliceptr represents a value in Value.any for KindSlice Values.
+	sliceptr *Value
+	// mapptr represents a value in Value.any for KindMap Values.
+	mapptr *Attr
+)
+
+// ValueKind is the kind of a [Value].
+type ValueKind int
+
+// ValueKind values.
+const (
+	ValueKindEmpty ValueKind = iota
+	ValueKindBool
+	ValueKindFloat64
+	ValueKindInt64
+	ValueKindString
+	ValueKindBytes
+	ValueKindSlice
+	ValueKindMap
+)
+
+var valueKindStrings = []string{
+	"Empty",
+	"Bool",
+	"Float64",
+	"Int64",
+	"String",
+	"Bytes",
+	"Slice",
+	"Map",
+}
+
+func (k ValueKind) String() string {
+	if k >= 0 && int(k) < len(valueKindStrings) {
+		return valueKindStrings[k]
+	}
+	return "<unknown telemetry.ValueKind>"
+}
+
+// StringValue returns a new [Value] for a string.
+func StringValue(v string) Value {
+	return Value{
+		num: uint64(len(v)),
+		any: stringptr(unsafe.StringData(v)),
+	}
+}
+
+// IntValue returns a [Value] for an int.
+func IntValue(v int) Value { return Int64Value(int64(v)) }
+
+// Int64Value returns a [Value] for an int64.
+func Int64Value(v int64) Value {
+	return Value{num: uint64(v), any: ValueKindInt64}
+}
+
+// Float64Value returns a [Value] for a float64.
+func Float64Value(v float64) Value {
+	return Value{num: math.Float64bits(v), any: ValueKindFloat64}
+}
+
+// BoolValue returns a [Value] for a bool.
+func BoolValue(v bool) Value { //nolint:revive // Not a control flag.
+	var n uint64
+	if v {
+		n = 1
+	}
+	return Value{num: n, any: ValueKindBool}
+}
+
+// BytesValue returns a [Value] for a byte slice. The passed slice must not be
+// changed after it is passed.
+func BytesValue(v []byte) Value {
+	return Value{
+		num: uint64(len(v)),
+		any: bytesptr(unsafe.SliceData(v)),
+	}
+}
+
+// SliceValue returns a [Value] for a slice of [Value]. The passed slice must
+// not be changed after it is passed.
+func SliceValue(vs ...Value) Value {
+	return Value{
+		num: uint64(len(vs)),
+		any: sliceptr(unsafe.SliceData(vs)),
+	}
+}
+
+// MapValue returns a new [Value] for a slice of key-value pairs. The passed
+// slice must not be changed after it is passed.
+func MapValue(kvs ...Attr) Value {
+	return Value{
+		num: uint64(len(kvs)),
+		any: mapptr(unsafe.SliceData(kvs)),
+	}
+}
+
+// AsString returns the value held by v as a string.
+func (v Value) AsString() string {
+	if sp, ok := v.any.(stringptr); ok {
+		return unsafe.String(sp, v.num)
+	}
+	// TODO: error handle
+	return ""
+}
+
+// asString returns the value held by v as a string. It will panic if the Value
+// is not KindString.
+func (v Value) asString() string {
+	return unsafe.String(v.any.(stringptr), v.num)
+}
+
+// AsInt64 returns the value held by v as an int64.
+func (v Value) AsInt64() int64 {
+	if v.Kind() != ValueKindInt64 {
+		// TODO: error handle
+		return 0
+	}
+	return v.asInt64()
+}
+
+// asInt64 returns the value held by v as an int64. If v is not of KindInt64,
+// this will return garbage.
+func (v Value) asInt64() int64 {
+	// Assumes v.num was a valid int64 (overflow not checked).
+	return int64(v.num) // nolint: gosec
+}
+
+// AsBool returns the value held by v as a bool.
+func (v Value) AsBool() bool {
+	if v.Kind() != ValueKindBool {
+		// TODO: error handle
+		return false
+	}
+	return v.asBool()
+}
+
+// asBool returns the value held by v as a bool. If v is not of KindBool, this
+// will return garbage.
+func (v Value) asBool() bool { return v.num == 1 }
+
+// AsFloat64 returns the value held by v as a float64.
+func (v Value) AsFloat64() float64 {
+	if v.Kind() != ValueKindFloat64 {
+		// TODO: error handle
+		return 0
+	}
+	return v.asFloat64()
+}
+
+// asFloat64 returns the value held by v as a float64. If v is not of
+// KindFloat64, this will return garbage.
+func (v Value) asFloat64() float64 { return math.Float64frombits(v.num) }
+
+// AsBytes returns the value held by v as a []byte.
+func (v Value) AsBytes() []byte {
+	if sp, ok := v.any.(bytesptr); ok {
+		return unsafe.Slice((*byte)(sp), v.num)
+	}
+	// TODO: error handle
+	return nil
+}
+
+// asBytes returns the value held by v as a []byte. It will panic if the Value
+// is not KindBytes.
+func (v Value) asBytes() []byte {
+	return unsafe.Slice((*byte)(v.any.(bytesptr)), v.num)
+}
+
+// AsSlice returns the value held by v as a []Value.
+func (v Value) AsSlice() []Value {
+	if sp, ok := v.any.(sliceptr); ok {
+		return unsafe.Slice((*Value)(sp), v.num)
+	}
+	// TODO: error handle
+	return nil
+}
+
+// asSlice returns the value held by v as a []Value. It will panic if the Value
+// is not KindSlice.
+func (v Value) asSlice() []Value {
+	return unsafe.Slice((*Value)(v.any.(sliceptr)), v.num)
+}
+
+// AsMap returns the value held by v as a []Attr.
+func (v Value) AsMap() []Attr {
+	if sp, ok := v.any.(mapptr); ok {
+		return unsafe.Slice((*Attr)(sp), v.num)
+	}
+	// TODO: error handle
+	return nil
+}
+
+// asMap returns the value held by v as a []Attr. It will panic if the
+// Value is not KindMap.
+func (v Value) asMap() []Attr {
+	return unsafe.Slice((*Attr)(v.any.(mapptr)), v.num)
+}
+
+// Kind returns the Kind of v.
+func (v Value) Kind() ValueKind {
+	switch x := v.any.(type) {
+	case ValueKind:
+		return x
+	case stringptr:
+		return ValueKindString
+	case bytesptr:
+		return ValueKindBytes
+	case sliceptr:
+		return ValueKindSlice
+	case mapptr:
+		return ValueKindMap
+	default:
+		return ValueKindEmpty
+	}
+}
+
+// Empty returns if v does not hold any value.
+func (v Value) Empty() bool { return v.Kind() == ValueKindEmpty }
+
+// Equal returns if v is equal to w.
+func (v Value) Equal(w Value) bool {
+	k1 := v.Kind()
+	k2 := w.Kind()
+	if k1 != k2 {
+		return false
+	}
+	switch k1 {
+	case ValueKindInt64, ValueKindBool:
+		return v.num == w.num
+	case ValueKindString:
+		return v.asString() == w.asString()
+	case ValueKindFloat64:
+		return v.asFloat64() == w.asFloat64()
+	case ValueKindSlice:
+		return slices.EqualFunc(v.asSlice(), w.asSlice(), Value.Equal)
+	case ValueKindMap:
+		sv := sortMap(v.asMap())
+		sw := sortMap(w.asMap())
+		return slices.EqualFunc(sv, sw, Attr.Equal)
+	case ValueKindBytes:
+		return bytes.Equal(v.asBytes(), w.asBytes())
+	case ValueKindEmpty:
+		return true
+	default:
+		// TODO: error handle
+		return false
+	}
+}
+
+func sortMap(m []Attr) []Attr {
+	sm := make([]Attr, len(m))
+	copy(sm, m)
+	slices.SortFunc(sm, func(a, b Attr) int {
+		return cmp.Compare(a.Key, b.Key)
+	})
+
+	return sm
+}
+
+// String returns Value's value as a string, formatted like [fmt.Sprint].
+//
+// The returned string is meant for debugging;
+// the string representation is not stable.
+func (v Value) String() string {
+	switch v.Kind() {
+	case ValueKindString:
+		return v.asString()
+	case ValueKindInt64:
+		// Assumes v.num was a valid int64 (overflow not checked).
+		return strconv.FormatInt(int64(v.num), 10) // nolint: gosec
+	case ValueKindFloat64:
+		return strconv.FormatFloat(v.asFloat64(), 'g', -1, 64)
+	case ValueKindBool:
+		return strconv.FormatBool(v.asBool())
+	case ValueKindBytes:
+		return fmt.Sprint(v.asBytes())
+	case ValueKindMap:
+		return fmt.Sprint(v.asMap())
+	case ValueKindSlice:
+		return fmt.Sprint(v.asSlice())
+	case ValueKindEmpty:
+		return "<nil>"
+	default:
+		// Try to handle this as gracefully as possible.
+		//
+		// Don't panic here. The goal here is to have developers find this
+		// first if a slog.Kind is is not handled. It is
+		// preferable to have user's open issue asking why their attributes
+		// have a "unhandled: " prefix than say that their code is panicking.
+		return fmt.Sprintf("<unhandled telemetry.ValueKind: %s>", v.Kind())
+	}
+}
+
+// MarshalJSON encodes v into OTLP formatted JSON.
+func (v *Value) MarshalJSON() ([]byte, error) {
+	switch v.Kind() {
+	case ValueKindString:
+		return json.Marshal(struct {
+			Value string `json:"stringValue"`
+		}{v.asString()})
+	case ValueKindInt64:
+		return json.Marshal(struct {
+			Value string `json:"intValue"`
+		}{strconv.FormatInt(int64(v.num), 10)})
+	case ValueKindFloat64:
+		return json.Marshal(struct {
+			Value float64 `json:"doubleValue"`
+		}{v.asFloat64()})
+	case ValueKindBool:
+		return json.Marshal(struct {
+			Value bool `json:"boolValue"`
+		}{v.asBool()})
+	case ValueKindBytes:
+		return json.Marshal(struct {
+			Value []byte `json:"bytesValue"`
+		}{v.asBytes()})
+	case ValueKindMap:
+		return json.Marshal(struct {
+			Value struct {
+				Values []Attr `json:"values"`
+			} `json:"kvlistValue"`
+		}{struct {
+			Values []Attr `json:"values"`
+		}{v.asMap()}})
+	case ValueKindSlice:
+		return json.Marshal(struct {
+			Value struct {
+				Values []Value `json:"values"`
+			} `json:"arrayValue"`
+		}{struct {
+			Values []Value `json:"values"`
+		}{v.asSlice()}})
+	case ValueKindEmpty:
+		return nil, nil
+	default:
+		return nil, fmt.Errorf("unknown Value kind: %s", v.Kind().String())
+	}
+}
+
+// UnmarshalJSON decodes the OTLP formatted JSON contained in data into v.
+func (v *Value) UnmarshalJSON(data []byte) error {
+	decoder := json.NewDecoder(bytes.NewReader(data))
+
+	t, err := decoder.Token()
+	if err != nil {
+		return err
+	}
+	if t != json.Delim('{') {
+		return errors.New("invalid Value type")
+	}
+
+	for decoder.More() {
+		keyIface, err := decoder.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				// Empty.
+				return nil
+			}
+			return err
+		}
+
+		key, ok := keyIface.(string)
+		if !ok {
+			return fmt.Errorf("invalid Value key: %#v", keyIface)
+		}
+
+		switch key {
+		case "stringValue", "string_value":
+			var val string
+			err = decoder.Decode(&val)
+			*v = StringValue(val)
+		case "boolValue", "bool_value":
+			var val bool
+			err = decoder.Decode(&val)
+			*v = BoolValue(val)
+		case "intValue", "int_value":
+			var val protoInt64
+			err = decoder.Decode(&val)
+			*v = Int64Value(val.Int64())
+		case "doubleValue", "double_value":
+			var val float64
+			err = decoder.Decode(&val)
+			*v = Float64Value(val)
+		case "bytesValue", "bytes_value":
+			var val64 string
+			if err := decoder.Decode(&val64); err != nil {
+				return err
+			}
+			var val []byte
+			val, err = base64.StdEncoding.DecodeString(val64)
+			*v = BytesValue(val)
+		case "arrayValue", "array_value":
+			var val struct{ Values []Value }
+			err = decoder.Decode(&val)
+			*v = SliceValue(val.Values...)
+		case "kvlistValue", "kvlist_value":
+			var val struct{ Values []Attr }
+			err = decoder.Decode(&val)
+			*v = MapValue(val.Values...)
+		default:
+			// Skip unknown.
+			continue
+		}
+		// Use first valid. Ignore the rest.
+		return err
+	}
+
+	// Only unknown fields. Return nil without unmarshaling any value.
+	return nil
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/limit.go b/vendor/go.opentelemetry.io/auto/sdk/limit.go
new file mode 100644
index 00000000..86babf1a
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/limit.go
@@ -0,0 +1,94 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package sdk
+
+import (
+	"log/slog"
+	"os"
+	"strconv"
+)
+
+// maxSpan are the span limits resolved during startup.
+var maxSpan = newSpanLimits()
+
+type spanLimits struct {
+	// Attrs is the number of allowed attributes for a span.
+	//
+	// This is resolved from the environment variable value for the
+	// OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT key if it exists. Otherwise, the
+	// environment variable value for OTEL_ATTRIBUTE_COUNT_LIMIT, or 128 if
+	// that is not set, is used.
+	Attrs int
+	// AttrValueLen is the maximum attribute value length allowed for a span.
+	//
+	// This is resolved from the environment variable value for the
+	// OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT key if it exists. Otherwise, the
+	// environment variable value for OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, or -1
+	// if that is not set, is used.
+	AttrValueLen int
+	// Events is the number of allowed events for a span.
+	//
+	// This is resolved from the environment variable value for the
+	// OTEL_SPAN_EVENT_COUNT_LIMIT key, or 128 is used if that is not set.
+	Events int
+	// EventAttrs is the number of allowed attributes for a span event.
+	//
+	// The is resolved from the environment variable value for the
+	// OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT key, or 128 is used if that is not set.
+	EventAttrs int
+	// Links is the number of allowed Links for a span.
+	//
+	// This is resolved from the environment variable value for the
+	// OTEL_SPAN_LINK_COUNT_LIMIT, or 128 is used if that is not set.
+	Links int
+	// LinkAttrs is the number of allowed attributes for a span link.
+	//
+	// This is resolved from the environment variable value for the
+	// OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, or 128 is used if that is not set.
+	LinkAttrs int
+}
+
+func newSpanLimits() spanLimits {
+	return spanLimits{
+		Attrs: firstEnv(
+			128,
+			"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT",
+			"OTEL_ATTRIBUTE_COUNT_LIMIT",
+		),
+		AttrValueLen: firstEnv(
+			-1, // Unlimited.
+			"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT",
+			"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT",
+		),
+		Events:     firstEnv(128, "OTEL_SPAN_EVENT_COUNT_LIMIT"),
+		EventAttrs: firstEnv(128, "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"),
+		Links:      firstEnv(128, "OTEL_SPAN_LINK_COUNT_LIMIT"),
+		LinkAttrs:  firstEnv(128, "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"),
+	}
+}
+
+// firstEnv returns the parsed integer value of the first matching environment
+// variable from keys. The defaultVal is returned if the value is not an
+// integer or no match is found.
+func firstEnv(defaultVal int, keys ...string) int {
+	for _, key := range keys {
+		strV := os.Getenv(key)
+		if strV == "" {
+			continue
+		}
+
+		v, err := strconv.Atoi(strV)
+		if err == nil {
+			return v
+		}
+		slog.Warn(
+			"invalid limit environment variable",
+			"error", err,
+			"key", key,
+			"value", strV,
+		)
+	}
+
+	return defaultVal
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/span.go b/vendor/go.opentelemetry.io/auto/sdk/span.go
new file mode 100644
index 00000000..6ebea12a
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/span.go
@@ -0,0 +1,432 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package sdk
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"runtime"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"time"
+	"unicode/utf8"
+
+	"go.opentelemetry.io/otel/attribute"
+	"go.opentelemetry.io/otel/codes"
+	semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
+	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/noop"
+
+	"go.opentelemetry.io/auto/sdk/internal/telemetry"
+)
+
+type span struct {
+	noop.Span
+
+	spanContext trace.SpanContext
+	sampled     atomic.Bool
+
+	mu     sync.Mutex
+	traces *telemetry.Traces
+	span   *telemetry.Span
+}
+
+func (s *span) SpanContext() trace.SpanContext {
+	if s == nil {
+		return trace.SpanContext{}
+	}
+	// s.spanContext is immutable, do not acquire lock s.mu.
+	return s.spanContext
+}
+
+func (s *span) IsRecording() bool {
+	if s == nil {
+		return false
+	}
+
+	return s.sampled.Load()
+}
+
+func (s *span) SetStatus(c codes.Code, msg string) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	if s.span.Status == nil {
+		s.span.Status = new(telemetry.Status)
+	}
+
+	s.span.Status.Message = msg
+
+	switch c {
+	case codes.Unset:
+		s.span.Status.Code = telemetry.StatusCodeUnset
+	case codes.Error:
+		s.span.Status.Code = telemetry.StatusCodeError
+	case codes.Ok:
+		s.span.Status.Code = telemetry.StatusCodeOK
+	}
+}
+
+func (s *span) SetAttributes(attrs ...attribute.KeyValue) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	limit := maxSpan.Attrs
+	if limit == 0 {
+		// No attributes allowed.
+		s.span.DroppedAttrs += uint32(len(attrs))
+		return
+	}
+
+	m := make(map[string]int)
+	for i, a := range s.span.Attrs {
+		m[a.Key] = i
+	}
+
+	for _, a := range attrs {
+		val := convAttrValue(a.Value)
+		if val.Empty() {
+			s.span.DroppedAttrs++
+			continue
+		}
+
+		if idx, ok := m[string(a.Key)]; ok {
+			s.span.Attrs[idx] = telemetry.Attr{
+				Key:   string(a.Key),
+				Value: val,
+			}
+		} else if limit < 0 || len(s.span.Attrs) < limit {
+			s.span.Attrs = append(s.span.Attrs, telemetry.Attr{
+				Key:   string(a.Key),
+				Value: val,
+			})
+			m[string(a.Key)] = len(s.span.Attrs) - 1
+		} else {
+			s.span.DroppedAttrs++
+		}
+	}
+}
+
+// convCappedAttrs converts up to limit attrs into a []telemetry.Attr. The
+// number of dropped attributes is also returned.
+func convCappedAttrs(limit int, attrs []attribute.KeyValue) ([]telemetry.Attr, uint32) {
+	if limit == 0 {
+		return nil, uint32(len(attrs))
+	}
+
+	if limit < 0 {
+		// Unlimited.
+		return convAttrs(attrs), 0
+	}
+
+	limit = min(len(attrs), limit)
+	return convAttrs(attrs[:limit]), uint32(len(attrs) - limit)
+}
+
+func convAttrs(attrs []attribute.KeyValue) []telemetry.Attr {
+	if len(attrs) == 0 {
+		// Avoid allocations if not necessary.
+		return nil
+	}
+
+	out := make([]telemetry.Attr, 0, len(attrs))
+	for _, attr := range attrs {
+		key := string(attr.Key)
+		val := convAttrValue(attr.Value)
+		if val.Empty() {
+			continue
+		}
+		out = append(out, telemetry.Attr{Key: key, Value: val})
+	}
+	return out
+}
+
+func convAttrValue(value attribute.Value) telemetry.Value {
+	switch value.Type() {
+	case attribute.BOOL:
+		return telemetry.BoolValue(value.AsBool())
+	case attribute.INT64:
+		return telemetry.Int64Value(value.AsInt64())
+	case attribute.FLOAT64:
+		return telemetry.Float64Value(value.AsFloat64())
+	case attribute.STRING:
+		v := truncate(maxSpan.AttrValueLen, value.AsString())
+		return telemetry.StringValue(v)
+	case attribute.BOOLSLICE:
+		slice := value.AsBoolSlice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			out = append(out, telemetry.BoolValue(v))
+		}
+		return telemetry.SliceValue(out...)
+	case attribute.INT64SLICE:
+		slice := value.AsInt64Slice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			out = append(out, telemetry.Int64Value(v))
+		}
+		return telemetry.SliceValue(out...)
+	case attribute.FLOAT64SLICE:
+		slice := value.AsFloat64Slice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			out = append(out, telemetry.Float64Value(v))
+		}
+		return telemetry.SliceValue(out...)
+	case attribute.STRINGSLICE:
+		slice := value.AsStringSlice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			v = truncate(maxSpan.AttrValueLen, v)
+			out = append(out, telemetry.StringValue(v))
+		}
+		return telemetry.SliceValue(out...)
+	}
+	return telemetry.Value{}
+}
+
+// truncate returns a truncated version of s such that it contains less than
+// the limit number of characters. Truncation is applied by returning the limit
+// number of valid characters contained in s.
+//
+// If limit is negative, it returns the original string.
+//
+// UTF-8 is supported. When truncating, all invalid characters are dropped
+// before applying truncation.
+//
+// If s already contains less than the limit number of bytes, it is returned
+// unchanged. No invalid characters are removed.
+func truncate(limit int, s string) string {
+	// This prioritize performance in the following order based on the most
+	// common expected use-cases.
+	//
+	//  - Short values less than the default limit (128).
+	//  - Strings with valid encodings that exceed the limit.
+	//  - No limit.
+	//  - Strings with invalid encodings that exceed the limit.
+	if limit < 0 || len(s) <= limit {
+		return s
+	}
+
+	// Optimistically, assume all valid UTF-8.
+	var b strings.Builder
+	count := 0
+	for i, c := range s {
+		if c != utf8.RuneError {
+			count++
+			if count > limit {
+				return s[:i]
+			}
+			continue
+		}
+
+		_, size := utf8.DecodeRuneInString(s[i:])
+		if size == 1 {
+			// Invalid encoding.
+			b.Grow(len(s) - 1)
+			_, _ = b.WriteString(s[:i])
+			s = s[i:]
+			break
+		}
+	}
+
+	// Fast-path, no invalid input.
+	if b.Cap() == 0 {
+		return s
+	}
+
+	// Truncate while validating UTF-8.
+	for i := 0; i < len(s) && count < limit; {
+		c := s[i]
+		if c < utf8.RuneSelf {
+			// Optimization for single byte runes (common case).
+			_ = b.WriteByte(c)
+			i++
+			count++
+			continue
+		}
+
+		_, size := utf8.DecodeRuneInString(s[i:])
+		if size == 1 {
+			// We checked for all 1-byte runes above, this is a RuneError.
+			i++
+			continue
+		}
+
+		_, _ = b.WriteString(s[i : i+size])
+		i += size
+		count++
+	}
+
+	return b.String()
+}
+
+func (s *span) End(opts ...trace.SpanEndOption) {
+	if s == nil || !s.sampled.Swap(false) {
+		return
+	}
+
+	// s.end exists so the lock (s.mu) is not held while s.ended is called.
+	s.ended(s.end(opts))
+}
+
+func (s *span) end(opts []trace.SpanEndOption) []byte {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	cfg := trace.NewSpanEndConfig(opts...)
+	if t := cfg.Timestamp(); !t.IsZero() {
+		s.span.EndTime = cfg.Timestamp()
+	} else {
+		s.span.EndTime = time.Now()
+	}
+
+	b, _ := json.Marshal(s.traces) // TODO: do not ignore this error.
+	return b
+}
+
+// Expected to be implemented in eBPF.
+//
+//go:noinline
+func (*span) ended(buf []byte) { ended(buf) }
+
+// ended is used for testing.
+var ended = func([]byte) {}
+
+func (s *span) RecordError(err error, opts ...trace.EventOption) {
+	if s == nil || err == nil || !s.sampled.Load() {
+		return
+	}
+
+	cfg := trace.NewEventConfig(opts...)
+
+	attrs := cfg.Attributes()
+	attrs = append(attrs,
+		semconv.ExceptionType(typeStr(err)),
+		semconv.ExceptionMessage(err.Error()),
+	)
+	if cfg.StackTrace() {
+		buf := make([]byte, 2048)
+		n := runtime.Stack(buf, false)
+		attrs = append(attrs, semconv.ExceptionStacktrace(string(buf[0:n])))
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.addEvent(semconv.ExceptionEventName, cfg.Timestamp(), attrs)
+}
+
+func typeStr(i any) string {
+	t := reflect.TypeOf(i)
+	if t.PkgPath() == "" && t.Name() == "" {
+		// Likely a builtin type.
+		return t.String()
+	}
+	return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
+}
+
+func (s *span) AddEvent(name string, opts ...trace.EventOption) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	cfg := trace.NewEventConfig(opts...)
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.addEvent(name, cfg.Timestamp(), cfg.Attributes())
+}
+
+// addEvent adds an event with name and attrs at tStamp to the span. The span
+// lock (s.mu) needs to be held by the caller.
+func (s *span) addEvent(name string, tStamp time.Time, attrs []attribute.KeyValue) {
+	limit := maxSpan.Events
+
+	if limit == 0 {
+		s.span.DroppedEvents++
+		return
+	}
+
+	if limit > 0 && len(s.span.Events) == limit {
+		// Drop head while avoiding allocation of more capacity.
+		copy(s.span.Events[:limit-1], s.span.Events[1:])
+		s.span.Events = s.span.Events[:limit-1]
+		s.span.DroppedEvents++
+	}
+
+	e := &telemetry.SpanEvent{Time: tStamp, Name: name}
+	e.Attrs, e.DroppedAttrs = convCappedAttrs(maxSpan.EventAttrs, attrs)
+
+	s.span.Events = append(s.span.Events, e)
+}
+
+func (s *span) AddLink(link trace.Link) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	l := maxSpan.Links
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	if l == 0 {
+		s.span.DroppedLinks++
+		return
+	}
+
+	if l > 0 && len(s.span.Links) == l {
+		// Drop head while avoiding allocation of more capacity.
+		copy(s.span.Links[:l-1], s.span.Links[1:])
+		s.span.Links = s.span.Links[:l-1]
+		s.span.DroppedLinks++
+	}
+
+	s.span.Links = append(s.span.Links, convLink(link))
+}
+
+func convLinks(links []trace.Link) []*telemetry.SpanLink {
+	out := make([]*telemetry.SpanLink, 0, len(links))
+	for _, link := range links {
+		out = append(out, convLink(link))
+	}
+	return out
+}
+
+func convLink(link trace.Link) *telemetry.SpanLink {
+	l := &telemetry.SpanLink{
+		TraceID:    telemetry.TraceID(link.SpanContext.TraceID()),
+		SpanID:     telemetry.SpanID(link.SpanContext.SpanID()),
+		TraceState: link.SpanContext.TraceState().String(),
+		Flags:      uint32(link.SpanContext.TraceFlags()),
+	}
+	l.Attrs, l.DroppedAttrs = convCappedAttrs(maxSpan.LinkAttrs, link.Attributes)
+
+	return l
+}
+
+func (s *span) SetName(name string) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.span.Name = name
+}
+
+func (*span) TracerProvider() trace.TracerProvider { return TracerProvider() }
diff --git a/vendor/go.opentelemetry.io/auto/sdk/tracer.go b/vendor/go.opentelemetry.io/auto/sdk/tracer.go
new file mode 100644
index 00000000..cbcfabde
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/tracer.go
@@ -0,0 +1,124 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package sdk
+
+import (
+	"context"
+	"time"
+
+	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/noop"
+
+	"go.opentelemetry.io/auto/sdk/internal/telemetry"
+)
+
+type tracer struct {
+	noop.Tracer
+
+	name, schemaURL, version string
+}
+
+var _ trace.Tracer = tracer{}
+
+func (t tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
+	var psc trace.SpanContext
+	sampled := true
+	span := new(span)
+
+	// Ask eBPF for sampling decision and span context info.
+	t.start(ctx, span, &psc, &sampled, &span.spanContext)
+
+	span.sampled.Store(sampled)
+
+	ctx = trace.ContextWithSpan(ctx, span)
+
+	if sampled {
+		// Only build traces if sampled.
+		cfg := trace.NewSpanStartConfig(opts...)
+		span.traces, span.span = t.traces(name, cfg, span.spanContext, psc)
+	}
+
+	return ctx, span
+}
+
+// Expected to be implemented in eBPF.
+//
+//go:noinline
+func (t *tracer) start(
+	ctx context.Context,
+	spanPtr *span,
+	psc *trace.SpanContext,
+	sampled *bool,
+	sc *trace.SpanContext,
+) {
+	start(ctx, spanPtr, psc, sampled, sc)
+}
+
+// start is used for testing.
+var start = func(context.Context, *span, *trace.SpanContext, *bool, *trace.SpanContext) {}
+
+func (t tracer) traces(name string, cfg trace.SpanConfig, sc, psc trace.SpanContext) (*telemetry.Traces, *telemetry.Span) {
+	span := &telemetry.Span{
+		TraceID:      telemetry.TraceID(sc.TraceID()),
+		SpanID:       telemetry.SpanID(sc.SpanID()),
+		Flags:        uint32(sc.TraceFlags()),
+		TraceState:   sc.TraceState().String(),
+		ParentSpanID: telemetry.SpanID(psc.SpanID()),
+		Name:         name,
+		Kind:         spanKind(cfg.SpanKind()),
+	}
+
+	span.Attrs, span.DroppedAttrs = convCappedAttrs(maxSpan.Attrs, cfg.Attributes())
+
+	links := cfg.Links()
+	if limit := maxSpan.Links; limit == 0 {
+		span.DroppedLinks = uint32(len(links))
+	} else {
+		if limit > 0 {
+			n := max(len(links)-limit, 0)
+			span.DroppedLinks = uint32(n)
+			links = links[n:]
+		}
+		span.Links = convLinks(links)
+	}
+
+	if t := cfg.Timestamp(); !t.IsZero() {
+		span.StartTime = cfg.Timestamp()
+	} else {
+		span.StartTime = time.Now()
+	}
+
+	return &telemetry.Traces{
+		ResourceSpans: []*telemetry.ResourceSpans{
+			{
+				ScopeSpans: []*telemetry.ScopeSpans{
+					{
+						Scope: &telemetry.Scope{
+							Name:    t.name,
+							Version: t.version,
+						},
+						Spans:     []*telemetry.Span{span},
+						SchemaURL: t.schemaURL,
+					},
+				},
+			},
+		},
+	}, span
+}
+
+func spanKind(kind trace.SpanKind) telemetry.SpanKind {
+	switch kind {
+	case trace.SpanKindInternal:
+		return telemetry.SpanKindInternal
+	case trace.SpanKindServer:
+		return telemetry.SpanKindServer
+	case trace.SpanKindClient:
+		return telemetry.SpanKindClient
+	case trace.SpanKindProducer:
+		return telemetry.SpanKindProducer
+	case trace.SpanKindConsumer:
+		return telemetry.SpanKindConsumer
+	}
+	return telemetry.SpanKind(0) // undefined.
+}
diff --git a/vendor/go.opentelemetry.io/auto/sdk/tracer_provider.go b/vendor/go.opentelemetry.io/auto/sdk/tracer_provider.go
new file mode 100644
index 00000000..dbc477a5
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/tracer_provider.go
@@ -0,0 +1,33 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package sdk
+
+import (
+	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/noop"
+)
+
+// TracerProvider returns an auto-instrumentable [trace.TracerProvider].
+//
+// If an [go.opentelemetry.io/auto.Instrumentation] is configured to instrument
+// the process using the returned TracerProvider, all of the telemetry it
+// produces will be processed and handled by that Instrumentation. By default,
+// if no Instrumentation instruments the TracerProvider it will not generate
+// any trace telemetry.
+func TracerProvider() trace.TracerProvider { return tracerProviderInstance }
+
+var tracerProviderInstance = new(tracerProvider)
+
+type tracerProvider struct{ noop.TracerProvider }
+
+var _ trace.TracerProvider = tracerProvider{}
+
+func (p tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
+	cfg := trace.NewTracerConfig(opts...)
+	return tracer{
+		name:      name,
+		version:   cfg.InstrumentationVersion(),
+		schemaURL: cfg.SchemaURL(),
+	}
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go
index 6aae83bf..b25641c5 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go
@@ -18,7 +18,7 @@ var DefaultClient = &http.Client{Transport: NewTransport(http.DefaultTransport)}
 
 // Get is a convenient replacement for http.Get that adds a span around the request.
 func Get(ctx context.Context, targetURL string) (resp *http.Response, err error) {
-	req, err := http.NewRequestWithContext(ctx, "GET", targetURL, nil)
+	req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -27,7 +27,7 @@ func Get(ctx context.Context, targetURL string) (resp *http.Response, err error)
 
 // Head is a convenient replacement for http.Head that adds a span around the request.
 func Head(ctx context.Context, targetURL string) (resp *http.Response, err error) {
-	req, err := http.NewRequestWithContext(ctx, "HEAD", targetURL, nil)
+	req, err := http.NewRequestWithContext(ctx, http.MethodHead, targetURL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -36,7 +36,7 @@ func Head(ctx context.Context, targetURL string) (resp *http.Response, err error
 
 // Post is a convenient replacement for http.Post that adds a span around the request.
 func Post(ctx context.Context, targetURL, contentType string, body io.Reader) (resp *http.Response, err error) {
-	req, err := http.NewRequestWithContext(ctx, "POST", targetURL, body)
+	req, err := http.NewRequestWithContext(ctx, http.MethodPost, targetURL, body)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
index e4236ab3..e555a475 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
@@ -117,6 +117,11 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
 		}
 	}
 
+	if startTime := StartTimeFromContext(ctx); !startTime.IsZero() {
+		opts = append(opts, trace.WithTimestamp(startTime))
+		requestStartTime = startTime
+	}
+
 	ctx, span := tracer.Start(ctx, h.spanNameFormatter(h.operation, r), opts...)
 	defer span.End()
 
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
index fb893b25..3b036f8a 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"os"
 	"strings"
+	"sync"
 
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/codes"
@@ -50,9 +51,9 @@ type HTTPServer struct {
 // The req Host will be used to determine the server instead.
 func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
 	if s.duplicate {
-		return append(oldHTTPServer{}.RequestTraceAttrs(server, req), newHTTPServer{}.RequestTraceAttrs(server, req)...)
+		return append(OldHTTPServer{}.RequestTraceAttrs(server, req), CurrentHTTPServer{}.RequestTraceAttrs(server, req)...)
 	}
-	return oldHTTPServer{}.RequestTraceAttrs(server, req)
+	return OldHTTPServer{}.RequestTraceAttrs(server, req)
 }
 
 // ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
@@ -60,14 +61,14 @@ func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request) []attrib
 // If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
 func (s HTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
 	if s.duplicate {
-		return append(oldHTTPServer{}.ResponseTraceAttrs(resp), newHTTPServer{}.ResponseTraceAttrs(resp)...)
+		return append(OldHTTPServer{}.ResponseTraceAttrs(resp), CurrentHTTPServer{}.ResponseTraceAttrs(resp)...)
 	}
-	return oldHTTPServer{}.ResponseTraceAttrs(resp)
+	return OldHTTPServer{}.ResponseTraceAttrs(resp)
 }
 
 // Route returns the attribute for the route.
 func (s HTTPServer) Route(route string) attribute.KeyValue {
-	return oldHTTPServer{}.Route(route)
+	return OldHTTPServer{}.Route(route)
 }
 
 // Status returns a span status code and message for an HTTP status code
@@ -102,18 +103,27 @@ type MetricData struct {
 	ElapsedTime float64
 }
 
+var metricAddOptionPool = &sync.Pool{
+	New: func() interface{} {
+		return &[]metric.AddOption{}
+	},
+}
+
 func (s HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) {
 	if s.requestBytesCounter == nil || s.responseBytesCounter == nil || s.serverLatencyMeasure == nil {
-		// This will happen if an HTTPServer{} is used insted of NewHTTPServer.
+		// This will happen if an HTTPServer{} is used instead of NewHTTPServer.
 		return
 	}
 
-	attributes := oldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
+	attributes := OldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
 	o := metric.WithAttributeSet(attribute.NewSet(attributes...))
-	addOpts := []metric.AddOption{o}
-	s.requestBytesCounter.Add(ctx, md.RequestSize, addOpts...)
-	s.responseBytesCounter.Add(ctx, md.ResponseSize, addOpts...)
+	addOpts := metricAddOptionPool.Get().(*[]metric.AddOption)
+	*addOpts = append(*addOpts, o)
+	s.requestBytesCounter.Add(ctx, md.RequestSize, *addOpts...)
+	s.responseBytesCounter.Add(ctx, md.ResponseSize, *addOpts...)
 	s.serverLatencyMeasure.Record(ctx, md.ElapsedTime, o)
+	*addOpts = (*addOpts)[:0]
+	metricAddOptionPool.Put(addOpts)
 
 	// TODO: Duplicate Metrics
 }
@@ -124,7 +134,7 @@ func NewHTTPServer(meter metric.Meter) HTTPServer {
 	server := HTTPServer{
 		duplicate: duplicate,
 	}
-	server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = oldHTTPServer{}.createMeasures(meter)
+	server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = OldHTTPServer{}.createMeasures(meter)
 	return server
 }
 
@@ -142,25 +152,25 @@ func NewHTTPClient(meter metric.Meter) HTTPClient {
 	client := HTTPClient{
 		duplicate: env == "http/dup",
 	}
-	client.requestBytesCounter, client.responseBytesCounter, client.latencyMeasure = oldHTTPClient{}.createMeasures(meter)
+	client.requestBytesCounter, client.responseBytesCounter, client.latencyMeasure = OldHTTPClient{}.createMeasures(meter)
 	return client
 }
 
 // RequestTraceAttrs returns attributes for an HTTP request made by a client.
 func (c HTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
 	if c.duplicate {
-		return append(oldHTTPClient{}.RequestTraceAttrs(req), newHTTPClient{}.RequestTraceAttrs(req)...)
+		return append(OldHTTPClient{}.RequestTraceAttrs(req), CurrentHTTPClient{}.RequestTraceAttrs(req)...)
 	}
-	return oldHTTPClient{}.RequestTraceAttrs(req)
+	return OldHTTPClient{}.RequestTraceAttrs(req)
 }
 
 // ResponseTraceAttrs returns metric attributes for an HTTP request made by a client.
 func (c HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
 	if c.duplicate {
-		return append(oldHTTPClient{}.ResponseTraceAttrs(resp), newHTTPClient{}.ResponseTraceAttrs(resp)...)
+		return append(OldHTTPClient{}.ResponseTraceAttrs(resp), CurrentHTTPClient{}.ResponseTraceAttrs(resp)...)
 	}
 
-	return oldHTTPClient{}.ResponseTraceAttrs(resp)
+	return OldHTTPClient{}.ResponseTraceAttrs(resp)
 }
 
 func (c HTTPClient) Status(code int) (codes.Code, string) {
@@ -175,7 +185,7 @@ func (c HTTPClient) Status(code int) (codes.Code, string) {
 
 func (c HTTPClient) ErrorType(err error) attribute.KeyValue {
 	if c.duplicate {
-		return newHTTPClient{}.ErrorType(err)
+		return CurrentHTTPClient{}.ErrorType(err)
 	}
 
 	return attribute.KeyValue{}
@@ -195,7 +205,7 @@ func (o MetricOpts) AddOptions() metric.AddOption {
 }
 
 func (c HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts {
-	attributes := oldHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
+	attributes := OldHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
 	// TODO: Duplicate Metrics
 	set := metric.WithAttributeSet(attribute.NewSet(attributes...))
 	return MetricOpts{
@@ -206,7 +216,7 @@ func (c HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts {
 
 func (s HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts MetricOpts) {
 	if s.requestBytesCounter == nil || s.latencyMeasure == nil {
-		// This will happen if an HTTPClient{} is used insted of NewHTTPClient().
+		// This will happen if an HTTPClient{} is used instead of NewHTTPClient().
 		return
 	}
 
@@ -218,7 +228,7 @@ func (s HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts Metri
 
 func (s HTTPClient) RecordResponseSize(ctx context.Context, responseData int64, opts metric.AddOption) {
 	if s.responseBytesCounter == nil {
-		// This will happen if an HTTPClient{} is used insted of NewHTTPClient().
+		// This will happen if an HTTPClient{} is used instead of NewHTTPClient().
 		return
 	}
 
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
index 745b8c67..dc9ec7bc 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
@@ -14,7 +14,7 @@ import (
 	semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
 )
 
-type newHTTPServer struct{}
+type CurrentHTTPServer struct{}
 
 // TraceRequest returns trace attributes for an HTTP request received by a
 // server.
@@ -32,18 +32,18 @@ type newHTTPServer struct{}
 //
 // If the primary server name is not known, server should be an empty string.
 // The req Host will be used to determine the server instead.
-func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
+func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
 	count := 3 // ServerAddress, Method, Scheme
 
 	var host string
 	var p int
 	if server == "" {
-		host, p = splitHostPort(req.Host)
+		host, p = SplitHostPort(req.Host)
 	} else {
 		// Prioritize the primary server name.
-		host, p = splitHostPort(server)
+		host, p = SplitHostPort(server)
 		if p < 0 {
-			_, p = splitHostPort(req.Host)
+			_, p = SplitHostPort(req.Host)
 		}
 	}
 
@@ -59,7 +59,7 @@ func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []att
 
 	scheme := n.scheme(req.TLS != nil)
 
-	if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
+	if peer, peerPort := SplitHostPort(req.RemoteAddr); peer != "" {
 		// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
 		// file-path that would be interpreted with a sock family.
 		count++
@@ -104,7 +104,7 @@ func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []att
 		attrs = append(attrs, methodOriginal)
 	}
 
-	if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
+	if peer, peerPort := SplitHostPort(req.RemoteAddr); peer != "" {
 		// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
 		// file-path that would be interpreted with a sock family.
 		attrs = append(attrs, semconvNew.NetworkPeerAddress(peer))
@@ -135,7 +135,7 @@ func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []att
 	return attrs
 }
 
-func (n newHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
+func (n CurrentHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
 	if method == "" {
 		return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
 	}
@@ -150,7 +150,7 @@ func (n newHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyV
 	return semconvNew.HTTPRequestMethodGet, orig
 }
 
-func (n newHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
+func (n CurrentHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
 	if https {
 		return semconvNew.URLScheme("https")
 	}
@@ -160,7 +160,7 @@ func (n newHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
 // TraceResponse returns trace attributes for telemetry from an HTTP response.
 //
 // If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
-func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
+func (n CurrentHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
 	var count int
 
 	if resp.ReadBytes > 0 {
@@ -195,14 +195,14 @@ func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
 }
 
 // Route returns the attribute for the route.
-func (n newHTTPServer) Route(route string) attribute.KeyValue {
+func (n CurrentHTTPServer) Route(route string) attribute.KeyValue {
 	return semconvNew.HTTPRoute(route)
 }
 
-type newHTTPClient struct{}
+type CurrentHTTPClient struct{}
 
 // RequestTraceAttrs returns trace attributes for an HTTP request made by a client.
-func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
+func (n CurrentHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
 	/*
 	   below attributes are returned:
 	   - http.request.method
@@ -222,7 +222,7 @@ func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue
 	var requestHost string
 	var requestPort int
 	for _, hostport := range []string{urlHost, req.Header.Get("Host")} {
-		requestHost, requestPort = splitHostPort(hostport)
+		requestHost, requestPort = SplitHostPort(hostport)
 		if requestHost != "" || requestPort > 0 {
 			break
 		}
@@ -284,7 +284,7 @@ func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue
 }
 
 // ResponseTraceAttrs returns trace attributes for an HTTP response made by a client.
-func (n newHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
+func (n CurrentHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
 	/*
 	   below attributes are returned:
 	   - http.response.status_code
@@ -311,7 +311,7 @@ func (n newHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyVa
 	return attrs
 }
 
-func (n newHTTPClient) ErrorType(err error) attribute.KeyValue {
+func (n CurrentHTTPClient) ErrorType(err error) attribute.KeyValue {
 	t := reflect.TypeOf(err)
 	var value string
 	if t.PkgPath() == "" && t.Name() == "" {
@@ -328,7 +328,7 @@ func (n newHTTPClient) ErrorType(err error) attribute.KeyValue {
 	return semconvNew.ErrorTypeKey.String(value)
 }
 
-func (n newHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) {
+func (n CurrentHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) {
 	if method == "" {
 		return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
 	}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
index e6e14924..93e8d0f9 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
@@ -14,14 +14,14 @@ import (
 	semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
 )
 
-// splitHostPort splits a network address hostport of the form "host",
+// SplitHostPort splits a network address hostport of the form "host",
 // "host%zone", "[host]", "[host%zone], "host:port", "host%zone:port",
 // "[host]:port", "[host%zone]:port", or ":port" into host or host%zone and
 // port.
 //
 // An empty host is returned if it is not provided or unparsable. A negative
 // port is returned if it is not provided or unparsable.
-func splitHostPort(hostport string) (host string, port int) {
+func SplitHostPort(hostport string) (host string, port int) {
 	port = -1
 
 	if strings.HasPrefix(hostport, "[") {
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
index 5367732e..c042249d 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
@@ -17,7 +17,7 @@ import (
 	semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
 )
 
-type oldHTTPServer struct{}
+type OldHTTPServer struct{}
 
 // RequestTraceAttrs returns trace attributes for an HTTP request received by a
 // server.
@@ -35,14 +35,14 @@ type oldHTTPServer struct{}
 //
 // If the primary server name is not known, server should be an empty string.
 // The req Host will be used to determine the server instead.
-func (o oldHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
+func (o OldHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
 	return semconvutil.HTTPServerRequest(server, req)
 }
 
 // ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
 //
 // If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
-func (o oldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
+func (o OldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
 	attributes := []attribute.KeyValue{}
 
 	if resp.ReadBytes > 0 {
@@ -67,7 +67,7 @@ func (o oldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
 }
 
 // Route returns the attribute for the route.
-func (o oldHTTPServer) Route(route string) attribute.KeyValue {
+func (o OldHTTPServer) Route(route string) attribute.KeyValue {
 	return semconv.HTTPRoute(route)
 }
 
@@ -84,7 +84,7 @@ const (
 	serverDuration     = "http.server.duration"      // Incoming end to end duration, milliseconds
 )
 
-func (h oldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
+func (h OldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
 	if meter == nil {
 		return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{}
 	}
@@ -113,17 +113,17 @@ func (h oldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter,
 	return requestBytesCounter, responseBytesCounter, serverLatencyMeasure
 }
 
-func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
+func (o OldHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
 	n := len(additionalAttributes) + 3
 	var host string
 	var p int
 	if server == "" {
-		host, p = splitHostPort(req.Host)
+		host, p = SplitHostPort(req.Host)
 	} else {
 		// Prioritize the primary server name.
-		host, p = splitHostPort(server)
+		host, p = SplitHostPort(server)
 		if p < 0 {
-			_, p = splitHostPort(req.Host)
+			_, p = SplitHostPort(req.Host)
 		}
 	}
 	hostPort := requiredHTTPPort(req.TLS != nil, p)
@@ -164,24 +164,24 @@ func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, status
 	return attributes
 }
 
-func (o oldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
+func (o OldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
 	if https {
 		return semconv.HTTPSchemeHTTPS
 	}
 	return semconv.HTTPSchemeHTTP
 }
 
-type oldHTTPClient struct{}
+type OldHTTPClient struct{}
 
-func (o oldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
+func (o OldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
 	return semconvutil.HTTPClientRequest(req)
 }
 
-func (o oldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
+func (o OldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
 	return semconvutil.HTTPClientResponse(resp)
 }
 
-func (o oldHTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
+func (o OldHTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
 	/* The following semantic conventions are returned if present:
 	http.method                     string
 	http.status_code             int
@@ -197,7 +197,7 @@ func (o oldHTTPClient) MetricAttributes(req *http.Request, statusCode int, addit
 	var requestHost string
 	var requestPort int
 	for _, hostport := range []string{h, req.Header.Get("Host")} {
-		requestHost, requestPort = splitHostPort(hostport)
+		requestHost, requestPort = SplitHostPort(hostport)
 		if requestHost != "" || requestPort > 0 {
 			break
 		}
@@ -235,7 +235,7 @@ const (
 	clientDuration     = "http.client.duration"      // Incoming end to end duration, milliseconds
 )
 
-func (o oldHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
+func (o OldHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
 	if meter == nil {
 		return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{}
 	}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go
new file mode 100644
index 00000000..9476ef01
--- /dev/null
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go
@@ -0,0 +1,29 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
+
+import (
+	"context"
+	"time"
+)
+
+type startTimeContextKeyType int
+
+const startTimeContextKey startTimeContextKeyType = 0
+
+// ContextWithStartTime returns a new context with the provided start time. The
+// start time will be used for metrics and traces emitted by the
+// instrumentation. Only one labeller can be injected into the context.
+// Injecting it multiple times will override the previous calls.
+func ContextWithStartTime(parent context.Context, start time.Time) context.Context {
+	return context.WithValue(parent, startTimeContextKey, start)
+}
+
+// StartTimeFromContext retrieves a time.Time from the provided context if one
+// is available. If no start time was found in the provided context, a new,
+// zero start time is returned and the second return value is false.
+func StartTimeFromContext(ctx context.Context) time.Time {
+	t, _ := ctx.Value(startTimeContextKey).(time.Time)
+	return t
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
index a07d8689..353e43b9 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
@@ -5,7 +5,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http
 
 // Version is the current release version of the otelhttp instrumentation.
 func Version() string {
-	return "0.56.0"
+	return "0.58.0"
 	// This string is updated by the pre_release.sh script during release
 }
 
diff --git a/vendor/go.opentelemetry.io/otel/.golangci.yml b/vendor/go.opentelemetry.io/otel/.golangci.yml
index dbfb2a16..ce3f40b6 100644
--- a/vendor/go.opentelemetry.io/otel/.golangci.yml
+++ b/vendor/go.opentelemetry.io/otel/.golangci.yml
@@ -22,6 +22,7 @@ linters:
     - govet
     - ineffassign
     - misspell
+    - perfsprint
     - revive
     - staticcheck
     - tenv
@@ -30,6 +31,7 @@ linters:
     - unconvert
     - unused
     - unparam
+    - usestdlibvars
 
 issues:
   # Maximum issues count per one linter.
@@ -61,10 +63,11 @@ issues:
       text: "calls to (.+) only in main[(][)] or init[(][)] functions"
       linters:
         - revive
-    # It's okay to not run gosec in a test.
+    # It's okay to not run gosec and perfsprint in a test.
     - path: _test\.go
       linters:
         - gosec
+        - perfsprint
     # Ignoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
     # as we commonly use it in tests and examples.
     - text: "G404:"
@@ -95,6 +98,13 @@ linters-settings:
           - pkg: "crypto/md5"
           - pkg: "crypto/sha1"
           - pkg: "crypto/**/pkix"
+      auto/sdk:
+        files:
+          - "!internal/global/trace.go"
+          - "~internal/global/trace_test.go"
+        deny:
+          - pkg: "go.opentelemetry.io/auto/sdk"
+            desc: Do not use SDK from automatic instrumentation.
       otlp-internal:
         files:
           - "!**/exporters/otlp/internal/**/*.go"
@@ -154,6 +164,12 @@ linters-settings:
     locale: US
     ignore-words:
       - cancelled
+  perfsprint:
+    err-error: true
+    errorf: true
+    int-conversion: true
+    sprintf1: true
+    strconcat: true
   revive:
     # Sets the default failure confidence.
     # This means that linting errors with less than 0.8 confidence will be ignored.
diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md
index 8f68dbd0..a30988f2 100644
--- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md
+++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md
@@ -8,6 +8,35 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 
 ## [Unreleased]
 
+## [1.33.0/0.55.0/0.9.0/0.0.12] 2024-12-12
+
+### Added
+
+- Add `Reset` method to `SpanRecorder` in `go.opentelemetry.io/otel/sdk/trace/tracetest`. (#5994)
+- Add `EnabledInstrument` interface in `go.opentelemetry.io/otel/sdk/metric/internal/x`.
+  This is an experimental interface that is implemented by synchronous instruments provided by `go.opentelemetry.io/otel/sdk/metric`.
+  Users can use it to avoid performing computationally expensive operations when recording measurements.
+  It does not fall within the scope of the OpenTelemetry Go versioning and stability [policy](./VERSIONING.md) and it may be changed in backwards incompatible ways or removed in feature releases. (#6016)
+
+### Changed
+
+- The default global API now supports full auto-instrumentation from the `go.opentelemetry.io/auto` package.
+  See that package for more information. (#5920)
+- Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5929)
+- Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5929)
+- Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5929)
+- Performance improvements for attribute value `AsStringSlice`, `AsFloat64Slice`, `AsInt64Slice`, `AsBoolSlice`. (#6011)
+- Change `EnabledParameters` to have a `Severity` field instead of a getter and setter in `go.opentelemetry.io/otel/log`. (#6009)
+
+### Fixed
+
+- Fix inconsistent request body closing in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5954)
+- Fix inconsistent request body closing in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5954)
+- Fix inconsistent request body closing in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5954)
+- Fix invalid exemplar keys in `go.opentelemetry.io/otel/exporters/prometheus`. (#5995)
+- Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/trace`. (#5997)
+- Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/log`. (#6032)
+
 <!-- Released section -->
 <!-- Don't change this section unless doing release -->
 
@@ -3156,7 +3185,8 @@ It contains api and sdk for trace and meter.
 - CircleCI build CI manifest files.
 - CODEOWNERS file to track owners of this project.
 
-[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.32.0...HEAD
+[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...HEAD
+[1.33.0/0.55.0/0.9.0/0.0.12]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.33.0
 [1.32.0/0.54.0/0.8.0/0.0.11]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.32.0
 [1.31.0/0.53.0/0.7.0/0.0.10]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.31.0
 [1.30.0/0.52.0/0.6.0/0.0.9]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.30.0
diff --git a/vendor/go.opentelemetry.io/otel/Makefile b/vendor/go.opentelemetry.io/otel/Makefile
index b8292a4f..a7f6d8cc 100644
--- a/vendor/go.opentelemetry.io/otel/Makefile
+++ b/vendor/go.opentelemetry.io/otel/Makefile
@@ -14,8 +14,8 @@ TIMEOUT = 60
 .DEFAULT_GOAL := precommit
 
 .PHONY: precommit ci
-precommit: generate license-check misspell go-mod-tidy golangci-lint-fix verify-readmes verify-mods test-default
-ci: generate license-check lint vanity-import-check verify-readmes verify-mods build test-default check-clean-work-tree test-coverage
+precommit: generate toolchain-check license-check misspell go-mod-tidy golangci-lint-fix verify-readmes verify-mods test-default
+ci: generate toolchain-check license-check lint vanity-import-check verify-readmes verify-mods build test-default check-clean-work-tree test-coverage
 
 # Tools
 
@@ -235,6 +235,16 @@ govulncheck/%: $(GOVULNCHECK)
 codespell: $(CODESPELL)
 	@$(DOCKERPY) $(CODESPELL)
 
+.PHONY: toolchain-check
+toolchain-check:
+	@toolchainRes=$$(for f in $(ALL_GO_MOD_DIRS); do \
+	           awk '/^toolchain/ { found=1; next } END { if (found) print FILENAME }' $$f/go.mod; \
+	done); \
+	if [ -n "$${toolchainRes}" ]; then \
+			echo "toolchain checking failed:"; echo "$${toolchainRes}"; \
+			exit 1; \
+	fi
+
 .PHONY: license-check
 license-check:
 	@licRes=$$(for f in $$(find . -type f \( -iname '*.go' -o -iname '*.sh' \) ! -path '**/third_party/*' ! -path './.git/*' ) ; do \
diff --git a/vendor/go.opentelemetry.io/otel/VERSIONING.md b/vendor/go.opentelemetry.io/otel/VERSIONING.md
index 412f1e36..b8cb605c 100644
--- a/vendor/go.opentelemetry.io/otel/VERSIONING.md
+++ b/vendor/go.opentelemetry.io/otel/VERSIONING.md
@@ -26,7 +26,7 @@ is designed so the following goals can be achieved.
       go.opentelemetry.io/otel/v2 v2.0.1`) and in the package import path
       (e.g., `import "go.opentelemetry.io/otel/v2/trace"`). This includes the
       paths used in `go get` commands (e.g., `go get
-      go.opentelemetry.io/otel/v2@v2.0.1`.  Note there is both a `/v2` and a
+      go.opentelemetry.io/otel/v2@v2.0.1`).  Note there is both a `/v2` and a
       `@v2.0.1` in that example. One way to think about it is that the module
       name now includes the `/v2`, so include `/v2` whenever you are using the
       module name).
diff --git a/vendor/go.opentelemetry.io/otel/baggage/baggage.go b/vendor/go.opentelemetry.io/otel/baggage/baggage.go
index 36f53670..0e1fe242 100644
--- a/vendor/go.opentelemetry.io/otel/baggage/baggage.go
+++ b/vendor/go.opentelemetry.io/otel/baggage/baggage.go
@@ -355,7 +355,7 @@ func parseMember(member string) (Member, error) {
 }
 
 // replaceInvalidUTF8Sequences replaces invalid UTF-8 sequences with '�'.
-func replaceInvalidUTF8Sequences(cap int, unescapeVal string) string {
+func replaceInvalidUTF8Sequences(c int, unescapeVal string) string {
 	if utf8.ValidString(unescapeVal) {
 		return unescapeVal
 	}
@@ -363,7 +363,7 @@ func replaceInvalidUTF8Sequences(cap int, unescapeVal string) string {
 	// https://github.com/w3c/baggage/blob/8c215efbeebd3fa4b1aceb937a747e56444f22f3/baggage/HTTP_HEADER_FORMAT.md?plain=1#L69
 
 	var b strings.Builder
-	b.Grow(cap)
+	b.Grow(c)
 	for i := 0; i < len(unescapeVal); {
 		r, size := utf8.DecodeRuneInString(unescapeVal[i:])
 		if r == utf8.RuneError && size == 1 {
diff --git a/vendor/go.opentelemetry.io/otel/codes/codes.go b/vendor/go.opentelemetry.io/otel/codes/codes.go
index 2acbac35..49a35b12 100644
--- a/vendor/go.opentelemetry.io/otel/codes/codes.go
+++ b/vendor/go.opentelemetry.io/otel/codes/codes.go
@@ -5,6 +5,7 @@ package codes // import "go.opentelemetry.io/otel/codes"
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"strconv"
 )
@@ -63,7 +64,7 @@ func (c *Code) UnmarshalJSON(b []byte) error {
 		return nil
 	}
 	if c == nil {
-		return fmt.Errorf("nil receiver passed to UnmarshalJSON")
+		return errors.New("nil receiver passed to UnmarshalJSON")
 	}
 
 	var x interface{}
diff --git a/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go b/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go
index 822d8479..691d96c7 100644
--- a/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go
+++ b/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go
@@ -49,12 +49,11 @@ func AsBoolSlice(v interface{}) []bool {
 	if rv.Type().Kind() != reflect.Array {
 		return nil
 	}
-	var zero bool
-	correctLen := rv.Len()
-	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
-	cpy := reflect.New(correctType)
-	_ = reflect.Copy(cpy.Elem(), rv)
-	return cpy.Elem().Slice(0, correctLen).Interface().([]bool)
+	cpy := make([]bool, rv.Len())
+	if len(cpy) > 0 {
+		_ = reflect.Copy(reflect.ValueOf(cpy), rv)
+	}
+	return cpy
 }
 
 // AsInt64Slice converts an int64 array into a slice into with same elements as array.
@@ -63,12 +62,11 @@ func AsInt64Slice(v interface{}) []int64 {
 	if rv.Type().Kind() != reflect.Array {
 		return nil
 	}
-	var zero int64
-	correctLen := rv.Len()
-	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
-	cpy := reflect.New(correctType)
-	_ = reflect.Copy(cpy.Elem(), rv)
-	return cpy.Elem().Slice(0, correctLen).Interface().([]int64)
+	cpy := make([]int64, rv.Len())
+	if len(cpy) > 0 {
+		_ = reflect.Copy(reflect.ValueOf(cpy), rv)
+	}
+	return cpy
 }
 
 // AsFloat64Slice converts a float64 array into a slice into with same elements as array.
@@ -77,12 +75,11 @@ func AsFloat64Slice(v interface{}) []float64 {
 	if rv.Type().Kind() != reflect.Array {
 		return nil
 	}
-	var zero float64
-	correctLen := rv.Len()
-	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
-	cpy := reflect.New(correctType)
-	_ = reflect.Copy(cpy.Elem(), rv)
-	return cpy.Elem().Slice(0, correctLen).Interface().([]float64)
+	cpy := make([]float64, rv.Len())
+	if len(cpy) > 0 {
+		_ = reflect.Copy(reflect.ValueOf(cpy), rv)
+	}
+	return cpy
 }
 
 // AsStringSlice converts a string array into a slice into with same elements as array.
@@ -91,10 +88,9 @@ func AsStringSlice(v interface{}) []string {
 	if rv.Type().Kind() != reflect.Array {
 		return nil
 	}
-	var zero string
-	correctLen := rv.Len()
-	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
-	cpy := reflect.New(correctType)
-	_ = reflect.Copy(cpy.Elem(), rv)
-	return cpy.Elem().Slice(0, correctLen).Interface().([]string)
+	cpy := make([]string, rv.Len())
+	if len(cpy) > 0 {
+		_ = reflect.Copy(reflect.ValueOf(cpy), rv)
+	}
+	return cpy
 }
diff --git a/vendor/go.opentelemetry.io/otel/internal/global/trace.go b/vendor/go.opentelemetry.io/otel/internal/global/trace.go
index ac65262c..8982aa0d 100644
--- a/vendor/go.opentelemetry.io/otel/internal/global/trace.go
+++ b/vendor/go.opentelemetry.io/otel/internal/global/trace.go
@@ -25,6 +25,7 @@ import (
 	"sync"
 	"sync/atomic"
 
+	"go.opentelemetry.io/auto/sdk"
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/codes"
 	"go.opentelemetry.io/otel/trace"
@@ -145,6 +146,30 @@ func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStart
 		return delegate.(trace.Tracer).Start(ctx, name, opts...)
 	}
 
+	return t.newSpan(ctx, autoInstEnabled, name, opts)
+}
+
+// autoInstEnabled determines if the auto-instrumentation SDK span is returned
+// from the tracer when not backed by a delegate and auto-instrumentation has
+// attached to this process.
+//
+// The auto-instrumentation is expected to overwrite this value to true when it
+// attaches. By default, this will point to false and mean a tracer will return
+// a nonRecordingSpan by default.
+var autoInstEnabled = new(bool)
+
+func (t *tracer) newSpan(ctx context.Context, autoSpan *bool, name string, opts []trace.SpanStartOption) (context.Context, trace.Span) {
+	// autoInstEnabled is passed to newSpan via the autoSpan parameter. This is
+	// so the auto-instrumentation can define a uprobe for (*t).newSpan and be
+	// provided with the address of the bool autoInstEnabled points to. It
+	// needs to be a parameter so that pointer can be reliably determined, it
+	// should not be read from the global.
+
+	if *autoSpan {
+		tracer := sdk.TracerProvider().Tracer(t.name, t.opts...)
+		return tracer.Start(ctx, name, opts...)
+	}
+
 	s := nonRecordingSpan{sc: trace.SpanContextFromContext(ctx), tracer: t}
 	ctx = trace.ContextWithSpan(ctx, s)
 	return ctx, s
diff --git a/vendor/go.opentelemetry.io/otel/trace/config.go b/vendor/go.opentelemetry.io/otel/trace/config.go
index 273d58e0..9c0b720a 100644
--- a/vendor/go.opentelemetry.io/otel/trace/config.go
+++ b/vendor/go.opentelemetry.io/otel/trace/config.go
@@ -213,7 +213,7 @@ var _ SpanStartEventOption = attributeOption{}
 
 // WithAttributes adds the attributes related to a span life-cycle event.
 // These attributes are used to describe the work a Span represents when this
-// option is provided to a Span's start or end events. Otherwise, these
+// option is provided to a Span's start event. Otherwise, these
 // attributes provide additional information about the event being recorded
 // (e.g. error, state change, processing progress, system event).
 //
diff --git a/vendor/go.opentelemetry.io/otel/trace/noop/README.md b/vendor/go.opentelemetry.io/otel/trace/noop/README.md
new file mode 100644
index 00000000..cd382c82
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/trace/noop/README.md
@@ -0,0 +1,3 @@
+# Trace Noop
+
+[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/trace/noop)](https://pkg.go.dev/go.opentelemetry.io/otel/trace/noop)
diff --git a/vendor/go.opentelemetry.io/otel/trace/noop/noop.go b/vendor/go.opentelemetry.io/otel/trace/noop/noop.go
new file mode 100644
index 00000000..64a4f1b3
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/trace/noop/noop.go
@@ -0,0 +1,112 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+// Package noop provides an implementation of the OpenTelemetry trace API that
+// produces no telemetry and minimizes used computation resources.
+//
+// Using this package to implement the OpenTelemetry trace API will effectively
+// disable OpenTelemetry.
+//
+// This implementation can be embedded in other implementations of the
+// OpenTelemetry trace API. Doing so will mean the implementation defaults to
+// no operation for methods it does not implement.
+package noop // import "go.opentelemetry.io/otel/trace/noop"
+
+import (
+	"context"
+
+	"go.opentelemetry.io/otel/attribute"
+	"go.opentelemetry.io/otel/codes"
+	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/embedded"
+)
+
+var (
+	// Compile-time check this implements the OpenTelemetry API.
+
+	_ trace.TracerProvider = TracerProvider{}
+	_ trace.Tracer         = Tracer{}
+	_ trace.Span           = Span{}
+)
+
+// TracerProvider is an OpenTelemetry No-Op TracerProvider.
+type TracerProvider struct{ embedded.TracerProvider }
+
+// NewTracerProvider returns a TracerProvider that does not record any telemetry.
+func NewTracerProvider() TracerProvider {
+	return TracerProvider{}
+}
+
+// Tracer returns an OpenTelemetry Tracer that does not record any telemetry.
+func (TracerProvider) Tracer(string, ...trace.TracerOption) trace.Tracer {
+	return Tracer{}
+}
+
+// Tracer is an OpenTelemetry No-Op Tracer.
+type Tracer struct{ embedded.Tracer }
+
+// Start creates a span. The created span will be set in a child context of ctx
+// and returned with the span.
+//
+// If ctx contains a span context, the returned span will also contain that
+// span context. If the span context in ctx is for a non-recording span, that
+// span instance will be returned directly.
+func (t Tracer) Start(ctx context.Context, _ string, _ ...trace.SpanStartOption) (context.Context, trace.Span) {
+	span := trace.SpanFromContext(ctx)
+
+	// If the parent context contains a non-zero span context, that span
+	// context needs to be returned as a non-recording span
+	// (https://github.com/open-telemetry/opentelemetry-specification/blob/3a1dde966a4ce87cce5adf464359fe369741bbea/specification/trace/api.md#behavior-of-the-api-in-the-absence-of-an-installed-sdk).
+	var zeroSC trace.SpanContext
+	if sc := span.SpanContext(); !sc.Equal(zeroSC) {
+		if !span.IsRecording() {
+			// If the span is not recording return it directly.
+			return ctx, span
+		}
+		// Otherwise, return the span context needs in a non-recording span.
+		span = Span{sc: sc}
+	} else {
+		// No parent, return a No-Op span with an empty span context.
+		span = noopSpanInstance
+	}
+	return trace.ContextWithSpan(ctx, span), span
+}
+
+var noopSpanInstance trace.Span = Span{}
+
+// Span is an OpenTelemetry No-Op Span.
+type Span struct {
+	embedded.Span
+
+	sc trace.SpanContext
+}
+
+// SpanContext returns an empty span context.
+func (s Span) SpanContext() trace.SpanContext { return s.sc }
+
+// IsRecording always returns false.
+func (Span) IsRecording() bool { return false }
+
+// SetStatus does nothing.
+func (Span) SetStatus(codes.Code, string) {}
+
+// SetAttributes does nothing.
+func (Span) SetAttributes(...attribute.KeyValue) {}
+
+// End does nothing.
+func (Span) End(...trace.SpanEndOption) {}
+
+// RecordError does nothing.
+func (Span) RecordError(error, ...trace.EventOption) {}
+
+// AddEvent does nothing.
+func (Span) AddEvent(string, ...trace.EventOption) {}
+
+// AddLink does nothing.
+func (Span) AddLink(trace.Link) {}
+
+// SetName does nothing.
+func (Span) SetName(string) {}
+
+// TracerProvider returns a No-Op TracerProvider.
+func (Span) TracerProvider() trace.TracerProvider { return TracerProvider{} }
diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go
index 59e24816..fb7d1267 100644
--- a/vendor/go.opentelemetry.io/otel/version.go
+++ b/vendor/go.opentelemetry.io/otel/version.go
@@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel"
 
 // Version is the current release version of OpenTelemetry in use.
 func Version() string {
-	return "1.32.0"
+	return "1.33.0"
 }
diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml
index c04b12f6..9f878cd1 100644
--- a/vendor/go.opentelemetry.io/otel/versions.yaml
+++ b/vendor/go.opentelemetry.io/otel/versions.yaml
@@ -3,7 +3,7 @@
 
 module-sets:
   stable-v1:
-    version: v1.32.0
+    version: v1.33.0
     modules:
       - go.opentelemetry.io/otel
       - go.opentelemetry.io/otel/bridge/opencensus
@@ -23,11 +23,11 @@ module-sets:
       - go.opentelemetry.io/otel/sdk/metric
       - go.opentelemetry.io/otel/trace
   experimental-metrics:
-    version: v0.54.0
+    version: v0.55.0
     modules:
       - go.opentelemetry.io/otel/exporters/prometheus
   experimental-logs:
-    version: v0.8.0
+    version: v0.9.0
     modules:
       - go.opentelemetry.io/otel/log
       - go.opentelemetry.io/otel/sdk/log
@@ -35,7 +35,7 @@ module-sets:
       - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
       - go.opentelemetry.io/otel/exporters/stdout/stdoutlog
   experimental-schema:
-    version: v0.0.11
+    version: v0.0.12
     modules:
       - go.opentelemetry.io/otel/schema
 excluded-modules:
diff --git a/vendor/modules.txt b/vendor/modules.txt
index a73ff5f3..647e41d7 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -98,8 +98,8 @@ github.com/containernetworking/cni/pkg/version
 # github.com/containernetworking/plugins v1.6.2
 ## explicit; go 1.23
 github.com/containernetworking/plugins/pkg/ns
-# github.com/containers/image/v5 v5.34.3-0.20250311194052-d84dbab374e7
-## explicit; go 1.22.8
+# github.com/containers/image/v5 v5.34.3-0.20250324170122-cfeba44147fc
+## explicit; go 1.23.3
 github.com/containers/image/v5/copy
 github.com/containers/image/v5/directory
 github.com/containers/image/v5/directory/explicitfilepath
@@ -255,7 +255,7 @@ github.com/distribution/reference
 ## explicit
 github.com/docker/distribution/registry/api/errcode
 github.com/docker/distribution/registry/api/v2
-# github.com/docker/docker v28.0.1+incompatible
+# github.com/docker/docker v28.0.2+incompatible
 ## explicit
 github.com/docker/docker/api
 github.com/docker/docker/api/types
@@ -281,7 +281,7 @@ github.com/docker/docker/client
 github.com/docker/docker/errdefs
 github.com/docker/docker/internal/lazyregexp
 github.com/docker/docker/internal/multierror
-# github.com/docker/docker-credential-helpers v0.9.2
+# github.com/docker/docker-credential-helpers v0.9.3
 ## explicit; go 1.21
 github.com/docker/docker-credential-helpers/client
 github.com/docker/docker-credential-helpers/credentials
@@ -371,8 +371,8 @@ github.com/google/go-cmp/cmp/internal/diff
 github.com/google/go-cmp/cmp/internal/flags
 github.com/google/go-cmp/cmp/internal/function
 github.com/google/go-cmp/cmp/internal/value
-# github.com/google/go-containerregistry v0.20.2
-## explicit; go 1.18
+# github.com/google/go-containerregistry v0.20.3
+## explicit; go 1.23.0
 github.com/google/go-containerregistry/pkg/name
 github.com/google/go-containerregistry/pkg/v1
 github.com/google/go-containerregistry/pkg/v1/types
@@ -555,10 +555,11 @@ github.com/ostreedev/ostree-go/pkg/otbuiltin
 # github.com/pkg/errors v0.9.1
 ## explicit
 github.com/pkg/errors
-# github.com/pkg/sftp v1.13.8
+# github.com/pkg/sftp v1.13.9
 ## explicit; go 1.15
 github.com/pkg/sftp
 github.com/pkg/sftp/internal/encoding/ssh/filexfer
+github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh
 # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
 ## explicit
 github.com/pmezard/go-difflib/difflib
@@ -574,8 +575,8 @@ github.com/seccomp/libseccomp-golang
 # github.com/secure-systems-lab/go-securesystemslib v0.9.0
 ## explicit; go 1.20
 github.com/secure-systems-lab/go-securesystemslib/encrypted
-# github.com/sigstore/fulcio v1.6.4
-## explicit; go 1.22.6
+# github.com/sigstore/fulcio v1.6.6
+## explicit; go 1.23.3
 github.com/sigstore/fulcio/pkg/certificate
 # github.com/sigstore/protobuf-specs v0.4.0
 ## explicit; go 1.22.0
@@ -583,8 +584,8 @@ github.com/sigstore/protobuf-specs/gen/pb-go/common/v1
 # github.com/sigstore/rekor v1.3.9
 ## explicit; go 1.22.0
 github.com/sigstore/rekor/pkg/generated/models
-# github.com/sigstore/sigstore v1.8.15
-## explicit; go 1.22.0
+# github.com/sigstore/sigstore v1.9.1
+## explicit; go 1.23.0
 github.com/sigstore/sigstore/pkg/cryptoutils
 github.com/sigstore/sigstore/pkg/signature
 github.com/sigstore/sigstore/pkg/signature/options
@@ -613,8 +614,8 @@ github.com/stefanberger/go-pkcs11uri
 github.com/stretchr/testify/assert
 github.com/stretchr/testify/assert/yaml
 github.com/stretchr/testify/require
-# github.com/sylabs/sif/v2 v2.20.2
-## explicit; go 1.22.0
+# github.com/sylabs/sif/v2 v2.21.1
+## explicit; go 1.23.0
 github.com/sylabs/sif/v2/pkg/sif
 # github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
 ## explicit
@@ -671,14 +672,18 @@ go.opencensus.io/internal
 go.opencensus.io/trace
 go.opencensus.io/trace/internal
 go.opencensus.io/trace/tracestate
-# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0
-## explicit; go 1.22
+# go.opentelemetry.io/auto/sdk v1.1.0
+## explicit; go 1.22.0
+go.opentelemetry.io/auto/sdk
+go.opentelemetry.io/auto/sdk/internal/telemetry
+# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0
+## explicit; go 1.22.0
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil
-# go.opentelemetry.io/otel v1.32.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel v1.33.0
+## explicit; go 1.22.0
 go.opentelemetry.io/otel
 go.opentelemetry.io/otel/attribute
 go.opentelemetry.io/otel/baggage
@@ -690,15 +695,16 @@ go.opentelemetry.io/otel/internal/global
 go.opentelemetry.io/otel/propagation
 go.opentelemetry.io/otel/semconv/v1.20.0
 go.opentelemetry.io/otel/semconv/v1.26.0
-# go.opentelemetry.io/otel/metric v1.32.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/metric v1.33.0
+## explicit; go 1.22.0
 go.opentelemetry.io/otel/metric
 go.opentelemetry.io/otel/metric/embedded
 go.opentelemetry.io/otel/metric/noop
-# go.opentelemetry.io/otel/trace v1.32.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/trace v1.33.0
+## explicit; go 1.22.0
 go.opentelemetry.io/otel/trace
 go.opentelemetry.io/otel/trace/embedded
+go.opentelemetry.io/otel/trace/noop
 # golang.org/x/crypto v0.36.0
 ## explicit; go 1.23.0
 golang.org/x/crypto/blowfish
@@ -781,7 +787,7 @@ golang.org/x/text/unicode/norm
 golang.org/x/tools/cover
 golang.org/x/tools/go/ast/inspector
 golang.org/x/tools/internal/astutil/edge
-# google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576
+# google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb
 ## explicit; go 1.21
 google.golang.org/genproto/googleapis/api
 google.golang.org/genproto/googleapis/api/annotations



Test patch:
diff --git a/pkg/secrets/secrets_test.go b/pkg/secrets/secrets_test.go
index 7677d719..550bf5ee 100644
--- a/pkg/secrets/secrets_test.go
+++ b/pkg/secrets/secrets_test.go
@@ -64,7 +64,7 @@ func TestAddSecretAndLookupData(t *testing.T) {
 
 	s, _, err = manager.LookupSecretData("mysecret")
 	require.NoError(t, err)
-	if s.CreatedAt == s.UpdatedAt {
+	if s.CreatedAt.Equal(s.UpdatedAt) {
 		t.Errorf("error: secret CreatedAt should not equal UpdatedAt after a Replace")
 	}