diff --git a/cache/remotecache/gha/gha.go b/cache/remotecache/gha/gha.go
index a8c781f73015..47a3d49a00a3 100644
--- a/cache/remotecache/gha/gha.go
+++ b/cache/remotecache/gha/gha.go
@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"os"
+ "os/exec"
"strconv"
"strings"
"sync"
@@ -16,6 +17,7 @@ import (
"github.com/containerd/containerd/v2/pkg/labels"
cerrdefs "github.com/containerd/errdefs"
"github.com/moby/buildkit/cache/remotecache"
+ "github.com/moby/buildkit/cache/remotecache/gha/ghatypes"
v1 "github.com/moby/buildkit/cache/remotecache/v1"
cacheimporttypes "github.com/moby/buildkit/cache/remotecache/v1/types"
"github.com/moby/buildkit/session"
@@ -26,9 +28,11 @@ import (
"github.com/moby/buildkit/util/tracing"
bkversion "github.com/moby/buildkit/version"
"github.com/moby/buildkit/worker"
+ policy "github.com/moby/policy-helpers"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
+ "github.com/sigstore/sigstore-go/pkg/fulcio/certificate"
actionscache "github.com/tonistiigi/go-actions-cache"
"golang.org/x/sync/errgroup"
)
@@ -51,6 +55,8 @@ const (
defaultTimeout = 10 * time.Minute
)
+type VerifierProvider func() (*policy.Verifier, error)
+
type Config struct {
Scope string
URL string
@@ -59,9 +65,12 @@ type Config struct {
Repository string
Version int
Timeout time.Duration
+
+ *ghatypes.CacheConfig
+ verifier VerifierProvider
}
-func getConfig(attrs map[string]string) (*Config, error) {
+func getConfig(conf *ghatypes.CacheConfig, v VerifierProvider, attrs map[string]string) (*Config, error) {
scope, ok := attrs[attrScope]
if !ok {
scope = "buildkit"
@@ -109,21 +118,28 @@ func getConfig(attrs map[string]string) (*Config, error) {
return nil, errors.Wrap(err, "failed to parse timeout for github actions cache")
}
}
+
+ if conf == nil {
+ conf = &ghatypes.CacheConfig{}
+ }
+
return &Config{
- Scope: scope,
- URL: url,
- Token: token,
- Timeout: timeout,
- GHToken: attrs[attrGHToken],
- Repository: attrs[attrRepository],
- Version: apiVersionInt,
+ Scope: scope,
+ URL: url,
+ Token: token,
+ Timeout: timeout,
+ GHToken: attrs[attrGHToken],
+ Repository: attrs[attrRepository],
+ Version: apiVersionInt,
+ CacheConfig: conf,
+ verifier: v,
}, nil
}
// ResolveCacheExporterFunc for Github actions cache exporter.
-func ResolveCacheExporterFunc() remotecache.ResolveCacheExporterFunc {
+func ResolveCacheExporterFunc(conf *ghatypes.CacheConfig, v VerifierProvider) remotecache.ResolveCacheExporterFunc {
return func(ctx context.Context, g session.Group, attrs map[string]string) (remotecache.Exporter, error) {
- cfg, err := getConfig(attrs)
+ cfg, err := getConfig(conf, v, attrs)
if err != nil {
return nil, err
}
@@ -163,12 +179,12 @@ func (ce *exporter) Config() remotecache.Config {
}
}
-func (ce *exporter) blobKeyPrefix() string {
+func blobKeyPrefix() string {
return "buildkit-blob-" + version + "-"
}
-func (ce *exporter) blobKey(dgst digest.Digest) string {
- return ce.blobKeyPrefix() + dgst.String()
+func blobKey(dgst digest.Digest) string {
+ return blobKeyPrefix() + dgst.String()
}
func (ce *exporter) indexKey() string {
@@ -178,8 +194,17 @@ func (ce *exporter) indexKey() string {
scope = s.Scope
}
}
+ return indexKey(scope, ce.config)
+}
+
+func indexKey(scope string, config *Config) string {
scope = digest.FromBytes([]byte(scope)).Hex()[:8]
- return "index-" + ce.config.Scope + "-" + version + "-" + scope
+ key := "index-" + config.Scope + "-" + version + "-" + scope
+ // just to be sure lets namespace the signed vs unsigned caches
+ if config.Sign != nil || config.Verify.Required {
+ key += "-sig"
+ }
+ return key
}
func (ce *exporter) initActiveKeyMap(ctx context.Context) {
@@ -204,14 +229,14 @@ func (ce *exporter) initActiveKeyMapOnce(ctx context.Context) (map[string]struct
if err != nil {
return nil, err
}
- keys, err := ce.cache.AllKeys(ctx, api, ce.blobKeyPrefix())
+ keys, err := ce.cache.AllKeys(ctx, api, blobKeyPrefix())
if err != nil {
return nil, err
}
return keys, nil
}
-func (ce *exporter) Finalize(ctx context.Context) (map[string]string, error) {
+func (ce *exporter) Finalize(ctx context.Context) (_ map[string]string, err error) {
// res := make(map[string]string)
config, descs, err := ce.chains.Marshal(ctx)
if err != nil {
@@ -239,7 +264,7 @@ func (ce *exporter) Finalize(ctx context.Context) (map[string]string, error) {
diffID = dgst
ce.initActiveKeyMap(ctx)
- key := ce.blobKey(dgstPair.Descriptor.Digest)
+ key := blobKey(dgstPair.Descriptor.Digest)
exists := false
if ce.keyMap != nil {
@@ -294,13 +319,111 @@ func (ce *exporter) Finalize(ctx context.Context) (map[string]string, error) {
return nil, err
}
+ if ce.config.Sign == nil {
+ return nil, nil
+ }
+
+ args := ce.config.Sign.Command
+ if len(args) == 0 {
+ return nil, nil
+ }
+
+ dgst := digest.FromBytes(dt)
+ signDone := progress.OneOff(ctx, fmt.Sprintf("signing cache index %s", dgst))
+ defer signDone(err)
+
+ cmd := exec.Command(args[0], args[1:]...) //nolint:gosec // defined in toml config
+ cmd.Stdin = bytes.NewReader(dt)
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ var stderr bytes.Buffer
+ cmd.Stderr = &stderr
+ if err := cmd.Run(); err != nil {
+ return nil, errors.Wrapf(err, "signing command failed: %s", stderr.String())
+ }
+
+ // validate signature before uploading
+ if err := verifySignature(ctx, dgst, out.Bytes(), ce.config); err != nil {
+ return nil, err
+ }
+
+ key := blobKey(dgst + "-sig")
+ if err := ce.cache.Save(ctx, key, actionscache.NewBlob(out.Bytes())); err != nil {
+ return nil, err
+ }
+
return nil, nil
}
+func verifySignature(ctx context.Context, dgst digest.Digest, bundle []byte, config *Config) error {
+ v, err := config.verifier()
+ if err != nil {
+ return err
+ }
+ if v == nil {
+ return errors.New("no verifier available for signed github actions cache")
+ }
+
+ sig, err := v.VerifyArtifact(ctx, dgst, bundle, policy.WithSLSANotRequired())
+ if err != nil {
+ return err
+ }
+ if sig.Signer == nil {
+ return errors.New("signature verification failed: no signer found")
+ }
+ numTimestamps := len(sig.Timestamps)
+ numTlog := 0
+ for _, t := range sig.Timestamps {
+ if t.Type == "Tlog" {
+ numTlog++
+ }
+ }
+ policyRules := config.Verify.Policy
+ if policyRules.TimestampThreshold > numTimestamps {
+ return errors.Errorf("signature verification failed: not enough timestamp authorities: have %d, need %d", numTimestamps, policyRules.TimestampThreshold)
+ }
+ if policyRules.TlogThreshold > numTlog {
+ return errors.Errorf("signature verification failed: not enough tlog authorities: have %d, need %d", numTlog, policyRules.TlogThreshold)
+ }
+
+ certRules, err := certToStringMap(&config.Verify.Policy.Summary)
+ if err != nil {
+ return err
+ }
+ certFields, err := certToStringMap(sig.Signer)
+ if err != nil {
+ return err
+ }
+ bklog.G(ctx).Debugf("signature verification: %+v", sig)
+ bklog.G(ctx).Debugf("signer: %+v", sig.Signer)
+ for k, v := range certRules {
+ if v == "" {
+ continue
+ }
+ if !simplePatternMatch(v, certFields[k]) {
+ return errors.Errorf("signature verification failed: certificate field %q does not match policy (%q != %q)", k, certFields[k], v)
+ }
+ bklog.G(ctx).Debugf("certificate field %q matches policy (%q)", k, certFields[k])
+ }
+ return nil
+}
+
+func certToStringMap(cert *certificate.Summary) (map[string]string, error) {
+ dt, err := json.Marshal(cert)
+ if err != nil {
+ return nil, err
+ }
+ m := map[string]string{}
+ if err := json.Unmarshal(dt, &m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
// ResolveCacheImporterFunc for Github actions cache importer.
-func ResolveCacheImporterFunc() remotecache.ResolveCacheImporterFunc {
+func ResolveCacheImporterFunc(conf *ghatypes.CacheConfig, v VerifierProvider) remotecache.ResolveCacheImporterFunc {
return func(ctx context.Context, g session.Group, attrs map[string]string) (remotecache.Importer, ocispecs.Descriptor, error) {
- cfg, err := getConfig(attrs)
+ cfg, err := getConfig(conf, v, attrs)
if err != nil {
return nil, ocispecs.Descriptor{}, err
}
@@ -360,8 +483,7 @@ func (ci *importer) makeDescriptorProviderPair(l cacheimporttypes.CacheLayer) (*
}
func (ci *importer) loadScope(ctx context.Context, scope string) (*v1.CacheChains, error) {
- scope = digest.FromBytes([]byte(scope)).Hex()[:8]
- key := "index-" + ci.config.Scope + "-" + version + "-" + scope
+ key := indexKey(scope, ci.config)
entry, err := ci.cache.Load(ctx, key)
if err != nil {
@@ -371,12 +493,38 @@ func (ci *importer) loadScope(ctx context.Context, scope string) (*v1.CacheChain
return v1.NewCacheChains(), nil
}
- // TODO: this buffer can be removed
buf := &bytes.Buffer{}
if err := entry.WriteTo(ctx, buf); err != nil {
return nil, err
}
+ if ci.config.Verify.Required {
+ dgst := digest.FromBytes(buf.Bytes())
+
+ verifyDone := progress.OneOff(ctx, fmt.Sprintf("verifying signature of cache index %s", dgst))
+ sigKey := blobKey(dgst) + "-sig"
+ sigEntry, err := ci.cache.Load(ctx, sigKey)
+ if err != nil {
+ verifyDone(err)
+ return nil, err
+ }
+ if sigEntry == nil {
+ err := errors.Errorf("missing signature for github actions cache")
+ verifyDone(err)
+ return nil, err
+ }
+ sigBuf := &bytes.Buffer{}
+ if err := sigEntry.WriteTo(ctx, sigBuf); err != nil {
+ verifyDone(err)
+ return nil, err
+ }
+ if err := verifySignature(ctx, dgst, sigBuf.Bytes(), ci.config); err != nil {
+ verifyDone(err)
+ return nil, err
+ }
+ verifyDone(nil)
+ }
+
var config cacheimporttypes.CacheConfig
if err := json.Unmarshal(buf.Bytes(), &config); err != nil {
return nil, errors.WithStack(err)
@@ -500,3 +648,19 @@ func (r *readerAt) ReadAt(p []byte, off int64) (int, error) {
func (r *readerAt) Size() int64 {
return r.desc.Size
}
+
+func simplePatternMatch(pat, s string) bool {
+ if pat == "*" {
+ return true
+ }
+ if strings.HasPrefix(pat, "*") && strings.HasSuffix(pat, "*") {
+ return strings.Contains(s, pat[1:len(pat)-1])
+ }
+ if strings.HasPrefix(pat, "*") {
+ return strings.HasSuffix(s, pat[1:])
+ }
+ if strings.HasSuffix(pat, "*") {
+ return strings.HasPrefix(s, pat[:len(pat)-1])
+ }
+ return s == pat
+}
diff --git a/cache/remotecache/gha/ghatypes/config.go b/cache/remotecache/gha/ghatypes/config.go
new file mode 100644
index 000000000000..770ef624edd3
--- /dev/null
+++ b/cache/remotecache/gha/ghatypes/config.go
@@ -0,0 +1,23 @@
+package ghatypes
+
+import "github.com/sigstore/sigstore-go/pkg/fulcio/certificate"
+
+type CacheConfig struct {
+ Sign *SignConfig `toml:"sign"`
+ Verify VerifyConfig `toml:"verify"`
+}
+
+type SignConfig struct {
+ Command []string `toml:"command"`
+}
+
+type VerifyConfig struct {
+ Required bool `toml:"required"`
+ Policy VerifyPolicy `toml:"policy"`
+}
+
+type VerifyPolicy struct {
+ TimestampThreshold int `toml:"timestampThreshold"`
+ TlogThreshold int `toml:"tlogThreshold"`
+ certificate.Summary
+}
diff --git a/cmd/buildkitd/config/config.go b/cmd/buildkitd/config/config.go
index 8e91bafcfc53..65447eda0cc4 100644
--- a/cmd/buildkitd/config/config.go
+++ b/cmd/buildkitd/config/config.go
@@ -1,6 +1,7 @@
package config
import (
+ "github.com/moby/buildkit/cache/remotecache/gha/ghatypes"
resolverconfig "github.com/moby/buildkit/util/resolver/config"
)
@@ -46,6 +47,12 @@ type Config struct {
// ProvenanceEnvDir is the directory where extra config is loaded
// that is added to the provenance of builds. Defaults to /etc/buildkit/provenance.d/ ,
ProvenanceEnvDir string `toml:"provenanceEnvDir"`
+
+ Cache CacheConfig `toml:"cache"`
+}
+
+type CacheConfig struct {
+ GHA *ghatypes.CacheConfig `toml:"gha"`
}
type SystemConfig struct {
diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go
index d579ed5211ff..3a9e72bec8c7 100644
--- a/cmd/buildkitd/main.go
+++ b/cmd/buildkitd/main.go
@@ -14,6 +14,7 @@ import (
"slices"
"strconv"
"strings"
+ "sync"
"github.com/containerd/containerd/v2/core/remotes/docker"
"github.com/containerd/containerd/v2/defaults"
@@ -60,6 +61,7 @@ import (
"github.com/moby/buildkit/util/tracing/transform"
"github.com/moby/buildkit/version"
"github.com/moby/buildkit/worker"
+ policy "github.com/moby/policy-helpers"
"github.com/moby/sys/userns"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -840,18 +842,23 @@ func newController(ctx context.Context, c *cli.Context, cfg *config.Config) (*co
return nil, err
}
+ var verifierProvider func() (*policy.Verifier, error)
+ if cfg.Cache.GHA != nil && cfg.Cache.GHA.Verify.Required {
+ verifierProvider = newVerifierProvider(cfg.Root)
+ }
+
remoteCacheExporterFuncs := map[string]remotecache.ResolveCacheExporterFunc{
"registry": registryremotecache.ResolveCacheExporterFunc(sessionManager, resolverFn),
"local": localremotecache.ResolveCacheExporterFunc(sessionManager),
"inline": inlineremotecache.ResolveCacheExporterFunc(),
- "gha": gha.ResolveCacheExporterFunc(),
+ "gha": gha.ResolveCacheExporterFunc(cfg.Cache.GHA, verifierProvider),
"s3": s3remotecache.ResolveCacheExporterFunc(),
"azblob": azblob.ResolveCacheExporterFunc(),
}
remoteCacheImporterFuncs := map[string]remotecache.ResolveCacheImporterFunc{
"registry": registryremotecache.ResolveCacheImporterFunc(sessionManager, w.ContentStore(), resolverFn),
"local": localremotecache.ResolveCacheImporterFunc(sessionManager),
- "gha": gha.ResolveCacheImporterFunc(),
+ "gha": gha.ResolveCacheImporterFunc(cfg.Cache.GHA, verifierProvider),
"s3": s3remotecache.ResolveCacheImporterFunc(),
"azblob": azblob.ResolveCacheImporterFunc(),
}
@@ -1095,3 +1102,22 @@ func getCDIManager(cfg config.CDIConfig) (*cdidevices.Manager, error) {
}
return cdidevices.NewManager(cdiCache, cfg.AutoAllowed), nil
}
+
+func newVerifierProvider(root string) func() (*policy.Verifier, error) {
+ var mu sync.Mutex
+ var verifier *policy.Verifier
+ var initErr error
+ return func() (*policy.Verifier, error) {
+ mu.Lock()
+ defer mu.Unlock()
+ if verifier != nil || initErr != nil {
+ return verifier, initErr
+ }
+ statePath := filepath.Join(root, "policy")
+ verifier, initErr = policy.NewVerifier(policy.Config{
+ StateDir: statePath,
+ RequireOnline: false,
+ })
+ return verifier, initErr
+ }
+}
diff --git a/docs/buildkitd.toml.md b/docs/buildkitd.toml.md
index 8587fe381659..00eef1ddbcb2 100644
--- a/docs/buildkitd.toml.md
+++ b/docs/buildkitd.toml.md
@@ -213,4 +213,19 @@ provenanceEnvDir = "/etc/buildkit/provenance.d"
[system]
# how often buildkit scans for changes in the supported emulated platforms
platformsCacheMaxAge = "1h"
+
+
+# optional signed cache configuration for GitHub Actions backend
+[ghacache.sign]
+# command that signs the payload in stdin and outputs the signature to stdout. Normally you want cosign to produce the signature bytes.
+cmd = ""
+[ghacache.verify]
+required = false
+[ghacache.verify.policy]
+timestampThreshold = 1
+tlogThreshold = 1
+# cetificate properties that need to match. Simple wildcards (*) are supported.
+certificateIssuer = ""
+subjectAlternativeName = ""
+buildSignerURI = ""
```
diff --git a/go.mod b/go.mod
index bc872bc5f0ca..5575baaad588 100644
--- a/go.mod
+++ b/go.mod
@@ -1,21 +1,21 @@
module github.com/moby/buildkit
-go 1.24.3
+go 1.25.0
require (
- github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2
- github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0
+ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0
github.com/Microsoft/go-winio v0.6.2
github.com/Microsoft/hcsshim v0.14.0-rc.1
github.com/ProtonMail/go-crypto v1.3.0
github.com/agext/levenshtein v1.2.3
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
- github.com/aws/aws-sdk-go-v2 v1.38.1
- github.com/aws/aws-sdk-go-v2/config v1.31.3
- github.com/aws/aws-sdk-go-v2/credentials v1.18.7
+ github.com/aws/aws-sdk-go-v2 v1.39.6
+ github.com/aws/aws-sdk-go-v2/config v1.31.20
+ github.com/aws/aws-sdk-go-v2/credentials v1.18.24
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.10
- github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1
+ github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1
github.com/cespare/xxhash/v2 v2.3.0
github.com/containerd/accelerated-container-image v1.3.0
github.com/containerd/console v1.0.5
@@ -52,7 +52,7 @@ require (
github.com/moby/go-archive v0.2.0
github.com/moby/locker v1.0.1
github.com/moby/patternmatcher v0.6.0
- github.com/moby/policy-helpers v0.0.0-20251105011237-bcaa71c99f14
+ github.com/moby/policy-helpers v0.0.0-20251206004813-9fcc1a9ec5c9
github.com/moby/profiles/seccomp v0.1.0
github.com/moby/sys/mountinfo v0.7.2
github.com/moby/sys/reexec v0.1.0
@@ -70,8 +70,9 @@ require (
github.com/pkg/profile v1.7.0
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10
github.com/prometheus/client_golang v1.23.2
- github.com/prometheus/procfs v0.16.1
+ github.com/prometheus/procfs v0.17.0
github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b
+ github.com/sigstore/sigstore-go v1.1.4-0.20251124094504-b5fe07a5a7d7
github.com/sirupsen/logrus v1.9.3
github.com/spdx/tools-golang v0.5.5
github.com/stretchr/testify v1.11.1
@@ -95,19 +96,19 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0
- go.opentelemetry.io/otel/exporters/prometheus v0.42.0
+ go.opentelemetry.io/otel/exporters/prometheus v0.60.0
go.opentelemetry.io/otel/sdk v1.38.0
go.opentelemetry.io/otel/sdk/metric v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
go.opentelemetry.io/proto/otlp v1.7.1
golang.org/x/crypto v0.45.0
golang.org/x/exp v0.0.0-20250911091902-df9299821621
- golang.org/x/mod v0.29.0
+ golang.org/x/mod v0.30.0
golang.org/x/net v0.47.0
golang.org/x/sync v0.18.0
golang.org/x/sys v0.38.0
golang.org/x/time v0.14.0
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101
google.golang.org/grpc v1.76.0
google.golang.org/protobuf v1.36.10
kernel.org/pub/linux/libs/security/libcap/cap v1.2.76
@@ -116,23 +117,25 @@ require (
require (
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
- github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
+ github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
- github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 // indirect
- github.com/aws/smithy-go v1.22.5 // indirect
+ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
+ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.12 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.3 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.12 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.30.3 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.7 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.40.2 // indirect
+ github.com/aws/smithy-go v1.23.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
+ github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/containerd/cgroups/v3 v3.1.2 // indirect
@@ -142,49 +145,89 @@ require (
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containernetworking/cni v1.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
+ github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect
+ github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/docker-credential-helpers v0.9.4 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
- github.com/fatih/color v1.18.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-openapi/analysis v0.24.1 // indirect
+ github.com/go-openapi/errors v0.22.4 // indirect
+ github.com/go-openapi/jsonpointer v0.22.1 // indirect
+ github.com/go-openapi/jsonreference v0.21.3 // indirect
+ github.com/go-openapi/loads v0.23.2 // indirect
+ github.com/go-openapi/runtime v0.29.2 // indirect
+ github.com/go-openapi/spec v0.22.1 // indirect
+ github.com/go-openapi/strfmt v0.25.0 // indirect
+ github.com/go-openapi/swag v0.25.3 // indirect
+ github.com/go-openapi/swag/cmdutils v0.25.3 // indirect
+ github.com/go-openapi/swag/conv v0.25.3 // indirect
+ github.com/go-openapi/swag/fileutils v0.25.3 // indirect
+ github.com/go-openapi/swag/jsonname v0.25.3 // indirect
+ github.com/go-openapi/swag/jsonutils v0.25.3 // indirect
+ github.com/go-openapi/swag/loading v0.25.3 // indirect
+ github.com/go-openapi/swag/mangling v0.25.3 // indirect
+ github.com/go-openapi/swag/netutils v0.25.3 // indirect
+ github.com/go-openapi/swag/stringutils v0.25.3 // indirect
+ github.com/go-openapi/swag/typeutils v0.25.3 // indirect
+ github.com/go-openapi/swag/yamlutils v0.25.3 // indirect
+ github.com/go-openapi/validate v0.25.1 // indirect
+ github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
+ github.com/google/certificate-transparency-go v1.3.2 // indirect
+ github.com/google/go-containerregistry v0.20.6 // indirect
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
+ github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
github.com/hanwen/go-fuse/v2 v2.8.0 // indirect
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
+ github.com/in-toto/attestation v1.1.2 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
- github.com/mattn/go-colorable v0.1.14 // indirect
github.com/moby/sys/capability v0.4.0 // indirect
github.com/moby/sys/mount v0.3.4 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/runtime-tools v0.9.1-0.20251114084447-edf4cb3d2116 // indirect
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
+ github.com/prometheus/otlptranslator v0.0.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sasha-s/go-deadlock v0.3.5 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
+ github.com/sigstore/protobuf-specs v0.5.0 // indirect
+ github.com/sigstore/rekor v1.4.3 // indirect
+ github.com/sigstore/rekor-tiles/v2 v2.0.1 // indirect
+ github.com/sigstore/sigstore v1.10.0 // indirect
+ github.com/sigstore/timestamp-authority/v2 v2.0.2 // indirect
+ github.com/theupdateframework/go-tuf/v2 v2.3.0 // indirect
+ github.com/transparency-dev/formats v0.0.0-20251017110053-404c0d5b696c // indirect
+ github.com/transparency-dev/merkle v0.0.2 // indirect
github.com/vbatts/tar-split v0.12.2 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
+ go.mongodb.org/mongo-driver v1.17.6 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
+ go.yaml.in/yaml/v3 v3.0.4 // indirect
+ golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 // indirect
diff --git a/go.sum b/go.sum
index d3d9b32e4336..3f4044fdc1b2 100644
--- a/go.sum
+++ b/go.sum
@@ -1,22 +1,44 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
+cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
+cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
+cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
+cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
+cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
+cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
+cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
+cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc=
+cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU=
+cloud.google.com/go/kms v1.23.2 h1:4IYDQL5hG4L+HzJBhzejUySoUOheh3Lk5YT4PCyyW6k=
+cloud.google.com/go/kms v1.23.2/go.mod h1:rZ5kK0I7Kn9W4erhYVoIRPtpizjunlrfU4fUkumUp8g=
+cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
+cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 h1:MhRfI58HblXzCtWEZCO0feHs8LweePB3s90r7WaR1KU=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0/go.mod h1:okZ+ZURbArNdlJ+ptXoyHNuOETzOl1Oww19rm8I2WLA=
+github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg=
+github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 h1:JXg2dwJUmPB9JmtVmdEB16APJ7jurfbY5jnfXpJoRMc=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc=
+github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0 h1:E4MgwLBGeVB5f2MdcIVD3ELVAWpr+WD6MUe1i+tM/PA=
+github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0/go.mod h1:Y2b/1clN4zsAoUd/pgNAQHjLDnTis/6ROkUfyob6psM=
+github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4=
+github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 h1:mlmW46Q0B79I+Aj4azKC6xDMFN9a9SyZWESlGWYXbFs=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0/go.mod h1:PXe2h+LKcWTX9afWdZoHyODqR4fBa5boUM/8uJfZ0Jo=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
@@ -31,55 +53,66 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
+github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/aws/aws-sdk-go-v2 v1.38.1 h1:j7sc33amE74Rz0M/PoCpsZQ6OunLqys/m5antM0J+Z8=
-github.com/aws/aws-sdk-go-v2 v1.38.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg=
-github.com/aws/aws-sdk-go-v2/config v1.31.3 h1:RIb3yr/+PZ18YYNe6MDiG/3jVoJrPmdoCARwNkMGvco=
-github.com/aws/aws-sdk-go-v2/config v1.31.3/go.mod h1:jjgx1n7x0FAKl6TnakqrpkHWWKcX3xfWtdnIJs5K9CE=
-github.com/aws/aws-sdk-go-v2/credentials v1.18.7 h1:zqg4OMrKj+t5HlswDApgvAHjxKtlduKS7KicXB+7RLg=
-github.com/aws/aws-sdk-go-v2/credentials v1.18.7/go.mod h1:/4M5OidTskkgkv+nCIfC9/tbiQ/c8qTox9QcUDV0cgc=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 h1:lpdMwTzmuDLkgW7086jE94HweHCqG+uOJwHf3LZs7T0=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4/go.mod h1:9xzb8/SV62W6gHQGC/8rrvgNXU6ZoYM3sAIJCIrXJxY=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE=
+github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
+github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk=
+github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 h1:t9yYsydLYNBk9cJ73rgPhPWqOh/52fcWDQB5b1JsKSY=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2/go.mod h1:IusfVNTmiSN3t4rhxWFaBAqn+mcNdwKtPcV16eYdgko=
+github.com/aws/aws-sdk-go-v2/config v1.31.20 h1:/jWF4Wu90EhKCgjTdy1DGxcbcbNrjfBHvksEL79tfQc=
+github.com/aws/aws-sdk-go-v2/config v1.31.20/go.mod h1:95Hh1Tc5VYKL9NJ7tAkDcqeKt+MCXQB1hQZaRdJIZE0=
+github.com/aws/aws-sdk-go-v2/credentials v1.18.24 h1:iJ2FmPT35EaIB0+kMa6TnQ+PwG5A1prEdAw+PsMzfHg=
+github.com/aws/aws-sdk-go-v2/credentials v1.18.24/go.mod h1:U91+DrfjAiXPDEGYhh/x29o4p0qHX5HDqG7y5VViv64=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 h1:T1brd5dR3/fzNFAQch/iBKeX07/ffu/cLu+q+RuzEWk=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13/go.mod h1:Peg/GBAQ6JDt+RoBf4meB1wylmAipb7Kg2ZFakZTlwk=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.10 h1:zeN9UtUlA6FTx0vFSayxSX32HDw73Yb6Hh2izDSFxXY=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.10/go.mod h1:3HKuexPDcwLWPaqpW2UR/9n8N/u/3CKcGAzSs8p8u8g=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 h1:IdCLsiiIj5YJ3AFevsewURCPV+YWUlOW8JiPhoAy8vg=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4/go.mod h1:l4bdfCD7XyyZA9BolKBo1eLqgaJxl0/x91PL4Yqe0ao=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 h1:j7vjtr1YIssWQOMeOWRbh3z8g2oY/xPjnZH2gLY4sGw=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4/go.mod h1:yDmJgqOiH4EA8Hndnv4KwAo8jCGTSnM5ASG1nBI+toA=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4 h1:BE/MNQ86yzTINrfxPPFS86QCBNQeLKY2A0KhDh47+wI=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4/go.mod h1:SPBBhkJxjcrzJBc+qY85e83MQ2q3qdra8fghhkkyrJg=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4 h1:Beh9oVgtQnBgR4sKKzkUBRQpf1GnL4wt0l4s8h2VCJ0=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4/go.mod h1:b17At0o8inygF+c6FOD3rNyYZufPw62o9XJbSfQPgbo=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 h1:ueB2Te0NacDMnaC+68za9jLwkjzxGWm0KB5HTUHjLTI=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4/go.mod h1:nLEfLnVMmLvyIG58/6gsSA03F1voKGaCfHV7+lR8S7s=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4 h1:HVSeukL40rHclNcUqVcBwE1YoZhOkoLeBfhUqR3tjIU=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4/go.mod h1:DnbBOv4FlIXHj2/xmrUQYtawRFC9L9ZmQPz+DBc6X5I=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1 h1:2n6Pd67eJwAb/5KCX62/8RTU0aFAAW7V5XIGSghiHrw=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1/go.mod h1:w5PC+6GHLkvMJKasYGVloB3TduOtROEMqm15HSuIbw4=
-github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 h1:ve9dYBB8CfJGTFqcQ3ZLAAb/KXWgYlgu/2R2TZL2Ko0=
-github.com/aws/aws-sdk-go-v2/service/sso v1.28.2/go.mod h1:n9bTZFZcBa9hGGqVz3i/a6+NG0zmZgtkB9qVVFDqPA8=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.0 h1:Bnr+fXrlrPEoR1MAFrHVsge3M/WoK4n23VNhRM7TPHI=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.0/go.mod h1:eknndR9rU8UpE/OmFpqU78V1EcXPKFTTm5l/buZYgvM=
-github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 h1:iV1Ko4Em/lkJIsoKyGfc0nQySi+v0Udxr6Igq+y9JZc=
-github.com/aws/aws-sdk-go-v2/service/sts v1.38.0/go.mod h1:bEPcjW7IbolPfK67G1nilqWyoxYMSPrDiIQ3RdIdKgo=
-github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
-github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 h1:a+8/MLcWlIxo1lF9xaGt3J/u3yOZx+CdSveSNwjhD40=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13/go.mod h1:oGnKwIYZ4XttyU2JWxFrwvhF6YKiK/9/wmE3v3Iu9K8=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 h1:HBSI2kDkMdWz4ZM7FjwE7e/pWDEZ+nR95x8Ztet1ooY=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13/go.mod h1:YE94ZoDArI7awZqJzBAZ3PDD2zSfuP7w6P2knOzIn8M=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
+github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.12 h1:itu4KHu8JK/N6NcLIISlf3LL1LccMqruLUXZ9y7yBZw=
+github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.12/go.mod h1:i+6vTU3xziikTY3vcox23X8pPGW5X3wVgd1VZ7ha+x8=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.3 h1:NEe7FaViguRQEm8zl8Ay/kC/QRsMtWUiCGZajQIsLdc=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.3/go.mod h1:JLuCKu5VfiLBBBl/5IzZILU7rxS0koQpHzMOCzycOJU=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 h1:kDqdFvMY4AtKoACfzIGD8A0+hbT41KTKF//gq7jITfM=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13/go.mod h1:lmKuogqSU3HzQCwZ9ZtcqOc5XGMqtDK7OIc2+DxiUEg=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.12 h1:R3uW0iKl8rgNEXNjVGliW/oMEh9fO/LlUEV8RvIFr1I=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.12/go.mod h1:XEttbEr5yqsw8ebi7vlDoGJJjMXRez4/s9pibpJyL5s=
+github.com/aws/aws-sdk-go-v2/service/kms v1.48.2 h1:aL8Y/AbB6I+uw0MjLbdo68NQ8t5lNs3CY3S848HpETk=
+github.com/aws/aws-sdk-go-v2/service/kms v1.48.2/go.mod h1:VJcNH6BLr+3VJwinRKdotLOMglHO8mIKlD3ea5c7hbw=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1 h1:Dq82AV+Qxpno/fG162eAhnD8d48t9S+GZCfz7yv1VeA=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1/go.mod h1:MbKLznDKpf7PnSonNRUVYZzfP0CeLkRIUexeblgKcU4=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.3 h1:NjShtS1t8r5LUfFVtFeI8xLAHQNTa7UI0VawXlrBMFQ=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.3/go.mod h1:fKvyjJcz63iL/ftA6RaM8sRCtN4r4zl4tjL3qw5ec7k=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.7 h1:gTsnx0xXNQ6SBbymoDvcoRHL+q4l/dAFsQuKfDWSaGc=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.7/go.mod h1:klO+ejMvYsB4QATfEOIXk8WAEwN4N0aBfJpvC+5SZBo=
+github.com/aws/aws-sdk-go-v2/service/sts v1.40.2 h1:HK5ON3KmQV2HcAunnx4sKLB9aPf3gKGwVAf7xnx0QT0=
+github.com/aws/aws-sdk-go-v2/service/sts v1.40.2/go.mod h1:E19xDjpzPZC7LS2knI9E6BaRFDK43Eul7vd6rSq2HWk=
+github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM=
+github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
+github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -138,15 +171,26 @@ github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEm
github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
github.com/containernetworking/plugins v1.9.0 h1:Mg3SXBdRGkdXyFC4lcwr6u2ZB2SDeL6LC3U+QrEANuQ=
github.com/containernetworking/plugins v1.9.0/go.mod h1:JG3BxoJifxxHBhG3hFyxyhid7JgRVBu/wtooGEvWf1c=
+github.com/coreos/go-oidc/v3 v3.16.0 h1:qRQUCFstKpXwmEjDQTIbyY/5jF00+asXzSkmkoa/mow=
+github.com/coreos/go-oidc/v3 v3.16.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=
+github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
+github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ=
+github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
+github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQMIAH7uKg0lrtNSOdpYsRXlwk3QbaE=
+github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
+github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 h1:lxmTCgmHE1GUYL7P0MlNa00M67axePTq+9nBSGddR8I=
+github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7/go.mod h1:GvWntX9qiTlOud0WkQ6ewFm0LPy5JUR1Xo0Ngbd1w6Y=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
@@ -171,6 +215,11 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
+github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
+github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
+github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
+github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -179,9 +228,63 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-openapi/analysis v0.24.1 h1:Xp+7Yn/KOnVWYG8d+hPksOYnCYImE3TieBa7rBOesYM=
+github.com/go-openapi/analysis v0.24.1/go.mod h1:dU+qxX7QGU1rl7IYhBC8bIfmWQdX4Buoea4TGtxXY84=
+github.com/go-openapi/errors v0.22.4 h1:oi2K9mHTOb5DPW2Zjdzs/NIvwi2N3fARKaTJLdNabaM=
+github.com/go-openapi/errors v0.22.4/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk=
+github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk=
+github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM=
+github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc=
+github.com/go-openapi/jsonreference v0.21.3/go.mod h1:RqkUP0MrLf37HqxZxrIAtTWW4ZJIK1VzduhXYBEeGc4=
+github.com/go-openapi/loads v0.23.2 h1:rJXAcP7g1+lWyBHC7iTY+WAF0rprtM+pm8Jxv1uQJp4=
+github.com/go-openapi/loads v0.23.2/go.mod h1:IEVw1GfRt/P2Pplkelxzj9BYFajiWOtY2nHZNj4UnWY=
+github.com/go-openapi/runtime v0.29.2 h1:UmwSGWNmWQqKm1c2MGgXVpC2FTGwPDQeUsBMufc5Yj0=
+github.com/go-openapi/runtime v0.29.2/go.mod h1:biq5kJXRJKBJxTDJXAa00DOTa/anflQPhT0/wmjuy+0=
+github.com/go-openapi/spec v0.22.1 h1:beZMa5AVQzRspNjvhe5aG1/XyBSMeX1eEOs7dMoXh/k=
+github.com/go-openapi/spec v0.22.1/go.mod h1:c7aeIQT175dVowfp7FeCvXXnjN/MrpaONStibD2WtDA=
+github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ=
+github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8=
+github.com/go-openapi/swag v0.25.3 h1:FAa5wJXyDtI7yUztKDfZxDrSx+8WTg31MfCQ9s3PV+s=
+github.com/go-openapi/swag v0.25.3/go.mod h1:tX9vI8Mj8Ny+uCEk39I1QADvIPI7lkndX4qCsEqhkS8=
+github.com/go-openapi/swag/cmdutils v0.25.3 h1:EIwGxN143JCThNHnqfqs85R8lJcJG06qjJRZp3VvjLI=
+github.com/go-openapi/swag/cmdutils v0.25.3/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
+github.com/go-openapi/swag/conv v0.25.3 h1:PcB18wwfba7MN5BVlBIV+VxvUUeC2kEuCEyJ2/t2X7E=
+github.com/go-openapi/swag/conv v0.25.3/go.mod h1:n4Ibfwhn8NJnPXNRhBO5Cqb9ez7alBR40JS4rbASUPU=
+github.com/go-openapi/swag/fileutils v0.25.3 h1:P52Uhd7GShkeU/a1cBOuqIcHMHBrA54Z2t5fLlE85SQ=
+github.com/go-openapi/swag/fileutils v0.25.3/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk=
+github.com/go-openapi/swag/jsonname v0.25.3 h1:U20VKDS74HiPaLV7UZkztpyVOw3JNVsit+w+gTXRj0A=
+github.com/go-openapi/swag/jsonname v0.25.3/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
+github.com/go-openapi/swag/jsonutils v0.25.3 h1:kV7wer79KXUM4Ea4tBdAVTU842Rg6tWstX3QbM4fGdw=
+github.com/go-openapi/swag/jsonutils v0.25.3/go.mod h1:ILcKqe4HC1VEZmJx51cVuZQ6MF8QvdfXsQfiaCs0z9o=
+github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3 h1:/i3E9hBujtXfHy91rjtwJ7Fgv5TuDHgnSrYjhFxwxOw=
+github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3/go.mod h1:8kYfCR2rHyOj25HVvxL5Nm8wkfzggddgjZm6RgjT8Ao=
+github.com/go-openapi/swag/loading v0.25.3 h1:Nn65Zlzf4854MY6Ft0JdNrtnHh2bdcS/tXckpSnOb2Y=
+github.com/go-openapi/swag/loading v0.25.3/go.mod h1:xajJ5P4Ang+cwM5gKFrHBgkEDWfLcsAKepIuzTmOb/c=
+github.com/go-openapi/swag/mangling v0.25.3 h1:rGIrEzXaYWuUW1MkFmG3pcH+EIA0/CoUkQnIyB6TUyo=
+github.com/go-openapi/swag/mangling v0.25.3/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg=
+github.com/go-openapi/swag/netutils v0.25.3 h1:XWXHZfL/65ABiv8rvGp9dtE0C6QHTYkCrNV77jTl358=
+github.com/go-openapi/swag/netutils v0.25.3/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg=
+github.com/go-openapi/swag/stringutils v0.25.3 h1:nAmWq1fUTWl/XiaEPwALjp/8BPZJun70iDHRNq/sH6w=
+github.com/go-openapi/swag/stringutils v0.25.3/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
+github.com/go-openapi/swag/typeutils v0.25.3 h1:2w4mEEo7DQt3V4veWMZw0yTPQibiL3ri2fdDV4t2TQc=
+github.com/go-openapi/swag/typeutils v0.25.3/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
+github.com/go-openapi/swag/yamlutils v0.25.3 h1:LKTJjCn/W1ZfMec0XDL4Vxh8kyAnv1orH5F2OREDUrg=
+github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao=
+github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4=
+github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
+github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
+github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
+github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw=
+github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc=
+github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
+github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -206,6 +309,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/certificate-transparency-go v1.3.2 h1:9ahSNZF2o7SYMaKaXhAumVEzXB2QaayzII9C8rv7v+A=
+github.com/google/certificate-transparency-go v1.3.2/go.mod h1:H5FpMUaGa5Ab2+KCYsxg6sELw3Flkl7pGZzWdBoYLXs=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -216,17 +321,31 @@ 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.6 h1:cvWX87UxxLgaH76b4hIvya6Dzz9qHB31qAwjAohdSTU=
+github.com/google/go-containerregistry v0.20.6/go.mod h1:T0x8MuoAoKX/873bkeSfLD2FAkwCDf9/HZgsFJ02E2Y=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
+github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
+github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
+github.com/google/trillian v1.7.2 h1:EPBxc4YWY4Ak8tcuhyFleY+zYlbCDCa4Sn24e1Ka8Js=
+github.com/google/trillian v1.7.2/go.mod h1:mfQJW4qRH6/ilABtPYNBerVJAJ/upxHLX81zxNQw05s=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
+github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
+github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
+github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
+github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
+github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248=
+github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs=
github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
@@ -241,15 +360,47 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
+github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
+github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM=
+github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0=
+github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
+github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
+github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw=
+github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I=
+github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
+github.com/hashicorp/vault/api v1.22.0 h1:+HYFquE35/B74fHoIeXlZIP2YADVboaPjaSicHEZiH0=
+github.com/hashicorp/vault/api v1.22.0/go.mod h1:IUZA2cDvr4Ok3+NtK2Oq/r+lJeXkeCrHRmqdyWfpmGM=
github.com/hiddeco/sshsig v0.2.0 h1:gMWllgKCITXdydVkDL+Zro0PU96QI55LwUwebSwNTSw=
github.com/hiddeco/sshsig v0.2.0/go.mod h1:nJc98aGgiH6Yql2doqH4CTBVHexQA40Q+hMMLHP4EqE=
+github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM=
+github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
+github.com/in-toto/attestation v1.1.2 h1:MBFn6lsMq6dptQZJBhalXTcWMb/aJy3V+GX3VYj/V1E=
+github.com/in-toto/attestation v1.1.2/go.mod h1:gYFddHMZj3DiQ0b62ltNi1Vj5rC879bTmBbrv9CRHpM=
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
+github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
+github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
+github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
+github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b h1:ZGiXF8sz7PDk6RgkP+A/SFfUD0ZR/AgG6SpRNEDKZy8=
+github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b/go.mod h1:hQmNrgofl+IY/8L+n20H6E6PWBBTokdsv+q49j0QhsU=
+github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY=
+github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
+github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY=
+github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@@ -267,13 +418,19 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/letsencrypt/boulder v0.20251110.0 h1:J8MnKICeilO91dyQ2n5eBbab24neHzUpYMUIOdOtbjc=
+github.com/letsencrypt/boulder v0.20251110.0/go.mod h1:ogKCJQwll82m7OVHWyTuf8eeFCjuzdRQlgnZcCl0V+8=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
@@ -282,8 +439,8 @@ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
-github.com/moby/policy-helpers v0.0.0-20251105011237-bcaa71c99f14 h1:JO22uXMy3CN7wh7A/wrtYQWV1WYQMg2gh6d8YO325k4=
-github.com/moby/policy-helpers v0.0.0-20251105011237-bcaa71c99f14/go.mod h1:HJfK0E8dR+Jpk5anJ3oADg2dRSom1gJK17sqEiiMS7w=
+github.com/moby/policy-helpers v0.0.0-20251206004813-9fcc1a9ec5c9 h1:SISQT6l9QO+JGSTJ8QN0yWCueiSgfTStSU9KT+p537M=
+github.com/moby/policy-helpers v0.0.0-20251206004813-9fcc1a9ec5c9/go.mod h1:nJ1clNCIXZqUu3jxCkaUBpeR5bKyzzb7wmEG4xhecTI=
github.com/moby/profiles/seccomp v0.1.0 h1:kVf1lc5ytNB1XPxEdZUVF+oPpbBYJHR50eEvPt/9k8A=
github.com/moby/profiles/seccomp v0.1.0/go.mod h1:Kqk57vxH6/wuOc5bmqRiSXJ6iEz8Pvo3LQRkv0ytFWs=
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
@@ -311,6 +468,10 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
+github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
+github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY=
github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk=
@@ -356,29 +517,63 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
+github.com/prometheus/otlptranslator v0.0.2 h1:+1CdeLVrRQ6Psmhnobldo0kTp96Rj80DRXRd5OSnMEQ=
+github.com/prometheus/otlptranslator v0.0.2/go.mod h1:P8AwMgdD7XEr6QRUJ2QWLpiAZTgTE2UYgjlu3svompI=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
-github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
-github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
+github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU=
github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U=
+github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A=
+github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk=
+github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4=
+github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k=
github.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL5qTdn9lR8XKHf4RUyG1Sx3g=
github.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU=
+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/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b h1:h+3JX2VoWTFuyQEo87pStk/a99dzIO1mM9KxIyLPGTU=
github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
+github.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY=
+github.com/sigstore/protobuf-specs v0.5.0/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc=
+github.com/sigstore/rekor v1.4.3 h1:2+aw4Gbgumv8vYM/QVg6b+hvr4x4Cukur8stJrVPKU0=
+github.com/sigstore/rekor v1.4.3/go.mod h1:o0zgY087Q21YwohVvGwV9vK1/tliat5mfnPiVI3i75o=
+github.com/sigstore/rekor-tiles/v2 v2.0.1 h1:1Wfz15oSRNGF5Dzb0lWn5W8+lfO50ork4PGIfEKjZeo=
+github.com/sigstore/rekor-tiles/v2 v2.0.1/go.mod h1:Pjsbhzj5hc3MKY8FfVTYHBUHQEnP0ozC4huatu4x7OU=
+github.com/sigstore/sigstore v1.10.0 h1:lQrmdzqlR8p9SCfWIpFoGUqdXEzJSZT2X+lTXOMPaQI=
+github.com/sigstore/sigstore v1.10.0/go.mod h1:Ygq+L/y9Bm3YnjpJTlQrOk/gXyrjkpn3/AEJpmk1n9Y=
+github.com/sigstore/sigstore-go v1.1.4-0.20251124094504-b5fe07a5a7d7 h1:94NLPmq4bxvdmslzcG670IOkrlS98CGpmob8cjpFHuI=
+github.com/sigstore/sigstore-go v1.1.4-0.20251124094504-b5fe07a5a7d7/go.mod h1:4r/PNX0G7uzkLpc3PSdYs5E2k4bWEJNXTK6kwAyw9TM=
+github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.0 h1:UOHpiyezCj5RuixgIvCV3QyuxIGQT+N6nGZEXA7OTTY=
+github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.0/go.mod h1:U0CZmA2psabDa8DdiV7yXab0AHODzfKqvD2isH7Hrvw=
+github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.0 h1:fq4+8Y4YadxeF8mzhoMRPZ1mVvDYXmI3BfS0vlkPT7M=
+github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.0/go.mod h1:u05nqPWY05lmcdHhv2lPaWTH3FGUhJzO7iW2hbboK3Q=
+github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.0 h1:iUEf5MZYOuXGnXxdF/WrarJrk0DTVHqeIOjYdtpVXtc=
+github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.0/go.mod h1:i6vg5JfEQix46R1rhQlrKmUtJoeH91drltyYOJEk1T4=
+github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.0 h1:dUvPv/MP23ZPIXZUW45kvCIgC0ZRfYxEof57AB6bAtU=
+github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.0/go.mod h1:fR/gDdPvJWGWL70/NgBBIL1O0/3Wma6JHs3tSSYg3s4=
+github.com/sigstore/timestamp-authority/v2 v2.0.2 h1:WavlEeLh6HKt+osbmsHDg6/FaM/8Pz9iVUMh9pAsl/o=
+github.com/sigstore/timestamp-authority/v2 v2.0.2/go.mod h1:D+wbQg8ASQzKnwBhLo7rIJD+9Zev4Ppqd4myPe8k57E=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
+github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
+github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
+github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
+github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -396,6 +591,20 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI=
+github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug=
+github.com/theupdateframework/go-tuf/v2 v2.3.0 h1:gt3X8xT8qu/HT4w+n1jgv+p7koi5ad8XEkLXXZqG9AA=
+github.com/theupdateframework/go-tuf/v2 v2.3.0/go.mod h1:xW8yNvgXRncmovMLvBxKwrKpsOwJZu/8x+aB0KtFcdw=
+github.com/tink-crypto/tink-go-awskms/v2 v2.1.0 h1:N9UxlsOzu5mttdjhxkDLbzwtEecuXmlxZVo/ds7JKJI=
+github.com/tink-crypto/tink-go-awskms/v2 v2.1.0/go.mod h1:PxSp9GlOkKL9rlybW804uspnHuO9nbD98V/fDX4uSis=
+github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0 h1:3B9i6XBXNTRspfkTC0asN5W0K6GhOSgcujNiECNRNb0=
+github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0/go.mod h1:jY5YN2BqD/KSCHM9SqZPIpJNG/u3zwfLXHgws4x2IRw=
+github.com/tink-crypto/tink-go-hcvault/v2 v2.3.0 h1:6nAX1aRGnkg2SEUMwO5toB2tQkP0Jd6cbmZ/K5Le1V0=
+github.com/tink-crypto/tink-go-hcvault/v2 v2.3.0/go.mod h1:HOC5NWW1wBI2Vke1FGcRBvDATkEYE7AUDiYbXqi2sBw=
+github.com/tink-crypto/tink-go/v2 v2.5.0 h1:B8KLF6AofxdBIE4UJIaFbmoj5/1ehEtt7/MmzfI4Zpw=
+github.com/tink-crypto/tink-go/v2 v2.5.0/go.mod h1:2WbBA6pfNsAfBwDCggboaHeB2X29wkU8XHtGwh2YIk8=
+github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=
+github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4=
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=
github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f h1:Z4NEQ86qFl1mHuCu9gwcE+EYCwDKfXAYXZbdIXyxmEA=
@@ -410,6 +619,10 @@ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw=
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
+github.com/transparency-dev/formats v0.0.0-20251017110053-404c0d5b696c h1:5a2XDQ2LiAUV+/RjckMyq9sXudfrPSuCY4FuPC1NyAw=
+github.com/transparency-dev/formats v0.0.0-20251017110053-404c0d5b696c/go.mod h1:g85IafeFJZLxlzZCDRu4JLpfS7HKzR+Hw9qRh3bVzDI=
+github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4=
+github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A=
github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ=
github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo=
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
@@ -426,8 +639,12 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms=
+github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
+go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss=
+go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
@@ -452,8 +669,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4D
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
-go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA=
-go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA=
+go.opentelemetry.io/otel/exporters/prometheus v0.60.0 h1:cGtQxGvZbnrWdC2GyjZi0PDKVSLWP/Jocix3QWfXtbo=
+go.opentelemetry.io/otel/exporters/prometheus v0.60.0/go.mod h1:hkd1EekxNo69PTV4OWFGZcKQiIqg0RfuWExcPKFvepk=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
@@ -464,10 +681,16 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
+go.step.sm/crypto v0.74.0 h1:/APBEv45yYR4qQFg47HA8w1nesIGcxh44pGyQNw6JRA=
+go.step.sm/crypto v0.74.0/go.mod h1:UoXqCAJjjRgzPte0Llaqen7O9P7XjPmgjgTHQGkKCDk=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -486,8 +709,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
-golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
+golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
+golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -502,6 +725,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
+golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -548,15 +773,19 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/api v0.256.0 h1:u6Khm8+F9sxbCTYNoBHg6/Hwv0N/i+V94MvkOSor6oI=
+google.golang.org/api v0.256.0/go.mod h1:KIgPhksXADEKJlnEoRa9qAII4rXcy40vfI8HRqcU964=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
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-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
+google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9 h1:LvZVVaPE0JSqL+ZWb6ErZfnEOKIqqFWUJE2D0fObSmc=
+google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9/go.mod h1:QFOrLhdAe2PsTp3vQY4quuLKTi9j3XG3r6JPPaw7MSc=
+google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU=
+google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -591,6 +820,8 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
+k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY=
@@ -598,6 +829,8 @@ kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6W
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
+software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=
+software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI=
tags.cncf.io/container-device-interface v1.1.0 h1:RnxNhxF1JOu6CJUVpetTYvrXHdxw9j9jFYgZpI+anSY=
tags.cncf.io/container-device-interface v1.1.0/go.mod h1:76Oj0Yqp9FwTx/pySDc8Bxjpg+VqXfDb50cKAXVJ34Q=
tags.cncf.io/container-device-interface/specs-go v1.1.0 h1:QRZVeAceQM+zTZe12eyfuJuuzp524EKYwhmvLd+h+yQ=
diff --git a/solver/resolvercache_test.go b/solver/resolvercache_test.go
index b8e3864bafc2..d8af7eb48d48 100644
--- a/solver/resolvercache_test.go
+++ b/solver/resolvercache_test.go
@@ -50,13 +50,11 @@ func TestResolverCache_ConcurrentWaiters(t *testing.T) {
// Two goroutines that will wait
for range 2 {
- wg.Add(1)
- go func() {
- defer wg.Done()
+ wg.Go(func() {
v, _, err := rc.Lock("shared")
results <- v
assert.NoError(t, err)
- }()
+ })
}
select {
diff --git a/util/cachedigest/db.go b/util/cachedigest/db.go
index 1471a3a22000..007d32081514 100644
--- a/util/cachedigest/db.go
+++ b/util/cachedigest/db.go
@@ -67,9 +67,8 @@ func (d *DB) saveFrames(key string, frames []Frame) {
if d.db == nil {
return
}
- d.wg.Add(1)
- go func() {
- defer d.wg.Done()
+
+ d.wg.Go(func() {
val, err := encodeFrames(frames)
if err != nil {
// Optionally log error
@@ -82,7 +81,7 @@ func (d *DB) saveFrames(key string, frames []Frame) {
}
return b.Put([]byte(key), val)
})
- }()
+ })
}
func (d *DB) Get(ctx context.Context, dgst string) (Type, []Frame, error) {
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
index a2261b7a3d49..47d2b85fa866 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
@@ -1,5 +1,33 @@
# Release History
+## 1.20.0 (2025-11-06)
+
+### Features Added
+
+* Added `runtime.FetcherForNextLinkOptions.HTTPVerb` to specify the HTTP verb when fetching the next page via next link. Defaults to `http.MethodGet`.
+
+### Bugs Fixed
+
+* Fixed potential panic when decoding base64 strings.
+* Fixed an issue in resource identifier parsing which prevented it from returning an error for malformed resource IDs.
+
+## 1.19.1 (2025-09-11)
+
+### Bugs Fixed
+
+* Fixed resource identifier parsing for provider-specific resource hierarchies containing "resourceGroups" segments.
+
+### Other Changes
+
+* Improved error fall-back for improperly authored long-running operations.
+* Upgraded dependencies.
+
+## 1.19.0 (2025-08-21)
+
+### Features Added
+
+* Added `runtime.APIVersionLocationPath` to be set by clients that set the API version in the path.
+
## 1.18.2 (2025-07-31)
### Bugs Fixed
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go
index a08d3d0ffa68..8a40ebe4d2fd 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go
@@ -123,9 +123,9 @@ func newResourceIDWithProvider(parent *ResourceID, providerNamespace, resourceTy
}
func chooseResourceType(resourceTypeName string, parent *ResourceID) ResourceType {
- if strings.EqualFold(resourceTypeName, resourceGroupsLowerKey) {
+ if strings.EqualFold(resourceTypeName, resourceGroupsLowerKey) && isSubscriptionResource(parent) {
return ResourceGroupResourceType
- } else if strings.EqualFold(resourceTypeName, subscriptionsKey) && parent != nil && parent.ResourceType.String() == TenantResourceType.String() {
+ } else if strings.EqualFold(resourceTypeName, subscriptionsKey) && isTenantResource(parent) {
return SubscriptionResourceType
}
@@ -182,12 +182,12 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err
if len(parts) == 1 {
// subscriptions and resourceGroups are not valid ids without their names
- if strings.EqualFold(parts[0], subscriptionsKey) || strings.EqualFold(parts[0], resourceGroupsLowerKey) {
+ if strings.EqualFold(parts[0], subscriptionsKey) && isTenantResource(parent) || strings.EqualFold(parts[0], resourceGroupsLowerKey) && isSubscriptionResource(parent) {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
// resourceGroup must contain either child or provider resource type
- if parent.ResourceType.String() == ResourceGroupResourceType.String() {
+ if isResourceGroupResource(parent) {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
@@ -196,7 +196,7 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err
if strings.EqualFold(parts[0], providersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], providersKey)) {
// provider resource can only be on a tenant or a subscription parent
- if parent.ResourceType.String() != SubscriptionResourceType.String() && parent.ResourceType.String() != TenantResourceType.String() {
+ if !isSubscriptionResource(parent) && !isTenantResource(parent) {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
@@ -217,6 +217,7 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err
func splitStringAndOmitEmpty(v, sep string) []string {
r := make([]string, 0)
for _, s := range strings.Split(v, sep) {
+ s = strings.TrimSpace(s)
if len(s) == 0 {
continue
}
@@ -225,3 +226,18 @@ func splitStringAndOmitEmpty(v, sep string) []string {
return r
}
+
+// isTenantResource returns true if the resourceID represents a tenant resource. The condition is resource ID matched with TenantResourceType and has no parent.
+func isTenantResource(resourceID *ResourceID) bool {
+ return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), TenantResourceType.String()) && resourceID.Parent == nil
+}
+
+// isSubscriptionResource returns true if the resourceID represents a subscription resource. The condition is resource ID matched with SubscriptionResourceType and its parent is a tenant resource.
+func isSubscriptionResource(resourceID *ResourceID) bool {
+ return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), SubscriptionResourceType.String()) && isTenantResource(resourceID.Parent)
+}
+
+// isResourceGroupResource returns true if the resourceID represents a resource group resource. The condition is resource ID matched with ResourceGroupResourceType and its parent is a subscription resource.
+func isResourceGroupResource(resourceID *ResourceID) bool {
+ return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), ResourceGroupResourceType.String()) && isSubscriptionResource(resourceID.Parent)
+}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
index 460170034aac..612af11ac613 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
@@ -92,7 +92,7 @@ func DecodeByteArray(s string, v *[]byte, format Base64Encoding) error {
return nil
}
payload := string(s)
- if payload[0] == '"' {
+ if len(payload) >= 2 && payload[0] == '"' && payload[len(payload)-1] == '"' {
// remove surrounding quotes
payload = payload[1 : len(payload)-1]
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
index ccca7b769d12..f152000913dd 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
@@ -40,5 +40,5 @@ const (
Module = "azcore"
// Version is the semantic version (see http://semver.org) of this module.
- Version = "v1.18.2"
+ Version = "v1.20.0"
)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
index c66fc0a90a56..edb4a3cd44f5 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
@@ -99,6 +99,11 @@ type FetcherForNextLinkOptions struct {
// StatusCodes contains additional HTTP status codes indicating success.
// The default value is http.StatusOK.
StatusCodes []int
+
+ // HTTPVerb specifies the HTTP verb to use when fetching the next page.
+ // The default value is http.MethodGet.
+ // This field is only used when NextReq is not specified.
+ HTTPVerb string
}
// FetcherForNextLink is a helper containing boilerplate code to simplify creating a PagingHandler[T].Fetcher from a next link URL.
@@ -119,7 +124,11 @@ func FetcherForNextLink(ctx context.Context, pl Pipeline, nextLink string, first
if options.NextReq != nil {
req, err = options.NextReq(ctx, nextLink)
} else {
- req, err = NewRequest(ctx, http.MethodGet, nextLink)
+ verb := http.MethodGet
+ if options.HTTPVerb != "" {
+ verb = options.HTTPVerb
+ }
+ req, err = NewRequest(ctx, verb, nextLink)
}
}
if err != nil {
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go
index e5309aa6c15b..c3646feb55b3 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go
@@ -16,9 +16,10 @@ import (
// APIVersionOptions contains options for API versions
type APIVersionOptions struct {
- // Location indicates where to set the version on a request, for example in a header or query param
+ // Location indicates where to set the version on a request, for example in a header or query param.
Location APIVersionLocation
- // Name is the name of the header or query parameter, for example "api-version"
+ // Name is the name of the header or query parameter, for example "api-version".
+ // For [APIVersionLocationPath] the value is not used.
Name string
}
@@ -30,6 +31,8 @@ const (
APIVersionLocationQueryParam = 0
// APIVersionLocationHeader indicates a header
APIVersionLocationHeader = 1
+ // APIVersionLocationPath indicates a path segment
+ APIVersionLocationPath = 2
)
// newAPIVersionPolicy constructs an APIVersionPolicy. If version is "", Do will be a no-op. If version
@@ -55,7 +58,10 @@ type apiVersionPolicy struct {
// Do sets the request's API version, if the policy is configured to do so, replacing any prior value.
func (a *apiVersionPolicy) Do(req *policy.Request) (*http.Response, error) {
- if a.version != "" {
+ // for API versions in the path, the client is responsible for
+ // setting the correct path segment with the version. so, if the
+ // location is path the policy is effectively a no-op.
+ if a.location != APIVersionLocationPath && a.version != "" {
if a.name == "" {
// user set ClientOptions.APIVersion but the client ctor didn't set PipelineOptions.APIVersionOptions
return nil, errors.New("this client doesn't support overriding its API version")
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
index 4f90e4474323..a89ae9b7b9d5 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
@@ -91,7 +91,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol
// this is a back-stop in case the swagger is incorrect (i.e. missing one or more status codes for success).
// ideally the codegen should return an error if the initial response failed and not even create a poller.
if !poller.StatusCodeValid(resp) {
- return nil, errors.New("the operation failed or was cancelled")
+ return nil, exported.NewResponseError(resp)
}
// determine the polling method
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
index 9e68cf670152..4a6349e16787 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
@@ -1,5 +1,46 @@
# Release History
+## 1.13.1 (2025-11-10)
+
+### Bugs Fixed
+
+- `AzureCLICredential` quoted arguments incorrectly on Windows
+
+## 1.13.0 (2025-10-07)
+
+### Features Added
+
+- Added `AzurePowerShellCredential`, which authenticates as the identity logged in to Azure PowerShell
+ (thanks [ArmaanMcleod](https://github.com/ArmaanMcleod))
+- When `AZURE_TOKEN_CREDENTIALS` is set to `ManagedIdentityCredential`, `DefaultAzureCredential` behaves the same as
+ does `ManagedIdentityCredential` when used directly. It doesn't apply special retry configuration or attempt to
+ determine whether IMDS is available. ([#25265](https://github.com/Azure/azure-sdk-for-go/issues/25265))
+
+### Breaking Changes
+
+* Removed the `WorkloadIdentityCredential` support for identity binding mode added in v1.13.0-beta.1.
+ It will return in v1.14.0-beta.1
+
+## 1.13.0-beta.1 (2025-09-17)
+
+### Features Added
+
+- Added `AzurePowerShellCredential`, which authenticates as the identity logged in to Azure PowerShell
+ (thanks [ArmaanMcleod](https://github.com/ArmaanMcleod))
+- `WorkloadIdentityCredential` supports identity binding mode ([#25056](https://github.com/Azure/azure-sdk-for-go/issues/25056))
+
+## 1.12.0 (2025-09-16)
+
+### Features Added
+- Added `DefaultAzureCredentialOptions.RequireAzureTokenCredentials`. `NewDefaultAzureCredential` returns an
+ error when this option is true and the environment variable `AZURE_TOKEN_CREDENTIALS` has no value.
+
+### Other Changes
+- `AzureDeveloperCLICredential` no longer hangs when AZD_DEBUG is set
+- `GetToken` methods of `AzureCLICredential` and `AzureDeveloperCLICredential` return an error when
+ `TokenRequestOptions.Claims` has a value because these credentials can't acquire a token in that
+ case. The error messages describe the action required to get a token.
+
## 1.11.0 (2025-08-05)
### Other Changes
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
index 069bc688d52f..127c25b72cf4 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
@@ -1,6 +1,6 @@
# Azure Identity Client Module for Go
-The Azure Identity module provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/entra/fundamentals/new-name)) token authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication.
+The Azure Identity module provides [Microsoft Entra ID](https://learn.microsoft.com/entra/fundamentals/whatis) token-based authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication.
[](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity)
| [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity/)
@@ -153,6 +153,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|-|-
|[AzureCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureCLICredential)|Authenticate as the user signed in to the Azure CLI
|[AzureDeveloperCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI
+|[AzurePowerShellCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzurePowerShellCredential)|Authenticates as the user signed in to Azure PowerShell
## Environment Variables
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
index da2094e36b1b..8bdaf816515b 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
@@ -40,6 +40,7 @@ The following table indicates the state of in-memory and persistent caching in e
| ------------------------------ | ------------------------------------------------------------------- | ------------------------ |
| `AzureCLICredential` | Not Supported | Not Supported |
| `AzureDeveloperCLICredential` | Not Supported | Not Supported |
+| `AzurePowerShellCredential` | Not Supported | Not Supported |
| `AzurePipelinesCredential` | Supported | Supported |
| `ClientAssertionCredential` | Supported | Supported |
| `ClientCertificateCredential` | Supported | Supported |
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
index 6ac513846d9e..517006a424fd 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
@@ -12,13 +12,13 @@ This troubleshooting guide covers failure investigation techniques, common error
- [Troubleshoot AzureCLICredential authentication issues](#troubleshoot-azureclicredential-authentication-issues)
- [Troubleshoot AzureDeveloperCLICredential authentication issues](#troubleshoot-azuredeveloperclicredential-authentication-issues)
- [Troubleshoot AzurePipelinesCredential authentication issues](#troubleshoot-azurepipelinescredential-authentication-issues)
+- [Troubleshoot AzurePowerShellCredential authentication issues](#troubleshoot-azurepowershellcredential-authentication-issues)
- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues)
- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues)
- [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues)
- [Troubleshoot EnvironmentCredential authentication issues](#troubleshoot-environmentcredential-authentication-issues)
- [Troubleshoot ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues)
- [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity)
- - [Azure Kubernetes Service managed identity](#azure-kubernetes-service-managed-identity)
- [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity)
- [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues)
- [Get additional help](#get-additional-help)
@@ -120,7 +120,6 @@ azlog.SetEvents(azidentity.EventAuthentication)
|---|---|---|
|Azure Virtual Machines and Scale Sets|[Configuration](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm)|[Troubleshooting](#azure-virtual-machine-managed-identity)|
|Azure App Service and Azure Functions|[Configuration](https://learn.microsoft.com/azure/app-service/overview-managed-identity)|[Troubleshooting](#azure-app-service-and-azure-functions-managed-identity)|
-|Azure Kubernetes Service|[Configuration](https://azure.github.io/aad-pod-identity/docs/)|[Troubleshooting](#azure-kubernetes-service-managed-identity)|
|Azure Arc|[Configuration](https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication)||
|Azure Service Fabric|[Configuration](https://learn.microsoft.com/azure/service-fabric/concepts-managed-identity)||
@@ -159,14 +158,6 @@ curl "$IDENTITY_ENDPOINT?resource=https://management.core.windows.net&api-versio
> This command's output will contain an access token and SHOULD NOT BE SHARED, to avoid compromising account security.
-### Azure Kubernetes Service managed identity
-
-#### Pod Identity
-
-| Error Message |Description| Mitigation |
-|---|---|---|
-|"no azure identity found for request clientID"|The application attempted to authenticate before an identity was assigned to its pod|Verify the pod is labeled correctly. This also occurs when a correctly labeled pod authenticates before the identity is ready. To prevent initialization races, configure NMI to set the Retry-After header in its responses as described in [Pod Identity documentation](https://azure.github.io/aad-pod-identity/docs/configure/feature_flags/#set-retry-after-header-in-nmi-response).
-
## Troubleshoot AzureCLICredential authentication issues
@@ -215,6 +206,34 @@ azd auth token --output json --scope https://management.core.windows.net/.defaul
```
>Note that output of this command will contain a valid access token, and SHOULD NOT BE SHARED to avoid compromising account security.
+
+## Troubleshoot `AzurePowerShellCredential` authentication issues
+
+| Error Message |Description| Mitigation |
+|---|---|---|
+|executable not found on path|No local installation of PowerShell was found.|Ensure that PowerShell is properly installed on the machine. Instructions for installing PowerShell can be found [here](https://learn.microsoft.com/powershell/scripting/install/installing-powershell).|
+|Az.Accounts module not found|The Az.Account module needed for authentication in Azure PowerShell isn't installed.|Install the latest Az.Account module. Installation instructions can be found [here](https://learn.microsoft.com/powershell/azure/install-az-ps).|
+|Please run "Connect-AzAccount" to set up account.|No account is currently logged into Azure PowerShell.|
Log in to Azure PowerShell using the `Connect-AzAccount` command. More instructions for authenticating Azure PowerShell can be found at [Sign in with Azure PowerShell](https://learn.microsoft.com/powershell/azure/authenticate-azureps).
Validate that Azure PowerShell can obtain tokens. For instructions, see [Verify Azure PowerShell can obtain tokens](#verify-azure-powershell-can-obtain-tokens).
|
+
+#### __Verify Azure PowerShell can obtain tokens__
+
+You can manually verify that Azure PowerShell is authenticated and can obtain tokens. First, use the `Get-AzContext` command to verify the account that is currently logged in to Azure PowerShell.
+
+```
+PS C:\> Get-AzContext
+
+Name Account SubscriptionName Environment TenantId
+---- ------- ---------------- ----------- --------
+Subscription1 (xxxxxxxx-xxxx-xxxx-xxx... test@outlook.com Subscription1 AzureCloud xxxxxxxx-x...
+```
+
+Once you've verified Azure PowerShell is using correct account, validate that it's able to obtain tokens for this account:
+
+```bash
+Get-AzAccessToken -ResourceUrl "https://management.core.windows.net"
+```
+>Note that output of this command will contain a valid access token, and SHOULD NOT BE SHARED to avoid compromising account security.
+
## Troubleshoot `WorkloadIdentityCredential` authentication issues
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
index 4118f99ef2c9..1646ff911674 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
@@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "go",
"TagPrefix": "go/azidentity",
- "Tag": "go/azidentity_191110b0dd"
+ "Tag": "go/azidentity_530ea4279b"
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
index 0fd03f45634a..6944152c96e1 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
@@ -7,14 +7,11 @@
package azidentity
import (
- "bytes"
"context"
+ "encoding/base64"
"encoding/json"
"errors"
"fmt"
- "os"
- "os/exec"
- "runtime"
"strings"
"sync"
"time"
@@ -26,8 +23,6 @@ import (
const credNameAzureCLI = "AzureCLICredential"
-type azTokenProvider func(ctx context.Context, scopes []string, tenant, subscription string) ([]byte, error)
-
// AzureCLICredentialOptions contains optional parameters for AzureCLICredential.
type AzureCLICredentialOptions struct {
// AdditionallyAllowedTenants specifies tenants to which the credential may authenticate, in addition to
@@ -45,15 +40,8 @@ type AzureCLICredentialOptions struct {
// inDefaultChain is true when the credential is part of DefaultAzureCredential
inDefaultChain bool
- // tokenProvider is used by tests to fake invoking az
- tokenProvider azTokenProvider
-}
-
-// init returns an instance of AzureCLICredentialOptions initialized with default values.
-func (o *AzureCLICredentialOptions) init() {
- if o.tokenProvider == nil {
- o.tokenProvider = defaultAzTokenProvider
- }
+ // exec is used by tests to fake invoking az
+ exec executor
}
// AzureCLICredential authenticates as the identity logged in to the Azure CLI.
@@ -80,7 +68,9 @@ func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredent
if cp.TenantID != "" && !validTenantID(cp.TenantID) {
return nil, errInvalidTenantID
}
- cp.init()
+ if cp.exec == nil {
+ cp.exec = shellExec
+ }
cp.AdditionallyAllowedTenants = resolveAdditionalTenants(cp.AdditionallyAllowedTenants)
return &AzureCLICredential{mu: &sync.Mutex{}, opts: cp}, nil
}
@@ -99,14 +89,37 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequ
if err != nil {
return at, err
}
+ // pass the CLI a Microsoft Entra ID v1 resource because we don't know which CLI version is installed and older ones don't support v2 scopes
+ resource := strings.TrimSuffix(opts.Scopes[0], defaultSuffix)
+ command := "az account get-access-token -o json --resource " + resource
+ tenantArg := ""
+ if tenant != "" {
+ tenantArg = " --tenant " + tenant
+ command += tenantArg
+ }
+ if c.opts.Subscription != "" {
+ // subscription needs quotes because it may contain spaces
+ command += ` --subscription "` + c.opts.Subscription + `"`
+ }
+ if opts.Claims != "" {
+ encoded := base64.StdEncoding.EncodeToString([]byte(opts.Claims))
+ return at, fmt.Errorf(
+ "%s.GetToken(): Azure CLI requires multifactor authentication or additional claims. Run this command then retry the operation: az login%s --claims-challenge %s",
+ credNameAzureCLI,
+ tenantArg,
+ encoded,
+ )
+ }
+
c.mu.Lock()
defer c.mu.Unlock()
- b, err := c.opts.tokenProvider(ctx, opts.Scopes, tenant, c.opts.Subscription)
+
+ b, err := c.opts.exec(ctx, credNameAzureCLI, command)
if err == nil {
at, err = c.createAccessToken(b)
}
if err != nil {
- err = unavailableIfInChain(err, c.opts.inDefaultChain)
+ err = unavailableIfInDAC(err, c.opts.inDefaultChain)
return at, err
}
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzureCLI, strings.Join(opts.Scopes, ", "))
@@ -114,63 +127,6 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequ
return at, nil
}
-// defaultAzTokenProvider invokes the Azure CLI to acquire a token. It assumes
-// callers have verified that all string arguments are safe to pass to the CLI.
-var defaultAzTokenProvider azTokenProvider = func(ctx context.Context, scopes []string, tenantID, subscription string) ([]byte, error) {
- // pass the CLI a Microsoft Entra ID v1 resource because we don't know which CLI version is installed and older ones don't support v2 scopes
- resource := strings.TrimSuffix(scopes[0], defaultSuffix)
- // set a default timeout for this authentication iff the application hasn't done so already
- var cancel context.CancelFunc
- if _, hasDeadline := ctx.Deadline(); !hasDeadline {
- ctx, cancel = context.WithTimeout(ctx, cliTimeout)
- defer cancel()
- }
- commandLine := "az account get-access-token -o json --resource " + resource
- if tenantID != "" {
- commandLine += " --tenant " + tenantID
- }
- if subscription != "" {
- // subscription needs quotes because it may contain spaces
- commandLine += ` --subscription "` + subscription + `"`
- }
- var cliCmd *exec.Cmd
- if runtime.GOOS == "windows" {
- dir := os.Getenv("SYSTEMROOT")
- if dir == "" {
- return nil, newCredentialUnavailableError(credNameAzureCLI, "environment variable 'SYSTEMROOT' has no value")
- }
- cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
- cliCmd.Dir = dir
- } else {
- cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
- cliCmd.Dir = "/bin"
- }
- cliCmd.Env = os.Environ()
- var stderr bytes.Buffer
- cliCmd.Stderr = &stderr
- cliCmd.WaitDelay = 100 * time.Millisecond
-
- stdout, err := cliCmd.Output()
- if errors.Is(err, exec.ErrWaitDelay) && len(stdout) > 0 {
- // The child process wrote to stdout and exited without closing it.
- // Swallow this error and return stdout because it may contain a token.
- return stdout, nil
- }
- if err != nil {
- msg := stderr.String()
- var exErr *exec.ExitError
- if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'az' is not recognized") {
- msg = "Azure CLI not found on path"
- }
- if msg == "" {
- msg = err.Error()
- }
- return nil, newCredentialUnavailableError(credNameAzureCLI, msg)
- }
-
- return stdout, nil
-}
-
func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
t := struct {
AccessToken string `json:"accessToken"`
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go
index 1bd3720b6497..f97bf95df9b7 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go
@@ -7,14 +7,11 @@
package azidentity
import (
- "bytes"
"context"
+ "encoding/base64"
"encoding/json"
"errors"
"fmt"
- "os"
- "os/exec"
- "runtime"
"strings"
"sync"
"time"
@@ -24,9 +21,10 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
)
-const credNameAzureDeveloperCLI = "AzureDeveloperCLICredential"
-
-type azdTokenProvider func(ctx context.Context, scopes []string, tenant string) ([]byte, error)
+const (
+ credNameAzureDeveloperCLI = "AzureDeveloperCLICredential"
+ mfaRequired = "Azure Developer CLI requires multifactor authentication or additional claims"
+)
// AzureDeveloperCLICredentialOptions contains optional parameters for AzureDeveloperCLICredential.
type AzureDeveloperCLICredentialOptions struct {
@@ -41,8 +39,8 @@ type AzureDeveloperCLICredentialOptions struct {
// inDefaultChain is true when the credential is part of DefaultAzureCredential
inDefaultChain bool
- // tokenProvider is used by tests to fake invoking azd
- tokenProvider azdTokenProvider
+ // exec is used by tests to fake invoking azd
+ exec executor
}
// AzureDeveloperCLICredential authenticates as the identity logged in to the [Azure Developer CLI].
@@ -62,8 +60,8 @@ func NewAzureDeveloperCLICredential(options *AzureDeveloperCLICredentialOptions)
if cp.TenantID != "" && !validTenantID(cp.TenantID) {
return nil, errInvalidTenantID
}
- if cp.tokenProvider == nil {
- cp.tokenProvider = defaultAzdTokenProvider
+ if cp.exec == nil {
+ cp.exec = shellExec
}
return &AzureDeveloperCLICredential{mu: &sync.Mutex{}, opts: cp}, nil
}
@@ -75,23 +73,52 @@ func (c *AzureDeveloperCLICredential) GetToken(ctx context.Context, opts policy.
if len(opts.Scopes) == 0 {
return at, errors.New(credNameAzureDeveloperCLI + ": GetToken() requires at least one scope")
}
+ command := "azd auth token -o json --no-prompt"
for _, scope := range opts.Scopes {
if !validScope(scope) {
return at, fmt.Errorf("%s.GetToken(): invalid scope %q", credNameAzureDeveloperCLI, scope)
}
+ command += " --scope " + scope
}
tenant, err := resolveTenant(c.opts.TenantID, opts.TenantID, credNameAzureDeveloperCLI, c.opts.AdditionallyAllowedTenants)
if err != nil {
return at, err
}
+ if tenant != "" {
+ command += " --tenant-id " + tenant
+ }
+ commandNoClaims := command
+ if opts.Claims != "" {
+ encoded := base64.StdEncoding.EncodeToString([]byte(opts.Claims))
+ command += " --claims " + encoded
+ }
+
c.mu.Lock()
defer c.mu.Unlock()
- b, err := c.opts.tokenProvider(ctx, opts.Scopes, tenant)
+
+ b, err := c.opts.exec(ctx, credNameAzureDeveloperCLI, command)
if err == nil {
at, err = c.createAccessToken(b)
}
if err != nil {
- err = unavailableIfInChain(err, c.opts.inDefaultChain)
+ msg := err.Error()
+ switch {
+ case strings.Contains(msg, "unknown flag: --claims"):
+ err = newAuthenticationFailedError(
+ credNameAzureDeveloperCLI,
+ mfaRequired+", however the installed version doesn't support this. Upgrade to version 1.18.1 or later",
+ nil,
+ )
+ case opts.Claims != "":
+ err = newAuthenticationFailedError(
+ credNameAzureDeveloperCLI,
+ mfaRequired+". Run this command then retry the operation: "+commandNoClaims,
+ nil,
+ )
+ case strings.Contains(msg, "azd auth login"):
+ err = newCredentialUnavailableError(credNameAzureDeveloperCLI, `please run "azd auth login" from a command prompt to authenticate before using this credential`)
+ }
+ err = unavailableIfInDAC(err, c.opts.inDefaultChain)
return at, err
}
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzureDeveloperCLI, strings.Join(opts.Scopes, ", "))
@@ -99,61 +126,6 @@ func (c *AzureDeveloperCLICredential) GetToken(ctx context.Context, opts policy.
return at, nil
}
-// defaultAzTokenProvider invokes the Azure Developer CLI to acquire a token. It assumes
-// callers have verified that all string arguments are safe to pass to the CLI.
-var defaultAzdTokenProvider azdTokenProvider = func(ctx context.Context, scopes []string, tenant string) ([]byte, error) {
- // set a default timeout for this authentication iff the application hasn't done so already
- var cancel context.CancelFunc
- if _, hasDeadline := ctx.Deadline(); !hasDeadline {
- ctx, cancel = context.WithTimeout(ctx, cliTimeout)
- defer cancel()
- }
- commandLine := "azd auth token -o json"
- if tenant != "" {
- commandLine += " --tenant-id " + tenant
- }
- for _, scope := range scopes {
- commandLine += " --scope " + scope
- }
- var cliCmd *exec.Cmd
- if runtime.GOOS == "windows" {
- dir := os.Getenv("SYSTEMROOT")
- if dir == "" {
- return nil, newCredentialUnavailableError(credNameAzureDeveloperCLI, "environment variable 'SYSTEMROOT' has no value")
- }
- cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
- cliCmd.Dir = dir
- } else {
- cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
- cliCmd.Dir = "/bin"
- }
- cliCmd.Env = os.Environ()
- var stderr bytes.Buffer
- cliCmd.Stderr = &stderr
- cliCmd.WaitDelay = 100 * time.Millisecond
-
- stdout, err := cliCmd.Output()
- if errors.Is(err, exec.ErrWaitDelay) && len(stdout) > 0 {
- // The child process wrote to stdout and exited without closing it.
- // Swallow this error and return stdout because it may contain a token.
- return stdout, nil
- }
- if err != nil {
- msg := stderr.String()
- var exErr *exec.ExitError
- if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'azd' is not recognized") {
- msg = "Azure Developer CLI not found on path"
- } else if strings.Contains(msg, "azd auth login") {
- msg = `please run "azd auth login" from a command prompt to authenticate before using this credential`
- }
- if msg == "" {
- msg = err.Error()
- }
- return nil, newCredentialUnavailableError(credNameAzureDeveloperCLI, msg)
- }
- return stdout, nil
-}
-
func (c *AzureDeveloperCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
t := struct {
AccessToken string `json:"token"`
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_powershell_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_powershell_credential.go
new file mode 100644
index 000000000000..0829655545f0
--- /dev/null
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_powershell_credential.go
@@ -0,0 +1,234 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azidentity
+
+import (
+ "context"
+ "encoding/base64"
+ "encoding/binary"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os/exec"
+ "runtime"
+ "strings"
+ "sync"
+ "time"
+ "unicode/utf16"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+ "github.com/Azure/azure-sdk-for-go/sdk/internal/log"
+)
+
+const (
+ credNameAzurePowerShell = "AzurePowerShellCredential"
+ noAzAccountModule = "Az.Accounts module not found"
+)
+
+// AzurePowerShellCredentialOptions contains optional parameters for AzurePowerShellCredential.
+type AzurePowerShellCredentialOptions struct {
+ // AdditionallyAllowedTenants specifies tenants to which the credential may authenticate, in addition to
+ // TenantID. When TenantID is empty, this option has no effect and the credential will authenticate to
+ // any requested tenant. Add the wildcard value "*" to allow the credential to authenticate to any tenant.
+ AdditionallyAllowedTenants []string
+
+ // TenantID identifies the tenant the credential should authenticate in.
+ // Defaults to Azure PowerShell's default tenant, which is typically the home tenant of the logged in user.
+ TenantID string
+
+ // inDefaultChain is true when the credential is part of DefaultAzureCredential
+ inDefaultChain bool
+
+ // exec is used by tests to fake invoking Azure PowerShell
+ exec executor
+}
+
+// AzurePowerShellCredential authenticates as the identity logged in to Azure PowerShell.
+type AzurePowerShellCredential struct {
+ mu *sync.Mutex
+ opts AzurePowerShellCredentialOptions
+}
+
+// NewAzurePowerShellCredential constructs an AzurePowerShellCredential. Pass nil to accept default options.
+func NewAzurePowerShellCredential(options *AzurePowerShellCredentialOptions) (*AzurePowerShellCredential, error) {
+ cp := AzurePowerShellCredentialOptions{}
+
+ if options != nil {
+ cp = *options
+ }
+
+ if cp.TenantID != "" && !validTenantID(cp.TenantID) {
+ return nil, errInvalidTenantID
+ }
+
+ if cp.exec == nil {
+ cp.exec = shellExec
+ }
+
+ cp.AdditionallyAllowedTenants = resolveAdditionalTenants(cp.AdditionallyAllowedTenants)
+
+ return &AzurePowerShellCredential{mu: &sync.Mutex{}, opts: cp}, nil
+}
+
+// GetToken requests a token from Azure PowerShell. This credential doesn't cache tokens, so every call invokes Azure PowerShell.
+// This method is called automatically by Azure SDK clients.
+func (c *AzurePowerShellCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
+ at := azcore.AccessToken{}
+
+ if len(opts.Scopes) != 1 {
+ return at, errors.New(credNameAzurePowerShell + ": GetToken() requires exactly one scope")
+ }
+
+ if !validScope(opts.Scopes[0]) {
+ return at, fmt.Errorf("%s.GetToken(): invalid scope %q", credNameAzurePowerShell, opts.Scopes[0])
+ }
+
+ tenant, err := resolveTenant(c.opts.TenantID, opts.TenantID, credNameAzurePowerShell, c.opts.AdditionallyAllowedTenants)
+ if err != nil {
+ return at, err
+ }
+
+ // Always pass a Microsoft Entra ID v1 resource URI (not a v2 scope) because Get-AzAccessToken only supports v1 resource URIs.
+ resource := strings.TrimSuffix(opts.Scopes[0], defaultSuffix)
+
+ tenantArg := ""
+ if tenant != "" {
+ tenantArg = fmt.Sprintf(" -TenantId '%s'", tenant)
+ }
+
+ if opts.Claims != "" {
+ encoded := base64.StdEncoding.EncodeToString([]byte(opts.Claims))
+ return at, fmt.Errorf(
+ "%s.GetToken(): Azure PowerShell requires multifactor authentication or additional claims. Run this command then retry the operation: Connect-AzAccount%s -ClaimsChallenge '%s'",
+ credNameAzurePowerShell,
+ tenantArg,
+ encoded,
+ )
+ }
+
+ // Inline script to handle Get-AzAccessToken differences between Az.Accounts versions with SecureString handling and minimum version requirement
+ script := fmt.Sprintf(`
+$ErrorActionPreference = 'Stop'
+[version]$minimumVersion = '2.2.0'
+
+$mod = Import-Module Az.Accounts -MinimumVersion $minimumVersion -PassThru -ErrorAction SilentlyContinue
+
+if (-not $mod) {
+ Write-Error '%s'
+}
+
+$params = @{
+ ResourceUrl = '%s'
+ WarningAction = 'Ignore'
+}
+
+# Only force AsSecureString for Az.Accounts versions > 2.17.0 and < 5.0.0 which return plain text token by default.
+# Newer Az.Accounts versions return SecureString token by default and no longer use AsSecureString parameter.
+if ($mod.Version -ge [version]'2.17.0' -and $mod.Version -lt [version]'5.0.0') {
+ $params['AsSecureString'] = $true
+}
+
+$tenantId = '%s'
+if ($tenantId.Length -gt 0) {
+ $params['TenantId'] = '%s'
+}
+
+$token = Get-AzAccessToken @params
+
+$customToken = New-Object -TypeName psobject
+
+# The following .NET interop pattern is supported in all PowerShell versions and safely converts SecureString to plain text.
+if ($token.Token -is [System.Security.SecureString]) {
+ $ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($token.Token)
+ try {
+ $plainToken = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)
+ } finally {
+ [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)
+ }
+ $customToken | Add-Member -MemberType NoteProperty -Name Token -Value $plainToken
+} else {
+ $customToken | Add-Member -MemberType NoteProperty -Name Token -Value $token.Token
+}
+$customToken | Add-Member -MemberType NoteProperty -Name ExpiresOn -Value $token.ExpiresOn.ToUnixTimeSeconds()
+
+$jsonToken = $customToken | ConvertTo-Json
+return $jsonToken
+`, noAzAccountModule, resource, tenant, tenant)
+
+ // Windows: prefer pwsh.exe (PowerShell Core), fallback to powershell.exe (Windows PowerShell)
+ // Unix: only support pwsh (PowerShell Core)
+ exe := "pwsh"
+ if runtime.GOOS == "windows" {
+ if _, err := exec.LookPath("pwsh.exe"); err == nil {
+ exe = "pwsh.exe"
+ } else {
+ exe = "powershell.exe"
+ }
+ }
+
+ command := exe + " -NoProfile -NonInteractive -OutputFormat Text -EncodedCommand " + base64EncodeUTF16LE(script)
+
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ b, err := c.opts.exec(ctx, credNameAzurePowerShell, command)
+ if err == nil {
+ at, err = c.createAccessToken(b)
+ }
+
+ if err != nil {
+ err = unavailableIfInDAC(err, c.opts.inDefaultChain)
+ return at, err
+ }
+
+ msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzurePowerShell, strings.Join(opts.Scopes, ", "))
+ log.Write(EventAuthentication, msg)
+
+ return at, nil
+}
+
+func (c *AzurePowerShellCredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
+ t := struct {
+ Token string `json:"Token"`
+ ExpiresOn int64 `json:"ExpiresOn"`
+ }{}
+
+ err := json.Unmarshal(tk, &t)
+ if err != nil {
+ return azcore.AccessToken{}, err
+ }
+
+ converted := azcore.AccessToken{
+ Token: t.Token,
+ ExpiresOn: time.Unix(t.ExpiresOn, 0).UTC(),
+ }
+
+ return converted, nil
+}
+
+// Encodes a string to Base64 using UTF-16LE encoding
+func base64EncodeUTF16LE(text string) string {
+ u16 := utf16.Encode([]rune(text))
+ buf := make([]byte, len(u16)*2)
+ for i, v := range u16 {
+ binary.LittleEndian.PutUint16(buf[i*2:], v)
+ }
+ return base64.StdEncoding.EncodeToString(buf)
+}
+
+// Decodes a Base64 UTF-16LE string back to string
+func base64DecodeUTF16LE(encoded string) (string, error) {
+ data, err := base64.StdEncoding.DecodeString(encoded)
+ if err != nil {
+ return "", err
+ }
+ u16 := make([]uint16, len(data)/2)
+ for i := range u16 {
+ u16[i] = binary.LittleEndian.Uint16(data[i*2:])
+ }
+ return string(utf16.Decode(u16)), nil
+}
+
+var _ azcore.TokenCredential = (*AzurePowerShellCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
index 38445e853669..51dd9793908b 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
@@ -41,6 +41,3 @@ extends:
GenerateVMJobs: true
Path: sdk/azidentity/managed-identity-matrix.json
Selection: sparse
- MatrixReplace:
- - Pool=.*LINUXPOOL.*/azsdk-pool-mms-ubuntu-2204-identitymsi
- - OSVmImage=.*LINUXVMIMAGE.*/azsdk-pool-mms-ubuntu-2204-1espt
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
index 2b94270a8c6a..aaaabc5c2f31 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
@@ -26,6 +26,7 @@ const (
managedIdentity
az
azd
+ azurePowerShell
)
// DefaultAzureCredentialOptions contains optional parameters for DefaultAzureCredential.
@@ -48,6 +49,10 @@ type DefaultAzureCredentialOptions struct {
// the application responsible for ensuring the configured authority is valid and trustworthy.
DisableInstanceDiscovery bool
+ // RequireAzureTokenCredentials determines whether NewDefaultAzureCredential returns an error when the environment
+ // variable AZURE_TOKEN_CREDENTIALS has no value.
+ RequireAzureTokenCredentials bool
+
// TenantID sets the default tenant for authentication via the Azure CLI, Azure Developer CLI, and workload identity.
TenantID string
}
@@ -67,6 +72,7 @@ type DefaultAzureCredentialOptions struct {
// - [ManagedIdentityCredential]
// - [AzureCLICredential]
// - [AzureDeveloperCLICredential]
+// - [AzurePowerShellCredential]
//
// Consult the documentation for these credential types for more information on how they authenticate.
// Once a credential has successfully authenticated, DefaultAzureCredential will use that credential for
@@ -79,9 +85,13 @@ type DefaultAzureCredentialOptions struct {
// Valid values for AZURE_TOKEN_CREDENTIALS are the name of any single type in the above chain, for example
// "EnvironmentCredential" or "AzureCLICredential", and these special values:
//
-// - "dev": try [AzureCLICredential] and [AzureDeveloperCLICredential], in that order
+// - "dev": try [AzureCLICredential], [AzureDeveloperCLICredential], and [AzurePowerShellCredential], in that order
// - "prod": try [EnvironmentCredential], [WorkloadIdentityCredential], and [ManagedIdentityCredential], in that order
//
+// [DefaultAzureCredentialOptions].RequireAzureTokenCredentials controls whether AZURE_TOKEN_CREDENTIALS must be set.
+// NewDefaultAzureCredential returns an error when RequireAzureTokenCredentials is true and AZURE_TOKEN_CREDENTIALS
+// has no value.
+//
// [DefaultAzureCredential overview]: https://aka.ms/azsdk/go/identity/credential-chains#defaultazurecredential-overview
type DefaultAzureCredential struct {
chain *ChainedTokenCredential
@@ -89,16 +99,20 @@ type DefaultAzureCredential struct {
// NewDefaultAzureCredential creates a DefaultAzureCredential. Pass nil for options to accept defaults.
func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*DefaultAzureCredential, error) {
+ if options == nil {
+ options = &DefaultAzureCredentialOptions{}
+ }
+
var (
creds []azcore.TokenCredential
errorMessages []string
- selected = env | workloadIdentity | managedIdentity | az | azd
+ selected = env | workloadIdentity | managedIdentity | az | azd | azurePowerShell
)
if atc, ok := os.LookupEnv(azureTokenCredentials); ok {
switch {
case atc == "dev":
- selected = az | azd
+ selected = az | azd | azurePowerShell
case atc == "prod":
selected = env | workloadIdentity | managedIdentity
case strings.EqualFold(atc, credNameEnvironment):
@@ -111,14 +125,15 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
selected = az
case strings.EqualFold(atc, credNameAzureDeveloperCLI):
selected = azd
+ case strings.EqualFold(atc, credNameAzurePowerShell):
+ selected = azurePowerShell
default:
return nil, fmt.Errorf(`invalid %s value %q. Valid values are "dev", "prod", or the name of any credential type in the default chain. See https://aka.ms/azsdk/go/identity/docs#DefaultAzureCredential for more information`, azureTokenCredentials, atc)
}
+ } else if options.RequireAzureTokenCredentials {
+ return nil, fmt.Errorf("%s must be set when RequireAzureTokenCredentials is true. See https://aka.ms/azsdk/go/identity/docs#DefaultAzureCredential for more information", azureTokenCredentials)
}
- if options == nil {
- options = &DefaultAzureCredentialOptions{}
- }
additionalTenants := options.AdditionallyAllowedTenants
if len(additionalTenants) == 0 {
if tenants := os.Getenv(azureAdditionallyAllowedTenants); tenants != "" {
@@ -153,7 +168,11 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
}
}
if selected&managedIdentity != 0 {
- o := &ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions, dac: true}
+ o := &ManagedIdentityCredentialOptions{
+ ClientOptions: options.ClientOptions,
+ // enable special DefaultAzureCredential behavior (IMDS probing) only when the chain contains another credential
+ dac: selected^managedIdentity != 0,
+ }
if ID, ok := os.LookupEnv(azureClientID); ok {
o.ID = ClientID(ID)
}
@@ -191,6 +210,19 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameAzureDeveloperCLI, err: err})
}
}
+ if selected&azurePowerShell != 0 {
+ azurePowerShellCred, err := NewAzurePowerShellCredential(&AzurePowerShellCredentialOptions{
+ AdditionallyAllowedTenants: additionalTenants,
+ TenantID: options.TenantID,
+ inDefaultChain: true,
+ })
+ if err == nil {
+ creds = append(creds, azurePowerShellCred)
+ } else {
+ errorMessages = append(errorMessages, credNameAzurePowerShell+": "+err.Error())
+ creds = append(creds, &defaultCredentialErrorReporter{credType: credNameAzurePowerShell, err: err})
+ }
+ }
if len(errorMessages) > 0 {
log.Writef(EventAuthentication, "NewDefaultAzureCredential failed to initialize some credentials:\n\t%s", strings.Join(errorMessages, "\n\t"))
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go
index be963d3a2af0..cb7dbe2e4b84 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go
@@ -7,22 +7,72 @@
package azidentity
import (
+ "bytes"
+ "context"
"errors"
+ "os"
+ "os/exec"
+ "strings"
"time"
)
// cliTimeout is the default timeout for authentication attempts via CLI tools
const cliTimeout = 10 * time.Second
-// unavailableIfInChain returns err or, if the credential was invoked by DefaultAzureCredential, a
+// executor runs a command and returns its output or an error
+type executor func(ctx context.Context, credName, command string) ([]byte, error)
+
+var shellExec = func(ctx context.Context, credName, command string) ([]byte, error) {
+ // set a default timeout for this authentication iff the caller hasn't done so already
+ var cancel context.CancelFunc
+ if _, hasDeadline := ctx.Deadline(); !hasDeadline {
+ ctx, cancel = context.WithTimeout(ctx, cliTimeout)
+ defer cancel()
+ }
+ cmd, err := buildCmd(ctx, credName, command)
+ if err != nil {
+ return nil, err
+ }
+ cmd.Env = os.Environ()
+ stderr := bytes.Buffer{}
+ cmd.Stderr = &stderr
+ cmd.WaitDelay = 100 * time.Millisecond
+
+ stdout, err := cmd.Output()
+ if errors.Is(err, exec.ErrWaitDelay) && len(stdout) > 0 {
+ // The child process wrote to stdout and exited without closing it.
+ // Swallow this error and return stdout because it may contain a token.
+ return stdout, nil
+ }
+ if err != nil {
+ msg := stderr.String()
+ var exErr *exec.ExitError
+ if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.Contains(msg, "' is not recognized") {
+ return nil, newCredentialUnavailableError(credName, "executable not found on path")
+ }
+ if credName == credNameAzurePowerShell {
+ if strings.Contains(msg, "Connect-AzAccount") {
+ msg = `Please run "Connect-AzAccount" to set up an account`
+ }
+ if strings.Contains(msg, noAzAccountModule) {
+ msg = noAzAccountModule
+ }
+ }
+ if msg == "" {
+ msg = err.Error()
+ }
+ return nil, newAuthenticationFailedError(credName, msg, nil)
+ }
+
+ return stdout, nil
+}
+
+// unavailableIfInDAC returns err or, if the credential was invoked by DefaultAzureCredential, a
// credentialUnavailableError having the same message. This ensures DefaultAzureCredential will try
// the next credential in its chain (another developer credential).
-func unavailableIfInChain(err error, inDefaultChain bool) error {
- if err != nil && inDefaultChain {
- var unavailableErr credentialUnavailable
- if !errors.As(err, &unavailableErr) {
- err = newCredentialUnavailableError(credNameAzureDeveloperCLI, err.Error())
- }
+func unavailableIfInDAC(err error, inDefaultChain bool) error {
+ if err != nil && inDefaultChain && !errors.As(err, new(credentialUnavailable)) {
+ err = NewCredentialUnavailableError(err.Error())
}
return err
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_nonwindows.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_nonwindows.go
new file mode 100644
index 000000000000..681fcd0cf9f5
--- /dev/null
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_nonwindows.go
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+//go:build !windows
+
+package azidentity
+
+import (
+ "context"
+ "os/exec"
+)
+
+func buildCmd(ctx context.Context, _, command string) (*exec.Cmd, error) {
+ cmd := exec.CommandContext(ctx, "/bin/sh", "-c", command)
+ cmd.Dir = "/bin"
+ return cmd, nil
+}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_windows.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_windows.go
new file mode 100644
index 000000000000..09c7a1a977c9
--- /dev/null
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_windows.go
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azidentity
+
+import (
+ "context"
+ "os"
+ "os/exec"
+ "syscall"
+)
+
+func buildCmd(ctx context.Context, credName, command string) (*exec.Cmd, error) {
+ dir := os.Getenv("SYSTEMROOT")
+ if dir == "" {
+ return nil, newCredentialUnavailableError(credName, `environment variable "SYSTEMROOT" has no value`)
+ }
+ cmd := exec.CommandContext(ctx, "cmd.exe")
+ cmd.Dir = dir
+ cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/c " + command}
+ return cmd, nil
+}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
index a6d7c6cbc78d..33cb63be09a8 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
@@ -99,6 +99,8 @@ func (e *AuthenticationFailedError) Error() string {
anchor = "apc"
case credNameCert:
anchor = "client-cert"
+ case credNameAzurePowerShell:
+ anchor = "azure-pwsh"
case credNameSecret:
anchor = "client-secret"
case credNameManagedIdentity:
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed-identity-matrix.json b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed-identity-matrix.json
index f92245533fcb..063325c69d67 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed-identity-matrix.json
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed-identity-matrix.json
@@ -10,8 +10,7 @@
},
"GoVersion": [
"env:GO_VERSION_PREVIOUS"
- ],
- "IDENTITY_IMDS_AVAILABLE": "1"
+ ]
}
]
-}
+}
\ No newline at end of file
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1 b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1
index 874d4ef37ddf..c5634cd21d07 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1
@@ -41,7 +41,7 @@ if ($CI) {
az account set --subscription $SubscriptionId
}
-Write-Host "Building container"
+Write-Host "##[group]Building container"
$image = "$($DeploymentOutputs['AZIDENTITY_ACR_LOGIN_SERVER'])/azidentity-managed-id-test"
Set-Content -Path "$PSScriptRoot/Dockerfile" -Value @"
FROM mcr.microsoft.com/oss/go/microsoft/golang:latest AS builder
@@ -62,11 +62,34 @@ CMD ["./managed-id-test"]
docker build -t $image "$PSScriptRoot"
az acr login -n $DeploymentOutputs['AZIDENTITY_ACR_NAME']
docker push $image
+Write-Host "##[endgroup]"
$rg = $DeploymentOutputs['AZIDENTITY_RESOURCE_GROUP']
+Write-Host "##[group]Deploying to VM"
+# az will return 0 when the script fails on the VM, so the script prints a UUID to indicate all commands succeeded
+$uuid = [guid]::NewGuid().ToString()
+$vmScript = @"
+az acr login -n $($DeploymentOutputs['AZIDENTITY_ACR_NAME']) && \
+sudo docker run \
+-e AZIDENTITY_STORAGE_NAME=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME']) \
+-e AZIDENTITY_STORAGE_NAME_USER_ASSIGNED=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME_USER_ASSIGNED']) \
+-e AZIDENTITY_USER_ASSIGNED_IDENTITY=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) \
+-e AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID']) \
+-e AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID']) \
+-p 80:8080 -d \
+$image && \
+/usr/bin/echo $uuid
+"@
+$output = az vm run-command invoke -g $rg -n $DeploymentOutputs['AZIDENTITY_VM_NAME'] --command-id RunShellScript --scripts "$vmScript" | Out-String
+Write-Host $output
+if (-not $output.Contains($uuid)) {
+ throw "couldn't start container on VM"
+}
+Write-Host "##[endgroup]"
+
# ACI is easier to provision here than in the bicep file because the image isn't available before now
-Write-Host "Deploying Azure Container Instance"
+Write-Host "##[group]Deploying Azure Container Instance"
$aciName = "azidentity-test"
az container create -g $rg -n $aciName --image $image `
--acr-identity $($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) `
@@ -85,23 +108,27 @@ az container create -g $rg -n $aciName --image $image `
FUNCTIONS_CUSTOMHANDLER_PORT=80
$aciIP = az container show -g $rg -n $aciName --query ipAddress.ip --output tsv
Write-Host "##vso[task.setvariable variable=AZIDENTITY_ACI_IP;]$aciIP"
+Write-Host "##[endgroup]"
# Azure Functions deployment: copy the Windows binary from the Docker image, deploy it in a zip
-Write-Host "Deploying to Azure Functions"
+Write-Host "##[group]Deploying to Azure Functions"
$container = docker create $image
docker cp ${container}:managed-id-test.exe "$PSScriptRoot/testdata/managed-id-test/"
docker rm -v $container
Compress-Archive -Path "$PSScriptRoot/testdata/managed-id-test/*" -DestinationPath func.zip -Force
az functionapp deploy -g $rg -n $DeploymentOutputs['AZIDENTITY_FUNCTION_NAME'] --src-path func.zip --type zip
+Write-Host "##[endgroup]"
-Write-Host "Creating federated identity"
+Write-Host "##[group]Creating federated identity"
$aksName = $DeploymentOutputs['AZIDENTITY_AKS_NAME']
$idName = $DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_NAME']
$issuer = az aks show -g $rg -n $aksName --query "oidcIssuerProfile.issuerUrl" -otsv
$podName = "azidentity-test"
$serviceAccountName = "workload-identity-sa"
az identity federated-credential create -g $rg --identity-name $idName --issuer $issuer --name $idName --subject system:serviceaccount:default:$serviceAccountName --audiences api://AzureADTokenExchange
-Write-Host "Deploying to AKS"
+Write-Host "##[endgroup]"
+
+Write-Host "##[group]Deploying to AKS"
az aks get-credentials -g $rg -n $aksName
az aks update --attach-acr $DeploymentOutputs['AZIDENTITY_ACR_NAME'] -g $rg -n $aksName
Set-Content -Path "$PSScriptRoot/k8s.yaml" -Value @"
@@ -138,3 +165,4 @@ spec:
"@
kubectl apply -f "$PSScriptRoot/k8s.yaml"
Write-Host "##vso[task.setvariable variable=AZIDENTITY_POD_NAME;]$podName"
+Write-Host "##[endgroup]"
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
index 135feb0178e1..cb3b5f4df42b 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
@@ -19,7 +19,10 @@ param location string = resourceGroup().location
// https://learn.microsoft.com/azure/role-based-access-control/built-in-roles
var acrPull = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
-var blobReader = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')
+var blobReader = subscriptionResourceId(
+ 'Microsoft.Authorization/roleDefinitions',
+ '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'
+)
resource sa 'Microsoft.Storage/storageAccounts@2021-08-01' = if (deployResources) {
kind: 'StorageV2'
@@ -60,6 +63,16 @@ resource acrPullContainerInstance 'Microsoft.Authorization/roleAssignments@2022-
scope: containerRegistry
}
+resource acrPullVM 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (deployResources) {
+ name: guid(resourceGroup().id, acrPull, 'vm')
+ properties: {
+ principalId: deployResources ? vm.identity.principalId : ''
+ principalType: 'ServicePrincipal'
+ roleDefinitionId: acrPull
+ }
+ scope: containerRegistry
+}
+
resource blobRoleUserAssigned 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (deployResources) {
scope: saUserAssigned
name: guid(resourceGroup().id, blobReader, usermgdid.id)
@@ -80,6 +93,16 @@ resource blobRoleFunc 'Microsoft.Authorization/roleAssignments@2022-04-01' = if
scope: sa
}
+resource blobRoleVM 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (deployResources) {
+ scope: sa
+ name: guid(resourceGroup().id, blobReader, 'vm')
+ properties: {
+ principalId: deployResources ? vm.identity.principalId : ''
+ roleDefinitionId: blobReader
+ principalType: 'ServicePrincipal'
+ }
+}
+
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = if (deployResources) {
location: location
name: uniqueString(resourceGroup().id)
@@ -215,6 +238,143 @@ resource aks 'Microsoft.ContainerService/managedClusters@2023-06-01' = if (deplo
}
}
+resource publicIP 'Microsoft.Network/publicIPAddresses@2023-05-01' = if (deployResources) {
+ name: '${baseName}PublicIP'
+ location: location
+ sku: {
+ name: 'Standard'
+ }
+ properties: {
+ publicIPAllocationMethod: 'Static'
+ }
+}
+
+resource nsg 'Microsoft.Network/networkSecurityGroups@2024-07-01' = if (deployResources) {
+ name: '${baseName}NSG'
+ location: location
+ properties: {
+ securityRules: [
+ {
+ name: 'AllowHTTP'
+ properties: {
+ description: 'Allow HTTP traffic on port 80'
+ protocol: 'Tcp'
+ sourcePortRange: '*'
+ destinationPortRange: '80'
+ sourceAddressPrefix: '*'
+ destinationAddressPrefix: '*'
+ access: 'Allow'
+ priority: 1000
+ direction: 'Inbound'
+ }
+ }
+ ]
+ }
+}
+
+resource vnet 'Microsoft.Network/virtualNetworks@2024-07-01' = if (deployResources) {
+ name: '${baseName}vnet'
+ location: location
+ properties: {
+ addressSpace: {
+ addressPrefixes: [
+ '10.0.0.0/16'
+ ]
+ }
+ subnets: [
+ {
+ name: '${baseName}subnet'
+ properties: {
+ addressPrefix: '10.0.0.0/24'
+ defaultOutboundAccess: false
+ networkSecurityGroup: {
+ id: deployResources ? nsg.id : ''
+ }
+ }
+ }
+ ]
+ }
+}
+
+resource nic 'Microsoft.Network/networkInterfaces@2024-07-01' = if (deployResources) {
+ name: '${baseName}NIC'
+ location: location
+ properties: {
+ ipConfigurations: [
+ {
+ name: 'myIPConfig'
+ properties: {
+ privateIPAllocationMethod: 'Dynamic'
+ publicIPAddress: {
+ id: deployResources ? publicIP.id : ''
+ }
+ subnet: {
+ id: deployResources ? vnet.properties.subnets[0].id : ''
+ }
+ }
+ }
+ ]
+ }
+}
+
+resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = if (deployResources) {
+ name: '${baseName}vm'
+ location: location
+ identity: {
+ type: 'SystemAssigned, UserAssigned'
+ userAssignedIdentities: {
+ '${deployResources ? usermgdid.id: ''}': {}
+ }
+ }
+ properties: {
+ hardwareProfile: {
+ vmSize: 'Standard_DS1_v2'
+ }
+ osProfile: {
+ adminUsername: adminUser
+ computerName: '${baseName}vm'
+ customData: base64('''
+#cloud-config
+package_update: true
+packages:
+ - docker.io
+runcmd:
+ - curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
+ - az login --identity --allow-no-subscriptions
+''')
+ linuxConfiguration: {
+ disablePasswordAuthentication: true
+ ssh: {
+ publicKeys: [
+ {
+ path: '/home/${adminUser}/.ssh/authorized_keys'
+ keyData: sshPubKey
+ }
+ ]
+ }
+ }
+ }
+ networkProfile: {
+ networkInterfaces: [
+ {
+ id: deployResources ? nic.id : ''
+ }
+ ]
+ }
+ storageProfile: {
+ imageReference: {
+ publisher: 'Canonical'
+ offer: 'ubuntu-24_04-lts'
+ sku: 'server'
+ version: 'latest'
+ }
+ osDisk: {
+ createOption: 'FromImage'
+ }
+ }
+ }
+}
+
output AZIDENTITY_ACR_LOGIN_SERVER string = deployResources ? containerRegistry.properties.loginServer : ''
output AZIDENTITY_ACR_NAME string = deployResources ? containerRegistry.name : ''
output AZIDENTITY_AKS_NAME string = deployResources ? aks.name : ''
@@ -226,3 +386,5 @@ output AZIDENTITY_USER_ASSIGNED_IDENTITY string = deployResources ? usermgdid.id
output AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID string = deployResources ? usermgdid.properties.clientId : ''
output AZIDENTITY_USER_ASSIGNED_IDENTITY_NAME string = deployResources ? usermgdid.name : ''
output AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID string = deployResources ? usermgdid.properties.principalId : ''
+output AZIDENTITY_VM_NAME string = deployResources ? vm.name : ''
+output AZIDENTITY_VM_IP string = deployResources ? publicIP.properties.ipAddress : ''
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
index c3a70c4f2e43..041f11658dfa 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
@@ -14,5 +14,5 @@ const (
module = "github.com/Azure/azure-sdk-for-go/sdk/" + component
// Version is the semantic version (see http://semver.org) of this module.
- version = "v1.11.0"
+ version = "v1.13.1"
)
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go
index 549d68ab991f..29c004320d62 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go
@@ -596,6 +596,11 @@ func (cca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts
return AuthResult{}, errors.New("call another AcquireToken method to request a new token having these claims")
}
+ // For service principal scenarios, require WithSilentAccount for public API
+ if o.account.IsZero() {
+ return AuthResult{}, errors.New("WithSilentAccount option is required")
+ }
+
silentParameters := base.AcquireTokenSilentParameters{
Scopes: scopes,
Account: o.account,
@@ -604,8 +609,15 @@ func (cca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts
IsAppCache: o.account.IsZero(),
TenantID: o.tenantID,
AuthnScheme: o.authnScheme,
+ Claims: o.claims,
}
+ return cca.acquireTokenSilentInternal(ctx, silentParameters)
+}
+
+// acquireTokenSilentInternal is the internal implementation shared by AcquireTokenSilent and AcquireTokenByCredential
+func (cca Client) acquireTokenSilentInternal(ctx context.Context, silentParameters base.AcquireTokenSilentParameters) (AuthResult, error) {
+
return cca.base.AcquireTokenSilent(ctx, silentParameters)
}
@@ -708,8 +720,10 @@ func (cca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redir
// acquireTokenByCredentialOptions contains optional configuration for AcquireTokenByCredential
type acquireTokenByCredentialOptions struct {
- claims, tenantID string
- authnScheme AuthenticationScheme
+ claims, tenantID string
+ authnScheme AuthenticationScheme
+ extraBodyParameters map[string]string
+ cacheKeyComponents map[string]string
}
// AcquireByCredentialOption is implemented by options for AcquireTokenByCredential
@@ -719,7 +733,7 @@ type AcquireByCredentialOption interface {
// AcquireTokenByCredential acquires a security token from the authority, using the client credentials grant.
//
-// Options: [WithClaims], [WithTenantID]
+// Options: [WithClaims], [WithTenantID], [WithFMIPath], [WithAttribute]
func (cca Client) AcquireTokenByCredential(ctx context.Context, scopes []string, opts ...AcquireByCredentialOption) (AuthResult, error) {
o := acquireTokenByCredentialOptions{}
err := options.ApplyOptions(&o, opts)
@@ -736,6 +750,29 @@ func (cca Client) AcquireTokenByCredential(ctx context.Context, scopes []string,
if o.authnScheme != nil {
authParams.AuthnScheme = o.authnScheme
}
+ authParams.ExtraBodyParameters = o.extraBodyParameters
+ authParams.CacheKeyComponents = o.cacheKeyComponents
+ if o.claims == "" {
+ silentParameters := base.AcquireTokenSilentParameters{
+ Scopes: scopes,
+ Account: Account{}, // empty account for app token
+ RequestType: accesstokens.ATConfidential,
+ Credential: cca.cred,
+ IsAppCache: true,
+ TenantID: o.tenantID,
+ AuthnScheme: o.authnScheme,
+ Claims: o.claims,
+ ExtraBodyParameters: o.extraBodyParameters,
+ CacheKeyComponents: o.cacheKeyComponents,
+ }
+
+ // Use internal method with empty account (service principal scenario)
+ cache, err := cca.acquireTokenSilentInternal(ctx, silentParameters)
+ if err == nil {
+ return cache, nil
+ }
+ }
+
token, err := cca.base.Token.Credential(ctx, authParams, cca.cred)
if err != nil {
return AuthResult{}, err
@@ -781,3 +818,63 @@ func (cca Client) Account(ctx context.Context, accountID string) (Account, error
func (cca Client) RemoveAccount(ctx context.Context, account Account) error {
return cca.base.RemoveAccount(ctx, account)
}
+
+// WithFMIPath specifies the path to a federated managed identity.
+// The path should point to a valid FMI configuration file that contains the necessary
+// identity information for authentication.
+func WithFMIPath(path string) interface {
+ AcquireByCredentialOption
+ options.CallOption
+} {
+ return struct {
+ AcquireByCredentialOption
+ options.CallOption
+ }{
+ CallOption: options.NewCallOption(
+ func(a any) error {
+ switch t := a.(type) {
+ case *acquireTokenByCredentialOptions:
+ if t.extraBodyParameters == nil {
+ t.extraBodyParameters = make(map[string]string)
+ }
+ if t.cacheKeyComponents == nil {
+ t.cacheKeyComponents = make(map[string]string)
+ }
+ t.cacheKeyComponents["fmi_path"] = path
+ t.extraBodyParameters["fmi_path"] = path
+ default:
+ return fmt.Errorf("unexpected options type %T", a)
+ }
+ return nil
+ },
+ ),
+ }
+}
+
+// WithAttribute specifies an identity attribute to include in the token request.
+// The attribute is sent as "attributes" in the request body and returned as "xmc_attr"
+// in the access token claims. This is sometimes used withFMIPath
+func WithAttribute(attrValue string) interface {
+ AcquireByCredentialOption
+ options.CallOption
+} {
+ return struct {
+ AcquireByCredentialOption
+ options.CallOption
+ }{
+ CallOption: options.NewCallOption(
+ func(a any) error {
+ switch t := a.(type) {
+ case *acquireTokenByCredentialOptions:
+ if t.extraBodyParameters == nil {
+ t.extraBodyParameters = make(map[string]string)
+ }
+ t.extraBodyParameters["attributes"] = attrValue
+ default:
+ return fmt.Errorf("unexpected options type %T", a)
+ }
+ return nil
+ },
+ ),
+ }
+}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go
index 61c1c4cec1e9..abf54f7e5093 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go
@@ -46,16 +46,18 @@ type accountManager interface {
// AcquireTokenSilentParameters contains the parameters to acquire a token silently (from cache).
type AcquireTokenSilentParameters struct {
- Scopes []string
- Account shared.Account
- RequestType accesstokens.AppType
- Credential *accesstokens.Credential
- IsAppCache bool
- TenantID string
- UserAssertion string
- AuthorizationType authority.AuthorizeType
- Claims string
- AuthnScheme authority.AuthenticationScheme
+ Scopes []string
+ Account shared.Account
+ RequestType accesstokens.AppType
+ Credential *accesstokens.Credential
+ IsAppCache bool
+ TenantID string
+ UserAssertion string
+ AuthorizationType authority.AuthorizeType
+ Claims string
+ AuthnScheme authority.AuthenticationScheme
+ ExtraBodyParameters map[string]string
+ CacheKeyComponents map[string]string
}
// AcquireTokenAuthCodeParameters contains the parameters required to acquire an access token using the auth code flow.
@@ -327,7 +329,12 @@ func (b Client) AcquireTokenSilent(ctx context.Context, silent AcquireTokenSilen
if silent.AuthnScheme != nil {
authParams.AuthnScheme = silent.AuthnScheme
}
-
+ if silent.CacheKeyComponents != nil {
+ authParams.CacheKeyComponents = silent.CacheKeyComponents
+ }
+ if silent.ExtraBodyParameters != nil {
+ authParams.ExtraBodyParameters = silent.ExtraBodyParameters
+ }
m := b.pmanager
if authParams.AuthorizationType != authority.ATOnBehalfOf {
authParams.AuthorizationType = authority.ATRefreshToken
@@ -367,8 +374,19 @@ func (b Client) AcquireTokenSilent(ctx context.Context, silent AcquireTokenSilen
// If the token is not same, we don't need to refresh it.
// Which means it refreshed.
if str, err := m.Read(ctx, authParams); err == nil && str.AccessToken.Secret == ar.AccessToken {
- if tr, er := b.Token.Credential(ctx, authParams, silent.Credential); er == nil {
- return b.AuthResultFromToken(ctx, authParams, tr)
+ switch silent.RequestType {
+ case accesstokens.ATConfidential:
+ if tr, er := b.Token.Credential(ctx, authParams, silent.Credential); er == nil {
+ return b.AuthResultFromToken(ctx, authParams, tr)
+ }
+ case accesstokens.ATPublic:
+ token, err := b.Token.Refresh(ctx, silent.RequestType, authParams, silent.Credential, storageTokenResponse.RefreshToken)
+ if err != nil {
+ return ar, err
+ }
+ return b.AuthResultFromToken(ctx, authParams, token)
+ case accesstokens.ATUnknown:
+ return ar, errors.New("silent request type cannot be ATUnknown")
}
}
}
@@ -446,6 +464,9 @@ func (b Client) AcquireTokenOnBehalfOf(ctx context.Context, onBehalfOfParams Acq
authParams.Claims = onBehalfOfParams.Claims
authParams.Scopes = onBehalfOfParams.Scopes
authParams.UserAssertion = onBehalfOfParams.UserAssertion
+ if authParams.ExtraBodyParameters != nil {
+ authParams.ExtraBodyParameters = silentParameters.ExtraBodyParameters
+ }
token, err := b.Token.OnBehalfOf(ctx, authParams, onBehalfOfParams.Credential)
if err == nil {
ar, err = b.AuthResultFromToken(ctx, authParams, token)
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/items.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/items.go
index 7379e2233c83..b7d1a670b1e1 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/items.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/items.go
@@ -79,6 +79,7 @@ type AccessToken struct {
UserAssertionHash string `json:"user_assertion_hash,omitempty"`
TokenType string `json:"token_type,omitempty"`
AuthnSchemeKeyID string `json:"keyid,omitempty"`
+ ExtCacheKey string `json:"ext_cache_key,omitempty"`
AdditionalFields map[string]interface{}
}
@@ -105,15 +106,21 @@ func NewAccessToken(homeID, env, realm, clientID string, cachedAt, refreshOn, ex
// Key outputs the key that can be used to uniquely look up this entry in a map.
func (a AccessToken) Key() string {
ks := []string{a.HomeAccountID, a.Environment, a.CredentialType, a.ClientID, a.Realm, a.Scopes}
- key := strings.Join(
- ks,
- shared.CacheKeySeparator,
- )
+
// add token type to key for new access tokens types. skip for bearer token type to
// preserve fwd and back compat between a common cache and msal clients
if !strings.EqualFold(a.TokenType, authority.AccessTokenTypeBearer) {
- key = strings.Join([]string{key, a.TokenType}, shared.CacheKeySeparator)
+ ks = append(ks, a.TokenType)
}
+ // add extra body param hash to key if present
+ if a.ExtCacheKey != "" {
+ ks[2] = "atext" // if the there is extra cache we add "atext" to the key replacing accesstoken
+ ks = append(ks, a.ExtCacheKey)
+ }
+ key := strings.Join(
+ ks,
+ shared.CacheKeySeparator,
+ )
return strings.ToLower(key)
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/storage.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/storage.go
index 84a234967ffe..825d8a0f6603 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/storage.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/storage/storage.go
@@ -135,7 +135,8 @@ func (m *Manager) Read(ctx context.Context, authParameters authority.AuthParams)
aliases = metadata.Aliases
}
- accessToken := m.readAccessToken(homeAccountID, aliases, realm, clientID, scopes, tokenType, authnSchemeKeyID)
+ accessToken := m.readAccessToken(homeAccountID, aliases, realm, clientID, scopes, tokenType, authnSchemeKeyID, authParameters.CacheExtKeyGenerator())
+
tr.AccessToken = accessToken
if homeAccountID == "" {
@@ -203,6 +204,7 @@ func (m *Manager) Write(authParameters authority.AuthParams, tokenResponse acces
authnSchemeKeyID,
)
+ accessToken.ExtCacheKey = authParameters.CacheExtKeyGenerator()
// Since we have a valid access token, cache it before moving on.
if err := accessToken.Validate(); err == nil {
if err := m.writeAccessToken(accessToken); err != nil {
@@ -291,26 +293,49 @@ func (m *Manager) aadMetadata(ctx context.Context, authorityInfo authority.Info)
return m.aadCache[authorityInfo.Host], nil
}
-func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, clientID string, scopes []string, tokenType, authnSchemeKeyID string) AccessToken {
+func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, clientID string, scopes []string, tokenType, authnSchemeKeyID, extCacheKey string) AccessToken {
m.contractMu.RLock()
- // TODO: linear search (over a map no less) is slow for a large number (thousands) of tokens.
- // this shows up as the dominating node in a profile. for real-world scenarios this likely isn't
- // an issue, however if it does become a problem then we know where to look.
- for k, at := range m.contract.AccessTokens {
+
+ tokensToSearch := m.contract.AccessTokens
+
+ for k, at := range tokensToSearch {
+ // TODO: linear search (over a map no less) is slow for a large number (thousands) of tokens.
+ // this shows up as the dominating node in a profile. for real-world scenarios this likely isn't
+ // an issue, however if it does become a problem then we know where to look.
if at.HomeAccountID == homeID && at.Realm == realm && at.ClientID == clientID {
- if (strings.EqualFold(at.TokenType, tokenType) && at.AuthnSchemeKeyID == authnSchemeKeyID) || (at.TokenType == "" && (tokenType == "" || tokenType == "Bearer")) {
- if checkAlias(at.Environment, envAliases) && isMatchingScopes(scopes, at.Scopes) {
- m.contractMu.RUnlock()
- if needsUpgrade(k) {
- m.contractMu.Lock()
- defer m.contractMu.Unlock()
- at = upgrade(m.contract.AccessTokens, k)
+ // Match token type and authentication scheme
+ tokenTypeMatch := (strings.EqualFold(at.TokenType, tokenType) && at.AuthnSchemeKeyID == authnSchemeKeyID) ||
+ (at.TokenType == "" && (tokenType == "" || tokenType == "Bearer"))
+ environmentAndScopesMatch := checkAlias(at.Environment, envAliases) && isMatchingScopes(scopes, at.Scopes)
+
+ if tokenTypeMatch && environmentAndScopesMatch {
+ // For hashed tokens, check that the key contains the hash
+ if extCacheKey != "" {
+ if !strings.Contains(k, extCacheKey) {
+ continue // Skip this token if the key doesn't contain the hash
+ }
+ } else {
+ // If no extCacheKey is provided, only match tokens that also have no extCacheKey
+ if at.ExtCacheKey != "" {
+ continue // Skip tokens that require a hash when no hash is provided
}
+ }
+ // Handle token upgrade if needed
+ if needsUpgrade(k) {
+ m.contractMu.RUnlock()
+ m.contractMu.Lock()
+ at = upgrade(tokensToSearch, k)
+ m.contractMu.Unlock()
return at
}
+
+ m.contractMu.RUnlock()
+ return at
}
}
}
+
+ // No token found, unlock and return empty token
m.contractMu.RUnlock()
return AccessToken{}
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go
index cda678e33426..c6baf2094777 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go
@@ -143,9 +143,10 @@ func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
headerErr := q.Get("error")
if headerErr != "" {
desc := html.EscapeString(q.Get("error_description"))
+ escapedHeaderErr := html.EscapeString(headerErr)
// Note: It is a little weird we handle some errors by not going to the failPage. If they all should,
// change this to s.error() and make s.error() write the failPage instead of an error code.
- _, _ = w.Write([]byte(fmt.Sprintf(failPage, headerErr, desc)))
+ _, _ = w.Write([]byte(fmt.Sprintf(failPage, escapedHeaderErr, desc)))
s.putResult(Result{Err: fmt.Errorf("%s", desc)})
return
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go
index d738c7591eed..481f9e434110 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go
@@ -281,6 +281,9 @@ func (c Client) FromClientSecret(ctx context.Context, authParameters authority.A
qv.Set(clientID, authParameters.ClientID)
addScopeQueryParam(qv, authParameters)
+ // Add extra body parameters if provided
+ addExtraBodyParameters(ctx, qv, authParameters)
+
return c.doTokenResp(ctx, authParameters, qv)
}
@@ -296,6 +299,9 @@ func (c Client) FromAssertion(ctx context.Context, authParameters authority.Auth
qv.Set(clientInfo, clientInfoVal)
addScopeQueryParam(qv, authParameters)
+ // Add extra body parameters if provided
+ addExtraBodyParameters(ctx, qv, authParameters)
+
return c.doTokenResp(ctx, authParameters, qv)
}
@@ -329,6 +335,8 @@ func (c Client) FromUserAssertionClientCertificate(ctx context.Context, authPara
qv.Set("requested_token_use", "on_behalf_of")
addScopeQueryParam(qv, authParameters)
+ // Add extra body parameters if provided
+ addExtraBodyParameters(ctx, qv, authParameters)
return c.doTokenResp(ctx, authParameters, qv)
}
@@ -466,3 +474,12 @@ func addScopeQueryParam(queryParams url.Values, authParameters authority.AuthPar
scopes := AppendDefaultScopes(authParameters)
queryParams.Set("scope", strings.Join(scopes, " "))
}
+
+// addExtraBodyParameters evaluates and adds extra body parameters to the request
+func addExtraBodyParameters(ctx context.Context, v url.Values, ap authority.AuthParams) {
+ for key, value := range ap.ExtraBodyParameters {
+ if value != "" {
+ v.Set(key, value)
+ }
+ }
+}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go
index c3c4a96fc302..debd465dbad3 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go
@@ -15,6 +15,7 @@ import (
"net/url"
"os"
"path"
+ "sort"
"strings"
"time"
@@ -46,13 +47,20 @@ type jsonCaller interface {
JSONCall(ctx context.Context, endpoint string, headers http.Header, qv url.Values, body, resp interface{}) error
}
+// For backward compatibility, accept both old and new China endpoints for a transition period.
+// This list is derived from the AAD instance discovery metadata and represents all known trusted hosts
+// across different Azure clouds (Public, China, Germany, US Government, etc.)
var aadTrustedHostList = map[string]bool{
"login.windows.net": true, // Microsoft Azure Worldwide - Used in validation scenarios where host is not this list
- "login.partner.microsoftonline.cn": true, // Microsoft Azure China
+ "login.partner.microsoftonline.cn": true, // Microsoft Azure China (new)
+ "login.chinacloudapi.cn": true, // Microsoft Azure China (legacy, backward compatibility)
"login.microsoftonline.de": true, // Microsoft Azure Blackforest
"login-us.microsoftonline.com": true, // Microsoft Azure US Government - Legacy
"login.microsoftonline.us": true, // Microsoft Azure US Government
"login.microsoftonline.com": true, // Microsoft Azure Worldwide
+ "login.microsoft.com": true,
+ "sts.windows.net": true,
+ "login.usgovcloudapi.net": true,
}
// TrustedHost checks if an AAD host is trusted/valid.
@@ -98,6 +106,51 @@ func (r *TenantDiscoveryResponse) Validate() error {
return nil
}
+// ValidateIssuerMatchesAuthority validates that the issuer in the TenantDiscoveryResponse matches the authority.
+// This is used to identity security or configuration issues in authorities and the OIDC endpoint
+func (r *TenantDiscoveryResponse) ValidateIssuerMatchesAuthority(authorityURI string, aliases map[string]bool) error {
+ if authorityURI == "" {
+ return errors.New("TenantDiscoveryResponse: empty authorityURI provided for validation")
+ }
+ if r.Issuer == "" {
+ return errors.New("TenantDiscoveryResponse: empty issuer in response")
+ }
+
+ issuerURL, err := url.Parse(r.Issuer)
+ if err != nil {
+ return fmt.Errorf("TenantDiscoveryResponse: failed to parse issuer URL: %w", err)
+ }
+ authorityURL, err := url.Parse(authorityURI)
+ if err != nil {
+ return fmt.Errorf("TenantDiscoveryResponse: failed to parse authority URL: %w", err)
+ }
+
+ // Fast path: exact scheme + host match
+ if issuerURL.Scheme == authorityURL.Scheme && issuerURL.Host == authorityURL.Host {
+ return nil
+ }
+
+ // Alias-based acceptance
+ if aliases != nil && aliases[issuerURL.Host] {
+ return nil
+ }
+
+ issuerHost := issuerURL.Host
+ authorityHost := authorityURL.Host
+
+ // Accept if issuer host is trusted
+ if TrustedHost(issuerHost) {
+ return nil
+ }
+
+ // Accept if authority is a regional variant ending with "."
+ if strings.HasSuffix(authorityHost, "."+issuerHost) {
+ return nil
+ }
+
+ return fmt.Errorf("TenantDiscoveryResponse: issuer '%s' does not match authority '%s' or any trusted/alias rule", r.Issuer, authorityURI)
+}
+
type InstanceDiscoveryMetadata struct {
PreferredNetwork string `json:"preferred_network"`
PreferredCache string `json:"preferred_cache"`
@@ -219,6 +272,12 @@ type AuthParams struct {
DomainHint string
// AuthnScheme is an optional scheme for formatting access tokens
AuthnScheme AuthenticationScheme
+ // ExtraBodyParameters are additional parameters to include in token requests.
+ // The functions are evaluated at request time to get the parameter values.
+ // These parameters are also included in the cache key.
+ ExtraBodyParameters map[string]string
+ // CacheKeyComponents are additional components to include in the cache key.
+ CacheKeyComponents map[string]string
}
// NewAuthParams creates an authorization parameters object.
@@ -354,6 +413,8 @@ type Info struct {
Tenant string
Region string
InstanceDiscoveryDisabled bool
+ // InstanceDiscoveryMetadata stores the metadata from AAD instance discovery
+ InstanceDiscoveryMetadata []InstanceDiscoveryMetadata
}
// NewInfoFromAuthorityURI creates an AuthorityInfo instance from the authority URL provided.
@@ -603,8 +664,42 @@ func (a *AuthParams) AssertionHash() string {
}
func (a *AuthParams) AppKey() string {
+ baseKey := a.ClientID + "_"
if a.AuthorityInfo.Tenant != "" {
- return fmt.Sprintf("%s_%s_AppTokenCache", a.ClientID, a.AuthorityInfo.Tenant)
+ baseKey += a.AuthorityInfo.Tenant
+ }
+
+ // Include extra body parameters in the cache key
+ paramHash := a.CacheExtKeyGenerator()
+ if paramHash != "" {
+ baseKey = fmt.Sprintf("%s_%s", baseKey, paramHash)
}
- return fmt.Sprintf("%s__AppTokenCache", a.ClientID)
+
+ return baseKey + "_AppTokenCache"
+}
+
+// CacheExtKeyGenerator computes a hash of the Cache key components key and values
+// to include in the cache key. This ensures tokens acquired with different
+// parameters are cached separately.
+func (a *AuthParams) CacheExtKeyGenerator() string {
+ if len(a.CacheKeyComponents) == 0 {
+ return ""
+ }
+
+ // Sort keys to ensure consistent hashing
+ keys := make([]string, 0, len(a.CacheKeyComponents))
+ for k := range a.CacheKeyComponents {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ // Create a string by concatenating key+value pairs
+ keyStr := ""
+ for _, key := range keys {
+ // Append key followed by its value with no separator
+ keyStr += key + a.CacheKeyComponents[key]
+ }
+
+ hash := sha256.Sum256([]byte(keyStr))
+ return strings.ToLower(base64.RawURLEncoding.EncodeToString(hash[:]))
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go
index 4030ec8d8f1b..d220a99466c1 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go
@@ -21,10 +21,12 @@ import (
type cacheEntry struct {
Endpoints authority.Endpoints
ValidForDomainsInList map[string]bool
+ // Aliases stores host aliases from instance discovery for quick lookup
+ Aliases map[string]bool
}
func createcacheEntry(endpoints authority.Endpoints) cacheEntry {
- return cacheEntry{endpoints, map[string]bool{}}
+ return cacheEntry{endpoints, map[string]bool{}, map[string]bool{}}
}
// AuthorityEndpoint retrieves endpoints from an authority for auth and token acquisition.
@@ -71,10 +73,15 @@ func (m *authorityEndpoint) ResolveEndpoints(ctx context.Context, authorityInfo
m.addCachedEndpoints(authorityInfo, userPrincipalName, endpoints)
+ if err := resp.ValidateIssuerMatchesAuthority(authorityInfo.CanonicalAuthorityURI,
+ m.cache[authorityInfo.CanonicalAuthorityURI].Aliases); err != nil {
+ return authority.Endpoints{}, fmt.Errorf("ResolveEndpoints(): %w", err)
+ }
+
return endpoints, nil
}
-// cachedEndpoints returns a the cached endpoints if they exists. If not, we return false.
+// cachedEndpoints returns the cached endpoints if they exist. If not, we return false.
func (m *authorityEndpoint) cachedEndpoints(authorityInfo authority.Info, userPrincipalName string) (authority.Endpoints, bool) {
m.mu.Lock()
defer m.mu.Unlock()
@@ -113,6 +120,13 @@ func (m *authorityEndpoint) addCachedEndpoints(authorityInfo authority.Info, use
}
}
+ // Extract aliases from instance discovery metadata and add to cache
+ for _, metadata := range authorityInfo.InstanceDiscoveryMetadata {
+ for _, alias := range metadata.Aliases {
+ updatedCacheEntry.Aliases[alias] = true
+ }
+ }
+
m.cache[authorityInfo.CanonicalAuthorityURI] = updatedCacheEntry
}
@@ -127,12 +141,14 @@ func (m *authorityEndpoint) openIDConfigurationEndpoint(ctx context.Context, aut
if err != nil {
return "", err
}
+ authorityInfo.InstanceDiscoveryMetadata = resp.Metadata
return resp.TenantDiscoveryEndpoint, nil
} else if authorityInfo.Region != "" {
resp, err := m.rest.Authority().AADInstanceDiscovery(ctx, authorityInfo)
if err != nil {
return "", err
}
+ authorityInfo.InstanceDiscoveryMetadata = resp.Metadata
return resp.TenantDiscoveryEndpoint, nil
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
index 7beed26174ec..797c086cb872 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
@@ -368,9 +368,9 @@ type AcquireByUsernamePasswordOption interface {
acquireByUsernamePasswordOption()
}
-// AcquireTokenByUsernamePassword acquires a security token from the authority, via Username/Password Authentication.
-// NOTE: this flow is NOT recommended.
+// Deprecated: This API will be removed in a future release. Use a more secure flow instead. Follow this migration guide: https://aka.ms/msal-ropc-migration
//
+// AcquireTokenByUsernamePassword acquires a security token from the authority, via Username/Password Authentication.
// Options: [WithClaims], [WithTenantID]
func (pca Client) AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username, password string, opts ...AcquireByUsernamePasswordOption) (AuthResult, error) {
o := acquireTokenByUsernamePasswordOptions{}
diff --git a/vendor/github.com/asaskevich/govalidator/.gitignore b/vendor/github.com/asaskevich/govalidator/.gitignore
new file mode 100644
index 000000000000..8d69a9418aa3
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/.gitignore
@@ -0,0 +1,15 @@
+bin/
+.idea/
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
diff --git a/vendor/github.com/asaskevich/govalidator/.travis.yml b/vendor/github.com/asaskevich/govalidator/.travis.yml
new file mode 100644
index 000000000000..bb83c6670df6
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/.travis.yml
@@ -0,0 +1,12 @@
+language: go
+dist: xenial
+go:
+ - '1.10'
+ - '1.11'
+ - '1.12'
+ - '1.13'
+ - 'tip'
+
+script:
+ - go test -coverpkg=./... -coverprofile=coverage.info -timeout=5s
+ - bash <(curl -s https://codecov.io/bash)
diff --git a/vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md b/vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..4b462b0d81b1
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md
@@ -0,0 +1,43 @@
+# Contributor Code of Conduct
+
+This project adheres to [The Code Manifesto](http://codemanifesto.com)
+as its guidelines for contributor interactions.
+
+## The Code Manifesto
+
+We want to work in an ecosystem that empowers developers to reach their
+potential — one that encourages growth and effective collaboration. A space
+that is safe for all.
+
+A space such as this benefits everyone that participates in it. It encourages
+new developers to enter our field. It is through discussion and collaboration
+that we grow, and through growth that we improve.
+
+In the effort to create such a place, we hold to these values:
+
+1. **Discrimination limits us.** This includes discrimination on the basis of
+ race, gender, sexual orientation, gender identity, age, nationality,
+ technology and any other arbitrary exclusion of a group of people.
+2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort
+ levels. Remember that, and if brought to your attention, heed it.
+3. **We are our biggest assets.** None of us were born masters of our trade.
+ Each of us has been helped along the way. Return that favor, when and where
+ you can.
+4. **We are resources for the future.** As an extension of #3, share what you
+ know. Make yourself a resource to help those that come after you.
+5. **Respect defines us.** Treat others as you wish to be treated. Make your
+ discussions, criticisms and debates from a position of respectfulness. Ask
+ yourself, is it true? Is it necessary? Is it constructive? Anything less is
+ unacceptable.
+6. **Reactions require grace.** Angry responses are valid, but abusive language
+ and vindictive actions are toxic. When something happens that offends you,
+ handle it assertively, but be respectful. Escalate reasonably, and try to
+ allow the offender an opportunity to explain themselves, and possibly
+ correct the issue.
+7. **Opinions are just that: opinions.** Each and every one of us, due to our
+ background and upbringing, have varying opinions. That is perfectly
+ acceptable. Remember this: if you respect your own opinions, you should
+ respect the opinions of others.
+8. **To err is human.** You might not intend it, but mistakes do happen and
+ contribute to build experience. Tolerate honest mistakes, and don't
+ hesitate to apologize if you make one yourself.
diff --git a/vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md b/vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md
new file mode 100644
index 000000000000..7ed268a1edd9
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md
@@ -0,0 +1,63 @@
+#### Support
+If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
+
+#### What to contribute
+If you don't know what to do, there are some features and functions that need to be done
+
+- [ ] Refactor code
+- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
+- [ ] Create actual list of contributors and projects that currently using this package
+- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
+- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
+- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
+- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
+- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
+- [ ] Implement fuzzing testing
+- [ ] Implement some struct/map/array utilities
+- [ ] Implement map/array validation
+- [ ] Implement benchmarking
+- [ ] Implement batch of examples
+- [ ] Look at forks for new features and fixes
+
+#### Advice
+Feel free to create what you want, but keep in mind when you implement new features:
+- Code must be clear and readable, names of variables/constants clearly describes what they are doing
+- Public functions must be documented and described in source file and added to README.md to the list of available functions
+- There are must be unit-tests for any new functions and improvements
+
+## Financial contributions
+
+We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/govalidator).
+Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
+
+
+## Credits
+
+
+### Contributors
+
+Thank you to all the people who have already contributed to govalidator!
+
+
+
+### Backers
+
+Thank you to all our backers! [[Become a backer](https://opencollective.com/govalidator#backer)]
+
+
+
+
+### Sponsors
+
+Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/govalidator#sponsor))
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/github.com/asaskevich/govalidator/LICENSE b/vendor/github.com/asaskevich/govalidator/LICENSE
new file mode 100644
index 000000000000..cacba9102400
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Alex Saskevich
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/github.com/asaskevich/govalidator/README.md b/vendor/github.com/asaskevich/govalidator/README.md
new file mode 100644
index 000000000000..2c3fc35eb644
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/README.md
@@ -0,0 +1,622 @@
+govalidator
+===========
+[](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://godoc.org/github.com/asaskevich/govalidator)
+[](https://travis-ci.org/asaskevich/govalidator)
+[](https://codecov.io/gh/asaskevich/govalidator) [](https://goreportcard.com/report/github.com/asaskevich/govalidator) [](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator) [](#backers) [](#sponsors) [](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_shield)
+
+A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js).
+
+#### Installation
+Make sure that Go is installed on your computer.
+Type the following command in your terminal:
+
+ go get github.com/asaskevich/govalidator
+
+or you can get specified release of the package with `gopkg.in`:
+
+ go get gopkg.in/asaskevich/govalidator.v10
+
+After it the package is ready to use.
+
+
+#### Import package in your project
+Add following line in your `*.go` file:
+```go
+import "github.com/asaskevich/govalidator"
+```
+If you are unhappy to use long `govalidator`, you can do something like this:
+```go
+import (
+ valid "github.com/asaskevich/govalidator"
+)
+```
+
+#### Activate behavior to require all fields have a validation tag by default
+`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function.
+
+`SetNilPtrAllowedByRequired` causes validation to pass when struct fields marked by `required` are set to nil. This is disabled by default for consistency, but some packages that need to be able to determine between `nil` and `zero value` state can use this. If disabled, both `nil` and `zero` values cause validation errors.
+
+```go
+import "github.com/asaskevich/govalidator"
+
+func init() {
+ govalidator.SetFieldsRequiredByDefault(true)
+}
+```
+
+Here's some code to explain it:
+```go
+// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
+type exampleStruct struct {
+ Name string ``
+ Email string `valid:"email"`
+}
+
+// this, however, will only fail when Email is empty or an invalid email address:
+type exampleStruct2 struct {
+ Name string `valid:"-"`
+ Email string `valid:"email"`
+}
+
+// lastly, this will only fail when Email is an invalid email address but not when it's empty:
+type exampleStruct2 struct {
+ Name string `valid:"-"`
+ Email string `valid:"email,optional"`
+}
+```
+
+#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123))
+##### Custom validator function signature
+A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible.
+```go
+import "github.com/asaskevich/govalidator"
+
+// old signature
+func(i interface{}) bool
+
+// new signature
+func(i interface{}, o interface{}) bool
+```
+
+##### Adding a custom validator
+This was changed to prevent data races when accessing custom validators.
+```go
+import "github.com/asaskevich/govalidator"
+
+// before
+govalidator.CustomTypeTagMap["customByteArrayValidator"] = func(i interface{}, o interface{}) bool {
+ // ...
+}
+
+// after
+govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, o interface{}) bool {
+ // ...
+})
+```
+
+#### List of functions:
+```go
+func Abs(value float64) float64
+func BlackList(str, chars string) string
+func ByteLength(str string, params ...string) bool
+func CamelCaseToUnderscore(str string) string
+func Contains(str, substring string) bool
+func Count(array []interface{}, iterator ConditionIterator) int
+func Each(array []interface{}, iterator Iterator)
+func ErrorByField(e error, field string) string
+func ErrorsByField(e error) map[string]string
+func Filter(array []interface{}, iterator ConditionIterator) []interface{}
+func Find(array []interface{}, iterator ConditionIterator) interface{}
+func GetLine(s string, index int) (string, error)
+func GetLines(s string) []string
+func HasLowerCase(str string) bool
+func HasUpperCase(str string) bool
+func HasWhitespace(str string) bool
+func HasWhitespaceOnly(str string) bool
+func InRange(value interface{}, left interface{}, right interface{}) bool
+func InRangeFloat32(value, left, right float32) bool
+func InRangeFloat64(value, left, right float64) bool
+func InRangeInt(value, left, right interface{}) bool
+func IsASCII(str string) bool
+func IsAlpha(str string) bool
+func IsAlphanumeric(str string) bool
+func IsBase64(str string) bool
+func IsByteLength(str string, min, max int) bool
+func IsCIDR(str string) bool
+func IsCRC32(str string) bool
+func IsCRC32b(str string) bool
+func IsCreditCard(str string) bool
+func IsDNSName(str string) bool
+func IsDataURI(str string) bool
+func IsDialString(str string) bool
+func IsDivisibleBy(str, num string) bool
+func IsEmail(str string) bool
+func IsExistingEmail(email string) bool
+func IsFilePath(str string) (bool, int)
+func IsFloat(str string) bool
+func IsFullWidth(str string) bool
+func IsHalfWidth(str string) bool
+func IsHash(str string, algorithm string) bool
+func IsHexadecimal(str string) bool
+func IsHexcolor(str string) bool
+func IsHost(str string) bool
+func IsIP(str string) bool
+func IsIPv4(str string) bool
+func IsIPv6(str string) bool
+func IsISBN(str string, version int) bool
+func IsISBN10(str string) bool
+func IsISBN13(str string) bool
+func IsISO3166Alpha2(str string) bool
+func IsISO3166Alpha3(str string) bool
+func IsISO4217(str string) bool
+func IsISO693Alpha2(str string) bool
+func IsISO693Alpha3b(str string) bool
+func IsIn(str string, params ...string) bool
+func IsInRaw(str string, params ...string) bool
+func IsInt(str string) bool
+func IsJSON(str string) bool
+func IsLatitude(str string) bool
+func IsLongitude(str string) bool
+func IsLowerCase(str string) bool
+func IsMAC(str string) bool
+func IsMD4(str string) bool
+func IsMD5(str string) bool
+func IsMagnetURI(str string) bool
+func IsMongoID(str string) bool
+func IsMultibyte(str string) bool
+func IsNatural(value float64) bool
+func IsNegative(value float64) bool
+func IsNonNegative(value float64) bool
+func IsNonPositive(value float64) bool
+func IsNotNull(str string) bool
+func IsNull(str string) bool
+func IsNumeric(str string) bool
+func IsPort(str string) bool
+func IsPositive(value float64) bool
+func IsPrintableASCII(str string) bool
+func IsRFC3339(str string) bool
+func IsRFC3339WithoutZone(str string) bool
+func IsRGBcolor(str string) bool
+func IsRegex(str string) bool
+func IsRequestURI(rawurl string) bool
+func IsRequestURL(rawurl string) bool
+func IsRipeMD128(str string) bool
+func IsRipeMD160(str string) bool
+func IsRsaPub(str string, params ...string) bool
+func IsRsaPublicKey(str string, keylen int) bool
+func IsSHA1(str string) bool
+func IsSHA256(str string) bool
+func IsSHA384(str string) bool
+func IsSHA512(str string) bool
+func IsSSN(str string) bool
+func IsSemver(str string) bool
+func IsTiger128(str string) bool
+func IsTiger160(str string) bool
+func IsTiger192(str string) bool
+func IsTime(str string, format string) bool
+func IsType(v interface{}, params ...string) bool
+func IsURL(str string) bool
+func IsUTFDigit(str string) bool
+func IsUTFLetter(str string) bool
+func IsUTFLetterNumeric(str string) bool
+func IsUTFNumeric(str string) bool
+func IsUUID(str string) bool
+func IsUUIDv3(str string) bool
+func IsUUIDv4(str string) bool
+func IsUUIDv5(str string) bool
+func IsULID(str string) bool
+func IsUnixTime(str string) bool
+func IsUpperCase(str string) bool
+func IsVariableWidth(str string) bool
+func IsWhole(value float64) bool
+func LeftTrim(str, chars string) string
+func Map(array []interface{}, iterator ResultIterator) []interface{}
+func Matches(str, pattern string) bool
+func MaxStringLength(str string, params ...string) bool
+func MinStringLength(str string, params ...string) bool
+func NormalizeEmail(str string) (string, error)
+func PadBoth(str string, padStr string, padLen int) string
+func PadLeft(str string, padStr string, padLen int) string
+func PadRight(str string, padStr string, padLen int) string
+func PrependPathToErrors(err error, path string) error
+func Range(str string, params ...string) bool
+func RemoveTags(s string) string
+func ReplacePattern(str, pattern, replace string) string
+func Reverse(s string) string
+func RightTrim(str, chars string) string
+func RuneLength(str string, params ...string) bool
+func SafeFileName(str string) string
+func SetFieldsRequiredByDefault(value bool)
+func SetNilPtrAllowedByRequired(value bool)
+func Sign(value float64) float64
+func StringLength(str string, params ...string) bool
+func StringMatches(s string, params ...string) bool
+func StripLow(str string, keepNewLines bool) string
+func ToBoolean(str string) (bool, error)
+func ToFloat(str string) (float64, error)
+func ToInt(value interface{}) (res int64, err error)
+func ToJSON(obj interface{}) (string, error)
+func ToString(obj interface{}) string
+func Trim(str, chars string) string
+func Truncate(str string, length int, ending string) string
+func TruncatingErrorf(str string, args ...interface{}) error
+func UnderscoreToCamelCase(s string) string
+func ValidateMap(inputMap map[string]interface{}, validationMap map[string]interface{}) (bool, error)
+func ValidateStruct(s interface{}) (bool, error)
+func WhiteList(str, chars string) string
+type ConditionIterator
+type CustomTypeValidator
+type Error
+func (e Error) Error() string
+type Errors
+func (es Errors) Error() string
+func (es Errors) Errors() []error
+type ISO3166Entry
+type ISO693Entry
+type InterfaceParamValidator
+type Iterator
+type ParamValidator
+type ResultIterator
+type UnsupportedTypeError
+func (e *UnsupportedTypeError) Error() string
+type Validator
+```
+
+#### Examples
+###### IsURL
+```go
+println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
+```
+###### IsType
+```go
+println(govalidator.IsType("Bob", "string"))
+println(govalidator.IsType(1, "int"))
+i := 1
+println(govalidator.IsType(&i, "*int"))
+```
+
+IsType can be used through the tag `type` which is essential for map validation:
+```go
+type User struct {
+ Name string `valid:"type(string)"`
+ Age int `valid:"type(int)"`
+ Meta interface{} `valid:"type(string)"`
+}
+result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"})
+if err != nil {
+ println("error: " + err.Error())
+}
+println(result)
+```
+###### ToString
+```go
+type User struct {
+ FirstName string
+ LastName string
+}
+
+str := govalidator.ToString(&User{"John", "Juan"})
+println(str)
+```
+###### Each, Map, Filter, Count for slices
+Each iterates over the slice/array and calls Iterator for every item
+```go
+data := []interface{}{1, 2, 3, 4, 5}
+var fn govalidator.Iterator = func(value interface{}, index int) {
+ println(value.(int))
+}
+govalidator.Each(data, fn)
+```
+```go
+data := []interface{}{1, 2, 3, 4, 5}
+var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
+ return value.(int) * 3
+}
+_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
+```
+```go
+data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
+ return value.(int)%2 == 0
+}
+_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
+_ = govalidator.Count(data, fn) // result = 5
+```
+###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2)
+If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this:
+```go
+govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
+ return str == "duck"
+})
+```
+For completely custom validators (interface-based), see below.
+
+Here is a list of available validators for struct fields (validator - used function):
+```go
+"email": IsEmail,
+"url": IsURL,
+"dialstring": IsDialString,
+"requrl": IsRequestURL,
+"requri": IsRequestURI,
+"alpha": IsAlpha,
+"utfletter": IsUTFLetter,
+"alphanum": IsAlphanumeric,
+"utfletternum": IsUTFLetterNumeric,
+"numeric": IsNumeric,
+"utfnumeric": IsUTFNumeric,
+"utfdigit": IsUTFDigit,
+"hexadecimal": IsHexadecimal,
+"hexcolor": IsHexcolor,
+"rgbcolor": IsRGBcolor,
+"lowercase": IsLowerCase,
+"uppercase": IsUpperCase,
+"int": IsInt,
+"float": IsFloat,
+"null": IsNull,
+"uuid": IsUUID,
+"uuidv3": IsUUIDv3,
+"uuidv4": IsUUIDv4,
+"uuidv5": IsUUIDv5,
+"creditcard": IsCreditCard,
+"isbn10": IsISBN10,
+"isbn13": IsISBN13,
+"json": IsJSON,
+"multibyte": IsMultibyte,
+"ascii": IsASCII,
+"printableascii": IsPrintableASCII,
+"fullwidth": IsFullWidth,
+"halfwidth": IsHalfWidth,
+"variablewidth": IsVariableWidth,
+"base64": IsBase64,
+"datauri": IsDataURI,
+"ip": IsIP,
+"port": IsPort,
+"ipv4": IsIPv4,
+"ipv6": IsIPv6,
+"dns": IsDNSName,
+"host": IsHost,
+"mac": IsMAC,
+"latitude": IsLatitude,
+"longitude": IsLongitude,
+"ssn": IsSSN,
+"semver": IsSemver,
+"rfc3339": IsRFC3339,
+"rfc3339WithoutZone": IsRFC3339WithoutZone,
+"ISO3166Alpha2": IsISO3166Alpha2,
+"ISO3166Alpha3": IsISO3166Alpha3,
+"ulid": IsULID,
+```
+Validators with parameters
+
+```go
+"range(min|max)": Range,
+"length(min|max)": ByteLength,
+"runelength(min|max)": RuneLength,
+"stringlength(min|max)": StringLength,
+"matches(pattern)": StringMatches,
+"in(string1|string2|...|stringN)": IsIn,
+"rsapub(keylength)" : IsRsaPub,
+"minstringlength(int): MinStringLength,
+"maxstringlength(int): MaxStringLength,
+```
+Validators with parameters for any type
+
+```go
+"type(type)": IsType,
+```
+
+And here is small example of usage:
+```go
+type Post struct {
+ Title string `valid:"alphanum,required"`
+ Message string `valid:"duck,ascii"`
+ Message2 string `valid:"animal(dog)"`
+ AuthorIP string `valid:"ipv4"`
+ Date string `valid:"-"`
+}
+post := &Post{
+ Title: "My Example Post",
+ Message: "duck",
+ Message2: "dog",
+ AuthorIP: "123.234.54.3",
+}
+
+// Add your own struct validation tags
+govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
+ return str == "duck"
+})
+
+// Add your own struct validation tags with parameter
+govalidator.ParamTagMap["animal"] = govalidator.ParamValidator(func(str string, params ...string) bool {
+ species := params[0]
+ return str == species
+})
+govalidator.ParamTagRegexMap["animal"] = regexp.MustCompile("^animal\\((\\w+)\\)$")
+
+result, err := govalidator.ValidateStruct(post)
+if err != nil {
+ println("error: " + err.Error())
+}
+println(result)
+```
+###### ValidateMap [#2](https://github.com/asaskevich/govalidator/pull/338)
+If you want to validate maps, you can use the map to be validated and a validation map that contain the same tags used in ValidateStruct, both maps have to be in the form `map[string]interface{}`
+
+So here is small example of usage:
+```go
+var mapTemplate = map[string]interface{}{
+ "name":"required,alpha",
+ "family":"required,alpha",
+ "email":"required,email",
+ "cell-phone":"numeric",
+ "address":map[string]interface{}{
+ "line1":"required,alphanum",
+ "line2":"alphanum",
+ "postal-code":"numeric",
+ },
+}
+
+var inputMap = map[string]interface{}{
+ "name":"Bob",
+ "family":"Smith",
+ "email":"foo@bar.baz",
+ "address":map[string]interface{}{
+ "line1":"",
+ "line2":"",
+ "postal-code":"",
+ },
+}
+
+result, err := govalidator.ValidateMap(inputMap, mapTemplate)
+if err != nil {
+ println("error: " + err.Error())
+}
+println(result)
+```
+
+###### WhiteList
+```go
+// Remove all characters from string ignoring characters between "a" and "z"
+println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
+```
+
+###### Custom validation functions
+Custom validation using your own domain specific validators is also available - here's an example of how to use it:
+```go
+import "github.com/asaskevich/govalidator"
+
+type CustomByteArray [6]byte // custom types are supported and can be validated
+
+type StructWithCustomByteArray struct {
+ ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence
+ Email string `valid:"email"`
+ CustomMinLength int `valid:"-"`
+}
+
+govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, context interface{}) bool {
+ switch v := context.(type) { // you can type switch on the context interface being validated
+ case StructWithCustomByteArray:
+ // you can check and validate against some other field in the context,
+ // return early or not validate against the context at all – your choice
+ case SomeOtherType:
+ // ...
+ default:
+ // expecting some other type? Throw/panic here or continue
+ }
+
+ switch v := i.(type) { // type switch on the struct field being validated
+ case CustomByteArray:
+ for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes
+ if e != 0 {
+ return true
+ }
+ }
+ }
+ return false
+})
+govalidator.CustomTypeTagMap.Set("customMinLengthValidator", func(i interface{}, context interface{}) bool {
+ switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation
+ case StructWithCustomByteArray:
+ return len(v.ID) >= v.CustomMinLength
+ }
+ return false
+})
+```
+
+###### Loop over Error()
+By default .Error() returns all errors in a single String. To access each error you can do this:
+```go
+ if err != nil {
+ errs := err.(govalidator.Errors).Errors()
+ for _, e := range errs {
+ fmt.Println(e.Error())
+ }
+ }
+```
+
+###### Custom error messages
+Custom error messages are supported via annotations by adding the `~` separator - here's an example of how to use it:
+```go
+type Ticket struct {
+ Id int64 `json:"id"`
+ FirstName string `json:"firstname" valid:"required~First name is blank"`
+}
+```
+
+#### Notes
+Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator).
+Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
+
+#### Support
+If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
+
+#### What to contribute
+If you don't know what to do, there are some features and functions that need to be done
+
+- [ ] Refactor code
+- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
+- [ ] Create actual list of contributors and projects that currently using this package
+- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
+- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
+- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
+- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
+- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
+- [ ] Implement fuzzing testing
+- [ ] Implement some struct/map/array utilities
+- [ ] Implement map/array validation
+- [ ] Implement benchmarking
+- [ ] Implement batch of examples
+- [ ] Look at forks for new features and fixes
+
+#### Advice
+Feel free to create what you want, but keep in mind when you implement new features:
+- Code must be clear and readable, names of variables/constants clearly describes what they are doing
+- Public functions must be documented and described in source file and added to README.md to the list of available functions
+- There are must be unit-tests for any new functions and improvements
+
+## Credits
+### Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+
+#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
+* [Daniel Lohse](https://github.com/annismckenzie)
+* [Attila Oláh](https://github.com/attilaolah)
+* [Daniel Korner](https://github.com/Dadie)
+* [Steven Wilkin](https://github.com/stevenwilkin)
+* [Deiwin Sarjas](https://github.com/deiwin)
+* [Noah Shibley](https://github.com/slugmobile)
+* [Nathan Davies](https://github.com/nathj07)
+* [Matt Sanford](https://github.com/mzsanford)
+* [Simon ccl1115](https://github.com/ccl1115)
+
+
+
+
+### Backers
+
+Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/govalidator#backer)]
+
+
+
+
+### Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/govalidator#sponsor)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## License
+[](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_large)
diff --git a/vendor/github.com/asaskevich/govalidator/arrays.go b/vendor/github.com/asaskevich/govalidator/arrays.go
new file mode 100644
index 000000000000..3e1da7cb480e
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/arrays.go
@@ -0,0 +1,87 @@
+package govalidator
+
+// Iterator is the function that accepts element of slice/array and its index
+type Iterator func(interface{}, int)
+
+// ResultIterator is the function that accepts element of slice/array and its index and returns any result
+type ResultIterator func(interface{}, int) interface{}
+
+// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean
+type ConditionIterator func(interface{}, int) bool
+
+// ReduceIterator is the function that accepts two element of slice/array and returns result of merging those values
+type ReduceIterator func(interface{}, interface{}) interface{}
+
+// Some validates that any item of array corresponds to ConditionIterator. Returns boolean.
+func Some(array []interface{}, iterator ConditionIterator) bool {
+ res := false
+ for index, data := range array {
+ res = res || iterator(data, index)
+ }
+ return res
+}
+
+// Every validates that every item of array corresponds to ConditionIterator. Returns boolean.
+func Every(array []interface{}, iterator ConditionIterator) bool {
+ res := true
+ for index, data := range array {
+ res = res && iterator(data, index)
+ }
+ return res
+}
+
+// Reduce boils down a list of values into a single value by ReduceIterator
+func Reduce(array []interface{}, iterator ReduceIterator, initialValue interface{}) interface{} {
+ for _, data := range array {
+ initialValue = iterator(initialValue, data)
+ }
+ return initialValue
+}
+
+// Each iterates over the slice and apply Iterator to every item
+func Each(array []interface{}, iterator Iterator) {
+ for index, data := range array {
+ iterator(data, index)
+ }
+}
+
+// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result.
+func Map(array []interface{}, iterator ResultIterator) []interface{} {
+ var result = make([]interface{}, len(array))
+ for index, data := range array {
+ result[index] = iterator(data, index)
+ }
+ return result
+}
+
+// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise.
+func Find(array []interface{}, iterator ConditionIterator) interface{} {
+ for index, data := range array {
+ if iterator(data, index) {
+ return data
+ }
+ }
+ return nil
+}
+
+// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice.
+func Filter(array []interface{}, iterator ConditionIterator) []interface{} {
+ var result = make([]interface{}, 0)
+ for index, data := range array {
+ if iterator(data, index) {
+ result = append(result, data)
+ }
+ }
+ return result
+}
+
+// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator.
+func Count(array []interface{}, iterator ConditionIterator) int {
+ count := 0
+ for index, data := range array {
+ if iterator(data, index) {
+ count = count + 1
+ }
+ }
+ return count
+}
diff --git a/vendor/github.com/asaskevich/govalidator/converter.go b/vendor/github.com/asaskevich/govalidator/converter.go
new file mode 100644
index 000000000000..d68e990fc256
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/converter.go
@@ -0,0 +1,81 @@
+package govalidator
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strconv"
+)
+
+// ToString convert the input to a string.
+func ToString(obj interface{}) string {
+ res := fmt.Sprintf("%v", obj)
+ return res
+}
+
+// ToJSON convert the input to a valid JSON string
+func ToJSON(obj interface{}) (string, error) {
+ res, err := json.Marshal(obj)
+ if err != nil {
+ res = []byte("")
+ }
+ return string(res), err
+}
+
+// ToFloat convert the input string to a float, or 0.0 if the input is not a float.
+func ToFloat(value interface{}) (res float64, err error) {
+ val := reflect.ValueOf(value)
+
+ switch value.(type) {
+ case int, int8, int16, int32, int64:
+ res = float64(val.Int())
+ case uint, uint8, uint16, uint32, uint64:
+ res = float64(val.Uint())
+ case float32, float64:
+ res = val.Float()
+ case string:
+ res, err = strconv.ParseFloat(val.String(), 64)
+ if err != nil {
+ res = 0
+ }
+ default:
+ err = fmt.Errorf("ToInt: unknown interface type %T", value)
+ res = 0
+ }
+
+ return
+}
+
+// ToInt convert the input string or any int type to an integer type 64, or 0 if the input is not an integer.
+func ToInt(value interface{}) (res int64, err error) {
+ val := reflect.ValueOf(value)
+
+ switch value.(type) {
+ case int, int8, int16, int32, int64:
+ res = val.Int()
+ case uint, uint8, uint16, uint32, uint64:
+ res = int64(val.Uint())
+ case float32, float64:
+ res = int64(val.Float())
+ case string:
+ if IsInt(val.String()) {
+ res, err = strconv.ParseInt(val.String(), 0, 64)
+ if err != nil {
+ res = 0
+ }
+ } else {
+ err = fmt.Errorf("ToInt: invalid numeric format %g", value)
+ res = 0
+ }
+ default:
+ err = fmt.Errorf("ToInt: unknown interface type %T", value)
+ res = 0
+ }
+
+ return
+}
+
+// ToBoolean convert the input string to a boolean.
+func ToBoolean(str string) (bool, error) {
+ return strconv.ParseBool(str)
+}
diff --git a/vendor/github.com/asaskevich/govalidator/doc.go b/vendor/github.com/asaskevich/govalidator/doc.go
new file mode 100644
index 000000000000..55dce62dc8c3
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/doc.go
@@ -0,0 +1,3 @@
+package govalidator
+
+// A package of validators and sanitizers for strings, structures and collections.
diff --git a/vendor/github.com/asaskevich/govalidator/error.go b/vendor/github.com/asaskevich/govalidator/error.go
new file mode 100644
index 000000000000..1da2336f47ee
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/error.go
@@ -0,0 +1,47 @@
+package govalidator
+
+import (
+ "sort"
+ "strings"
+)
+
+// Errors is an array of multiple errors and conforms to the error interface.
+type Errors []error
+
+// Errors returns itself.
+func (es Errors) Errors() []error {
+ return es
+}
+
+func (es Errors) Error() string {
+ var errs []string
+ for _, e := range es {
+ errs = append(errs, e.Error())
+ }
+ sort.Strings(errs)
+ return strings.Join(errs, ";")
+}
+
+// Error encapsulates a name, an error and whether there's a custom error message or not.
+type Error struct {
+ Name string
+ Err error
+ CustomErrorMessageExists bool
+
+ // Validator indicates the name of the validator that failed
+ Validator string
+ Path []string
+}
+
+func (e Error) Error() string {
+ if e.CustomErrorMessageExists {
+ return e.Err.Error()
+ }
+
+ errName := e.Name
+ if len(e.Path) > 0 {
+ errName = strings.Join(append(e.Path, e.Name), ".")
+ }
+
+ return errName + ": " + e.Err.Error()
+}
diff --git a/vendor/github.com/asaskevich/govalidator/numerics.go b/vendor/github.com/asaskevich/govalidator/numerics.go
new file mode 100644
index 000000000000..5041d9e86844
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/numerics.go
@@ -0,0 +1,100 @@
+package govalidator
+
+import (
+ "math"
+)
+
+// Abs returns absolute value of number
+func Abs(value float64) float64 {
+ return math.Abs(value)
+}
+
+// Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise
+func Sign(value float64) float64 {
+ if value > 0 {
+ return 1
+ } else if value < 0 {
+ return -1
+ } else {
+ return 0
+ }
+}
+
+// IsNegative returns true if value < 0
+func IsNegative(value float64) bool {
+ return value < 0
+}
+
+// IsPositive returns true if value > 0
+func IsPositive(value float64) bool {
+ return value > 0
+}
+
+// IsNonNegative returns true if value >= 0
+func IsNonNegative(value float64) bool {
+ return value >= 0
+}
+
+// IsNonPositive returns true if value <= 0
+func IsNonPositive(value float64) bool {
+ return value <= 0
+}
+
+// InRangeInt returns true if value lies between left and right border
+func InRangeInt(value, left, right interface{}) bool {
+ value64, _ := ToInt(value)
+ left64, _ := ToInt(left)
+ right64, _ := ToInt(right)
+ if left64 > right64 {
+ left64, right64 = right64, left64
+ }
+ return value64 >= left64 && value64 <= right64
+}
+
+// InRangeFloat32 returns true if value lies between left and right border
+func InRangeFloat32(value, left, right float32) bool {
+ if left > right {
+ left, right = right, left
+ }
+ return value >= left && value <= right
+}
+
+// InRangeFloat64 returns true if value lies between left and right border
+func InRangeFloat64(value, left, right float64) bool {
+ if left > right {
+ left, right = right, left
+ }
+ return value >= left && value <= right
+}
+
+// InRange returns true if value lies between left and right border, generic type to handle int, float32, float64 and string.
+// All types must the same type.
+// False if value doesn't lie in range or if it incompatible or not comparable
+func InRange(value interface{}, left interface{}, right interface{}) bool {
+ switch value.(type) {
+ case int:
+ intValue, _ := ToInt(value)
+ intLeft, _ := ToInt(left)
+ intRight, _ := ToInt(right)
+ return InRangeInt(intValue, intLeft, intRight)
+ case float32, float64:
+ intValue, _ := ToFloat(value)
+ intLeft, _ := ToFloat(left)
+ intRight, _ := ToFloat(right)
+ return InRangeFloat64(intValue, intLeft, intRight)
+ case string:
+ return value.(string) >= left.(string) && value.(string) <= right.(string)
+ default:
+ return false
+ }
+}
+
+// IsWhole returns true if value is whole number
+func IsWhole(value float64) bool {
+ return math.Remainder(value, 1) == 0
+}
+
+// IsNatural returns true if value is natural number (positive and whole)
+func IsNatural(value float64) bool {
+ return IsWhole(value) && IsPositive(value)
+}
diff --git a/vendor/github.com/asaskevich/govalidator/patterns.go b/vendor/github.com/asaskevich/govalidator/patterns.go
new file mode 100644
index 000000000000..bafc3765ea12
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/patterns.go
@@ -0,0 +1,113 @@
+package govalidator
+
+import "regexp"
+
+// Basic regular expressions for validating strings
+const (
+ Email string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
+ CreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$"
+ ISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$"
+ ISBN13 string = "^(?:[0-9]{13})$"
+ UUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
+ UUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
+ UUID5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
+ UUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
+ Alpha string = "^[a-zA-Z]+$"
+ Alphanumeric string = "^[a-zA-Z0-9]+$"
+ Numeric string = "^[0-9]+$"
+ Int string = "^(?:[-+]?(?:0|[1-9][0-9]*))$"
+ Float string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$"
+ Hexadecimal string = "^[0-9a-fA-F]+$"
+ Hexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
+ RGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
+ ASCII string = "^[\x00-\x7F]+$"
+ Multibyte string = "[^\x00-\x7F]"
+ FullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
+ HalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
+ Base64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
+ PrintableASCII string = "^[\x20-\x7E]+$"
+ DataURI string = "^data:.+\\/(.+);base64$"
+ MagnetURI string = "^magnet:\\?xt=urn:[a-zA-Z0-9]+:[a-zA-Z0-9]{32,40}&dn=.+&tr=.+$"
+ Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
+ Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
+ DNSName string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
+ IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
+ URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)`
+ URLUsername string = `(\S+(:\S*)?@)`
+ URLPath string = `((\/|\?|#)[^\s]*)`
+ URLPort string = `(:(\d{1,5}))`
+ URLIP string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3]|24\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-5]))`
+ URLSubdomain string = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))`
+ URL = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$`
+ SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
+ WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
+ UnixPath string = `^(/[^/\x00]*)+/?$`
+ WinARPath string = `^(?:(?:[a-zA-Z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\|\\?[^\\/:*?"<>|\r\n]+\\?)(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
+ UnixARPath string = `^((\.{0,2}/)?([^/\x00]*))+/?$`
+ Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$"
+ tagName string = "valid"
+ hasLowerCase string = ".*[[:lower:]]"
+ hasUpperCase string = ".*[[:upper:]]"
+ hasWhitespace string = ".*[[:space:]]"
+ hasWhitespaceOnly string = "^[[:space:]]+$"
+ IMEI string = "^[0-9a-f]{14}$|^\\d{15}$|^\\d{18}$"
+ IMSI string = "^\\d{14,15}$"
+ E164 string = `^\+?[1-9]\d{1,14}$`
+)
+
+// Used by IsFilePath func
+const (
+ // Unknown is unresolved OS type
+ Unknown = iota
+ // Win is Windows type
+ Win
+ // Unix is *nix OS types
+ Unix
+)
+
+var (
+ userRegexp = regexp.MustCompile("^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$")
+ hostRegexp = regexp.MustCompile("^[^\\s]+\\.[^\\s]+$")
+ userDotRegexp = regexp.MustCompile("(^[.]{1})|([.]{1}$)|([.]{2,})")
+ rxEmail = regexp.MustCompile(Email)
+ rxCreditCard = regexp.MustCompile(CreditCard)
+ rxISBN10 = regexp.MustCompile(ISBN10)
+ rxISBN13 = regexp.MustCompile(ISBN13)
+ rxUUID3 = regexp.MustCompile(UUID3)
+ rxUUID4 = regexp.MustCompile(UUID4)
+ rxUUID5 = regexp.MustCompile(UUID5)
+ rxUUID = regexp.MustCompile(UUID)
+ rxAlpha = regexp.MustCompile(Alpha)
+ rxAlphanumeric = regexp.MustCompile(Alphanumeric)
+ rxNumeric = regexp.MustCompile(Numeric)
+ rxInt = regexp.MustCompile(Int)
+ rxFloat = regexp.MustCompile(Float)
+ rxHexadecimal = regexp.MustCompile(Hexadecimal)
+ rxHexcolor = regexp.MustCompile(Hexcolor)
+ rxRGBcolor = regexp.MustCompile(RGBcolor)
+ rxASCII = regexp.MustCompile(ASCII)
+ rxPrintableASCII = regexp.MustCompile(PrintableASCII)
+ rxMultibyte = regexp.MustCompile(Multibyte)
+ rxFullWidth = regexp.MustCompile(FullWidth)
+ rxHalfWidth = regexp.MustCompile(HalfWidth)
+ rxBase64 = regexp.MustCompile(Base64)
+ rxDataURI = regexp.MustCompile(DataURI)
+ rxMagnetURI = regexp.MustCompile(MagnetURI)
+ rxLatitude = regexp.MustCompile(Latitude)
+ rxLongitude = regexp.MustCompile(Longitude)
+ rxDNSName = regexp.MustCompile(DNSName)
+ rxURL = regexp.MustCompile(URL)
+ rxSSN = regexp.MustCompile(SSN)
+ rxWinPath = regexp.MustCompile(WinPath)
+ rxUnixPath = regexp.MustCompile(UnixPath)
+ rxARWinPath = regexp.MustCompile(WinARPath)
+ rxARUnixPath = regexp.MustCompile(UnixARPath)
+ rxSemver = regexp.MustCompile(Semver)
+ rxHasLowerCase = regexp.MustCompile(hasLowerCase)
+ rxHasUpperCase = regexp.MustCompile(hasUpperCase)
+ rxHasWhitespace = regexp.MustCompile(hasWhitespace)
+ rxHasWhitespaceOnly = regexp.MustCompile(hasWhitespaceOnly)
+ rxIMEI = regexp.MustCompile(IMEI)
+ rxIMSI = regexp.MustCompile(IMSI)
+ rxE164 = regexp.MustCompile(E164)
+)
diff --git a/vendor/github.com/asaskevich/govalidator/types.go b/vendor/github.com/asaskevich/govalidator/types.go
new file mode 100644
index 000000000000..c573abb51aff
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/types.go
@@ -0,0 +1,656 @@
+package govalidator
+
+import (
+ "reflect"
+ "regexp"
+ "sort"
+ "sync"
+)
+
+// Validator is a wrapper for a validator function that returns bool and accepts string.
+type Validator func(str string) bool
+
+// CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type.
+// The second parameter should be the context (in the case of validating a struct: the whole object being validated).
+type CustomTypeValidator func(i interface{}, o interface{}) bool
+
+// ParamValidator is a wrapper for validator functions that accept additional parameters.
+type ParamValidator func(str string, params ...string) bool
+
+// InterfaceParamValidator is a wrapper for functions that accept variants parameters for an interface value
+type InterfaceParamValidator func(in interface{}, params ...string) bool
+type tagOptionsMap map[string]tagOption
+
+func (t tagOptionsMap) orderedKeys() []string {
+ var keys []string
+ for k := range t {
+ keys = append(keys, k)
+ }
+
+ sort.Slice(keys, func(a, b int) bool {
+ return t[keys[a]].order < t[keys[b]].order
+ })
+
+ return keys
+}
+
+type tagOption struct {
+ name string
+ customErrorMessage string
+ order int
+}
+
+// UnsupportedTypeError is a wrapper for reflect.Type
+type UnsupportedTypeError struct {
+ Type reflect.Type
+}
+
+// stringValues is a slice of reflect.Value holding *reflect.StringValue.
+// It implements the methods to sort by string.
+type stringValues []reflect.Value
+
+// InterfaceParamTagMap is a map of functions accept variants parameters for an interface value
+var InterfaceParamTagMap = map[string]InterfaceParamValidator{
+ "type": IsType,
+}
+
+// InterfaceParamTagRegexMap maps interface param tags to their respective regexes.
+var InterfaceParamTagRegexMap = map[string]*regexp.Regexp{
+ "type": regexp.MustCompile(`^type\((.*)\)$`),
+}
+
+// ParamTagMap is a map of functions accept variants parameters
+var ParamTagMap = map[string]ParamValidator{
+ "length": ByteLength,
+ "range": Range,
+ "runelength": RuneLength,
+ "stringlength": StringLength,
+ "matches": StringMatches,
+ "in": IsInRaw,
+ "rsapub": IsRsaPub,
+ "minstringlength": MinStringLength,
+ "maxstringlength": MaxStringLength,
+}
+
+// ParamTagRegexMap maps param tags to their respective regexes.
+var ParamTagRegexMap = map[string]*regexp.Regexp{
+ "range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"),
+ "length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"),
+ "runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"),
+ "stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
+ "in": regexp.MustCompile(`^in\((.*)\)`),
+ "matches": regexp.MustCompile(`^matches\((.+)\)$`),
+ "rsapub": regexp.MustCompile("^rsapub\\((\\d+)\\)$"),
+ "minstringlength": regexp.MustCompile("^minstringlength\\((\\d+)\\)$"),
+ "maxstringlength": regexp.MustCompile("^maxstringlength\\((\\d+)\\)$"),
+}
+
+type customTypeTagMap struct {
+ validators map[string]CustomTypeValidator
+
+ sync.RWMutex
+}
+
+func (tm *customTypeTagMap) Get(name string) (CustomTypeValidator, bool) {
+ tm.RLock()
+ defer tm.RUnlock()
+ v, ok := tm.validators[name]
+ return v, ok
+}
+
+func (tm *customTypeTagMap) Set(name string, ctv CustomTypeValidator) {
+ tm.Lock()
+ defer tm.Unlock()
+ tm.validators[name] = ctv
+}
+
+// CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function.
+// Use this to validate compound or custom types that need to be handled as a whole, e.g.
+// `type UUID [16]byte` (this would be handled as an array of bytes).
+var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeValidator)}
+
+// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
+var TagMap = map[string]Validator{
+ "email": IsEmail,
+ "url": IsURL,
+ "dialstring": IsDialString,
+ "requrl": IsRequestURL,
+ "requri": IsRequestURI,
+ "alpha": IsAlpha,
+ "utfletter": IsUTFLetter,
+ "alphanum": IsAlphanumeric,
+ "utfletternum": IsUTFLetterNumeric,
+ "numeric": IsNumeric,
+ "utfnumeric": IsUTFNumeric,
+ "utfdigit": IsUTFDigit,
+ "hexadecimal": IsHexadecimal,
+ "hexcolor": IsHexcolor,
+ "rgbcolor": IsRGBcolor,
+ "lowercase": IsLowerCase,
+ "uppercase": IsUpperCase,
+ "int": IsInt,
+ "float": IsFloat,
+ "null": IsNull,
+ "notnull": IsNotNull,
+ "uuid": IsUUID,
+ "uuidv3": IsUUIDv3,
+ "uuidv4": IsUUIDv4,
+ "uuidv5": IsUUIDv5,
+ "creditcard": IsCreditCard,
+ "isbn10": IsISBN10,
+ "isbn13": IsISBN13,
+ "json": IsJSON,
+ "multibyte": IsMultibyte,
+ "ascii": IsASCII,
+ "printableascii": IsPrintableASCII,
+ "fullwidth": IsFullWidth,
+ "halfwidth": IsHalfWidth,
+ "variablewidth": IsVariableWidth,
+ "base64": IsBase64,
+ "datauri": IsDataURI,
+ "ip": IsIP,
+ "port": IsPort,
+ "ipv4": IsIPv4,
+ "ipv6": IsIPv6,
+ "dns": IsDNSName,
+ "host": IsHost,
+ "mac": IsMAC,
+ "latitude": IsLatitude,
+ "longitude": IsLongitude,
+ "ssn": IsSSN,
+ "semver": IsSemver,
+ "rfc3339": IsRFC3339,
+ "rfc3339WithoutZone": IsRFC3339WithoutZone,
+ "ISO3166Alpha2": IsISO3166Alpha2,
+ "ISO3166Alpha3": IsISO3166Alpha3,
+ "ISO4217": IsISO4217,
+ "IMEI": IsIMEI,
+ "ulid": IsULID,
+}
+
+// ISO3166Entry stores country codes
+type ISO3166Entry struct {
+ EnglishShortName string
+ FrenchShortName string
+ Alpha2Code string
+ Alpha3Code string
+ Numeric string
+}
+
+//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes"
+var ISO3166List = []ISO3166Entry{
+ {"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"},
+ {"Albania", "Albanie (l')", "AL", "ALB", "008"},
+ {"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"},
+ {"Algeria", "Algérie (l')", "DZ", "DZA", "012"},
+ {"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"},
+ {"Andorra", "Andorre (l')", "AD", "AND", "020"},
+ {"Angola", "Angola (l')", "AO", "AGO", "024"},
+ {"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"},
+ {"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"},
+ {"Argentina", "Argentine (l')", "AR", "ARG", "032"},
+ {"Australia", "Australie (l')", "AU", "AUS", "036"},
+ {"Austria", "Autriche (l')", "AT", "AUT", "040"},
+ {"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"},
+ {"Bahrain", "Bahreïn", "BH", "BHR", "048"},
+ {"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"},
+ {"Armenia", "Arménie (l')", "AM", "ARM", "051"},
+ {"Barbados", "Barbade (la)", "BB", "BRB", "052"},
+ {"Belgium", "Belgique (la)", "BE", "BEL", "056"},
+ {"Bermuda", "Bermudes (les)", "BM", "BMU", "060"},
+ {"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"},
+ {"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"},
+ {"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"},
+ {"Botswana", "Botswana (le)", "BW", "BWA", "072"},
+ {"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"},
+ {"Brazil", "Brésil (le)", "BR", "BRA", "076"},
+ {"Belize", "Belize (le)", "BZ", "BLZ", "084"},
+ {"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"},
+ {"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"},
+ {"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"},
+ {"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"},
+ {"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"},
+ {"Myanmar", "Myanmar (le)", "MM", "MMR", "104"},
+ {"Burundi", "Burundi (le)", "BI", "BDI", "108"},
+ {"Belarus", "Bélarus (le)", "BY", "BLR", "112"},
+ {"Cambodia", "Cambodge (le)", "KH", "KHM", "116"},
+ {"Cameroon", "Cameroun (le)", "CM", "CMR", "120"},
+ {"Canada", "Canada (le)", "CA", "CAN", "124"},
+ {"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"},
+ {"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"},
+ {"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"},
+ {"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"},
+ {"Chad", "Tchad (le)", "TD", "TCD", "148"},
+ {"Chile", "Chili (le)", "CL", "CHL", "152"},
+ {"China", "Chine (la)", "CN", "CHN", "156"},
+ {"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"},
+ {"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"},
+ {"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"},
+ {"Colombia", "Colombie (la)", "CO", "COL", "170"},
+ {"Comoros (the)", "Comores (les)", "KM", "COM", "174"},
+ {"Mayotte", "Mayotte", "YT", "MYT", "175"},
+ {"Congo (the)", "Congo (le)", "CG", "COG", "178"},
+ {"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"},
+ {"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"},
+ {"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"},
+ {"Croatia", "Croatie (la)", "HR", "HRV", "191"},
+ {"Cuba", "Cuba", "CU", "CUB", "192"},
+ {"Cyprus", "Chypre", "CY", "CYP", "196"},
+ {"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"},
+ {"Benin", "Bénin (le)", "BJ", "BEN", "204"},
+ {"Denmark", "Danemark (le)", "DK", "DNK", "208"},
+ {"Dominica", "Dominique (la)", "DM", "DMA", "212"},
+ {"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"},
+ {"Ecuador", "Équateur (l')", "EC", "ECU", "218"},
+ {"El Salvador", "El Salvador", "SV", "SLV", "222"},
+ {"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"},
+ {"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"},
+ {"Eritrea", "Érythrée (l')", "ER", "ERI", "232"},
+ {"Estonia", "Estonie (l')", "EE", "EST", "233"},
+ {"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"},
+ {"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"},
+ {"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"},
+ {"Fiji", "Fidji (les)", "FJ", "FJI", "242"},
+ {"Finland", "Finlande (la)", "FI", "FIN", "246"},
+ {"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"},
+ {"France", "France (la)", "FR", "FRA", "250"},
+ {"French Guiana", "Guyane française (la )", "GF", "GUF", "254"},
+ {"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"},
+ {"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"},
+ {"Djibouti", "Djibouti", "DJ", "DJI", "262"},
+ {"Gabon", "Gabon (le)", "GA", "GAB", "266"},
+ {"Georgia", "Géorgie (la)", "GE", "GEO", "268"},
+ {"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"},
+ {"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"},
+ {"Germany", "Allemagne (l')", "DE", "DEU", "276"},
+ {"Ghana", "Ghana (le)", "GH", "GHA", "288"},
+ {"Gibraltar", "Gibraltar", "GI", "GIB", "292"},
+ {"Kiribati", "Kiribati", "KI", "KIR", "296"},
+ {"Greece", "Grèce (la)", "GR", "GRC", "300"},
+ {"Greenland", "Groenland (le)", "GL", "GRL", "304"},
+ {"Grenada", "Grenade (la)", "GD", "GRD", "308"},
+ {"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"},
+ {"Guam", "Guam", "GU", "GUM", "316"},
+ {"Guatemala", "Guatemala (le)", "GT", "GTM", "320"},
+ {"Guinea", "Guinée (la)", "GN", "GIN", "324"},
+ {"Guyana", "Guyana (le)", "GY", "GUY", "328"},
+ {"Haiti", "Haïti", "HT", "HTI", "332"},
+ {"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"},
+ {"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"},
+ {"Honduras", "Honduras (le)", "HN", "HND", "340"},
+ {"Hong Kong", "Hong Kong", "HK", "HKG", "344"},
+ {"Hungary", "Hongrie (la)", "HU", "HUN", "348"},
+ {"Iceland", "Islande (l')", "IS", "ISL", "352"},
+ {"India", "Inde (l')", "IN", "IND", "356"},
+ {"Indonesia", "Indonésie (l')", "ID", "IDN", "360"},
+ {"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"},
+ {"Iraq", "Iraq (l')", "IQ", "IRQ", "368"},
+ {"Ireland", "Irlande (l')", "IE", "IRL", "372"},
+ {"Israel", "Israël", "IL", "ISR", "376"},
+ {"Italy", "Italie (l')", "IT", "ITA", "380"},
+ {"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"},
+ {"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"},
+ {"Japan", "Japon (le)", "JP", "JPN", "392"},
+ {"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"},
+ {"Jordan", "Jordanie (la)", "JO", "JOR", "400"},
+ {"Kenya", "Kenya (le)", "KE", "KEN", "404"},
+ {"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"},
+ {"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"},
+ {"Kuwait", "Koweït (le)", "KW", "KWT", "414"},
+ {"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"},
+ {"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"},
+ {"Lebanon", "Liban (le)", "LB", "LBN", "422"},
+ {"Lesotho", "Lesotho (le)", "LS", "LSO", "426"},
+ {"Latvia", "Lettonie (la)", "LV", "LVA", "428"},
+ {"Liberia", "Libéria (le)", "LR", "LBR", "430"},
+ {"Libya", "Libye (la)", "LY", "LBY", "434"},
+ {"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"},
+ {"Lithuania", "Lituanie (la)", "LT", "LTU", "440"},
+ {"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"},
+ {"Macao", "Macao", "MO", "MAC", "446"},
+ {"Madagascar", "Madagascar", "MG", "MDG", "450"},
+ {"Malawi", "Malawi (le)", "MW", "MWI", "454"},
+ {"Malaysia", "Malaisie (la)", "MY", "MYS", "458"},
+ {"Maldives", "Maldives (les)", "MV", "MDV", "462"},
+ {"Mali", "Mali (le)", "ML", "MLI", "466"},
+ {"Malta", "Malte", "MT", "MLT", "470"},
+ {"Martinique", "Martinique (la)", "MQ", "MTQ", "474"},
+ {"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"},
+ {"Mauritius", "Maurice", "MU", "MUS", "480"},
+ {"Mexico", "Mexique (le)", "MX", "MEX", "484"},
+ {"Monaco", "Monaco", "MC", "MCO", "492"},
+ {"Mongolia", "Mongolie (la)", "MN", "MNG", "496"},
+ {"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"},
+ {"Montenegro", "Monténégro (le)", "ME", "MNE", "499"},
+ {"Montserrat", "Montserrat", "MS", "MSR", "500"},
+ {"Morocco", "Maroc (le)", "MA", "MAR", "504"},
+ {"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"},
+ {"Oman", "Oman", "OM", "OMN", "512"},
+ {"Namibia", "Namibie (la)", "NA", "NAM", "516"},
+ {"Nauru", "Nauru", "NR", "NRU", "520"},
+ {"Nepal", "Népal (le)", "NP", "NPL", "524"},
+ {"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"},
+ {"Curaçao", "Curaçao", "CW", "CUW", "531"},
+ {"Aruba", "Aruba", "AW", "ABW", "533"},
+ {"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"},
+ {"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"},
+ {"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"},
+ {"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"},
+ {"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"},
+ {"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"},
+ {"Niger (the)", "Niger (le)", "NE", "NER", "562"},
+ {"Nigeria", "Nigéria (le)", "NG", "NGA", "566"},
+ {"Niue", "Niue", "NU", "NIU", "570"},
+ {"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"},
+ {"Norway", "Norvège (la)", "NO", "NOR", "578"},
+ {"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"},
+ {"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"},
+ {"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"},
+ {"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"},
+ {"Palau", "Palaos (les)", "PW", "PLW", "585"},
+ {"Pakistan", "Pakistan (le)", "PK", "PAK", "586"},
+ {"Panama", "Panama (le)", "PA", "PAN", "591"},
+ {"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"},
+ {"Paraguay", "Paraguay (le)", "PY", "PRY", "600"},
+ {"Peru", "Pérou (le)", "PE", "PER", "604"},
+ {"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"},
+ {"Pitcairn", "Pitcairn", "PN", "PCN", "612"},
+ {"Poland", "Pologne (la)", "PL", "POL", "616"},
+ {"Portugal", "Portugal (le)", "PT", "PRT", "620"},
+ {"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"},
+ {"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"},
+ {"Puerto Rico", "Porto Rico", "PR", "PRI", "630"},
+ {"Qatar", "Qatar (le)", "QA", "QAT", "634"},
+ {"Réunion", "Réunion (La)", "RE", "REU", "638"},
+ {"Romania", "Roumanie (la)", "RO", "ROU", "642"},
+ {"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"},
+ {"Rwanda", "Rwanda (le)", "RW", "RWA", "646"},
+ {"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"},
+ {"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"},
+ {"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"},
+ {"Anguilla", "Anguilla", "AI", "AIA", "660"},
+ {"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"},
+ {"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"},
+ {"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"},
+ {"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"},
+ {"San Marino", "Saint-Marin", "SM", "SMR", "674"},
+ {"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"},
+ {"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"},
+ {"Senegal", "Sénégal (le)", "SN", "SEN", "686"},
+ {"Serbia", "Serbie (la)", "RS", "SRB", "688"},
+ {"Seychelles", "Seychelles (les)", "SC", "SYC", "690"},
+ {"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"},
+ {"Singapore", "Singapour", "SG", "SGP", "702"},
+ {"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"},
+ {"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"},
+ {"Slovenia", "Slovénie (la)", "SI", "SVN", "705"},
+ {"Somalia", "Somalie (la)", "SO", "SOM", "706"},
+ {"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"},
+ {"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"},
+ {"Spain", "Espagne (l')", "ES", "ESP", "724"},
+ {"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"},
+ {"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"},
+ {"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"},
+ {"Suriname", "Suriname (le)", "SR", "SUR", "740"},
+ {"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"},
+ {"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"},
+ {"Sweden", "Suède (la)", "SE", "SWE", "752"},
+ {"Switzerland", "Suisse (la)", "CH", "CHE", "756"},
+ {"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"},
+ {"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"},
+ {"Thailand", "Thaïlande (la)", "TH", "THA", "764"},
+ {"Togo", "Togo (le)", "TG", "TGO", "768"},
+ {"Tokelau", "Tokelau (les)", "TK", "TKL", "772"},
+ {"Tonga", "Tonga (les)", "TO", "TON", "776"},
+ {"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"},
+ {"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"},
+ {"Tunisia", "Tunisie (la)", "TN", "TUN", "788"},
+ {"Turkey", "Turquie (la)", "TR", "TUR", "792"},
+ {"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"},
+ {"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"},
+ {"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"},
+ {"Uganda", "Ouganda (l')", "UG", "UGA", "800"},
+ {"Ukraine", "Ukraine (l')", "UA", "UKR", "804"},
+ {"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'ex‑République yougoslave de)", "MK", "MKD", "807"},
+ {"Egypt", "Égypte (l')", "EG", "EGY", "818"},
+ {"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"},
+ {"Guernsey", "Guernesey", "GG", "GGY", "831"},
+ {"Jersey", "Jersey", "JE", "JEY", "832"},
+ {"Isle of Man", "Île de Man", "IM", "IMN", "833"},
+ {"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"},
+ {"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"},
+ {"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"},
+ {"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"},
+ {"Uruguay", "Uruguay (l')", "UY", "URY", "858"},
+ {"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"},
+ {"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"},
+ {"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"},
+ {"Samoa", "Samoa (le)", "WS", "WSM", "882"},
+ {"Yemen", "Yémen (le)", "YE", "YEM", "887"},
+ {"Zambia", "Zambie (la)", "ZM", "ZMB", "894"},
+}
+
+// ISO4217List is the list of ISO currency codes
+var ISO4217List = []string{
+ "AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN",
+ "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD",
+ "CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK",
+ "DJF", "DKK", "DOP", "DZD",
+ "EGP", "ERN", "ETB", "EUR",
+ "FJD", "FKP",
+ "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD",
+ "HKD", "HNL", "HRK", "HTG", "HUF",
+ "IDR", "ILS", "INR", "IQD", "IRR", "ISK",
+ "JMD", "JOD", "JPY",
+ "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT",
+ "LAK", "LBP", "LKR", "LRD", "LSL", "LYD",
+ "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN",
+ "NAD", "NGN", "NIO", "NOK", "NPR", "NZD",
+ "OMR",
+ "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG",
+ "QAR",
+ "RON", "RSD", "RUB", "RWF",
+ "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "STN", "SVC", "SYP", "SZL",
+ "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS",
+ "UAH", "UGX", "USD", "USN", "UYI", "UYU", "UYW", "UZS",
+ "VEF", "VES", "VND", "VUV",
+ "WST",
+ "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX",
+ "YER",
+ "ZAR", "ZMW", "ZWL",
+}
+
+// ISO693Entry stores ISO language codes
+type ISO693Entry struct {
+ Alpha3bCode string
+ Alpha2Code string
+ English string
+}
+
+//ISO693List based on http://data.okfn.org/data/core/language-codes/r/language-codes-3b2.json
+var ISO693List = []ISO693Entry{
+ {Alpha3bCode: "aar", Alpha2Code: "aa", English: "Afar"},
+ {Alpha3bCode: "abk", Alpha2Code: "ab", English: "Abkhazian"},
+ {Alpha3bCode: "afr", Alpha2Code: "af", English: "Afrikaans"},
+ {Alpha3bCode: "aka", Alpha2Code: "ak", English: "Akan"},
+ {Alpha3bCode: "alb", Alpha2Code: "sq", English: "Albanian"},
+ {Alpha3bCode: "amh", Alpha2Code: "am", English: "Amharic"},
+ {Alpha3bCode: "ara", Alpha2Code: "ar", English: "Arabic"},
+ {Alpha3bCode: "arg", Alpha2Code: "an", English: "Aragonese"},
+ {Alpha3bCode: "arm", Alpha2Code: "hy", English: "Armenian"},
+ {Alpha3bCode: "asm", Alpha2Code: "as", English: "Assamese"},
+ {Alpha3bCode: "ava", Alpha2Code: "av", English: "Avaric"},
+ {Alpha3bCode: "ave", Alpha2Code: "ae", English: "Avestan"},
+ {Alpha3bCode: "aym", Alpha2Code: "ay", English: "Aymara"},
+ {Alpha3bCode: "aze", Alpha2Code: "az", English: "Azerbaijani"},
+ {Alpha3bCode: "bak", Alpha2Code: "ba", English: "Bashkir"},
+ {Alpha3bCode: "bam", Alpha2Code: "bm", English: "Bambara"},
+ {Alpha3bCode: "baq", Alpha2Code: "eu", English: "Basque"},
+ {Alpha3bCode: "bel", Alpha2Code: "be", English: "Belarusian"},
+ {Alpha3bCode: "ben", Alpha2Code: "bn", English: "Bengali"},
+ {Alpha3bCode: "bih", Alpha2Code: "bh", English: "Bihari languages"},
+ {Alpha3bCode: "bis", Alpha2Code: "bi", English: "Bislama"},
+ {Alpha3bCode: "bos", Alpha2Code: "bs", English: "Bosnian"},
+ {Alpha3bCode: "bre", Alpha2Code: "br", English: "Breton"},
+ {Alpha3bCode: "bul", Alpha2Code: "bg", English: "Bulgarian"},
+ {Alpha3bCode: "bur", Alpha2Code: "my", English: "Burmese"},
+ {Alpha3bCode: "cat", Alpha2Code: "ca", English: "Catalan; Valencian"},
+ {Alpha3bCode: "cha", Alpha2Code: "ch", English: "Chamorro"},
+ {Alpha3bCode: "che", Alpha2Code: "ce", English: "Chechen"},
+ {Alpha3bCode: "chi", Alpha2Code: "zh", English: "Chinese"},
+ {Alpha3bCode: "chu", Alpha2Code: "cu", English: "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic"},
+ {Alpha3bCode: "chv", Alpha2Code: "cv", English: "Chuvash"},
+ {Alpha3bCode: "cor", Alpha2Code: "kw", English: "Cornish"},
+ {Alpha3bCode: "cos", Alpha2Code: "co", English: "Corsican"},
+ {Alpha3bCode: "cre", Alpha2Code: "cr", English: "Cree"},
+ {Alpha3bCode: "cze", Alpha2Code: "cs", English: "Czech"},
+ {Alpha3bCode: "dan", Alpha2Code: "da", English: "Danish"},
+ {Alpha3bCode: "div", Alpha2Code: "dv", English: "Divehi; Dhivehi; Maldivian"},
+ {Alpha3bCode: "dut", Alpha2Code: "nl", English: "Dutch; Flemish"},
+ {Alpha3bCode: "dzo", Alpha2Code: "dz", English: "Dzongkha"},
+ {Alpha3bCode: "eng", Alpha2Code: "en", English: "English"},
+ {Alpha3bCode: "epo", Alpha2Code: "eo", English: "Esperanto"},
+ {Alpha3bCode: "est", Alpha2Code: "et", English: "Estonian"},
+ {Alpha3bCode: "ewe", Alpha2Code: "ee", English: "Ewe"},
+ {Alpha3bCode: "fao", Alpha2Code: "fo", English: "Faroese"},
+ {Alpha3bCode: "fij", Alpha2Code: "fj", English: "Fijian"},
+ {Alpha3bCode: "fin", Alpha2Code: "fi", English: "Finnish"},
+ {Alpha3bCode: "fre", Alpha2Code: "fr", English: "French"},
+ {Alpha3bCode: "fry", Alpha2Code: "fy", English: "Western Frisian"},
+ {Alpha3bCode: "ful", Alpha2Code: "ff", English: "Fulah"},
+ {Alpha3bCode: "geo", Alpha2Code: "ka", English: "Georgian"},
+ {Alpha3bCode: "ger", Alpha2Code: "de", English: "German"},
+ {Alpha3bCode: "gla", Alpha2Code: "gd", English: "Gaelic; Scottish Gaelic"},
+ {Alpha3bCode: "gle", Alpha2Code: "ga", English: "Irish"},
+ {Alpha3bCode: "glg", Alpha2Code: "gl", English: "Galician"},
+ {Alpha3bCode: "glv", Alpha2Code: "gv", English: "Manx"},
+ {Alpha3bCode: "gre", Alpha2Code: "el", English: "Greek, Modern (1453-)"},
+ {Alpha3bCode: "grn", Alpha2Code: "gn", English: "Guarani"},
+ {Alpha3bCode: "guj", Alpha2Code: "gu", English: "Gujarati"},
+ {Alpha3bCode: "hat", Alpha2Code: "ht", English: "Haitian; Haitian Creole"},
+ {Alpha3bCode: "hau", Alpha2Code: "ha", English: "Hausa"},
+ {Alpha3bCode: "heb", Alpha2Code: "he", English: "Hebrew"},
+ {Alpha3bCode: "her", Alpha2Code: "hz", English: "Herero"},
+ {Alpha3bCode: "hin", Alpha2Code: "hi", English: "Hindi"},
+ {Alpha3bCode: "hmo", Alpha2Code: "ho", English: "Hiri Motu"},
+ {Alpha3bCode: "hrv", Alpha2Code: "hr", English: "Croatian"},
+ {Alpha3bCode: "hun", Alpha2Code: "hu", English: "Hungarian"},
+ {Alpha3bCode: "ibo", Alpha2Code: "ig", English: "Igbo"},
+ {Alpha3bCode: "ice", Alpha2Code: "is", English: "Icelandic"},
+ {Alpha3bCode: "ido", Alpha2Code: "io", English: "Ido"},
+ {Alpha3bCode: "iii", Alpha2Code: "ii", English: "Sichuan Yi; Nuosu"},
+ {Alpha3bCode: "iku", Alpha2Code: "iu", English: "Inuktitut"},
+ {Alpha3bCode: "ile", Alpha2Code: "ie", English: "Interlingue; Occidental"},
+ {Alpha3bCode: "ina", Alpha2Code: "ia", English: "Interlingua (International Auxiliary Language Association)"},
+ {Alpha3bCode: "ind", Alpha2Code: "id", English: "Indonesian"},
+ {Alpha3bCode: "ipk", Alpha2Code: "ik", English: "Inupiaq"},
+ {Alpha3bCode: "ita", Alpha2Code: "it", English: "Italian"},
+ {Alpha3bCode: "jav", Alpha2Code: "jv", English: "Javanese"},
+ {Alpha3bCode: "jpn", Alpha2Code: "ja", English: "Japanese"},
+ {Alpha3bCode: "kal", Alpha2Code: "kl", English: "Kalaallisut; Greenlandic"},
+ {Alpha3bCode: "kan", Alpha2Code: "kn", English: "Kannada"},
+ {Alpha3bCode: "kas", Alpha2Code: "ks", English: "Kashmiri"},
+ {Alpha3bCode: "kau", Alpha2Code: "kr", English: "Kanuri"},
+ {Alpha3bCode: "kaz", Alpha2Code: "kk", English: "Kazakh"},
+ {Alpha3bCode: "khm", Alpha2Code: "km", English: "Central Khmer"},
+ {Alpha3bCode: "kik", Alpha2Code: "ki", English: "Kikuyu; Gikuyu"},
+ {Alpha3bCode: "kin", Alpha2Code: "rw", English: "Kinyarwanda"},
+ {Alpha3bCode: "kir", Alpha2Code: "ky", English: "Kirghiz; Kyrgyz"},
+ {Alpha3bCode: "kom", Alpha2Code: "kv", English: "Komi"},
+ {Alpha3bCode: "kon", Alpha2Code: "kg", English: "Kongo"},
+ {Alpha3bCode: "kor", Alpha2Code: "ko", English: "Korean"},
+ {Alpha3bCode: "kua", Alpha2Code: "kj", English: "Kuanyama; Kwanyama"},
+ {Alpha3bCode: "kur", Alpha2Code: "ku", English: "Kurdish"},
+ {Alpha3bCode: "lao", Alpha2Code: "lo", English: "Lao"},
+ {Alpha3bCode: "lat", Alpha2Code: "la", English: "Latin"},
+ {Alpha3bCode: "lav", Alpha2Code: "lv", English: "Latvian"},
+ {Alpha3bCode: "lim", Alpha2Code: "li", English: "Limburgan; Limburger; Limburgish"},
+ {Alpha3bCode: "lin", Alpha2Code: "ln", English: "Lingala"},
+ {Alpha3bCode: "lit", Alpha2Code: "lt", English: "Lithuanian"},
+ {Alpha3bCode: "ltz", Alpha2Code: "lb", English: "Luxembourgish; Letzeburgesch"},
+ {Alpha3bCode: "lub", Alpha2Code: "lu", English: "Luba-Katanga"},
+ {Alpha3bCode: "lug", Alpha2Code: "lg", English: "Ganda"},
+ {Alpha3bCode: "mac", Alpha2Code: "mk", English: "Macedonian"},
+ {Alpha3bCode: "mah", Alpha2Code: "mh", English: "Marshallese"},
+ {Alpha3bCode: "mal", Alpha2Code: "ml", English: "Malayalam"},
+ {Alpha3bCode: "mao", Alpha2Code: "mi", English: "Maori"},
+ {Alpha3bCode: "mar", Alpha2Code: "mr", English: "Marathi"},
+ {Alpha3bCode: "may", Alpha2Code: "ms", English: "Malay"},
+ {Alpha3bCode: "mlg", Alpha2Code: "mg", English: "Malagasy"},
+ {Alpha3bCode: "mlt", Alpha2Code: "mt", English: "Maltese"},
+ {Alpha3bCode: "mon", Alpha2Code: "mn", English: "Mongolian"},
+ {Alpha3bCode: "nau", Alpha2Code: "na", English: "Nauru"},
+ {Alpha3bCode: "nav", Alpha2Code: "nv", English: "Navajo; Navaho"},
+ {Alpha3bCode: "nbl", Alpha2Code: "nr", English: "Ndebele, South; South Ndebele"},
+ {Alpha3bCode: "nde", Alpha2Code: "nd", English: "Ndebele, North; North Ndebele"},
+ {Alpha3bCode: "ndo", Alpha2Code: "ng", English: "Ndonga"},
+ {Alpha3bCode: "nep", Alpha2Code: "ne", English: "Nepali"},
+ {Alpha3bCode: "nno", Alpha2Code: "nn", English: "Norwegian Nynorsk; Nynorsk, Norwegian"},
+ {Alpha3bCode: "nob", Alpha2Code: "nb", English: "Bokmål, Norwegian; Norwegian Bokmål"},
+ {Alpha3bCode: "nor", Alpha2Code: "no", English: "Norwegian"},
+ {Alpha3bCode: "nya", Alpha2Code: "ny", English: "Chichewa; Chewa; Nyanja"},
+ {Alpha3bCode: "oci", Alpha2Code: "oc", English: "Occitan (post 1500); Provençal"},
+ {Alpha3bCode: "oji", Alpha2Code: "oj", English: "Ojibwa"},
+ {Alpha3bCode: "ori", Alpha2Code: "or", English: "Oriya"},
+ {Alpha3bCode: "orm", Alpha2Code: "om", English: "Oromo"},
+ {Alpha3bCode: "oss", Alpha2Code: "os", English: "Ossetian; Ossetic"},
+ {Alpha3bCode: "pan", Alpha2Code: "pa", English: "Panjabi; Punjabi"},
+ {Alpha3bCode: "per", Alpha2Code: "fa", English: "Persian"},
+ {Alpha3bCode: "pli", Alpha2Code: "pi", English: "Pali"},
+ {Alpha3bCode: "pol", Alpha2Code: "pl", English: "Polish"},
+ {Alpha3bCode: "por", Alpha2Code: "pt", English: "Portuguese"},
+ {Alpha3bCode: "pus", Alpha2Code: "ps", English: "Pushto; Pashto"},
+ {Alpha3bCode: "que", Alpha2Code: "qu", English: "Quechua"},
+ {Alpha3bCode: "roh", Alpha2Code: "rm", English: "Romansh"},
+ {Alpha3bCode: "rum", Alpha2Code: "ro", English: "Romanian; Moldavian; Moldovan"},
+ {Alpha3bCode: "run", Alpha2Code: "rn", English: "Rundi"},
+ {Alpha3bCode: "rus", Alpha2Code: "ru", English: "Russian"},
+ {Alpha3bCode: "sag", Alpha2Code: "sg", English: "Sango"},
+ {Alpha3bCode: "san", Alpha2Code: "sa", English: "Sanskrit"},
+ {Alpha3bCode: "sin", Alpha2Code: "si", English: "Sinhala; Sinhalese"},
+ {Alpha3bCode: "slo", Alpha2Code: "sk", English: "Slovak"},
+ {Alpha3bCode: "slv", Alpha2Code: "sl", English: "Slovenian"},
+ {Alpha3bCode: "sme", Alpha2Code: "se", English: "Northern Sami"},
+ {Alpha3bCode: "smo", Alpha2Code: "sm", English: "Samoan"},
+ {Alpha3bCode: "sna", Alpha2Code: "sn", English: "Shona"},
+ {Alpha3bCode: "snd", Alpha2Code: "sd", English: "Sindhi"},
+ {Alpha3bCode: "som", Alpha2Code: "so", English: "Somali"},
+ {Alpha3bCode: "sot", Alpha2Code: "st", English: "Sotho, Southern"},
+ {Alpha3bCode: "spa", Alpha2Code: "es", English: "Spanish; Castilian"},
+ {Alpha3bCode: "srd", Alpha2Code: "sc", English: "Sardinian"},
+ {Alpha3bCode: "srp", Alpha2Code: "sr", English: "Serbian"},
+ {Alpha3bCode: "ssw", Alpha2Code: "ss", English: "Swati"},
+ {Alpha3bCode: "sun", Alpha2Code: "su", English: "Sundanese"},
+ {Alpha3bCode: "swa", Alpha2Code: "sw", English: "Swahili"},
+ {Alpha3bCode: "swe", Alpha2Code: "sv", English: "Swedish"},
+ {Alpha3bCode: "tah", Alpha2Code: "ty", English: "Tahitian"},
+ {Alpha3bCode: "tam", Alpha2Code: "ta", English: "Tamil"},
+ {Alpha3bCode: "tat", Alpha2Code: "tt", English: "Tatar"},
+ {Alpha3bCode: "tel", Alpha2Code: "te", English: "Telugu"},
+ {Alpha3bCode: "tgk", Alpha2Code: "tg", English: "Tajik"},
+ {Alpha3bCode: "tgl", Alpha2Code: "tl", English: "Tagalog"},
+ {Alpha3bCode: "tha", Alpha2Code: "th", English: "Thai"},
+ {Alpha3bCode: "tib", Alpha2Code: "bo", English: "Tibetan"},
+ {Alpha3bCode: "tir", Alpha2Code: "ti", English: "Tigrinya"},
+ {Alpha3bCode: "ton", Alpha2Code: "to", English: "Tonga (Tonga Islands)"},
+ {Alpha3bCode: "tsn", Alpha2Code: "tn", English: "Tswana"},
+ {Alpha3bCode: "tso", Alpha2Code: "ts", English: "Tsonga"},
+ {Alpha3bCode: "tuk", Alpha2Code: "tk", English: "Turkmen"},
+ {Alpha3bCode: "tur", Alpha2Code: "tr", English: "Turkish"},
+ {Alpha3bCode: "twi", Alpha2Code: "tw", English: "Twi"},
+ {Alpha3bCode: "uig", Alpha2Code: "ug", English: "Uighur; Uyghur"},
+ {Alpha3bCode: "ukr", Alpha2Code: "uk", English: "Ukrainian"},
+ {Alpha3bCode: "urd", Alpha2Code: "ur", English: "Urdu"},
+ {Alpha3bCode: "uzb", Alpha2Code: "uz", English: "Uzbek"},
+ {Alpha3bCode: "ven", Alpha2Code: "ve", English: "Venda"},
+ {Alpha3bCode: "vie", Alpha2Code: "vi", English: "Vietnamese"},
+ {Alpha3bCode: "vol", Alpha2Code: "vo", English: "Volapük"},
+ {Alpha3bCode: "wel", Alpha2Code: "cy", English: "Welsh"},
+ {Alpha3bCode: "wln", Alpha2Code: "wa", English: "Walloon"},
+ {Alpha3bCode: "wol", Alpha2Code: "wo", English: "Wolof"},
+ {Alpha3bCode: "xho", Alpha2Code: "xh", English: "Xhosa"},
+ {Alpha3bCode: "yid", Alpha2Code: "yi", English: "Yiddish"},
+ {Alpha3bCode: "yor", Alpha2Code: "yo", English: "Yoruba"},
+ {Alpha3bCode: "zha", Alpha2Code: "za", English: "Zhuang; Chuang"},
+ {Alpha3bCode: "zul", Alpha2Code: "zu", English: "Zulu"},
+}
diff --git a/vendor/github.com/asaskevich/govalidator/utils.go b/vendor/github.com/asaskevich/govalidator/utils.go
new file mode 100644
index 000000000000..f4c30f824a22
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/utils.go
@@ -0,0 +1,270 @@
+package govalidator
+
+import (
+ "errors"
+ "fmt"
+ "html"
+ "math"
+ "path"
+ "regexp"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// Contains checks if the string contains the substring.
+func Contains(str, substring string) bool {
+ return strings.Contains(str, substring)
+}
+
+// Matches checks if string matches the pattern (pattern is regular expression)
+// In case of error return false
+func Matches(str, pattern string) bool {
+ match, _ := regexp.MatchString(pattern, str)
+ return match
+}
+
+// LeftTrim trims characters from the left side of the input.
+// If second argument is empty, it will remove leading spaces.
+func LeftTrim(str, chars string) string {
+ if chars == "" {
+ return strings.TrimLeftFunc(str, unicode.IsSpace)
+ }
+ r, _ := regexp.Compile("^[" + chars + "]+")
+ return r.ReplaceAllString(str, "")
+}
+
+// RightTrim trims characters from the right side of the input.
+// If second argument is empty, it will remove trailing spaces.
+func RightTrim(str, chars string) string {
+ if chars == "" {
+ return strings.TrimRightFunc(str, unicode.IsSpace)
+ }
+ r, _ := regexp.Compile("[" + chars + "]+$")
+ return r.ReplaceAllString(str, "")
+}
+
+// Trim trims characters from both sides of the input.
+// If second argument is empty, it will remove spaces.
+func Trim(str, chars string) string {
+ return LeftTrim(RightTrim(str, chars), chars)
+}
+
+// WhiteList removes characters that do not appear in the whitelist.
+func WhiteList(str, chars string) string {
+ pattern := "[^" + chars + "]+"
+ r, _ := regexp.Compile(pattern)
+ return r.ReplaceAllString(str, "")
+}
+
+// BlackList removes characters that appear in the blacklist.
+func BlackList(str, chars string) string {
+ pattern := "[" + chars + "]+"
+ r, _ := regexp.Compile(pattern)
+ return r.ReplaceAllString(str, "")
+}
+
+// StripLow removes characters with a numerical value < 32 and 127, mostly control characters.
+// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
+func StripLow(str string, keepNewLines bool) string {
+ chars := ""
+ if keepNewLines {
+ chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
+ } else {
+ chars = "\x00-\x1F\x7F"
+ }
+ return BlackList(str, chars)
+}
+
+// ReplacePattern replaces regular expression pattern in string
+func ReplacePattern(str, pattern, replace string) string {
+ r, _ := regexp.Compile(pattern)
+ return r.ReplaceAllString(str, replace)
+}
+
+// Escape replaces <, >, & and " with HTML entities.
+var Escape = html.EscapeString
+
+func addSegment(inrune, segment []rune) []rune {
+ if len(segment) == 0 {
+ return inrune
+ }
+ if len(inrune) != 0 {
+ inrune = append(inrune, '_')
+ }
+ inrune = append(inrune, segment...)
+ return inrune
+}
+
+// UnderscoreToCamelCase converts from underscore separated form to camel case form.
+// Ex.: my_func => MyFunc
+func UnderscoreToCamelCase(s string) string {
+ return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
+}
+
+// CamelCaseToUnderscore converts from camel case form to underscore separated form.
+// Ex.: MyFunc => my_func
+func CamelCaseToUnderscore(str string) string {
+ var output []rune
+ var segment []rune
+ for _, r := range str {
+
+ // not treat number as separate segment
+ if !unicode.IsLower(r) && string(r) != "_" && !unicode.IsNumber(r) {
+ output = addSegment(output, segment)
+ segment = nil
+ }
+ segment = append(segment, unicode.ToLower(r))
+ }
+ output = addSegment(output, segment)
+ return string(output)
+}
+
+// Reverse returns reversed string
+func Reverse(s string) string {
+ r := []rune(s)
+ for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
+ r[i], r[j] = r[j], r[i]
+ }
+ return string(r)
+}
+
+// GetLines splits string by "\n" and return array of lines
+func GetLines(s string) []string {
+ return strings.Split(s, "\n")
+}
+
+// GetLine returns specified line of multiline string
+func GetLine(s string, index int) (string, error) {
+ lines := GetLines(s)
+ if index < 0 || index >= len(lines) {
+ return "", errors.New("line index out of bounds")
+ }
+ return lines[index], nil
+}
+
+// RemoveTags removes all tags from HTML string
+func RemoveTags(s string) string {
+ return ReplacePattern(s, "<[^>]*>", "")
+}
+
+// SafeFileName returns safe string that can be used in file names
+func SafeFileName(str string) string {
+ name := strings.ToLower(str)
+ name = path.Clean(path.Base(name))
+ name = strings.Trim(name, " ")
+ separators, err := regexp.Compile(`[ &_=+:]`)
+ if err == nil {
+ name = separators.ReplaceAllString(name, "-")
+ }
+ legal, err := regexp.Compile(`[^[:alnum:]-.]`)
+ if err == nil {
+ name = legal.ReplaceAllString(name, "")
+ }
+ for strings.Contains(name, "--") {
+ name = strings.Replace(name, "--", "-", -1)
+ }
+ return name
+}
+
+// NormalizeEmail canonicalize an email address.
+// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
+// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
+// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
+// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
+// normalized to @gmail.com.
+func NormalizeEmail(str string) (string, error) {
+ if !IsEmail(str) {
+ return "", fmt.Errorf("%s is not an email", str)
+ }
+ parts := strings.Split(str, "@")
+ parts[0] = strings.ToLower(parts[0])
+ parts[1] = strings.ToLower(parts[1])
+ if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
+ parts[1] = "gmail.com"
+ parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
+ }
+ return strings.Join(parts, "@"), nil
+}
+
+// Truncate a string to the closest length without breaking words.
+func Truncate(str string, length int, ending string) string {
+ var aftstr, befstr string
+ if len(str) > length {
+ words := strings.Fields(str)
+ before, present := 0, 0
+ for i := range words {
+ befstr = aftstr
+ before = present
+ aftstr = aftstr + words[i] + " "
+ present = len(aftstr)
+ if present > length && i != 0 {
+ if (length - before) < (present - length) {
+ return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
+ }
+ return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
+ }
+ }
+ }
+
+ return str
+}
+
+// PadLeft pads left side of a string if size of string is less then indicated pad length
+func PadLeft(str string, padStr string, padLen int) string {
+ return buildPadStr(str, padStr, padLen, true, false)
+}
+
+// PadRight pads right side of a string if size of string is less then indicated pad length
+func PadRight(str string, padStr string, padLen int) string {
+ return buildPadStr(str, padStr, padLen, false, true)
+}
+
+// PadBoth pads both sides of a string if size of string is less then indicated pad length
+func PadBoth(str string, padStr string, padLen int) string {
+ return buildPadStr(str, padStr, padLen, true, true)
+}
+
+// PadString either left, right or both sides.
+// Note that padding string can be unicode and more then one character
+func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string {
+
+ // When padded length is less then the current string size
+ if padLen < utf8.RuneCountInString(str) {
+ return str
+ }
+
+ padLen -= utf8.RuneCountInString(str)
+
+ targetLen := padLen
+
+ targetLenLeft := targetLen
+ targetLenRight := targetLen
+ if padLeft && padRight {
+ targetLenLeft = padLen / 2
+ targetLenRight = padLen - targetLenLeft
+ }
+
+ strToRepeatLen := utf8.RuneCountInString(padStr)
+
+ repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen)))
+ repeatedString := strings.Repeat(padStr, repeatTimes)
+
+ leftSide := ""
+ if padLeft {
+ leftSide = repeatedString[0:targetLenLeft]
+ }
+
+ rightSide := ""
+ if padRight {
+ rightSide = repeatedString[0:targetLenRight]
+ }
+
+ return leftSide + str + rightSide
+}
+
+// TruncatingErrorf removes extra args from fmt.Errorf if not formatted in the str object
+func TruncatingErrorf(str string, args ...interface{}) error {
+ n := strings.Count(str, "%s")
+ return fmt.Errorf(str, args[:n]...)
+}
diff --git a/vendor/github.com/asaskevich/govalidator/validator.go b/vendor/github.com/asaskevich/govalidator/validator.go
new file mode 100644
index 000000000000..c9c4fac0655a
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/validator.go
@@ -0,0 +1,1768 @@
+// Package govalidator is package of validators and sanitizers for strings, structs and collections.
+package govalidator
+
+import (
+ "bytes"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/json"
+ "encoding/pem"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/url"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+var (
+ fieldsRequiredByDefault bool
+ nilPtrAllowedByRequired = false
+ notNumberRegexp = regexp.MustCompile("[^0-9]+")
+ whiteSpacesAndMinus = regexp.MustCompile(`[\s-]+`)
+ paramsRegexp = regexp.MustCompile(`\(.*\)$`)
+)
+
+const maxURLRuneCount = 2083
+const minURLRuneCount = 3
+const rfc3339WithoutZone = "2006-01-02T15:04:05"
+
+// SetFieldsRequiredByDefault causes validation to fail when struct fields
+// do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`).
+// This struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
+// type exampleStruct struct {
+// Name string ``
+// Email string `valid:"email"`
+// This, however, will only fail when Email is empty or an invalid email address:
+// type exampleStruct2 struct {
+// Name string `valid:"-"`
+// Email string `valid:"email"`
+// Lastly, this will only fail when Email is an invalid email address but not when it's empty:
+// type exampleStruct2 struct {
+// Name string `valid:"-"`
+// Email string `valid:"email,optional"`
+func SetFieldsRequiredByDefault(value bool) {
+ fieldsRequiredByDefault = value
+}
+
+// SetNilPtrAllowedByRequired causes validation to pass for nil ptrs when a field is set to required.
+// The validation will still reject ptr fields in their zero value state. Example with this enabled:
+// type exampleStruct struct {
+// Name *string `valid:"required"`
+// With `Name` set to "", this will be considered invalid input and will cause a validation error.
+// With `Name` set to nil, this will be considered valid by validation.
+// By default this is disabled.
+func SetNilPtrAllowedByRequired(value bool) {
+ nilPtrAllowedByRequired = value
+}
+
+// IsEmail checks if the string is an email.
+func IsEmail(str string) bool {
+ // TODO uppercase letters are not supported
+ return rxEmail.MatchString(str)
+}
+
+// IsExistingEmail checks if the string is an email of existing domain
+func IsExistingEmail(email string) bool {
+
+ if len(email) < 6 || len(email) > 254 {
+ return false
+ }
+ at := strings.LastIndex(email, "@")
+ if at <= 0 || at > len(email)-3 {
+ return false
+ }
+ user := email[:at]
+ host := email[at+1:]
+ if len(user) > 64 {
+ return false
+ }
+ switch host {
+ case "localhost", "example.com":
+ return true
+ }
+ if userDotRegexp.MatchString(user) || !userRegexp.MatchString(user) || !hostRegexp.MatchString(host) {
+ return false
+ }
+ if _, err := net.LookupMX(host); err != nil {
+ if _, err := net.LookupIP(host); err != nil {
+ return false
+ }
+ }
+
+ return true
+}
+
+// IsURL checks if the string is an URL.
+func IsURL(str string) bool {
+ if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") {
+ return false
+ }
+ strTemp := str
+ if strings.Contains(str, ":") && !strings.Contains(str, "://") {
+ // support no indicated urlscheme but with colon for port number
+ // http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
+ strTemp = "http://" + str
+ }
+ u, err := url.Parse(strTemp)
+ if err != nil {
+ return false
+ }
+ if strings.HasPrefix(u.Host, ".") {
+ return false
+ }
+ if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
+ return false
+ }
+ return rxURL.MatchString(str)
+}
+
+// IsRequestURL checks if the string rawurl, assuming
+// it was received in an HTTP request, is a valid
+// URL confirm to RFC 3986
+func IsRequestURL(rawurl string) bool {
+ url, err := url.ParseRequestURI(rawurl)
+ if err != nil {
+ return false //Couldn't even parse the rawurl
+ }
+ if len(url.Scheme) == 0 {
+ return false //No Scheme found
+ }
+ return true
+}
+
+// IsRequestURI checks if the string rawurl, assuming
+// it was received in an HTTP request, is an
+// absolute URI or an absolute path.
+func IsRequestURI(rawurl string) bool {
+ _, err := url.ParseRequestURI(rawurl)
+ return err == nil
+}
+
+// IsAlpha checks if the string contains only letters (a-zA-Z). Empty string is valid.
+func IsAlpha(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxAlpha.MatchString(str)
+}
+
+//IsUTFLetter checks if the string contains only unicode letter characters.
+//Similar to IsAlpha but for all languages. Empty string is valid.
+func IsUTFLetter(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+
+ for _, c := range str {
+ if !unicode.IsLetter(c) {
+ return false
+ }
+ }
+ return true
+
+}
+
+// IsAlphanumeric checks if the string contains only letters and numbers. Empty string is valid.
+func IsAlphanumeric(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxAlphanumeric.MatchString(str)
+}
+
+// IsUTFLetterNumeric checks if the string contains only unicode letters and numbers. Empty string is valid.
+func IsUTFLetterNumeric(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ for _, c := range str {
+ if !unicode.IsLetter(c) && !unicode.IsNumber(c) { //letters && numbers are ok
+ return false
+ }
+ }
+ return true
+
+}
+
+// IsNumeric checks if the string contains only numbers. Empty string is valid.
+func IsNumeric(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxNumeric.MatchString(str)
+}
+
+// IsUTFNumeric checks if the string contains only unicode numbers of any kind.
+// Numbers can be 0-9 but also Fractions ¾,Roman Ⅸ and Hangzhou 〩. Empty string is valid.
+func IsUTFNumeric(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ if strings.IndexAny(str, "+-") > 0 {
+ return false
+ }
+ if len(str) > 1 {
+ str = strings.TrimPrefix(str, "-")
+ str = strings.TrimPrefix(str, "+")
+ }
+ for _, c := range str {
+ if !unicode.IsNumber(c) { //numbers && minus sign are ok
+ return false
+ }
+ }
+ return true
+
+}
+
+// IsUTFDigit checks if the string contains only unicode radix-10 decimal digits. Empty string is valid.
+func IsUTFDigit(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ if strings.IndexAny(str, "+-") > 0 {
+ return false
+ }
+ if len(str) > 1 {
+ str = strings.TrimPrefix(str, "-")
+ str = strings.TrimPrefix(str, "+")
+ }
+ for _, c := range str {
+ if !unicode.IsDigit(c) { //digits && minus sign are ok
+ return false
+ }
+ }
+ return true
+
+}
+
+// IsHexadecimal checks if the string is a hexadecimal number.
+func IsHexadecimal(str string) bool {
+ return rxHexadecimal.MatchString(str)
+}
+
+// IsHexcolor checks if the string is a hexadecimal color.
+func IsHexcolor(str string) bool {
+ return rxHexcolor.MatchString(str)
+}
+
+// IsRGBcolor checks if the string is a valid RGB color in form rgb(RRR, GGG, BBB).
+func IsRGBcolor(str string) bool {
+ return rxRGBcolor.MatchString(str)
+}
+
+// IsLowerCase checks if the string is lowercase. Empty string is valid.
+func IsLowerCase(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return str == strings.ToLower(str)
+}
+
+// IsUpperCase checks if the string is uppercase. Empty string is valid.
+func IsUpperCase(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return str == strings.ToUpper(str)
+}
+
+// HasLowerCase checks if the string contains at least 1 lowercase. Empty string is valid.
+func HasLowerCase(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxHasLowerCase.MatchString(str)
+}
+
+// HasUpperCase checks if the string contains as least 1 uppercase. Empty string is valid.
+func HasUpperCase(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxHasUpperCase.MatchString(str)
+}
+
+// IsInt checks if the string is an integer. Empty string is valid.
+func IsInt(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxInt.MatchString(str)
+}
+
+// IsFloat checks if the string is a float.
+func IsFloat(str string) bool {
+ return str != "" && rxFloat.MatchString(str)
+}
+
+// IsDivisibleBy checks if the string is a number that's divisible by another.
+// If second argument is not valid integer or zero, it's return false.
+// Otherwise, if first argument is not valid integer or zero, it's return true (Invalid string converts to zero).
+func IsDivisibleBy(str, num string) bool {
+ f, _ := ToFloat(str)
+ p := int64(f)
+ q, _ := ToInt(num)
+ if q == 0 {
+ return false
+ }
+ return (p == 0) || (p%q == 0)
+}
+
+// IsNull checks if the string is null.
+func IsNull(str string) bool {
+ return len(str) == 0
+}
+
+// IsNotNull checks if the string is not null.
+func IsNotNull(str string) bool {
+ return !IsNull(str)
+}
+
+// HasWhitespaceOnly checks the string only contains whitespace
+func HasWhitespaceOnly(str string) bool {
+ return len(str) > 0 && rxHasWhitespaceOnly.MatchString(str)
+}
+
+// HasWhitespace checks if the string contains any whitespace
+func HasWhitespace(str string) bool {
+ return len(str) > 0 && rxHasWhitespace.MatchString(str)
+}
+
+// IsByteLength checks if the string's length (in bytes) falls in a range.
+func IsByteLength(str string, min, max int) bool {
+ return len(str) >= min && len(str) <= max
+}
+
+// IsUUIDv3 checks if the string is a UUID version 3.
+func IsUUIDv3(str string) bool {
+ return rxUUID3.MatchString(str)
+}
+
+// IsUUIDv4 checks if the string is a UUID version 4.
+func IsUUIDv4(str string) bool {
+ return rxUUID4.MatchString(str)
+}
+
+// IsUUIDv5 checks if the string is a UUID version 5.
+func IsUUIDv5(str string) bool {
+ return rxUUID5.MatchString(str)
+}
+
+// IsUUID checks if the string is a UUID (version 3, 4 or 5).
+func IsUUID(str string) bool {
+ return rxUUID.MatchString(str)
+}
+
+// Byte to index table for O(1) lookups when unmarshaling.
+// We use 0xFF as sentinel value for invalid indexes.
+var ulidDec = [...]byte{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF,
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14,
+ 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
+ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+}
+
+// EncodedSize is the length of a text encoded ULID.
+const ulidEncodedSize = 26
+
+// IsULID checks if the string is a ULID.
+//
+// Implementation got from:
+// https://github.com/oklog/ulid (Apache-2.0 License)
+//
+func IsULID(str string) bool {
+ // Check if a base32 encoded ULID is the right length.
+ if len(str) != ulidEncodedSize {
+ return false
+ }
+
+ // Check if all the characters in a base32 encoded ULID are part of the
+ // expected base32 character set.
+ if ulidDec[str[0]] == 0xFF ||
+ ulidDec[str[1]] == 0xFF ||
+ ulidDec[str[2]] == 0xFF ||
+ ulidDec[str[3]] == 0xFF ||
+ ulidDec[str[4]] == 0xFF ||
+ ulidDec[str[5]] == 0xFF ||
+ ulidDec[str[6]] == 0xFF ||
+ ulidDec[str[7]] == 0xFF ||
+ ulidDec[str[8]] == 0xFF ||
+ ulidDec[str[9]] == 0xFF ||
+ ulidDec[str[10]] == 0xFF ||
+ ulidDec[str[11]] == 0xFF ||
+ ulidDec[str[12]] == 0xFF ||
+ ulidDec[str[13]] == 0xFF ||
+ ulidDec[str[14]] == 0xFF ||
+ ulidDec[str[15]] == 0xFF ||
+ ulidDec[str[16]] == 0xFF ||
+ ulidDec[str[17]] == 0xFF ||
+ ulidDec[str[18]] == 0xFF ||
+ ulidDec[str[19]] == 0xFF ||
+ ulidDec[str[20]] == 0xFF ||
+ ulidDec[str[21]] == 0xFF ||
+ ulidDec[str[22]] == 0xFF ||
+ ulidDec[str[23]] == 0xFF ||
+ ulidDec[str[24]] == 0xFF ||
+ ulidDec[str[25]] == 0xFF {
+ return false
+ }
+
+ // Check if the first character in a base32 encoded ULID will overflow. This
+ // happens because the base32 representation encodes 130 bits, while the
+ // ULID is only 128 bits.
+ //
+ // See https://github.com/oklog/ulid/issues/9 for details.
+ if str[0] > '7' {
+ return false
+ }
+ return true
+}
+
+// IsCreditCard checks if the string is a credit card.
+func IsCreditCard(str string) bool {
+ sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
+ if !rxCreditCard.MatchString(sanitized) {
+ return false
+ }
+
+ number, _ := ToInt(sanitized)
+ number, lastDigit := number / 10, number % 10
+
+ var sum int64
+ for i:=0; number > 0; i++ {
+ digit := number % 10
+
+ if i % 2 == 0 {
+ digit *= 2
+ if digit > 9 {
+ digit -= 9
+ }
+ }
+
+ sum += digit
+ number = number / 10
+ }
+
+ return (sum + lastDigit) % 10 == 0
+}
+
+// IsISBN10 checks if the string is an ISBN version 10.
+func IsISBN10(str string) bool {
+ return IsISBN(str, 10)
+}
+
+// IsISBN13 checks if the string is an ISBN version 13.
+func IsISBN13(str string) bool {
+ return IsISBN(str, 13)
+}
+
+// IsISBN checks if the string is an ISBN (version 10 or 13).
+// If version value is not equal to 10 or 13, it will be checks both variants.
+func IsISBN(str string, version int) bool {
+ sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
+ var checksum int32
+ var i int32
+ if version == 10 {
+ if !rxISBN10.MatchString(sanitized) {
+ return false
+ }
+ for i = 0; i < 9; i++ {
+ checksum += (i + 1) * int32(sanitized[i]-'0')
+ }
+ if sanitized[9] == 'X' {
+ checksum += 10 * 10
+ } else {
+ checksum += 10 * int32(sanitized[9]-'0')
+ }
+ if checksum%11 == 0 {
+ return true
+ }
+ return false
+ } else if version == 13 {
+ if !rxISBN13.MatchString(sanitized) {
+ return false
+ }
+ factor := []int32{1, 3}
+ for i = 0; i < 12; i++ {
+ checksum += factor[i%2] * int32(sanitized[i]-'0')
+ }
+ return (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0
+ }
+ return IsISBN(str, 10) || IsISBN(str, 13)
+}
+
+// IsJSON checks if the string is valid JSON (note: uses json.Unmarshal).
+func IsJSON(str string) bool {
+ var js json.RawMessage
+ return json.Unmarshal([]byte(str), &js) == nil
+}
+
+// IsMultibyte checks if the string contains one or more multibyte chars. Empty string is valid.
+func IsMultibyte(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxMultibyte.MatchString(str)
+}
+
+// IsASCII checks if the string contains ASCII chars only. Empty string is valid.
+func IsASCII(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxASCII.MatchString(str)
+}
+
+// IsPrintableASCII checks if the string contains printable ASCII chars only. Empty string is valid.
+func IsPrintableASCII(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxPrintableASCII.MatchString(str)
+}
+
+// IsFullWidth checks if the string contains any full-width chars. Empty string is valid.
+func IsFullWidth(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxFullWidth.MatchString(str)
+}
+
+// IsHalfWidth checks if the string contains any half-width chars. Empty string is valid.
+func IsHalfWidth(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxHalfWidth.MatchString(str)
+}
+
+// IsVariableWidth checks if the string contains a mixture of full and half-width chars. Empty string is valid.
+func IsVariableWidth(str string) bool {
+ if IsNull(str) {
+ return true
+ }
+ return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str)
+}
+
+// IsBase64 checks if a string is base64 encoded.
+func IsBase64(str string) bool {
+ return rxBase64.MatchString(str)
+}
+
+// IsFilePath checks is a string is Win or Unix file path and returns it's type.
+func IsFilePath(str string) (bool, int) {
+ if rxWinPath.MatchString(str) {
+ //check windows path limit see:
+ // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
+ if len(str[3:]) > 32767 {
+ return false, Win
+ }
+ return true, Win
+ } else if rxUnixPath.MatchString(str) {
+ return true, Unix
+ }
+ return false, Unknown
+}
+
+//IsWinFilePath checks both relative & absolute paths in Windows
+func IsWinFilePath(str string) bool {
+ if rxARWinPath.MatchString(str) {
+ //check windows path limit see:
+ // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
+ if len(str[3:]) > 32767 {
+ return false
+ }
+ return true
+ }
+ return false
+}
+
+//IsUnixFilePath checks both relative & absolute paths in Unix
+func IsUnixFilePath(str string) bool {
+ if rxARUnixPath.MatchString(str) {
+ return true
+ }
+ return false
+}
+
+// IsDataURI checks if a string is base64 encoded data URI such as an image
+func IsDataURI(str string) bool {
+ dataURI := strings.Split(str, ",")
+ if !rxDataURI.MatchString(dataURI[0]) {
+ return false
+ }
+ return IsBase64(dataURI[1])
+}
+
+// IsMagnetURI checks if a string is valid magnet URI
+func IsMagnetURI(str string) bool {
+ return rxMagnetURI.MatchString(str)
+}
+
+// IsISO3166Alpha2 checks if a string is valid two-letter country code
+func IsISO3166Alpha2(str string) bool {
+ for _, entry := range ISO3166List {
+ if str == entry.Alpha2Code {
+ return true
+ }
+ }
+ return false
+}
+
+// IsISO3166Alpha3 checks if a string is valid three-letter country code
+func IsISO3166Alpha3(str string) bool {
+ for _, entry := range ISO3166List {
+ if str == entry.Alpha3Code {
+ return true
+ }
+ }
+ return false
+}
+
+// IsISO693Alpha2 checks if a string is valid two-letter language code
+func IsISO693Alpha2(str string) bool {
+ for _, entry := range ISO693List {
+ if str == entry.Alpha2Code {
+ return true
+ }
+ }
+ return false
+}
+
+// IsISO693Alpha3b checks if a string is valid three-letter language code
+func IsISO693Alpha3b(str string) bool {
+ for _, entry := range ISO693List {
+ if str == entry.Alpha3bCode {
+ return true
+ }
+ }
+ return false
+}
+
+// IsDNSName will validate the given string as a DNS name
+func IsDNSName(str string) bool {
+ if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 {
+ // constraints already violated
+ return false
+ }
+ return !IsIP(str) && rxDNSName.MatchString(str)
+}
+
+// IsHash checks if a string is a hash of type algorithm.
+// Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
+func IsHash(str string, algorithm string) bool {
+ var len string
+ algo := strings.ToLower(algorithm)
+
+ if algo == "crc32" || algo == "crc32b" {
+ len = "8"
+ } else if algo == "md5" || algo == "md4" || algo == "ripemd128" || algo == "tiger128" {
+ len = "32"
+ } else if algo == "sha1" || algo == "ripemd160" || algo == "tiger160" {
+ len = "40"
+ } else if algo == "tiger192" {
+ len = "48"
+ } else if algo == "sha3-224" {
+ len = "56"
+ } else if algo == "sha256" || algo == "sha3-256" {
+ len = "64"
+ } else if algo == "sha384" || algo == "sha3-384" {
+ len = "96"
+ } else if algo == "sha512" || algo == "sha3-512" {
+ len = "128"
+ } else {
+ return false
+ }
+
+ return Matches(str, "^[a-f0-9]{"+len+"}$")
+}
+
+// IsSHA3224 checks is a string is a SHA3-224 hash. Alias for `IsHash(str, "sha3-224")`
+func IsSHA3224(str string) bool {
+ return IsHash(str, "sha3-224")
+}
+
+// IsSHA3256 checks is a string is a SHA3-256 hash. Alias for `IsHash(str, "sha3-256")`
+func IsSHA3256(str string) bool {
+ return IsHash(str, "sha3-256")
+}
+
+// IsSHA3384 checks is a string is a SHA3-384 hash. Alias for `IsHash(str, "sha3-384")`
+func IsSHA3384(str string) bool {
+ return IsHash(str, "sha3-384")
+}
+
+// IsSHA3512 checks is a string is a SHA3-512 hash. Alias for `IsHash(str, "sha3-512")`
+func IsSHA3512(str string) bool {
+ return IsHash(str, "sha3-512")
+}
+
+// IsSHA512 checks is a string is a SHA512 hash. Alias for `IsHash(str, "sha512")`
+func IsSHA512(str string) bool {
+ return IsHash(str, "sha512")
+}
+
+// IsSHA384 checks is a string is a SHA384 hash. Alias for `IsHash(str, "sha384")`
+func IsSHA384(str string) bool {
+ return IsHash(str, "sha384")
+}
+
+// IsSHA256 checks is a string is a SHA256 hash. Alias for `IsHash(str, "sha256")`
+func IsSHA256(str string) bool {
+ return IsHash(str, "sha256")
+}
+
+// IsTiger192 checks is a string is a Tiger192 hash. Alias for `IsHash(str, "tiger192")`
+func IsTiger192(str string) bool {
+ return IsHash(str, "tiger192")
+}
+
+// IsTiger160 checks is a string is a Tiger160 hash. Alias for `IsHash(str, "tiger160")`
+func IsTiger160(str string) bool {
+ return IsHash(str, "tiger160")
+}
+
+// IsRipeMD160 checks is a string is a RipeMD160 hash. Alias for `IsHash(str, "ripemd160")`
+func IsRipeMD160(str string) bool {
+ return IsHash(str, "ripemd160")
+}
+
+// IsSHA1 checks is a string is a SHA-1 hash. Alias for `IsHash(str, "sha1")`
+func IsSHA1(str string) bool {
+ return IsHash(str, "sha1")
+}
+
+// IsTiger128 checks is a string is a Tiger128 hash. Alias for `IsHash(str, "tiger128")`
+func IsTiger128(str string) bool {
+ return IsHash(str, "tiger128")
+}
+
+// IsRipeMD128 checks is a string is a RipeMD128 hash. Alias for `IsHash(str, "ripemd128")`
+func IsRipeMD128(str string) bool {
+ return IsHash(str, "ripemd128")
+}
+
+// IsCRC32 checks is a string is a CRC32 hash. Alias for `IsHash(str, "crc32")`
+func IsCRC32(str string) bool {
+ return IsHash(str, "crc32")
+}
+
+// IsCRC32b checks is a string is a CRC32b hash. Alias for `IsHash(str, "crc32b")`
+func IsCRC32b(str string) bool {
+ return IsHash(str, "crc32b")
+}
+
+// IsMD5 checks is a string is a MD5 hash. Alias for `IsHash(str, "md5")`
+func IsMD5(str string) bool {
+ return IsHash(str, "md5")
+}
+
+// IsMD4 checks is a string is a MD4 hash. Alias for `IsHash(str, "md4")`
+func IsMD4(str string) bool {
+ return IsHash(str, "md4")
+}
+
+// IsDialString validates the given string for usage with the various Dial() functions
+func IsDialString(str string) bool {
+ if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) {
+ return true
+ }
+
+ return false
+}
+
+// IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP`
+func IsIP(str string) bool {
+ return net.ParseIP(str) != nil
+}
+
+// IsPort checks if a string represents a valid port
+func IsPort(str string) bool {
+ if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 {
+ return true
+ }
+ return false
+}
+
+// IsIPv4 checks if the string is an IP version 4.
+func IsIPv4(str string) bool {
+ ip := net.ParseIP(str)
+ return ip != nil && strings.Contains(str, ".")
+}
+
+// IsIPv6 checks if the string is an IP version 6.
+func IsIPv6(str string) bool {
+ ip := net.ParseIP(str)
+ return ip != nil && strings.Contains(str, ":")
+}
+
+// IsCIDR checks if the string is an valid CIDR notiation (IPV4 & IPV6)
+func IsCIDR(str string) bool {
+ _, _, err := net.ParseCIDR(str)
+ return err == nil
+}
+
+// IsMAC checks if a string is valid MAC address.
+// Possible MAC formats:
+// 01:23:45:67:89:ab
+// 01:23:45:67:89:ab:cd:ef
+// 01-23-45-67-89-ab
+// 01-23-45-67-89-ab-cd-ef
+// 0123.4567.89ab
+// 0123.4567.89ab.cdef
+func IsMAC(str string) bool {
+ _, err := net.ParseMAC(str)
+ return err == nil
+}
+
+// IsHost checks if the string is a valid IP (both v4 and v6) or a valid DNS name
+func IsHost(str string) bool {
+ return IsIP(str) || IsDNSName(str)
+}
+
+// IsMongoID checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.
+func IsMongoID(str string) bool {
+ return rxHexadecimal.MatchString(str) && (len(str) == 24)
+}
+
+// IsLatitude checks if a string is valid latitude.
+func IsLatitude(str string) bool {
+ return rxLatitude.MatchString(str)
+}
+
+// IsLongitude checks if a string is valid longitude.
+func IsLongitude(str string) bool {
+ return rxLongitude.MatchString(str)
+}
+
+// IsIMEI checks if a string is valid IMEI
+func IsIMEI(str string) bool {
+ return rxIMEI.MatchString(str)
+}
+
+// IsIMSI checks if a string is valid IMSI
+func IsIMSI(str string) bool {
+ if !rxIMSI.MatchString(str) {
+ return false
+ }
+
+ mcc, err := strconv.ParseInt(str[0:3], 10, 32)
+ if err != nil {
+ return false
+ }
+
+ switch mcc {
+ case 202, 204, 206, 208, 212, 213, 214, 216, 218, 219:
+ case 220, 221, 222, 226, 228, 230, 231, 232, 234, 235:
+ case 238, 240, 242, 244, 246, 247, 248, 250, 255, 257:
+ case 259, 260, 262, 266, 268, 270, 272, 274, 276, 278:
+ case 280, 282, 283, 284, 286, 288, 289, 290, 292, 293:
+ case 294, 295, 297, 302, 308, 310, 311, 312, 313, 314:
+ case 315, 316, 330, 332, 334, 338, 340, 342, 344, 346:
+ case 348, 350, 352, 354, 356, 358, 360, 362, 363, 364:
+ case 365, 366, 368, 370, 372, 374, 376, 400, 401, 402:
+ case 404, 405, 406, 410, 412, 413, 414, 415, 416, 417:
+ case 418, 419, 420, 421, 422, 424, 425, 426, 427, 428:
+ case 429, 430, 431, 432, 434, 436, 437, 438, 440, 441:
+ case 450, 452, 454, 455, 456, 457, 460, 461, 466, 467:
+ case 470, 472, 502, 505, 510, 514, 515, 520, 525, 528:
+ case 530, 536, 537, 539, 540, 541, 542, 543, 544, 545:
+ case 546, 547, 548, 549, 550, 551, 552, 553, 554, 555:
+ case 602, 603, 604, 605, 606, 607, 608, 609, 610, 611:
+ case 612, 613, 614, 615, 616, 617, 618, 619, 620, 621:
+ case 622, 623, 624, 625, 626, 627, 628, 629, 630, 631:
+ case 632, 633, 634, 635, 636, 637, 638, 639, 640, 641:
+ case 642, 643, 645, 646, 647, 648, 649, 650, 651, 652:
+ case 653, 654, 655, 657, 658, 659, 702, 704, 706, 708:
+ case 710, 712, 714, 716, 722, 724, 730, 732, 734, 736:
+ case 738, 740, 742, 744, 746, 748, 750, 995:
+ return true
+ default:
+ return false
+ }
+ return true
+}
+
+// IsRsaPublicKey checks if a string is valid public key with provided length
+func IsRsaPublicKey(str string, keylen int) bool {
+ bb := bytes.NewBufferString(str)
+ pemBytes, err := ioutil.ReadAll(bb)
+ if err != nil {
+ return false
+ }
+ block, _ := pem.Decode(pemBytes)
+ if block != nil && block.Type != "PUBLIC KEY" {
+ return false
+ }
+ var der []byte
+
+ if block != nil {
+ der = block.Bytes
+ } else {
+ der, err = base64.StdEncoding.DecodeString(str)
+ if err != nil {
+ return false
+ }
+ }
+
+ key, err := x509.ParsePKIXPublicKey(der)
+ if err != nil {
+ return false
+ }
+ pubkey, ok := key.(*rsa.PublicKey)
+ if !ok {
+ return false
+ }
+ bitlen := len(pubkey.N.Bytes()) * 8
+ return bitlen == int(keylen)
+}
+
+// IsRegex checks if a give string is a valid regex with RE2 syntax or not
+func IsRegex(str string) bool {
+ if _, err := regexp.Compile(str); err == nil {
+ return true
+ }
+ return false
+}
+
+func toJSONName(tag string) string {
+ if tag == "" {
+ return ""
+ }
+
+ // JSON name always comes first. If there's no options then split[0] is
+ // JSON name, if JSON name is not set, then split[0] is an empty string.
+ split := strings.SplitN(tag, ",", 2)
+
+ name := split[0]
+
+ // However it is possible that the field is skipped when
+ // (de-)serializing from/to JSON, in which case assume that there is no
+ // tag name to use
+ if name == "-" {
+ return ""
+ }
+ return name
+}
+
+func prependPathToErrors(err error, path string) error {
+ switch err2 := err.(type) {
+ case Error:
+ err2.Path = append([]string{path}, err2.Path...)
+ return err2
+ case Errors:
+ errors := err2.Errors()
+ for i, err3 := range errors {
+ errors[i] = prependPathToErrors(err3, path)
+ }
+ return err2
+ }
+ return err
+}
+
+// ValidateArray performs validation according to condition iterator that validates every element of the array
+func ValidateArray(array []interface{}, iterator ConditionIterator) bool {
+ return Every(array, iterator)
+}
+
+// ValidateMap use validation map for fields.
+// result will be equal to `false` if there are any errors.
+// s is the map containing the data to be validated.
+// m is the validation map in the form:
+// map[string]interface{}{"name":"required,alpha","address":map[string]interface{}{"line1":"required,alphanum"}}
+func ValidateMap(s map[string]interface{}, m map[string]interface{}) (bool, error) {
+ if s == nil {
+ return true, nil
+ }
+ result := true
+ var err error
+ var errs Errors
+ var index int
+ val := reflect.ValueOf(s)
+ for key, value := range s {
+ presentResult := true
+ validator, ok := m[key]
+ if !ok {
+ presentResult = false
+ var err error
+ err = fmt.Errorf("all map keys has to be present in the validation map; got %s", key)
+ err = prependPathToErrors(err, key)
+ errs = append(errs, err)
+ }
+ valueField := reflect.ValueOf(value)
+ mapResult := true
+ typeResult := true
+ structResult := true
+ resultField := true
+ switch subValidator := validator.(type) {
+ case map[string]interface{}:
+ var err error
+ if v, ok := value.(map[string]interface{}); !ok {
+ mapResult = false
+ err = fmt.Errorf("map validator has to be for the map type only; got %s", valueField.Type().String())
+ err = prependPathToErrors(err, key)
+ errs = append(errs, err)
+ } else {
+ mapResult, err = ValidateMap(v, subValidator)
+ if err != nil {
+ mapResult = false
+ err = prependPathToErrors(err, key)
+ errs = append(errs, err)
+ }
+ }
+ case string:
+ if (valueField.Kind() == reflect.Struct ||
+ (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) &&
+ subValidator != "-" {
+ var err error
+ structResult, err = ValidateStruct(valueField.Interface())
+ if err != nil {
+ err = prependPathToErrors(err, key)
+ errs = append(errs, err)
+ }
+ }
+ resultField, err = typeCheck(valueField, reflect.StructField{
+ Name: key,
+ PkgPath: "",
+ Type: val.Type(),
+ Tag: reflect.StructTag(fmt.Sprintf("%s:%q", tagName, subValidator)),
+ Offset: 0,
+ Index: []int{index},
+ Anonymous: false,
+ }, val, nil)
+ if err != nil {
+ errs = append(errs, err)
+ }
+ case nil:
+ // already handlerd when checked before
+ default:
+ typeResult = false
+ err = fmt.Errorf("map validator has to be either map[string]interface{} or string; got %s", valueField.Type().String())
+ err = prependPathToErrors(err, key)
+ errs = append(errs, err)
+ }
+ result = result && presentResult && typeResult && resultField && structResult && mapResult
+ index++
+ }
+ // checks required keys
+ requiredResult := true
+ for key, value := range m {
+ if schema, ok := value.(string); ok {
+ tags := parseTagIntoMap(schema)
+ if required, ok := tags["required"]; ok {
+ if _, ok := s[key]; !ok {
+ requiredResult = false
+ if required.customErrorMessage != "" {
+ err = Error{key, fmt.Errorf(required.customErrorMessage), true, "required", []string{}}
+ } else {
+ err = Error{key, fmt.Errorf("required field missing"), false, "required", []string{}}
+ }
+ errs = append(errs, err)
+ }
+ }
+ }
+ }
+
+ if len(errs) > 0 {
+ err = errs
+ }
+ return result && requiredResult, err
+}
+
+// ValidateStruct use tags for fields.
+// result will be equal to `false` if there are any errors.
+// todo currently there is no guarantee that errors will be returned in predictable order (tests may to fail)
+func ValidateStruct(s interface{}) (bool, error) {
+ if s == nil {
+ return true, nil
+ }
+ result := true
+ var err error
+ val := reflect.ValueOf(s)
+ if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
+ val = val.Elem()
+ }
+ // we only accept structs
+ if val.Kind() != reflect.Struct {
+ return false, fmt.Errorf("function only accepts structs; got %s", val.Kind())
+ }
+ var errs Errors
+ for i := 0; i < val.NumField(); i++ {
+ valueField := val.Field(i)
+ typeField := val.Type().Field(i)
+ if typeField.PkgPath != "" {
+ continue // Private field
+ }
+ structResult := true
+ if valueField.Kind() == reflect.Interface {
+ valueField = valueField.Elem()
+ }
+ if (valueField.Kind() == reflect.Struct ||
+ (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) &&
+ typeField.Tag.Get(tagName) != "-" {
+ var err error
+ structResult, err = ValidateStruct(valueField.Interface())
+ if err != nil {
+ err = prependPathToErrors(err, typeField.Name)
+ errs = append(errs, err)
+ }
+ }
+ resultField, err2 := typeCheck(valueField, typeField, val, nil)
+ if err2 != nil {
+
+ // Replace structure name with JSON name if there is a tag on the variable
+ jsonTag := toJSONName(typeField.Tag.Get("json"))
+ if jsonTag != "" {
+ switch jsonError := err2.(type) {
+ case Error:
+ jsonError.Name = jsonTag
+ err2 = jsonError
+ case Errors:
+ for i2, err3 := range jsonError {
+ switch customErr := err3.(type) {
+ case Error:
+ customErr.Name = jsonTag
+ jsonError[i2] = customErr
+ }
+ }
+
+ err2 = jsonError
+ }
+ }
+
+ errs = append(errs, err2)
+ }
+ result = result && resultField && structResult
+ }
+ if len(errs) > 0 {
+ err = errs
+ }
+ return result, err
+}
+
+// ValidateStructAsync performs async validation of the struct and returns results through the channels
+func ValidateStructAsync(s interface{}) (<-chan bool, <-chan error) {
+ res := make(chan bool)
+ errors := make(chan error)
+
+ go func() {
+ defer close(res)
+ defer close(errors)
+
+ isValid, isFailed := ValidateStruct(s)
+
+ res <- isValid
+ errors <- isFailed
+ }()
+
+ return res, errors
+}
+
+// ValidateMapAsync performs async validation of the map and returns results through the channels
+func ValidateMapAsync(s map[string]interface{}, m map[string]interface{}) (<-chan bool, <-chan error) {
+ res := make(chan bool)
+ errors := make(chan error)
+
+ go func() {
+ defer close(res)
+ defer close(errors)
+
+ isValid, isFailed := ValidateMap(s, m)
+
+ res <- isValid
+ errors <- isFailed
+ }()
+
+ return res, errors
+}
+
+// parseTagIntoMap parses a struct tag `valid:required~Some error message,length(2|3)` into map[string]string{"required": "Some error message", "length(2|3)": ""}
+func parseTagIntoMap(tag string) tagOptionsMap {
+ optionsMap := make(tagOptionsMap)
+ options := strings.Split(tag, ",")
+
+ for i, option := range options {
+ option = strings.TrimSpace(option)
+
+ validationOptions := strings.Split(option, "~")
+ if !isValidTag(validationOptions[0]) {
+ continue
+ }
+ if len(validationOptions) == 2 {
+ optionsMap[validationOptions[0]] = tagOption{validationOptions[0], validationOptions[1], i}
+ } else {
+ optionsMap[validationOptions[0]] = tagOption{validationOptions[0], "", i}
+ }
+ }
+ return optionsMap
+}
+
+func isValidTag(s string) bool {
+ if s == "" {
+ return false
+ }
+ for _, c := range s {
+ switch {
+ case strings.ContainsRune("\\'\"!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
+ // Backslash and quote chars are reserved, but
+ // otherwise any punctuation chars are allowed
+ // in a tag name.
+ default:
+ if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// IsSSN will validate the given string as a U.S. Social Security Number
+func IsSSN(str string) bool {
+ if str == "" || len(str) != 11 {
+ return false
+ }
+ return rxSSN.MatchString(str)
+}
+
+// IsSemver checks if string is valid semantic version
+func IsSemver(str string) bool {
+ return rxSemver.MatchString(str)
+}
+
+// IsType checks if interface is of some type
+func IsType(v interface{}, params ...string) bool {
+ if len(params) == 1 {
+ typ := params[0]
+ return strings.Replace(reflect.TypeOf(v).String(), " ", "", -1) == strings.Replace(typ, " ", "", -1)
+ }
+ return false
+}
+
+// IsTime checks if string is valid according to given format
+func IsTime(str string, format string) bool {
+ _, err := time.Parse(format, str)
+ return err == nil
+}
+
+// IsUnixTime checks if string is valid unix timestamp value
+func IsUnixTime(str string) bool {
+ if _, err := strconv.Atoi(str); err == nil {
+ return true
+ }
+ return false
+}
+
+// IsRFC3339 checks if string is valid timestamp value according to RFC3339
+func IsRFC3339(str string) bool {
+ return IsTime(str, time.RFC3339)
+}
+
+// IsRFC3339WithoutZone checks if string is valid timestamp value according to RFC3339 which excludes the timezone.
+func IsRFC3339WithoutZone(str string) bool {
+ return IsTime(str, rfc3339WithoutZone)
+}
+
+// IsISO4217 checks if string is valid ISO currency code
+func IsISO4217(str string) bool {
+ for _, currency := range ISO4217List {
+ if str == currency {
+ return true
+ }
+ }
+
+ return false
+}
+
+// ByteLength checks string's length
+func ByteLength(str string, params ...string) bool {
+ if len(params) == 2 {
+ min, _ := ToInt(params[0])
+ max, _ := ToInt(params[1])
+ return len(str) >= int(min) && len(str) <= int(max)
+ }
+
+ return false
+}
+
+// RuneLength checks string's length
+// Alias for StringLength
+func RuneLength(str string, params ...string) bool {
+ return StringLength(str, params...)
+}
+
+// IsRsaPub checks whether string is valid RSA key
+// Alias for IsRsaPublicKey
+func IsRsaPub(str string, params ...string) bool {
+ if len(params) == 1 {
+ len, _ := ToInt(params[0])
+ return IsRsaPublicKey(str, int(len))
+ }
+
+ return false
+}
+
+// StringMatches checks if a string matches a given pattern.
+func StringMatches(s string, params ...string) bool {
+ if len(params) == 1 {
+ pattern := params[0]
+ return Matches(s, pattern)
+ }
+ return false
+}
+
+// StringLength checks string's length (including multi byte strings)
+func StringLength(str string, params ...string) bool {
+
+ if len(params) == 2 {
+ strLength := utf8.RuneCountInString(str)
+ min, _ := ToInt(params[0])
+ max, _ := ToInt(params[1])
+ return strLength >= int(min) && strLength <= int(max)
+ }
+
+ return false
+}
+
+// MinStringLength checks string's minimum length (including multi byte strings)
+func MinStringLength(str string, params ...string) bool {
+
+ if len(params) == 1 {
+ strLength := utf8.RuneCountInString(str)
+ min, _ := ToInt(params[0])
+ return strLength >= int(min)
+ }
+
+ return false
+}
+
+// MaxStringLength checks string's maximum length (including multi byte strings)
+func MaxStringLength(str string, params ...string) bool {
+
+ if len(params) == 1 {
+ strLength := utf8.RuneCountInString(str)
+ max, _ := ToInt(params[0])
+ return strLength <= int(max)
+ }
+
+ return false
+}
+
+// Range checks string's length
+func Range(str string, params ...string) bool {
+ if len(params) == 2 {
+ value, _ := ToFloat(str)
+ min, _ := ToFloat(params[0])
+ max, _ := ToFloat(params[1])
+ return InRange(value, min, max)
+ }
+
+ return false
+}
+
+// IsInRaw checks if string is in list of allowed values
+func IsInRaw(str string, params ...string) bool {
+ if len(params) == 1 {
+ rawParams := params[0]
+
+ parsedParams := strings.Split(rawParams, "|")
+
+ return IsIn(str, parsedParams...)
+ }
+
+ return false
+}
+
+// IsIn checks if string str is a member of the set of strings params
+func IsIn(str string, params ...string) bool {
+ for _, param := range params {
+ if str == param {
+ return true
+ }
+ }
+
+ return false
+}
+
+func checkRequired(v reflect.Value, t reflect.StructField, options tagOptionsMap) (bool, error) {
+ if nilPtrAllowedByRequired {
+ k := v.Kind()
+ if (k == reflect.Ptr || k == reflect.Interface) && v.IsNil() {
+ return true, nil
+ }
+ }
+
+ if requiredOption, isRequired := options["required"]; isRequired {
+ if len(requiredOption.customErrorMessage) > 0 {
+ return false, Error{t.Name, fmt.Errorf(requiredOption.customErrorMessage), true, "required", []string{}}
+ }
+ return false, Error{t.Name, fmt.Errorf("non zero value required"), false, "required", []string{}}
+ } else if _, isOptional := options["optional"]; fieldsRequiredByDefault && !isOptional {
+ return false, Error{t.Name, fmt.Errorf("Missing required field"), false, "required", []string{}}
+ }
+ // not required and empty is valid
+ return true, nil
+}
+
+func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options tagOptionsMap) (isValid bool, resultErr error) {
+ if !v.IsValid() {
+ return false, nil
+ }
+
+ tag := t.Tag.Get(tagName)
+
+ // checks if the field should be ignored
+ switch tag {
+ case "":
+ if v.Kind() != reflect.Slice && v.Kind() != reflect.Map {
+ if !fieldsRequiredByDefault {
+ return true, nil
+ }
+ return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required", []string{}}
+ }
+ case "-":
+ return true, nil
+ }
+
+ isRootType := false
+ if options == nil {
+ isRootType = true
+ options = parseTagIntoMap(tag)
+ }
+
+ if isEmptyValue(v) {
+ // an empty value is not validated, checks only required
+ isValid, resultErr = checkRequired(v, t, options)
+ for key := range options {
+ delete(options, key)
+ }
+ return isValid, resultErr
+ }
+
+ var customTypeErrors Errors
+ optionsOrder := options.orderedKeys()
+ for _, validatorName := range optionsOrder {
+ validatorStruct := options[validatorName]
+ if validatefunc, ok := CustomTypeTagMap.Get(validatorName); ok {
+ delete(options, validatorName)
+
+ if result := validatefunc(v.Interface(), o.Interface()); !result {
+ if len(validatorStruct.customErrorMessage) > 0 {
+ customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: TruncatingErrorf(validatorStruct.customErrorMessage, fmt.Sprint(v), validatorName), CustomErrorMessageExists: true, Validator: stripParams(validatorName)})
+ continue
+ }
+ customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false, Validator: stripParams(validatorName)})
+ }
+ }
+ }
+
+ if len(customTypeErrors.Errors()) > 0 {
+ return false, customTypeErrors
+ }
+
+ if isRootType {
+ // Ensure that we've checked the value by all specified validators before report that the value is valid
+ defer func() {
+ delete(options, "optional")
+ delete(options, "required")
+
+ if isValid && resultErr == nil && len(options) != 0 {
+ optionsOrder := options.orderedKeys()
+ for _, validator := range optionsOrder {
+ isValid = false
+ resultErr = Error{t.Name, fmt.Errorf(
+ "The following validator is invalid or can't be applied to the field: %q", validator), false, stripParams(validator), []string{}}
+ return
+ }
+ }
+ }()
+ }
+
+ for _, validatorSpec := range optionsOrder {
+ validatorStruct := options[validatorSpec]
+ var negate bool
+ validator := validatorSpec
+ customMsgExists := len(validatorStruct.customErrorMessage) > 0
+
+ // checks whether the tag looks like '!something' or 'something'
+ if validator[0] == '!' {
+ validator = validator[1:]
+ negate = true
+ }
+
+ // checks for interface param validators
+ for key, value := range InterfaceParamTagRegexMap {
+ ps := value.FindStringSubmatch(validator)
+ if len(ps) == 0 {
+ continue
+ }
+
+ validatefunc, ok := InterfaceParamTagMap[key]
+ if !ok {
+ continue
+ }
+
+ delete(options, validatorSpec)
+
+ field := fmt.Sprint(v)
+ if result := validatefunc(v.Interface(), ps[1:]...); (!result && !negate) || (result && negate) {
+ if customMsgExists {
+ return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ if negate {
+ return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ }
+ }
+
+ switch v.Kind() {
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
+ reflect.Float32, reflect.Float64,
+ reflect.String:
+ // for each tag option checks the map of validator functions
+ for _, validatorSpec := range optionsOrder {
+ validatorStruct := options[validatorSpec]
+ var negate bool
+ validator := validatorSpec
+ customMsgExists := len(validatorStruct.customErrorMessage) > 0
+
+ // checks whether the tag looks like '!something' or 'something'
+ if validator[0] == '!' {
+ validator = validator[1:]
+ negate = true
+ }
+
+ // checks for param validators
+ for key, value := range ParamTagRegexMap {
+ ps := value.FindStringSubmatch(validator)
+ if len(ps) == 0 {
+ continue
+ }
+
+ validatefunc, ok := ParamTagMap[key]
+ if !ok {
+ continue
+ }
+
+ delete(options, validatorSpec)
+
+ switch v.Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Float32, reflect.Float64:
+
+ field := fmt.Sprint(v) // make value into string, then validate with regex
+ if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) {
+ if customMsgExists {
+ return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ if negate {
+ return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ default:
+ // type not yet supported, fail
+ return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false, stripParams(validatorSpec), []string{}}
+ }
+ }
+
+ if validatefunc, ok := TagMap[validator]; ok {
+ delete(options, validatorSpec)
+
+ switch v.Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Float32, reflect.Float64:
+ field := fmt.Sprint(v) // make value into string, then validate with regex
+ if result := validatefunc(field); !result && !negate || result && negate {
+ if customMsgExists {
+ return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ if negate {
+ return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
+ }
+ default:
+ //Not Yet Supported Types (Fail here!)
+ err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", validator, v.Kind(), v)
+ return false, Error{t.Name, err, false, stripParams(validatorSpec), []string{}}
+ }
+ }
+ }
+ return true, nil
+ case reflect.Map:
+ if v.Type().Key().Kind() != reflect.String {
+ return false, &UnsupportedTypeError{v.Type()}
+ }
+ var sv stringValues
+ sv = v.MapKeys()
+ sort.Sort(sv)
+ result := true
+ for i, k := range sv {
+ var resultItem bool
+ var err error
+ if v.MapIndex(k).Kind() != reflect.Struct {
+ resultItem, err = typeCheck(v.MapIndex(k), t, o, options)
+ if err != nil {
+ return false, err
+ }
+ } else {
+ resultItem, err = ValidateStruct(v.MapIndex(k).Interface())
+ if err != nil {
+ err = prependPathToErrors(err, t.Name+"."+sv[i].Interface().(string))
+ return false, err
+ }
+ }
+ result = result && resultItem
+ }
+ return result, nil
+ case reflect.Slice, reflect.Array:
+ result := true
+ for i := 0; i < v.Len(); i++ {
+ var resultItem bool
+ var err error
+ if v.Index(i).Kind() != reflect.Struct {
+ resultItem, err = typeCheck(v.Index(i), t, o, options)
+ if err != nil {
+ return false, err
+ }
+ } else {
+ resultItem, err = ValidateStruct(v.Index(i).Interface())
+ if err != nil {
+ err = prependPathToErrors(err, t.Name+"."+strconv.Itoa(i))
+ return false, err
+ }
+ }
+ result = result && resultItem
+ }
+ return result, nil
+ case reflect.Interface:
+ // If the value is an interface then encode its element
+ if v.IsNil() {
+ return true, nil
+ }
+ return ValidateStruct(v.Interface())
+ case reflect.Ptr:
+ // If the value is a pointer then checks its element
+ if v.IsNil() {
+ return true, nil
+ }
+ return typeCheck(v.Elem(), t, o, options)
+ case reflect.Struct:
+ return true, nil
+ default:
+ return false, &UnsupportedTypeError{v.Type()}
+ }
+}
+
+func stripParams(validatorString string) string {
+ return paramsRegexp.ReplaceAllString(validatorString, "")
+}
+
+// isEmptyValue checks whether value empty or not
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.String, reflect.Array:
+ return v.Len() == 0
+ case reflect.Map, reflect.Slice:
+ return v.Len() == 0 || v.IsNil()
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ }
+
+ return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
+}
+
+// ErrorByField returns error for specified field of the struct
+// validated by ValidateStruct or empty string if there are no errors
+// or this field doesn't exists or doesn't have any errors.
+func ErrorByField(e error, field string) string {
+ if e == nil {
+ return ""
+ }
+ return ErrorsByField(e)[field]
+}
+
+// ErrorsByField returns map of errors of the struct validated
+// by ValidateStruct or empty map if there are no errors.
+func ErrorsByField(e error) map[string]string {
+ m := make(map[string]string)
+ if e == nil {
+ return m
+ }
+ // prototype for ValidateStruct
+
+ switch e := e.(type) {
+ case Error:
+ m[e.Name] = e.Err.Error()
+ case Errors:
+ for _, item := range e.Errors() {
+ n := ErrorsByField(item)
+ for k, v := range n {
+ m[k] = v
+ }
+ }
+ }
+
+ return m
+}
+
+// Error returns string equivalent for reflect.Type
+func (e *UnsupportedTypeError) Error() string {
+ return "validator: unsupported type: " + e.Type.String()
+}
+
+func (sv stringValues) Len() int { return len(sv) }
+func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
+func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
+func (sv stringValues) get(i int) string { return sv[i].String() }
+
+func IsE164(str string) bool {
+ return rxE164.MatchString(str)
+}
diff --git a/vendor/github.com/asaskevich/govalidator/wercker.yml b/vendor/github.com/asaskevich/govalidator/wercker.yml
new file mode 100644
index 000000000000..bc5f7b0864bd
--- /dev/null
+++ b/vendor/github.com/asaskevich/govalidator/wercker.yml
@@ -0,0 +1,15 @@
+box: golang
+build:
+ steps:
+ - setup-go-workspace
+
+ - script:
+ name: go get
+ code: |
+ go version
+ go get -t ./...
+
+ - script:
+ name: go test
+ code: |
+ go test -race -v ./...
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
index 89449f67b266..372d0f9839ab 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
@@ -3,4 +3,4 @@
package aws
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.38.1"
+const goModuleVersion = "1.39.6"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go
index 6ee3391be273..3314230fd8ca 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go
@@ -135,6 +135,8 @@ const (
UserAgentFeatureCredentialsAwsSdkStore = "y" // n/a (this is used by .NET based sdk)
UserAgentFeatureCredentialsHTTP = "z"
UserAgentFeatureCredentialsIMDS = "0"
+
+ UserAgentFeatureBearerServiceEnvVars = "3"
)
var credentialSourceToFeature = map[aws.CredentialSource]UserAgentFeature{
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md
index 73d112597f02..50a42b248cac 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md
@@ -1,3 +1,11 @@
+# v1.7.2 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+
+# v1.7.1 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+
# v1.7.0 (2025-07-28)
* **Feature**: Add support for HTTP interceptors.
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go
index 7b63c276311c..d37513c837fc 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go
@@ -3,4 +3,4 @@
package eventstream
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.7.0"
+const goModuleVersion = "1.7.2"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/timeout_read_closer.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/timeout_read_closer.go
index 993929bd9b7a..4881ae1445b6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/timeout_read_closer.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/timeout_read_closer.go
@@ -64,6 +64,11 @@ func (r *timeoutReadCloser) Close() error {
// AddResponseReadTimeoutMiddleware adds a middleware to the stack that wraps the
// response body so that a read that takes too long will return an error.
+//
+// Deprecated: This API was previously exposed to customize behavior of the
+// Kinesis service. That customization has been removed and this middleware's
+// implementation can cause panics within the standard library networking loop.
+// See #2752.
func AddResponseReadTimeoutMiddleware(stack *middleware.Stack, duration time.Duration) error {
return stack.Deserialize.Add(&readTimeout{duration: duration}, middleware.After)
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
index 7c5a87fbe7c0..b6e17fb82efd 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
@@ -1,3 +1,74 @@
+# v1.31.20 (2025-11-12)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.19 (2025-11-11)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.18 (2025-11-10)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.17 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.31.16 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.15 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.14 (2025-10-22)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.13 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.12 (2025-09-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.11 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.10 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.9 (2025-09-22)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.8 (2025-09-10)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.5 (2025-08-28)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.31.4 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.31.3 (2025-08-26)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
index 0e8449a5f06b..b9582cdb6dcf 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
@@ -3,4 +3,4 @@
package config
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.31.3"
+const goModuleVersion = "1.31.20"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
index 6a3ab82df511..7ca5a13402ce 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
@@ -1,3 +1,74 @@
+# v1.18.24 (2025-11-12)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.23 (2025-11-11)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.22 (2025-11-10)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.21 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.18.20 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.19 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.18 (2025-10-22)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.17 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.16 (2025-09-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.15 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.14 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.13 (2025-09-22)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.12 (2025-09-10)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.11 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.10 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.9 (2025-08-28)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.8 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.18.7 (2025-08-26)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
index 9d3c95a4e8c1..bbcdcea37af8 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
@@ -3,4 +3,4 @@
package credentials
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.18.7"
+const goModuleVersion = "1.18.24"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
index dcda88e2067e..cfb9d77fe05b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
@@ -1,3 +1,42 @@
+# v1.18.13 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.18.12 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.11 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.10 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.18.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.18.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
index 48db67d7e2d4..1af019aec274 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
@@ -3,4 +3,4 @@
package imds
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.18.4"
+const goModuleVersion = "1.18.13"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
index 48b7efd9d6c4..0981931aa785 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
@@ -1,3 +1,42 @@
+# v1.4.13 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.4.12 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.11 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.10 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.4.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
index e304ef67cf6a..970e61deed8a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
@@ -3,4 +3,4 @@
package configsources
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.4.4"
+const goModuleVersion = "1.4.13"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.go
index 83e5ac62bf76..6ab4d9669fb9 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.go
@@ -3,7 +3,8 @@
package awsrulesfn
// GetPartition returns an AWS [Partition] for the region provided. If the
-// partition cannot be determined nil will be returned.
+// partition cannot be determined then the default partition (AWS commercial)
+// will be returned.
func GetPartition(region string) *PartitionConfig {
return getPartition(partitions, region)
}
@@ -112,6 +113,13 @@ var partitions = []Partition{
SupportsFIPS: nil,
SupportsDualStack: nil,
},
+ "ap-southeast-6": {
+ Name: nil,
+ DnsSuffix: nil,
+ DualStackDnsSuffix: nil,
+ SupportsFIPS: nil,
+ SupportsDualStack: nil,
+ },
"ap-southeast-7": {
Name: nil,
DnsSuffix: nil,
@@ -304,7 +312,7 @@ var partitions = []Partition{
DnsSuffix: "amazonaws.eu",
DualStackDnsSuffix: "api.amazonwebservices.eu",
SupportsFIPS: true,
- SupportsDualStack: false,
+ SupportsDualStack: true,
ImplicitGlobalRegion: "eusc-de-east-1",
},
Regions: map[string]RegionOverrides{
@@ -325,7 +333,7 @@ var partitions = []Partition{
DnsSuffix: "c2s.ic.gov",
DualStackDnsSuffix: "api.aws.ic.gov",
SupportsFIPS: true,
- SupportsDualStack: false,
+ SupportsDualStack: true,
ImplicitGlobalRegion: "us-iso-east-1",
},
Regions: map[string]RegionOverrides{
@@ -360,7 +368,7 @@ var partitions = []Partition{
DnsSuffix: "sc2s.sgov.gov",
DualStackDnsSuffix: "api.aws.scloud",
SupportsFIPS: true,
- SupportsDualStack: false,
+ SupportsDualStack: true,
ImplicitGlobalRegion: "us-isob-east-1",
},
Regions: map[string]RegionOverrides{
@@ -378,6 +386,13 @@ var partitions = []Partition{
SupportsFIPS: nil,
SupportsDualStack: nil,
},
+ "us-isob-west-1": {
+ Name: nil,
+ DnsSuffix: nil,
+ DualStackDnsSuffix: nil,
+ SupportsFIPS: nil,
+ SupportsDualStack: nil,
+ },
},
},
{
@@ -388,7 +403,7 @@ var partitions = []Partition{
DnsSuffix: "cloud.adc-e.uk",
DualStackDnsSuffix: "api.cloud-aws.adc-e.uk",
SupportsFIPS: true,
- SupportsDualStack: false,
+ SupportsDualStack: true,
ImplicitGlobalRegion: "eu-isoe-west-1",
},
Regions: map[string]RegionOverrides{
@@ -416,7 +431,7 @@ var partitions = []Partition{
DnsSuffix: "csp.hci.ic.gov",
DualStackDnsSuffix: "api.aws.hci.ic.gov",
SupportsFIPS: true,
- SupportsDualStack: false,
+ SupportsDualStack: true,
ImplicitGlobalRegion: "us-isof-south-1",
},
Regions: map[string]RegionOverrides{
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.json b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.json
index 299cb220419f..c789264d2b0e 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.json
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.json
@@ -50,6 +50,9 @@
"ap-southeast-5" : {
"description" : "Asia Pacific (Malaysia)"
},
+ "ap-southeast-6" : {
+ "description" : "Asia Pacific (New Zealand)"
+ },
"ap-southeast-7" : {
"description" : "Asia Pacific (Thailand)"
},
@@ -143,7 +146,7 @@
"dualStackDnsSuffix" : "api.amazonwebservices.eu",
"implicitGlobalRegion" : "eusc-de-east-1",
"name" : "aws-eusc",
- "supportsDualStack" : false,
+ "supportsDualStack" : true,
"supportsFIPS" : true
},
"regionRegex" : "^eusc\\-(de)\\-\\w+\\-\\d+$",
@@ -159,7 +162,7 @@
"dualStackDnsSuffix" : "api.aws.ic.gov",
"implicitGlobalRegion" : "us-iso-east-1",
"name" : "aws-iso",
- "supportsDualStack" : false,
+ "supportsDualStack" : true,
"supportsFIPS" : true
},
"regionRegex" : "^us\\-iso\\-\\w+\\-\\d+$",
@@ -181,7 +184,7 @@
"dualStackDnsSuffix" : "api.aws.scloud",
"implicitGlobalRegion" : "us-isob-east-1",
"name" : "aws-iso-b",
- "supportsDualStack" : false,
+ "supportsDualStack" : true,
"supportsFIPS" : true
},
"regionRegex" : "^us\\-isob\\-\\w+\\-\\d+$",
@@ -191,6 +194,9 @@
},
"us-isob-east-1" : {
"description" : "US ISOB East (Ohio)"
+ },
+ "us-isob-west-1" : {
+ "description" : "US ISOB West"
}
}
}, {
@@ -200,7 +206,7 @@
"dualStackDnsSuffix" : "api.cloud-aws.adc-e.uk",
"implicitGlobalRegion" : "eu-isoe-west-1",
"name" : "aws-iso-e",
- "supportsDualStack" : false,
+ "supportsDualStack" : true,
"supportsFIPS" : true
},
"regionRegex" : "^eu\\-isoe\\-\\w+\\-\\d+$",
@@ -219,7 +225,7 @@
"dualStackDnsSuffix" : "api.aws.hci.ic.gov",
"implicitGlobalRegion" : "us-isof-south-1",
"name" : "aws-iso-f",
- "supportsDualStack" : false,
+ "supportsDualStack" : true,
"supportsFIPS" : true
},
"regionRegex" : "^us\\-isof\\-\\w+\\-\\d+$",
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md
index ec7d54beffda..9c3aafe1da13 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md
@@ -1,3 +1,42 @@
+# v2.7.13 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v2.7.12 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.11 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.10 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v2.7.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v2.7.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
index e7b4e1cd18cf..9675feb419bb 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
@@ -3,4 +3,4 @@
package endpoints
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "2.7.4"
+const goModuleVersion = "2.7.13"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/CHANGELOG.md
index f729db535b72..4791d328c042 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/CHANGELOG.md
@@ -1,3 +1,7 @@
+# v1.8.4 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+
# v1.8.3 (2025-02-18)
* **Bug Fix**: Bump go version to 1.22
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/go_module_metadata.go
index 00df0e3cb9bc..f94970e7742c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/ini/go_module_metadata.go
@@ -3,4 +3,4 @@
package ini
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.8.3"
+const goModuleVersion = "1.8.4"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md
index 637b81ddd63f..e9f7fa2c253b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md
@@ -1,3 +1,37 @@
+# v1.4.12 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.11 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.10 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.4.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.4.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go
index 0eb6d8d74d13..894656d2d9a5 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go
@@ -3,4 +3,4 @@
package v4a
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.4.4"
+const goModuleVersion = "1.4.12"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md
index 32c9d515746a..c05f82ea411f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md
@@ -1,3 +1,15 @@
+# v1.13.3 (2025-11-04)
+
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.13.2 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+
+# v1.13.1 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+
# v1.13.0 (2025-07-28)
* **Feature**: Add support for HTTP interceptors.
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go
index f4b9f0b94886..6a4c336055a4 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go
@@ -3,4 +3,4 @@
package acceptencoding
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.13.0"
+const goModuleVersion = "1.13.3"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/CHANGELOG.md
index 0cb8b67bfd5f..ca333b4104ad 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/CHANGELOG.md
@@ -1,3 +1,41 @@
+# v1.9.3 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.9.2 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.9.1 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.9.0 (2025-10-07)
+
+* **Feature**: Cache first calculated checksum and reuse it in retry, this feature avoids checksum re-calculation and enables request payload consistency check among attempts.
+
+# v1.8.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.8.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.8.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.8.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.8.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.8.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/go_module_metadata.go
index df89189f6e08..ad97e8fc7903 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/go_module_metadata.go
@@ -3,4 +3,4 @@
package checksum
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.8.4"
+const goModuleVersion = "1.9.3"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/middleware_compute_input_checksum.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/middleware_compute_input_checksum.go
index 31853839c765..348264bdb25c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/middleware_compute_input_checksum.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/checksum/middleware_compute_input_checksum.go
@@ -65,6 +65,10 @@ type ComputeInputPayloadChecksum struct {
// when used with trailing checksums, and aws-chunked content-encoding.
EnableDecodedContentLengthHeader bool
+ checksum string
+
+ sha256Checksum string
+
useTrailer bool
}
@@ -186,22 +190,29 @@ func (m *ComputeInputPayloadChecksum) HandleFinalize(
}
var sha256Checksum string
- checksum, sha256Checksum, err = computeStreamChecksum(
- algorithm, stream, computePayloadHash)
- if err != nil {
- return out, metadata, computeInputHeaderChecksumError{
- Msg: "failed to compute stream checksum",
- Err: err,
- }
- }
- // only attempt rewind if the stream length has been determined and is non-zero
- if streamLength > 0 {
- if err := req.RewindStream(); err != nil {
+ if m.checksum != "" {
+ checksum = m.checksum
+ sha256Checksum = m.sha256Checksum
+ } else {
+ checksum, sha256Checksum, err = computeStreamChecksum(
+ algorithm, stream, computePayloadHash)
+ if err != nil {
return out, metadata, computeInputHeaderChecksumError{
- Msg: "failed to rewind stream",
+ Msg: "failed to compute stream checksum",
Err: err,
}
}
+ m.checksum = checksum
+ m.sha256Checksum = sha256Checksum
+ // only attempt rewind if the stream length has been determined and is non-zero
+ if streamLength > 0 {
+ if err := req.RewindStream(); err != nil {
+ return out, metadata, computeInputHeaderChecksumError{
+ Msg: "failed to rewind stream",
+ Err: err,
+ }
+ }
+ }
}
checksumHeader := AlgorithmHTTPHeader(algorithm)
@@ -238,6 +249,7 @@ type AddInputChecksumTrailer struct {
EnableTrailingChecksum bool
EnableComputePayloadHash bool
EnableDecodedContentLengthHeader bool
+ checksum string
}
// ID identifies this middleware.
@@ -314,7 +326,12 @@ func (m *AddInputChecksumTrailer) HandleFinalize(
awsChunkedReader := newUnsignedAWSChunkedEncoding(checksumReader,
func(o *awsChunkedEncodingOptions) {
o.Trailers[AlgorithmHTTPHeader(checksumReader.Algorithm())] = awsChunkedTrailerValue{
- Get: checksumReader.Base64Checksum,
+ Get: func() (string, error) {
+ if m.checksum != "" {
+ return m.checksum, nil
+ }
+ return checksumReader.Base64Checksum()
+ },
Length: checksumReader.Base64ChecksumLength(),
}
o.StreamLength = streamLength
@@ -346,17 +363,27 @@ func (m *AddInputChecksumTrailer) HandleFinalize(
out, metadata, err = next.HandleFinalize(ctx, in)
if err == nil {
- checksum, err := checksumReader.Base64Checksum()
- if err != nil {
- return out, metadata, fmt.Errorf("failed to get computed checksum, %w", err)
+ checksum := m.checksum
+ var e error
+ if checksum == "" {
+ checksum, e = checksumReader.Base64Checksum()
+ if e != nil {
+ return out, metadata, fmt.Errorf("failed to get computed checksum, %w", e)
+ }
}
-
// Record the checksum and algorithm that was computed
SetComputedInputChecksums(&metadata, map[string]string{
string(algorithm): checksum,
})
}
-
+ // store the calculated checksum if there's no one cached previously and the value is available in this attempt,
+ // no matter if the request failed or not
+ if m.checksum == "" {
+ checksum, e := checksumReader.Base64Checksum()
+ if e == nil {
+ m.checksum = checksum
+ }
+ }
return out, metadata, err
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md
index 62da8050f3b5..2021865dd0ed 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md
@@ -1,3 +1,42 @@
+# v1.13.13 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.13.12 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.11 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.10 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.13.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.13.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go
index 4a0c6ae3c9c2..9d29218c3136 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go
@@ -3,4 +3,4 @@
package presignedurl
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.13.4"
+const goModuleVersion = "1.13.13"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/CHANGELOG.md
index d4dcf9d694e5..095f95d2d6bd 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/CHANGELOG.md
@@ -1,3 +1,37 @@
+# v1.19.12 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.11 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.10 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.9 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.8 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.7 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.6 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.19.5 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.19.4 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go
index 7ddf2e5e7e40..8f32d6619658 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go
@@ -3,4 +3,4 @@
package s3shared
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.19.4"
+const goModuleVersion = "1.19.12"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/CHANGELOG.md
index 81a4c25f824e..9fc53a62cfe4 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/CHANGELOG.md
@@ -1,3 +1,54 @@
+# v1.89.1 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.89.0 (2025-10-28)
+
+* **Feature**: Amazon Simple Storage Service / Features: Add conditional writes in CopyObject on destination key to prevent unintended object modifications.
+
+# v1.88.7 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.88.6 (2025-10-22)
+
+* No change notes available for this release.
+
+# v1.88.5 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.88.4 (2025-10-07)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.88.3 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.88.2 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.88.1 (2025-09-10)
+
+* No change notes available for this release.
+
+# v1.88.0 (2025-09-08)
+
+* **Feature**: This release includes backward compatibility work on the "Expires" parameter.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.87.3 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.87.2 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.87.1 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_AbortMultipartUpload.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_AbortMultipartUpload.go
index 35d55ea81195..8cfbb10fb159 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_AbortMultipartUpload.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_AbortMultipartUpload.go
@@ -72,6 +72,10 @@ import (
//
// [ListMultipartUploads]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListParts]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [UploadPart]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CompleteMultipartUpload.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CompleteMultipartUpload.go
index d428c98c9df7..a43a07577df6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CompleteMultipartUpload.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CompleteMultipartUpload.go
@@ -131,6 +131,10 @@ import (
//
// [ListMultipartUploads]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Uploading Objects Using Multipart Upload]: https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html
// [Amazon S3 Error Best Practices]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ErrorBestPractices.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
@@ -370,7 +374,7 @@ type CompleteMultipartUploadOutput struct {
BucketKeyEnabled *bool
// The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only
- // be present if the checksum was uploaded with the object. When you use an API
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -399,8 +403,8 @@ type CompleteMultipartUploadOutput struct {
// [Checking object integrity in the Amazon S3 User Guide]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use the API
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use the API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -410,8 +414,8 @@ type CompleteMultipartUploadOutput struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#large-object-checksums
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use an API
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CopyObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CopyObject.go
index f593667eaf1f..68e70c682f61 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CopyObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CopyObject.go
@@ -15,19 +15,17 @@ import (
"time"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will discontinue
-// support for creating new Email Grantee Access Control Lists (ACL). Email Grantee
-// ACLs created prior to this date will continue to work and remain accessible
-// through the Amazon Web Services Management Console, Command Line Interface
-// (CLI), SDKs, and REST API. However, you will no longer be able to create new
-// Email Grantee ACLs.
+// Creates a copy of an object that is already stored in Amazon S3.
//
-// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
//
-// Creates a copy of an object that is already stored in Amazon S3.
+// This change affects the following Amazon Web Services Regions: US East (N.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
//
// You can store individual objects of up to 5 TB in Amazon S3. You create a copy
// of your object up to 5 GB in size in a single atomic action using this API.
@@ -164,6 +162,10 @@ import (
//
// [GetObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-security-iam-identity-policies.html
// [Resolve the Error 200 response when copying objects to Amazon S3]: https://repost.aws/knowledge-center/s3-resolve-200-internalerror
@@ -518,6 +520,32 @@ type CopyObjectInput struct {
// - This functionality is not supported for Amazon S3 on Outposts.
GrantWriteACP *string
+ // Copies the object if the entity tag (ETag) of the destination object matches
+ // the specified tag. If the ETag values do not match, the operation returns a 412
+ // Precondition Failed error. If a concurrent operation occurs during the upload S3
+ // returns a 409 ConditionalRequestConflict response. On a 409 failure you should
+ // fetch the object's ETag and retry the upload.
+ //
+ // Expects the ETag value as a string.
+ //
+ // For more information about conditional requests, see [RFC 7232].
+ //
+ // [RFC 7232]: https://tools.ietf.org/html/rfc7232
+ IfMatch *string
+
+ // Copies the object only if the object key name at the destination does not
+ // already exist in the bucket specified. Otherwise, Amazon S3 returns a 412
+ // Precondition Failed error. If a concurrent operation occurs during the upload S3
+ // returns a 409 ConditionalRequestConflict response. On a 409 failure you should
+ // retry the upload.
+ //
+ // Expects the '*' (asterisk) character.
+ //
+ // For more information about conditional requests, see [RFC 7232].
+ //
+ // [RFC 7232]: https://tools.ietf.org/html/rfc7232
+ IfNoneMatch *string
+
// A map of metadata to store with the object in S3.
Metadata map[string]string
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucket.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucket.go
index e5365fbf2bd0..14a5cd3b071f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucket.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucket.go
@@ -14,28 +14,15 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will discontinue
-// support for creating new Email Grantee Access Control Lists (ACL). Email Grantee
-// ACLs created prior to this date will continue to work and remain accessible
-// through the Amazon Web Services Management Console, Command Line Interface
-// (CLI), SDKs, and REST API. However, you will no longer be able to create new
-// Email Grantee ACLs.
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
//
// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
-//
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
-// DisplayName .
-//
-// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
//
// This action creates an Amazon S3 bucket. To create an Amazon S3 on Outposts
// bucket, see [CreateBucket]CreateBucket .
@@ -136,6 +123,10 @@ import (
//
// [DeleteBucket]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Creating, configuring, and working with Amazon S3 buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-buckets-s3.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [PutObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataConfiguration.go
index aef91a974a39..395513a11c53 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataConfiguration.go
@@ -60,6 +60,10 @@ import (
//
// [UpdateBucketMetadataJournalTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketMetadataConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetadataConfiguration.html
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [UpdateBucketMetadataJournalTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateBucketMetadataJournalTableConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataTableConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataTableConfiguration.go
index f920f7aaf363..3dc59aaa8a62 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataTableConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateBucketMetadataTableConfiguration.go
@@ -54,6 +54,10 @@ import (
//
// [GetBucketMetadataTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [GetBucketMetadataTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetadataTableConfiguration.html
// [DeleteBucketMetadataTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketMetadataTableConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateMultipartUpload.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateMultipartUpload.go
index 1195c232d094..e9874b036f00 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateMultipartUpload.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateMultipartUpload.go
@@ -14,17 +14,15 @@ import (
"time"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will discontinue
-// support for creating new Email Grantee Access Control Lists (ACL). Email Grantee
-// ACLs created prior to this date will continue to work and remain accessible
-// through the Amazon Web Services Management Console, Command Line Interface
-// (CLI), SDKs, and REST API. However, you will no longer be able to create new
-// Email Grantee ACLs.
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
//
// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
//
// This action initiates a multipart upload and returns an upload ID. This upload
// ID is used to associate all of the parts in the specific multipart upload. You
@@ -214,6 +212,10 @@ import (
//
// [ListMultipartUploads]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [ListParts]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html
// [UploadPart]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateSession.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateSession.go
index 2ed480363d2f..35f4001ea00d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateSession.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_CreateSession.go
@@ -123,6 +123,10 @@ import (
// HTTP Host header syntax Directory buckets - The HTTP Host header syntax is
// Bucket-name.s3express-zone-id.region-code.amazonaws.com .
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Specifying server-side encryption with KMS for new object uploads]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-specifying-kms-encryption.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Performance guidelines and design patterns]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-optimizing-performance-guidelines-design-patterns.html#s3-express-optimizing-performance-session-authentication
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucket.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucket.go
index dda0b97174a3..bb2e720034e1 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucket.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucket.go
@@ -49,6 +49,10 @@ import (
//
// [DeleteObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [DeleteObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html
// [CreateBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketAnalyticsConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketAnalyticsConfiguration.go
index f1b1e2149534..4a0d73efc97e 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketAnalyticsConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketAnalyticsConfiguration.go
@@ -33,6 +33,10 @@ import (
//
// [PutBucketAnalyticsConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Analytics – Storage Class Analysis]: https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [GetBucketAnalyticsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAnalyticsConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketCors.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketCors.go
index d45bed38b6f4..2bcfacf15696 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketCors.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketCors.go
@@ -29,6 +29,10 @@ import (
//
// [RESTOPTIONSobject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketCors]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html
// [Enabling Cross-Origin Resource Sharing]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html
// [RESTOPTIONSobject]: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTOPTIONSobject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketEncryption.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketEncryption.go
index 310e48b31ccb..fb3346f0e1f9 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketEncryption.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketEncryption.go
@@ -46,6 +46,10 @@ import (
//
// [GetBucketEncryption]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketEncryption]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html
// [PutBucketEncryption]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html
// [Setting default server-side encryption behavior for directory buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-bucket-encryption.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketIntelligentTieringConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketIntelligentTieringConfiguration.go
index b6fdc8d4aa6f..10095cdbe626 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketIntelligentTieringConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketIntelligentTieringConfiguration.go
@@ -41,6 +41,10 @@ import (
//
// [ListBucketIntelligentTieringConfigurations]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListBucketIntelligentTieringConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketIntelligentTieringConfigurations.html
// [GetBucketIntelligentTieringConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketIntelligentTieringConfiguration.html
// [PutBucketIntelligentTieringConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketIntelligentTieringConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketInventoryConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketInventoryConfiguration.go
index 40ce0377149a..6352e36d0138 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketInventoryConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketInventoryConfiguration.go
@@ -33,6 +33,10 @@ import (
//
// [ListBucketInventoryConfigurations]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Inventory]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html
// [ListBucketInventoryConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketInventoryConfigurations.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketLifecycle.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketLifecycle.go
index 1871b2688724..feca85c27bd6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketLifecycle.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketLifecycle.go
@@ -60,6 +60,10 @@ import (
//
// [GetBucketLifecycleConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketLifecycleConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html
// [Elements to Describe Lifecycle Actions]: https://docs.aws.amazon.com/AmazonS3/latest/dev/intro-lifecycle-rules.html#intro-lifecycle-rules-actions
// [GetBucketLifecycleConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataConfiguration.go
index 1fa3599ee362..112954298100 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataConfiguration.go
@@ -38,6 +38,10 @@ import (
//
// [UpdateBucketMetadataJournalTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketMetadataConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetadataConfiguration.html
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [UpdateBucketMetadataJournalTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateBucketMetadataJournalTableConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataTableConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataTableConfiguration.go
index 1ef17a359554..1faa0dcad912 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataTableConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetadataTableConfiguration.go
@@ -44,6 +44,10 @@ import (
//
// [GetBucketMetadataTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [GetBucketMetadataTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetadataTableConfiguration.html
// [CreateBucketMetadataTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucketMetadataTableConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetricsConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetricsConfiguration.go
index 68e6a5b73716..4a20e0ba6139 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetricsConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketMetricsConfiguration.go
@@ -36,6 +36,10 @@ import (
//
// [Monitoring Metrics with Amazon CloudWatch]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [Monitoring Metrics with Amazon CloudWatch]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html
// [GetBucketMetricsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetricsConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketOwnershipControls.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketOwnershipControls.go
index 341f123cf946..1bd386e23778 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketOwnershipControls.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketOwnershipControls.go
@@ -27,6 +27,10 @@ import (
//
// # PutBucketOwnershipControls
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Using Object Ownership]: https://docs.aws.amazon.com/AmazonS3/latest/dev/about-object-ownership.html
// [Specifying Permissions in a Policy]: https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html
func (c *Client) DeleteBucketOwnershipControls(ctx context.Context, params *DeleteBucketOwnershipControlsInput, optFns ...func(*Options)) (*DeleteBucketOwnershipControlsOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketPolicy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketPolicy.go
index 564fba34f6c4..cda71fd91d1f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketPolicy.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketPolicy.go
@@ -60,6 +60,10 @@ import (
//
// [DeleteObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [DeleteObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html
// [Using Bucket Policies and User Policies]: https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketReplication.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketReplication.go
index 1fa0f46986fc..974ad7da7a89 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketReplication.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketReplication.go
@@ -34,6 +34,10 @@ import (
//
// [GetBucketReplication]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketReplication]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [PutBucketReplication]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketTagging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketTagging.go
index 9d678376c590..3fb7dd0f6bc0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketTagging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketTagging.go
@@ -27,6 +27,10 @@ import (
//
// [PutBucketTagging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html
// [PutBucketTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html
func (c *Client) DeleteBucketTagging(ctx context.Context, params *DeleteBucketTaggingInput, optFns ...func(*Options)) (*DeleteBucketTaggingOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketWebsite.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketWebsite.go
index bd0eadf38d36..0377abd9a088 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketWebsite.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteBucketWebsite.go
@@ -35,6 +35,10 @@ import (
//
// [PutBucketWebsite]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketWebsite]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketWebsite.html
// [PutBucketWebsite]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketWebsite.html
// [Hosting Websites on Amazon S3]: https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObject.go
index 454f15b07a41..b7d2ca5deea8 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObject.go
@@ -96,6 +96,14 @@ import (
//
// [PutObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
+// The If-Match header is supported for both general purpose and directory
+// buckets. IfMatchLastModifiedTime and IfMatchSize is only supported for
+// directory buckets.
+//
// [Sample Request]: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html#ExampleVersionObjectDelete
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Deleting objects from versioning-suspended buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/DeletingObjectsfromVersioningSuspendedBuckets.html
@@ -177,14 +185,14 @@ type DeleteObjectInput struct {
// status code 403 Forbidden (access denied).
ExpectedBucketOwner *string
- // The If-Match header field makes the request method conditional on ETags. If the
- // ETag value does not match, the operation returns a 412 Precondition Failed
- // error. If the ETag matches or if the object doesn't exist, the operation will
- // return a 204 Success (No Content) response .
+ // Deletes the object if the ETag (entity tag) value provided during the delete
+ // operation matches the ETag of the object in S3. If the ETag values do not match,
+ // the operation returns a 412 Precondition Failed error.
//
- // For more information about conditional requests, see [RFC 7232].
+ // Expects the ETag value as a string. If-Match does accept a string value of an
+ // '*' (asterisk) character to denote a match of any ETag.
//
- // This functionality is only supported for directory buckets.
+ // For more information about conditional requests, see [RFC 7232].
//
// [RFC 7232]: https://tools.ietf.org/html/rfc7232
IfMatch *string
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjectTagging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjectTagging.go
index f105f09628f1..47227b6b1477 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjectTagging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjectTagging.go
@@ -30,6 +30,10 @@ import (
//
// [GetObjectTagging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutObjectTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html
// [Object Tagging]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-tagging.html
// [GetObjectTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjects.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjects.go
index 53424ad6a49e..650a93b524e4 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjects.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeleteObjects.go
@@ -104,6 +104,10 @@ import (
//
// [AbortMultipartUpload]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [ListParts]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html
// [AbortMultipartUpload]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeletePublicAccessBlock.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeletePublicAccessBlock.go
index 6096be7b784a..7fb22427a6a2 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeletePublicAccessBlock.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_DeletePublicAccessBlock.go
@@ -29,6 +29,10 @@ import (
//
// [GetBucketPolicyStatus]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetPublicAccessBlock.html
// [PutPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutPublicAccessBlock.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAccelerateConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAccelerateConfiguration.go
index d905b6a7248b..afb13625f7e8 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAccelerateConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAccelerateConfiguration.go
@@ -40,6 +40,10 @@ import (
//
// [PutBucketAccelerateConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketAccelerateConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAccelerateConfiguration.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [Managing Access Permissions to your Amazon S3 Resources]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAcl.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAcl.go
index 6fd57ef54d7c..8624f3bcb325 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAcl.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAcl.go
@@ -14,10 +14,10 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -47,6 +47,10 @@ import (
// bucket-owner-full-control ACL with the owner being the account that created the
// bucket. For more information, see [Controlling object ownership and disabling ACLs]in the Amazon S3 User Guide.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// The following operations are related to GetBucketAcl :
//
// [ListObjects]
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAnalyticsConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAnalyticsConfiguration.go
index 2d1f41fe7cf6..c2fa47a92dfc 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAnalyticsConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketAnalyticsConfiguration.go
@@ -35,6 +35,10 @@ import (
//
// [PutBucketAnalyticsConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Analytics – Storage Class Analysis]: https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html
// [DeleteBucketAnalyticsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketAnalyticsConfiguration.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketCors.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketCors.go
index 0fa6c3eb3255..8bee103ec2c5 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketCors.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketCors.go
@@ -40,6 +40,10 @@ import (
//
// [DeleteBucketCors]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketCors]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html
// [Enabling Cross-Origin Resource Sharing]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html
// [List of Error Codes]: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketEncryption.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketEncryption.go
index 183bca49604a..f96a0924e4e9 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketEncryption.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketEncryption.go
@@ -48,6 +48,10 @@ import (
//
// [DeleteBucketEncryption]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [DeleteBucketEncryption]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html
// [PutBucketEncryption]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html
// [Setting default server-side encryption behavior for directory buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-bucket-encryption.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketIntelligentTieringConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketIntelligentTieringConfiguration.go
index 29969eae580a..c129c8afb23b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketIntelligentTieringConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketIntelligentTieringConfiguration.go
@@ -42,6 +42,10 @@ import (
//
// [ListBucketIntelligentTieringConfigurations]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListBucketIntelligentTieringConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketIntelligentTieringConfigurations.html
// [PutBucketIntelligentTieringConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketIntelligentTieringConfiguration.html
// [Storage class for automatically optimizing frequently and infrequently accessed objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html#sc-dynamic-data-access
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketInventoryConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketInventoryConfiguration.go
index 2bfff901c373..55f5c172cb7a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketInventoryConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketInventoryConfiguration.go
@@ -34,6 +34,10 @@ import (
//
// [PutBucketInventoryConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Inventory]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html
// [ListBucketInventoryConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketInventoryConfigurations.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLifecycleConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLifecycleConfiguration.go
index 89f2b1f2398a..2ee20be617f0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLifecycleConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLifecycleConfiguration.go
@@ -80,6 +80,10 @@ import (
//
// [DeleteBucketLifecycle]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketLifecycle]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycle.html
// [Object Lifecycle Management]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html
// [Authorizing Regional endpoint APIs with IAM]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-security-iam.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLocation.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLocation.go
index 10b781392473..be94c8c3cd07 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLocation.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLocation.go
@@ -20,12 +20,23 @@ import (
"io"
)
-// This operation is not supported for directory buckets.
+// Using the GetBucketLocation operation is no longer a best practice. To return
+// the Region that a bucket resides in, we recommend that you use the [HeadBucket]operation
+// instead. For backward compatibility, Amazon S3 continues to support the
+// GetBucketLocation operation.
//
// Returns the Region the bucket resides in. You set the bucket's Region using the
// LocationConstraint request parameter in a CreateBucket request. For more
// information, see [CreateBucket].
//
+// In a bucket's home Region, calls to the GetBucketLocation operation are
+// governed by the bucket's policy. In other Regions, the bucket policy doesn't
+// apply, which means that cross-account access won't be authorized. However, calls
+// to the HeadBucket operation always return the bucket’s location through an HTTP
+// response header, whether access to the bucket is authorized or not. Therefore,
+// we recommend using the HeadBucket operation for bucket Region discovery and to
+// avoid using the GetBucketLocation operation.
+//
// When you use this API operation with an access point, provide the alias of the
// access point in place of the bucket name.
//
@@ -35,8 +46,7 @@ import (
// InvalidAccessPointAliasError is returned. For more information about
// InvalidAccessPointAliasError , see [List of Error Codes].
//
-// We recommend that you use [HeadBucket] to return the Region that a bucket resides in. For
-// backward compatibility, Amazon S3 continues to support GetBucketLocation.
+// This operation is not supported for directory buckets.
//
// The following operations are related to GetBucketLocation :
//
@@ -44,6 +54,10 @@ import (
//
// [CreateBucket]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [List of Error Codes]: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
// [CreateBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html
// [GetObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLogging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLogging.go
index 45142425b9aa..c45f1f860528 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLogging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketLogging.go
@@ -14,10 +14,10 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -36,6 +36,10 @@ import (
//
// [PutBucketLogging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketLogging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLogging.html
// [CreateBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html
func (c *Client) GetBucketLogging(ctx context.Context, params *GetBucketLoggingInput, optFns ...func(*Options)) (*GetBucketLoggingOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataConfiguration.go
index 8f6b2609d8ea..3a7310e21eaa 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataConfiguration.go
@@ -38,6 +38,10 @@ import (
//
// [UpdateBucketMetadataJournalTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [UpdateBucketMetadataJournalTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateBucketMetadataJournalTableConfiguration.html
// [Accelerating data discovery with S3 Metadata]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-overview.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataTableConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataTableConfiguration.go
index eccbb6bee039..936d771887a5 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataTableConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetadataTableConfiguration.go
@@ -45,6 +45,10 @@ import (
//
// [DeleteBucketMetadataTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [CreateBucketMetadataTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucketMetadataTableConfiguration.html
// [DeleteBucketMetadataTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketMetadataTableConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetricsConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetricsConfiguration.go
index 54a3027d206a..544f299e7b38 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetricsConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketMetricsConfiguration.go
@@ -36,6 +36,10 @@ import (
//
// [Monitoring Metrics with Amazon CloudWatch]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [Monitoring Metrics with Amazon CloudWatch]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html
// [ListBucketMetricsConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketMetricsConfigurations.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketNotificationConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketNotificationConfiguration.go
index d2de8bc5fa5e..bdce1f85436f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketNotificationConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketNotificationConfiguration.go
@@ -42,6 +42,10 @@ import (
//
// [PutBucketNotification]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Using Bucket Policies]: https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html
// [Setting Up Notification of Bucket Events]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
// [List of Error Codes]: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketOwnershipControls.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketOwnershipControls.go
index 0c492f5eb0b1..47a48e8a66f0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketOwnershipControls.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketOwnershipControls.go
@@ -38,6 +38,10 @@ import (
//
// # DeleteBucketOwnershipControls
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Using Object Ownership]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
// [Specifying permissions in a policy]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html
func (c *Client) GetBucketOwnershipControls(ctx context.Context, params *GetBucketOwnershipControlsInput, optFns ...func(*Options)) (*GetBucketOwnershipControlsOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicy.go
index 6cc341d7d818..3545478ea722 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicy.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicy.go
@@ -63,6 +63,10 @@ import (
//
// [GetObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Bucket policy examples]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Example bucket policies for S3 Express One Zone]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-security-iam-example-bucket-policies.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicyStatus.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicyStatus.go
index 76a10e132b49..5097e1480c45 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicyStatus.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketPolicyStatus.go
@@ -33,6 +33,10 @@ import (
//
// [DeletePublicAccessBlock]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetPublicAccessBlock.html
// [PutPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutPublicAccessBlock.html
// [DeletePublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeletePublicAccessBlock.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketReplication.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketReplication.go
index dec0e0a6570f..3a34710f87c9 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketReplication.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketReplication.go
@@ -40,6 +40,10 @@ import (
//
// [DeleteBucketReplication]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketReplication]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html
// [Using Bucket Policies and User Policies]: https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html
// [Replication]: https://docs.aws.amazon.com/AmazonS3/latest/dev/replication.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketRequestPayment.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketRequestPayment.go
index 81e855209a41..4008bc04ef56 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketRequestPayment.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketRequestPayment.go
@@ -23,6 +23,10 @@ import (
//
// [ListObjects]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListObjects]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html
// [Requester Pays Buckets]: https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html
func (c *Client) GetBucketRequestPayment(ctx context.Context, params *GetBucketRequestPaymentInput, optFns ...func(*Options)) (*GetBucketRequestPaymentOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketTagging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketTagging.go
index 29a440048cd6..7b95aedaa2c8 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketTagging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketTagging.go
@@ -34,6 +34,10 @@ import (
//
// [DeleteBucketTagging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html
// [DeleteBucketTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html
func (c *Client) GetBucketTagging(ctx context.Context, params *GetBucketTaggingInput, optFns ...func(*Options)) (*GetBucketTaggingOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketVersioning.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketVersioning.go
index 7f91571619e6..20d42350f00c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketVersioning.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketVersioning.go
@@ -32,6 +32,10 @@ import (
//
// [DeleteObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [DeleteObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html
// [PutObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
// [GetObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketWebsite.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketWebsite.go
index a0601bc0d7d5..c85abb8ab94e 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketWebsite.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetBucketWebsite.go
@@ -31,6 +31,10 @@ import (
//
// [PutBucketWebsite]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketWebsite]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketWebsite.html
// [Hosting Websites on Amazon S3]: https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
// [DeleteBucketWebsite]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketWebsite.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObject.go
index 6d18100eda40..02102e4e0ed0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObject.go
@@ -153,6 +153,10 @@ import (
//
// [GetObjectAcl]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [RestoreObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html
// [Protecting data with server-side encryption]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-serv-side-encryption.html
@@ -450,8 +454,8 @@ type GetObjectOutput struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC32 *string
- // The Base64 encoded, 32-bit CRC32C checksum of the object. This will only be
- // present if the object was uploaded with the object. For more information, see [Checking object integrity]
+ // The Base64 encoded, 32-bit CRC32C checksum of the object. This checksum is only
+ // present if the checksum was uploaded with the object. For more information, see [Checking object integrity]
// in the Amazon S3 User Guide.
//
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
@@ -463,15 +467,15 @@ type GetObjectOutput struct {
// [Checking object integrity in the Amazon S3 User Guide]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. For more information, see [Checking object integrity]
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. For more information, see [Checking object integrity]
// in the Amazon S3 User Guide.
//
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. For more information, see [Checking object integrity]
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. For more information, see [Checking object integrity]
// in the Amazon S3 User Guide.
//
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAcl.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAcl.go
index ec7554529bb6..94117a2f9f9d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAcl.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAcl.go
@@ -13,6 +13,17 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// DisplayName .
+//
+// This change affects the following Amazon Web Services Regions: US East (N.
+// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
+// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
+// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+//
// This operation is not supported for directory buckets.
//
// Returns the access control list (ACL) of an object. To use this operation, you
@@ -40,6 +51,10 @@ import (
//
// [PutObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [DeleteObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html
// [Mapping of ACL permissions and access policy permissions]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#acl-access-policy-permission-mapping
// [GetObjectAttributes]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAttributes.go
index d4c0f41c6470..0eeedfdd1b6a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAttributes.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectAttributes.go
@@ -157,6 +157,10 @@ import (
//
// [ListParts]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Specifying server-side encryption with KMS for new object uploads]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-specifying-kms-encryption.html
// [GetObjectLegalHold]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLegalHold.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLegalHold.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLegalHold.go
index 2ceb969b0597..bf2d0b81000a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLegalHold.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLegalHold.go
@@ -23,6 +23,10 @@ import (
//
// [GetObjectAttributes]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetObjectAttributes]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html
// [Locking Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
func (c *Client) GetObjectLegalHold(ctx context.Context, params *GetObjectLegalHoldInput, optFns ...func(*Options)) (*GetObjectLegalHoldOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLockConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLockConfiguration.go
index 401fe9c23560..f6ba7fe0f0ca 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLockConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectLockConfiguration.go
@@ -23,6 +23,10 @@ import (
//
// [GetObjectAttributes]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetObjectAttributes]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html
// [Locking Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
func (c *Client) GetObjectLockConfiguration(ctx context.Context, params *GetObjectLockConfigurationInput, optFns ...func(*Options)) (*GetObjectLockConfigurationOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectRetention.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectRetention.go
index 58289b515afe..90f28f4943ed 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectRetention.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectRetention.go
@@ -23,6 +23,10 @@ import (
//
// [GetObjectAttributes]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetObjectAttributes]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html
// [Locking Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
func (c *Client) GetObjectRetention(ctx context.Context, params *GetObjectRetentionInput, optFns ...func(*Options)) (*GetObjectRetentionOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTagging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTagging.go
index fac5d36b9e9d..3e2b21cb6e52 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTagging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTagging.go
@@ -38,6 +38,10 @@ import (
//
// [PutObjectTagging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [DeleteObjectTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html
// [PutObjectTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html
// [GetObjectAttributes]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTorrent.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTorrent.go
index 1fa6a28626d9..a99250a9ce7c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTorrent.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetObjectTorrent.go
@@ -31,6 +31,10 @@ import (
//
// [GetObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
func (c *Client) GetObjectTorrent(ctx context.Context, params *GetObjectTorrentInput, optFns ...func(*Options)) (*GetObjectTorrentOutput, error) {
if params == nil {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetPublicAccessBlock.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetPublicAccessBlock.go
index 417ca07a77e5..b9aca77f884b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetPublicAccessBlock.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_GetPublicAccessBlock.go
@@ -40,6 +40,10 @@ import (
//
// [DeletePublicAccessBlock]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetPublicAccessBlock.html
// [PutPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutPublicAccessBlock.html
// [DeletePublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeletePublicAccessBlock.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadBucket.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadBucket.go
index 80a8011b51ee..81404bafbce1 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadBucket.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadBucket.go
@@ -18,13 +18,17 @@ import (
)
// You can use this operation to determine if a bucket exists and if you have
-// permission to access it. The action returns a 200 OK if the bucket exists and
-// you have permission to access it.
+// permission to access it. The action returns a 200 OK HTTP status code if the
+// bucket exists and you have permission to access it. You can make a HeadBucket
+// call on any bucket name to any Region in the partition, and regardless of the
+// permissions on the bucket, you will receive a response header with the correct
+// bucket location so that you can then make a proper, signed request to the
+// appropriate Regional endpoint.
//
-// If the bucket does not exist or you do not have permission to access it, the
-// HEAD request returns a generic 400 Bad Request , 403 Forbidden or 404 Not Found
-// code. A message body is not included, so you cannot determine the exception
-// beyond these HTTP response codes.
+// If the bucket doesn't exist or you don't have permission to access it, the HEAD
+// request returns a generic 400 Bad Request , 403 Forbidden , or 404 Not Found
+// HTTP status code. A message body isn't included, so you can't determine the
+// exception beyond these HTTP response codes.
//
// Authentication and authorization General purpose buckets - Request to public
// buckets that grant the s3:ListBucket permission publicly do not need to be
@@ -66,6 +70,10 @@ import (
// Zones, see [Regional and Zonal endpoints for directory buckets in Availability Zones]in the Amazon S3 User Guide. For more information about endpoints in
// Local Zones, see [Concepts for directory buckets in Local Zones]in the Amazon S3 User Guide.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-security-iam-identity-policies.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [REST Authentication]: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadObject.go
index bf93bcfe1000..5b599e24bb24 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_HeadObject.go
@@ -129,6 +129,10 @@ import (
//
// [GetObjectAttributes]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Server-Side Encryption (Using Customer-Provided Encryption Keys)]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html
// [GetObjectAttributes]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html
@@ -383,7 +387,7 @@ type HeadObjectOutput struct {
CacheControl *string
// The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only
- // be present if the checksum was uploaded with the object. When you use an API
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -410,8 +414,8 @@ type HeadObjectOutput struct {
// [Checking object integrity in the Amazon S3 User Guide]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use the API
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use the API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -421,8 +425,8 @@ type HeadObjectOutput struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#large-object-checksums
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use an API
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketAnalyticsConfigurations.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketAnalyticsConfigurations.go
index 985bfc486888..369ad60de661 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketAnalyticsConfigurations.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketAnalyticsConfigurations.go
@@ -42,6 +42,10 @@ import (
//
// [PutBucketAnalyticsConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Analytics – Storage Class Analysis]: https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html
// [DeleteBucketAnalyticsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketAnalyticsConfiguration.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketIntelligentTieringConfigurations.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketIntelligentTieringConfigurations.go
index c800119a1475..836ce4c98d14 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketIntelligentTieringConfigurations.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketIntelligentTieringConfigurations.go
@@ -42,6 +42,10 @@ import (
//
// [GetBucketIntelligentTieringConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketIntelligentTieringConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketIntelligentTieringConfiguration.html
// [PutBucketIntelligentTieringConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketIntelligentTieringConfiguration.html
// [Storage class for automatically optimizing frequently and infrequently accessed objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html#sc-dynamic-data-access
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketInventoryConfigurations.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketInventoryConfigurations.go
index 90d3a33bc0c7..59bde277f8f1 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketInventoryConfigurations.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketInventoryConfigurations.go
@@ -17,7 +17,7 @@ import (
// This operation is not supported for directory buckets.
//
// Returns a list of S3 Inventory configurations for the bucket. You can have up
-// to 1,000 analytics configurations per bucket.
+// to 1,000 inventory configurations per bucket.
//
// This action supports list pagination and does not return more than 100
// configurations at a time. Always check the IsTruncated element in the response.
@@ -42,6 +42,10 @@ import (
//
// [PutBucketInventoryConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Inventory]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [DeleteBucketInventoryConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketInventoryConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketMetricsConfigurations.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketMetricsConfigurations.go
index 4f9402d666cd..b0997945290b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketMetricsConfigurations.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBucketMetricsConfigurations.go
@@ -43,6 +43,10 @@ import (
//
// [DeleteBucketMetricsConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [Monitoring Metrics with Amazon CloudWatch]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html
// [GetBucketMetricsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetricsConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBuckets.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBuckets.go
index 21c03cd37481..6926792f0c1c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBuckets.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListBuckets.go
@@ -13,10 +13,10 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -40,6 +40,10 @@ import (
// will be rejected for Amazon Web Services accounts with a general purpose bucket
// quota greater than 10,000.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Creating, configuring, and working with Amazon S3 buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-buckets-s3.html
func (c *Client) ListBuckets(ctx context.Context, params *ListBucketsInput, optFns ...func(*Options)) (*ListBucketsOutput, error) {
if params == nil {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListDirectoryBuckets.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListDirectoryBuckets.go
index edf98a062b1e..a8df8516f335 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListDirectoryBuckets.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListDirectoryBuckets.go
@@ -37,6 +37,10 @@ import (
// The BucketRegion response element is not part of the ListDirectoryBuckets
// Response Syntax.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Directory buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html
// [Regional and Zonal endpoints for directory buckets in Availability Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/endpoint-directory-buckets-AZ.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListMultipartUploads.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListMultipartUploads.go
index 3de297cc643f..d999e834c3ab 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListMultipartUploads.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListMultipartUploads.go
@@ -13,10 +13,10 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -110,6 +110,10 @@ import (
//
// [AbortMultipartUpload]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Uploading Objects Using Multipart Upload]: https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [ListParts]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectVersions.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectVersions.go
index 1d443236610d..afc00affa42c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectVersions.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectVersions.go
@@ -13,10 +13,10 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -48,6 +48,10 @@ import (
//
// [DeleteObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [DeleteObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html
// [PutObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
// [GetObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjects.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjects.go
index abb77c5089f3..fead5e33099d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjects.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjects.go
@@ -13,10 +13,10 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -48,6 +48,10 @@ import (
//
// [ListBuckets]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListBuckets]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html
// [PutObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
// [GetObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectsV2.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectsV2.go
index bf3a492df2af..5cabc9de421a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectsV2.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListObjectsV2.go
@@ -13,6 +13,17 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// DisplayName .
+//
+// This change affects the following Amazon Web Services Regions: US East (N.
+// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
+// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
+// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+//
// Returns some or all (up to 1,000) of the objects in a bucket with each request.
// You can use the request parameters as selection criteria to return a subset of
// the objects in a bucket. A 200 OK response can contain valid or invalid XML.
@@ -78,6 +89,10 @@ import (
//
// [CreateBucket]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListObjects]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListParts.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListParts.go
index cd2184077dd9..062156c82cbb 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListParts.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_ListParts.go
@@ -14,10 +14,10 @@ import (
"time"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
@@ -88,6 +88,10 @@ import (
//
// [ListMultipartUploads]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Uploading Objects Using Multipart Upload]: https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [AbortMultipartUpload]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAccelerateConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAccelerateConfiguration.go
index f8f349db7240..d9136c3c215d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAccelerateConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAccelerateConfiguration.go
@@ -49,6 +49,10 @@ import (
//
// [CreateBucket]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [Transfer Acceleration]: https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
// [GetBucketAccelerateConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAccelerateConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAcl.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAcl.go
index 045fa12c0260..a31dd277b2fd 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAcl.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAcl.go
@@ -15,17 +15,15 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will discontinue
-// support for creating new Email Grantee Access Control Lists (ACL). Email Grantee
-// ACLs created prior to this date will continue to work and remain accessible
-// through the Amazon Web Services Management Console, Command Line Interface
-// (CLI), SDKs, and REST API. However, you will no longer be able to create new
-// Email Grantee ACLs.
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
//
// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
//
// This operation is not supported for directory buckets.
//
@@ -174,6 +172,10 @@ import (
//
// [GetObjectAcl]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Regions and Endpoints]: https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
// [Access Control List (ACL) Overview]: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
// [Controlling object ownership]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAnalyticsConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAnalyticsConfiguration.go
index 76658c53c60c..b058066a2118 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAnalyticsConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketAnalyticsConfiguration.go
@@ -68,6 +68,10 @@ import (
//
// [ListBucketAnalyticsConfigurations]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Amazon S3 Analytics – Storage Class Analysis]: https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html
// [Granting Permissions for Amazon S3 Inventory and Storage Class Analysis]: https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-9
// [DeleteBucketAnalyticsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketAnalyticsConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketCors.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketCors.go
index d241ba8d37ca..7158f1aad9b6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketCors.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketCors.go
@@ -59,6 +59,10 @@ import (
//
// [RESTOPTIONSobject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketCors]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketCors.html
// [Enabling Cross-Origin Resource Sharing]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html
// [RESTOPTIONSobject]: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTOPTIONSobject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketEncryption.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketEncryption.go
index 197a4f184fea..a4a917049195 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketEncryption.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketEncryption.go
@@ -106,6 +106,10 @@ import (
//
// [DeleteBucketEncryption]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Specifying server-side encryption with KMS for new object uploads]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-specifying-kms-encryption.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [KMS customer managed key]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketIntelligentTieringConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketIntelligentTieringConfiguration.go
index 5a7b8989bb51..e27c56f7e360 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketIntelligentTieringConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketIntelligentTieringConfiguration.go
@@ -62,6 +62,10 @@ import (
// or you do not have the s3:PutIntelligentTieringConfiguration bucket permission
// to set the configuration on the bucket.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [ListBucketIntelligentTieringConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketIntelligentTieringConfigurations.html
// [GetBucketIntelligentTieringConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketIntelligentTieringConfiguration.html
// [Storage class for automatically optimizing frequently and infrequently accessed objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html#sc-dynamic-data-access
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketInventoryConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketInventoryConfiguration.go
index 162ac031abe4..a3f85c618b6f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketInventoryConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketInventoryConfiguration.go
@@ -74,6 +74,10 @@ import (
//
// [ListBucketInventoryConfigurations]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Granting Permissions for Amazon S3 Inventory and Storage Class Analysis]: https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-9
// [Amazon S3 Inventory]: https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html
// [ListBucketInventoryConfigurations]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketInventoryConfigurations.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLifecycleConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLifecycleConfiguration.go
index df972372105c..cc1ecd65467f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLifecycleConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLifecycleConfiguration.go
@@ -111,6 +111,10 @@ import (
//
// [DeleteBucketLifecycle]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Object Lifecycle Management]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html
// [Lifecycle Configuration Elements]: https://docs.aws.amazon.com/AmazonS3/latest/dev/intro-lifecycle-rules.html
// [GetBucketLifecycleConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLogging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLogging.go
index 060341128568..8db95219218a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLogging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketLogging.go
@@ -15,17 +15,15 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will discontinue
-// support for creating new Email Grantee Access Control Lists (ACL). Email Grantee
-// ACLs created prior to this date will continue to work and remain accessible
-// through the Amazon Web Services Management Console, Command Line Interface
-// (CLI), SDKs, and REST API. However, you will no longer be able to create new
-// Email Grantee ACLs.
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
//
// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
//
// This operation is not supported for directory buckets.
//
@@ -85,6 +83,10 @@ import (
//
// [GetBucketLogging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Permissions for server access log delivery]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/enable-server-access-logging.html#grant-log-delivery-permissions-general
// [DeleteBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html
// [GetBucketLogging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLogging.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketMetricsConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketMetricsConfiguration.go
index c665b2efec83..023a8a0f4d27 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketMetricsConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketMetricsConfiguration.go
@@ -46,6 +46,10 @@ import (
//
// - HTTP Status Code: HTTP 400 Bad Request
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
// [Monitoring Metrics with Amazon CloudWatch]: https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html
// [GetBucketMetricsConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetricsConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketNotificationConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketNotificationConfiguration.go
index 6ec91374fc5e..72cd0a308f71 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketNotificationConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketNotificationConfiguration.go
@@ -63,6 +63,10 @@ import (
//
// [GetBucketNotificationConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Configuring Notifications for Amazon S3 Events]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
// [Amazon S3 service quotas]: https://docs.aws.amazon.com/general/latest/gr/s3.html#limits_s3
// [GetBucketNotificationConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotificationConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketOwnershipControls.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketOwnershipControls.go
index e84f53627c35..3c7612532b0b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketOwnershipControls.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketOwnershipControls.go
@@ -29,6 +29,10 @@ import (
//
// # DeleteBucketOwnershipControls
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Specifying permissions in a policy]: https://docs.aws.amazon.com/AmazonS3/latest/user-guide/using-with-s3-actions.html
// [Using object ownership]: https://docs.aws.amazon.com/AmazonS3/latest/user-guide/about-object-ownership.html
func (c *Client) PutBucketOwnershipControls(ctx context.Context, params *PutBucketOwnershipControlsInput, optFns ...func(*Options)) (*PutBucketOwnershipControlsOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketPolicy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketPolicy.go
index 6c326792695a..026312a87edc 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketPolicy.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketPolicy.go
@@ -67,6 +67,10 @@ import (
//
// [DeleteBucket]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Bucket policy examples]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Example bucket policies for S3 Express One Zone]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-security-iam-example-bucket-policies.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketReplication.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketReplication.go
index 0ce30ce23605..90838820c6e3 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketReplication.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketReplication.go
@@ -69,6 +69,10 @@ import (
//
// [DeleteBucketReplication]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [iam:PassRole]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_passrole.html
// [GetBucketReplication]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html
// [aws:RequestedRegion]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requestedregion
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketRequestPayment.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketRequestPayment.go
index e2f172eb1864..121daf2b0411 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketRequestPayment.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketRequestPayment.go
@@ -28,6 +28,10 @@ import (
//
// [GetBucketRequestPayment]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketRequestPayment]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketRequestPayment.html
// [Requester Pays Buckets]: https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html
// [CreateBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketTagging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketTagging.go
index a5a58186a184..1ea4c9053517 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketTagging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketTagging.go
@@ -56,6 +56,10 @@ import (
//
// [DeleteBucketTagging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Error Responses]: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
// [GetBucketTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html
// [Cost Allocation and Tagging]: https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketVersioning.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketVersioning.go
index c30435638f7b..6e11d057b52b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketVersioning.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketVersioning.go
@@ -59,6 +59,10 @@ import (
//
// [GetBucketVersioning]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [DeleteBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html
// [CreateBucket]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html
// [Lifecycle and Versioning]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html#lifecycle-and-other-bucket-config
@@ -119,7 +123,14 @@ type PutBucketVersioningInput struct {
ExpectedBucketOwner *string
// The concatenation of the authentication device's serial number, a space, and
- // the value that is displayed on your authentication device.
+ // the value that is displayed on your authentication device. The serial number is
+ // the number that uniquely identifies the MFA device. For physical MFA devices,
+ // this is the unique serial number that's provided with the device. For virtual
+ // MFA devices, the serial number is the device ARN. For more information, see [Enabling versioning on buckets]and [Configuring MFA delete]
+ // in the Amazon Simple Storage Service User Guide.
+ //
+ // [Enabling versioning on buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/manage-versioning-examples.html
+ // [Configuring MFA delete]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiFactorAuthenticationDelete.html
MFA *string
noSmithyDocumentSerde
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketWebsite.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketWebsite.go
index 9c8222ba8a47..26471bbcbabd 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketWebsite.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutBucketWebsite.go
@@ -84,6 +84,10 @@ import (
//
// The maximum request length is limited to 128 KB.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Hosting Websites on Amazon S3]: https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
// [Configuring an Object Redirect]: https://docs.aws.amazon.com/AmazonS3/latest/dev/how-to-page-redirect.html
func (c *Client) PutBucketWebsite(ctx context.Context, params *PutBucketWebsiteInput, optFns ...func(*Options)) (*PutBucketWebsiteOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObject.go
index 774134be499e..272c5e7adebb 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObject.go
@@ -17,17 +17,15 @@ import (
"time"
)
-// End of support notice: Beginning October 1, 2025, Amazon S3 will discontinue
-// support for creating new Email Grantee Access Control Lists (ACL). Email Grantee
-// ACLs created prior to this date will continue to work and remain accessible
-// through the Amazon Web Services Management Console, Command Line Interface
-// (CLI), SDKs, and REST API. However, you will no longer be able to create new
-// Email Grantee ACLs.
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
//
// This change affects the following Amazon Web Services Regions: US East (N.
-// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
-// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
-// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
//
// Adds an object to a bucket.
//
@@ -132,6 +130,10 @@ import (
//
// [DeleteObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [Amazon S3 Object Lock]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html
// [DeleteObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html
@@ -680,7 +682,7 @@ type PutObjectOutput struct {
BucketKeyEnabled *bool
// The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only
- // be present if the checksum was uploaded with the object. When you use an API
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -710,8 +712,8 @@ type PutObjectOutput struct {
// [Checking object integrity in the Amazon S3 User Guide]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use the API
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use the API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -721,8 +723,8 @@ type PutObjectOutput struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#large-object-checksums
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use an API
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectAcl.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectAcl.go
index 110cf08cae98..1ad8faee0d62 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectAcl.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectAcl.go
@@ -14,6 +14,16 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
+// End of support notice: As of October 1, 2025, Amazon S3 has discontinued
+// support for Email Grantee Access Control Lists (ACLs). If you attempt to use an
+// Email Grantee ACL in a request after October 1, 2025, the request will receive
+// an HTTP 405 (Method Not Allowed) error.
+//
+// This change affects the following Amazon Web Services Regions: US East (N.
+// Virginia), US West (N. California), US West (Oregon), Asia Pacific (Singapore),
+// Asia Pacific (Sydney), Asia Pacific (Tokyo), Europe (Ireland), and South America
+// (São Paulo).
+//
// This operation is not supported for directory buckets.
//
// Uses the acl subresource to set the access control list (ACL) permissions for a
@@ -155,6 +165,10 @@ import (
//
// [GetObject]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Regions and Endpoints]: https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
// [Access Control List (ACL) Overview]: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
// [Controlling object ownership]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLegalHold.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLegalHold.go
index 1c937604c790..79c696caeb35 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLegalHold.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLegalHold.go
@@ -21,6 +21,10 @@ import (
//
// This functionality is not supported for Amazon S3 on Outposts.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Locking Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
func (c *Client) PutObjectLegalHold(ctx context.Context, params *PutObjectLegalHoldInput, optFns ...func(*Options)) (*PutObjectLegalHoldOutput, error) {
if params == nil {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLockConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLockConfiguration.go
index 14837e1013b4..aab10fc48041 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLockConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectLockConfiguration.go
@@ -28,6 +28,10 @@ import (
// - You can enable Object Lock for new or existing buckets. For more
// information, see [Configuring Object Lock].
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Configuring Object Lock]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock-configure.html
// [Locking Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
func (c *Client) PutObjectLockConfiguration(ctx context.Context, params *PutObjectLockConfigurationInput, optFns ...func(*Options)) (*PutObjectLockConfigurationOutput, error) {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectRetention.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectRetention.go
index f0ef2185c137..0152d0574880 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectRetention.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectRetention.go
@@ -23,6 +23,10 @@ import (
//
// This functionality is not supported for Amazon S3 on Outposts.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Locking Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
func (c *Client) PutObjectRetention(ctx context.Context, params *PutObjectRetentionInput, optFns ...func(*Options)) (*PutObjectRetentionOutput, error) {
if params == nil {
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectTagging.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectTagging.go
index 7c59221c013b..370faaf8be2d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectTagging.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutObjectTagging.go
@@ -53,6 +53,10 @@ import (
//
// [DeleteObjectTagging]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Error Responses]: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
// [DeleteObjectTagging]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html
// [Object Tagging]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-tagging.html
@@ -135,16 +139,9 @@ type PutObjectTaggingInput struct {
// status code 403 Forbidden (access denied).
ExpectedBucketOwner *string
- // Confirms that the requester knows that they will be charged for the request.
- // Bucket owners need not specify this parameter in their requests. If either the
- // source or destination S3 bucket has Requester Pays enabled, the requester will
- // pay for corresponding charges to copy the object. For information about
- // downloading objects from Requester Pays buckets, see [Downloading Objects in Requester Pays Buckets]in the Amazon S3 User
- // Guide.
- //
- // This functionality is not supported for directory buckets.
- //
- // [Downloading Objects in Requester Pays Buckets]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html
+ // Confirms that the requester knows that she or he will be charged for the
+ // tagging object request. Bucket owners need not specify this parameter in their
+ // requests.
RequestPayer types.RequestPayer
// The versionId of the object that the tag-set will be added to.
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutPublicAccessBlock.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutPublicAccessBlock.go
index 8f79019b10fd..eef520f5ce81 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutPublicAccessBlock.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_PutPublicAccessBlock.go
@@ -41,6 +41,10 @@ import (
//
// [Using Amazon S3 Block Public Access]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetPublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetPublicAccessBlock.html
// [DeletePublicAccessBlock]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeletePublicAccessBlock.html
// [Using Amazon S3 Block Public Access]: https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RenameObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RenameObject.go
index ab057ffa6cc0..293bed7a8509 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RenameObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RenameObject.go
@@ -51,6 +51,10 @@ import (
// HTTP Host header syntax Directory buckets - The HTTP Host header syntax is
// Bucket-name.s3express-zone-id.region-code.amazonaws.com .
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [CreateSession]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateSession.html
// [RFC 7232]: https://datatracker.ietf.org/doc/rfc7232/
// [Authorizing Zonal endpoint API operations with CreateSession]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-create-session.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RestoreObject.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RestoreObject.go
index 75c6957be0cd..f361fee8d240 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RestoreObject.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_RestoreObject.go
@@ -149,6 +149,10 @@ import (
//
// [GetBucketNotificationConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [PutBucketLifecycleConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html
// [Object Lifecycle Management]: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html
// [Permissions Related to Bucket Subresource Operations]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_SelectObjectContent.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_SelectObjectContent.go
index 2051618a3350..2fd7c4c0ff66 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_SelectObjectContent.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_SelectObjectContent.go
@@ -89,6 +89,10 @@ import (
//
// [PutBucketLifecycleConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Appendix: SelectObjectContent Response]: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTSelectObjectAppendix.html
// [Selecting Content from Objects]: https://docs.aws.amazon.com/AmazonS3/latest/dev/selecting-content-from-objects.html
// [PutBucketLifecycleConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataInventoryTableConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataInventoryTableConfiguration.go
index 6e919c9b9021..6c7c24657e7c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataInventoryTableConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataInventoryTableConfiguration.go
@@ -52,6 +52,10 @@ import (
//
// [UpdateBucketMetadataJournalTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketMetadataConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetadataConfiguration.html
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [UpdateBucketMetadataJournalTableConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateBucketMetadataJournalTableConfiguration.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataJournalTableConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataJournalTableConfiguration.go
index 9c16afea3ab6..dcde9f70f6e0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataJournalTableConfiguration.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UpdateBucketMetadataJournalTableConfiguration.go
@@ -34,6 +34,10 @@ import (
//
// [UpdateBucketMetadataInventoryTableConfiguration]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [GetBucketMetadataConfiguration]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetadataConfiguration.html
// [Setting up permissions for configuring metadata tables]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-permissions.html
// [Accelerating data discovery with S3 Metadata]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-overview.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPart.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPart.go
index 17f82aecb185..a6e9cc879190 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPart.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPart.go
@@ -157,6 +157,10 @@ import (
//
// [ListMultipartUploads]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [ListParts]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html
// [Authenticating Requests: Using the Authorization Header (Amazon Web Services Signature Version 4)]: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html
@@ -371,7 +375,7 @@ type UploadPartOutput struct {
BucketKeyEnabled *bool
// The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only
- // be present if the checksum was uploaded with the object. When you use an API
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -400,8 +404,8 @@ type UploadPartOutput struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use the API
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use the API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -411,8 +415,8 @@ type UploadPartOutput struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#large-object-checksums
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use an API
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPartCopy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPartCopy.go
index d2ef00bb3171..fafe990ca0ee 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPartCopy.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_UploadPartCopy.go
@@ -157,6 +157,10 @@ import (
//
// [ListMultipartUploads]
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Uploading Objects Using Multipart Upload]: https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html
// [Concepts for directory buckets in Local Zones]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-lzs-for-directory-buckets.html
// [ListParts]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_WriteGetObjectResponse.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_WriteGetObjectResponse.go
index fefeb1be614b..b2c06d761930 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_WriteGetObjectResponse.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/api_op_WriteGetObjectResponse.go
@@ -63,6 +63,10 @@ import (
// For information on how to view and use these functions, see [Using Amazon Web Services built Lambda functions] in the Amazon S3
// User Guide.
//
+// You must URL encode any signed header values that contain spaces. For example,
+// if your header value is my file.txt , containing two spaces after my , you must
+// URL encode this value to my%20%20file.txt .
+//
// [Transforming objects with Object Lambda access points]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/transforming-objects.html
// [Using Amazon Web Services built Lambda functions]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/olap-examples.html
// [GetObject]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/endpoints.go
index 9734372c4ed4..578f0225e106 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/endpoints.go
@@ -466,11 +466,17 @@ func (r *resolver) ResolveEndpoint(
return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err)
}
_UseFIPS := *params.UseFIPS
+ _ = _UseFIPS
_UseDualStack := *params.UseDualStack
+ _ = _UseDualStack
_ForcePathStyle := *params.ForcePathStyle
+ _ = _ForcePathStyle
_Accelerate := *params.Accelerate
+ _ = _Accelerate
_UseGlobalEndpoint := *params.UseGlobalEndpoint
+ _ = _UseGlobalEndpoint
_DisableMultiRegionAccessPoints := *params.DisableMultiRegionAccessPoints
+ _ = _DisableMultiRegionAccessPoints
if exprVal := params.Region; exprVal != nil {
_Region := *exprVal
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/generated.json
index 6268fcb7ecde..c72a5cf1c0f2 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/generated.json
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/generated.json
@@ -139,7 +139,7 @@
"types/types_exported_test.go",
"validators.go"
],
- "go": "1.22",
+ "go": "1.23",
"module": "github.com/aws/aws-sdk-go-v2/service/s3",
"unstable": false
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/go_module_metadata.go
index 4af533e66541..0bec3adac2b1 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/go_module_metadata.go
@@ -3,4 +3,4 @@
package s3
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.87.1"
+const goModuleVersion = "1.89.1"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/internal/endpoints/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/internal/endpoints/endpoints.go
index 89faaa4601df..c4e24020370a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/internal/endpoints/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/internal/endpoints/endpoints.go
@@ -266,6 +266,9 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "s3.dualstack.ap-southeast-5.amazonaws.com",
},
+ endpoints.EndpointKey{
+ Region: "ap-southeast-6",
+ }: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-southeast-7",
}: endpoints.Endpoint{},
@@ -817,6 +820,9 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "s3-fips.us-isob-east-1.sc2s.sgov.gov",
},
+ endpoints.EndpointKey{
+ Region: "us-isob-west-1",
+ }: endpoints.Endpoint{},
},
},
{
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/serializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/serializers.go
index 050717e85592..252097ba555f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/serializers.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/serializers.go
@@ -452,6 +452,16 @@ func awsRestxml_serializeOpHttpBindingsCopyObjectInput(v *CopyObjectInput, encod
encoder.SetHeader(locationName).String(*v.GrantWriteACP)
}
+ if v.IfMatch != nil {
+ locationName := "If-Match"
+ encoder.SetHeader(locationName).String(*v.IfMatch)
+ }
+
+ if v.IfNoneMatch != nil {
+ locationName := "If-None-Match"
+ encoder.SetHeader(locationName).String(*v.IfNoneMatch)
+ }
+
if v.Key == nil || len(*v.Key) == 0 {
return &smithy.SerializationError{Err: fmt.Errorf("input member Key must not be empty")}
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/types/types.go b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/types/types.go
index 28afadb27bec..394d4fef6578 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/s3/types/types.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/s3/types/types.go
@@ -252,7 +252,7 @@ type BucketLoggingStatus struct {
type Checksum struct {
// The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only
- // be present if the checksum was uploaded with the object. When you use an API
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -282,8 +282,8 @@ type Checksum struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use the API
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use the API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -293,8 +293,8 @@ type Checksum struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#large-object-checksums
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. When you use an API
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. When you use an API
// operation on an object that was uploaded using multipart uploads, this value may
// not be a direct checksum value of the full object. Instead, it's a calculation
// based on the checksum values of each individual part. For more information about
@@ -441,8 +441,8 @@ type CopyObjectResult struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC32 *string
- // The Base64 encoded, 32-bit CRC32C checksum of the object. This will only be
- // present if the object was uploaded with the object. For more information, see [Checking object integrity]
+ // The Base64 encoded, 32-bit CRC32C checksum of the object. This checksum is only
+ // present if the checksum was uploaded with the object. For more information, see [Checking object integrity]
// in the Amazon S3 User Guide.
//
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
@@ -457,15 +457,15 @@ type CopyObjectResult struct {
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumCRC64NVME *string
- // The Base64 encoded, 160-bit SHA1 digest of the object. This will only be
- // present if the object was uploaded with the object. For more information, see [Checking object integrity]
+ // The Base64 encoded, 160-bit SHA1 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. For more information, see [Checking object integrity]
// in the Amazon S3 User Guide.
//
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
ChecksumSHA1 *string
- // The Base64 encoded, 256-bit SHA256 digest of the object. This will only be
- // present if the object was uploaded with the object. For more information, see [Checking object integrity]
+ // The Base64 encoded, 256-bit SHA256 digest of the object. This checksum is only
+ // present if the checksum was uploaded with the object. For more information, see [Checking object integrity]
// in the Amazon S3 User Guide.
//
// [Checking object integrity]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
@@ -628,8 +628,11 @@ type CreateBucketConfiguration struct {
// are key-value pairs of metadata used to categorize and organize your buckets,
// track costs, and control access.
//
- // This parameter is only supported for S3 directory buckets. For more
- // information, see [Using tags with directory buckets].
+ // - This parameter is only supported for S3 directory buckets. For more
+ // information, see [Using tags with directory buckets].
+ //
+ // - You must have the s3express:TagResource permission to create a directory
+ // bucket with tags.
//
// [Using tags with directory buckets]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-tagging.html
Tags []Tag
@@ -2112,6 +2115,17 @@ type Grant struct {
noSmithyDocumentSerde
}
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// DisplayName .
+//
+// This change affects the following Amazon Web Services Regions: US East (N.
+// Virginia) Region, US West (N. California) Region, US West (Oregon) Region, Asia
+// Pacific (Singapore) Region, Asia Pacific (Sydney) Region, Asia Pacific (Tokyo)
+// Region, Europe (Ireland) Region, and South America (São Paulo) Region.
+//
// Container for the person being granted permissions.
type Grantee struct {
@@ -2698,8 +2712,10 @@ type LifecycleRule struct {
// directory bucket lifecycle configurations.
NoncurrentVersionTransitions []NoncurrentVersionTransition
- // Prefix identifying one or more objects to which the rule applies. This is no
- // longer used; use Filter instead.
+ // The general purpose bucket prefix that identifies one or more objects to which
+ // the rule applies. We recommend using Filter instead of Prefix for new PUTs.
+ // Previous configurations where a prefix is defined will continue to operate as
+ // before.
//
// Replacement must be made for object keys containing special characters (such as
// carriage returns) when using XML requests. For more information, see [XML related object key constraints].
@@ -3476,10 +3492,10 @@ type OutputSerialization struct {
noSmithyDocumentSerde
}
-// End of support notice: Beginning October 1, 2025, Amazon S3 will stop returning
-// DisplayName . Update your applications to use canonical IDs (unique identifier
-// for Amazon Web Services accounts), Amazon Web Services account ID (12 digit
-// identifier) or IAM ARNs (full resource naming) as a direct replacement of
+// End of support notice: Beginning November 21, 2025, Amazon S3 will stop
+// returning DisplayName . Update your applications to use canonical IDs (unique
+// identifier for Amazon Web Services accounts), Amazon Web Services account ID (12
+// digit identifier) or IAM ARNs (full resource naming) as a direct replacement of
// DisplayName .
//
// This change affects the following Amazon Web Services Regions: US East (N.
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md
index dafddce704b8..81c4718eca20 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md
@@ -1,3 +1,65 @@
+# v1.30.3 (2025-11-12)
+
+* **Bug Fix**: Further reduce allocation overhead when the metrics system isn't in-use.
+* **Bug Fix**: Reduce allocation overhead when the client doesn't have any HTTP interceptors configured.
+* **Bug Fix**: Remove blank trace spans towards the beginning of the request that added no additional information. This conveys a slight reduction in overall allocations.
+
+# v1.30.2 (2025-11-11)
+
+* **Bug Fix**: Return validation error if input region is not a valid host label.
+
+# v1.30.1 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.30.0 (2025-10-30)
+
+* **Feature**: Update endpoint ruleset parameters casing
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.8 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.7 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.6 (2025-09-29)
+
+* No change notes available for this release.
+
+# v1.29.5 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.4 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.3 (2025-09-10)
+
+* No change notes available for this release.
+
+# v1.29.2 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.1 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.29.0 (2025-08-28)
+
+* **Feature**: Remove incorrect endpoint tests
+
+# v1.28.3 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.28.2 (2025-08-21)
* **Dependency Update**: Updated to the latest SDK module versions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go
index 2c498e4689a9..8e5a2e77f874 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go
@@ -65,7 +65,12 @@ func timeOperationMetric[T any](
ctx context.Context, metric string, fn func() (T, error),
opts ...metrics.RecordMetricOption,
) (T, error) {
- instr := getOperationMetrics(ctx).histogramFor(metric)
+ mm := getOperationMetrics(ctx)
+ if mm == nil { // not using the metrics system
+ return fn()
+ }
+
+ instr := mm.histogramFor(metric)
opts = append([]metrics.RecordMetricOption{withOperationMetadata(ctx)}, opts...)
start := time.Now()
@@ -78,7 +83,12 @@ func timeOperationMetric[T any](
}
func startMetricTimer(ctx context.Context, metric string, opts ...metrics.RecordMetricOption) func() {
- instr := getOperationMetrics(ctx).histogramFor(metric)
+ mm := getOperationMetrics(ctx)
+ if mm == nil { // not using the metrics system
+ return func() {}
+ }
+
+ instr := mm.histogramFor(metric)
opts = append([]metrics.RecordMetricOption{withOperationMetadata(ctx)}, opts...)
var ended bool
@@ -106,6 +116,12 @@ func withOperationMetadata(ctx context.Context) metrics.RecordMetricOption {
type operationMetricsKey struct{}
func withOperationMetrics(parent context.Context, mp metrics.MeterProvider) (context.Context, error) {
+ if _, ok := mp.(metrics.NopMeterProvider); ok {
+ // not using the metrics system - setting up the metrics context is a memory-intensive operation
+ // so we should skip it in this case
+ return parent, nil
+ }
+
meter := mp.Meter("github.com/aws/aws-sdk-go-v2/service/sso")
om := &operationMetrics{}
@@ -153,7 +169,10 @@ func operationMetricTimer(m metrics.Meter, name, desc string) (metrics.Float64Hi
}
func getOperationMetrics(ctx context.Context) *operationMetrics {
- return ctx.Value(operationMetricsKey{}).(*operationMetrics)
+ if v := ctx.Value(operationMetricsKey{}); v != nil {
+ return v.(*operationMetrics)
+ }
+ return nil
}
func operationTracer(p tracing.TracerProvider) tracing.Tracer {
@@ -882,138 +901,49 @@ func addInterceptAttempt(stack *middleware.Stack, opts Options) error {
}, "Retry", middleware.After)
}
-func addInterceptExecution(stack *middleware.Stack, opts Options) error {
- return stack.Initialize.Add(&smithyhttp.InterceptExecution{
- BeforeExecution: opts.Interceptors.BeforeExecution,
- AfterExecution: opts.Interceptors.AfterExecution,
- }, middleware.Before)
-}
-
-func addInterceptBeforeSerialization(stack *middleware.Stack, opts Options) error {
- return stack.Serialize.Insert(&smithyhttp.InterceptBeforeSerialization{
- Interceptors: opts.Interceptors.BeforeSerialization,
- }, "OperationSerializer", middleware.Before)
-}
-
-func addInterceptAfterSerialization(stack *middleware.Stack, opts Options) error {
- return stack.Serialize.Insert(&smithyhttp.InterceptAfterSerialization{
- Interceptors: opts.Interceptors.AfterSerialization,
- }, "OperationSerializer", middleware.After)
-}
-
-func addInterceptBeforeSigning(stack *middleware.Stack, opts Options) error {
- return stack.Finalize.Insert(&smithyhttp.InterceptBeforeSigning{
- Interceptors: opts.Interceptors.BeforeSigning,
- }, "Signing", middleware.Before)
-}
-
-func addInterceptAfterSigning(stack *middleware.Stack, opts Options) error {
- return stack.Finalize.Insert(&smithyhttp.InterceptAfterSigning{
- Interceptors: opts.Interceptors.AfterSigning,
- }, "Signing", middleware.After)
-}
-
-func addInterceptTransmit(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Add(&smithyhttp.InterceptTransmit{
- BeforeTransmit: opts.Interceptors.BeforeTransmit,
- AfterTransmit: opts.Interceptors.AfterTransmit,
- }, middleware.After)
-}
-
-func addInterceptBeforeDeserialization(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Insert(&smithyhttp.InterceptBeforeDeserialization{
- Interceptors: opts.Interceptors.BeforeDeserialization,
- }, "OperationDeserializer", middleware.After) // (deserialize stack is called in reverse)
-}
-
-func addInterceptAfterDeserialization(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Insert(&smithyhttp.InterceptAfterDeserialization{
- Interceptors: opts.Interceptors.AfterDeserialization,
- }, "OperationDeserializer", middleware.Before)
-}
-
-type spanInitializeStart struct {
-}
-
-func (*spanInitializeStart) ID() string {
- return "spanInitializeStart"
-}
-
-func (m *spanInitializeStart) HandleInitialize(
- ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
-) (
- middleware.InitializeOutput, middleware.Metadata, error,
-) {
- ctx, _ = tracing.StartSpan(ctx, "Initialize")
-
- return next.HandleInitialize(ctx, in)
-}
-
-type spanInitializeEnd struct {
-}
-
-func (*spanInitializeEnd) ID() string {
- return "spanInitializeEnd"
-}
-
-func (m *spanInitializeEnd) HandleInitialize(
- ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
-) (
- middleware.InitializeOutput, middleware.Metadata, error,
-) {
- ctx, span := tracing.PopSpan(ctx)
- span.End()
-
- return next.HandleInitialize(ctx, in)
-}
-
-type spanBuildRequestStart struct {
-}
-
-func (*spanBuildRequestStart) ID() string {
- return "spanBuildRequestStart"
-}
-
-func (m *spanBuildRequestStart) HandleSerialize(
- ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler,
-) (
- middleware.SerializeOutput, middleware.Metadata, error,
-) {
- ctx, _ = tracing.StartSpan(ctx, "BuildRequest")
-
- return next.HandleSerialize(ctx, in)
-}
-
-type spanBuildRequestEnd struct {
-}
-
-func (*spanBuildRequestEnd) ID() string {
- return "spanBuildRequestEnd"
-}
-
-func (m *spanBuildRequestEnd) HandleBuild(
- ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
-) (
- middleware.BuildOutput, middleware.Metadata, error,
-) {
- ctx, span := tracing.PopSpan(ctx)
- span.End()
-
- return next.HandleBuild(ctx, in)
-}
-
-func addSpanInitializeStart(stack *middleware.Stack) error {
- return stack.Initialize.Add(&spanInitializeStart{}, middleware.Before)
-}
-
-func addSpanInitializeEnd(stack *middleware.Stack) error {
- return stack.Initialize.Add(&spanInitializeEnd{}, middleware.After)
-}
-
-func addSpanBuildRequestStart(stack *middleware.Stack) error {
- return stack.Serialize.Add(&spanBuildRequestStart{}, middleware.Before)
-}
+func addInterceptors(stack *middleware.Stack, opts Options) error {
+ // middlewares are expensive, don't add all of these interceptor ones unless the caller
+ // actually has at least one interceptor configured
+ //
+ // at the moment it's all-or-nothing because some of the middlewares here are responsible for
+ // setting fields in the interceptor context for future ones
+ if len(opts.Interceptors.BeforeExecution) == 0 &&
+ len(opts.Interceptors.BeforeSerialization) == 0 && len(opts.Interceptors.AfterSerialization) == 0 &&
+ len(opts.Interceptors.BeforeRetryLoop) == 0 &&
+ len(opts.Interceptors.BeforeAttempt) == 0 &&
+ len(opts.Interceptors.BeforeSigning) == 0 && len(opts.Interceptors.AfterSigning) == 0 &&
+ len(opts.Interceptors.BeforeTransmit) == 0 && len(opts.Interceptors.AfterTransmit) == 0 &&
+ len(opts.Interceptors.BeforeDeserialization) == 0 && len(opts.Interceptors.AfterDeserialization) == 0 &&
+ len(opts.Interceptors.AfterAttempt) == 0 && len(opts.Interceptors.AfterExecution) == 0 {
+ return nil
+ }
-func addSpanBuildRequestEnd(stack *middleware.Stack) error {
- return stack.Build.Add(&spanBuildRequestEnd{}, middleware.After)
+ return errors.Join(
+ stack.Initialize.Add(&smithyhttp.InterceptExecution{
+ BeforeExecution: opts.Interceptors.BeforeExecution,
+ AfterExecution: opts.Interceptors.AfterExecution,
+ }, middleware.Before),
+ stack.Serialize.Insert(&smithyhttp.InterceptBeforeSerialization{
+ Interceptors: opts.Interceptors.BeforeSerialization,
+ }, "OperationSerializer", middleware.Before),
+ stack.Serialize.Insert(&smithyhttp.InterceptAfterSerialization{
+ Interceptors: opts.Interceptors.AfterSerialization,
+ }, "OperationSerializer", middleware.After),
+ stack.Finalize.Insert(&smithyhttp.InterceptBeforeSigning{
+ Interceptors: opts.Interceptors.BeforeSigning,
+ }, "Signing", middleware.Before),
+ stack.Finalize.Insert(&smithyhttp.InterceptAfterSigning{
+ Interceptors: opts.Interceptors.AfterSigning,
+ }, "Signing", middleware.After),
+ stack.Deserialize.Add(&smithyhttp.InterceptTransmit{
+ BeforeTransmit: opts.Interceptors.BeforeTransmit,
+ AfterTransmit: opts.Interceptors.AfterTransmit,
+ }, middleware.After),
+ stack.Deserialize.Insert(&smithyhttp.InterceptBeforeDeserialization{
+ Interceptors: opts.Interceptors.BeforeDeserialization,
+ }, "OperationDeserializer", middleware.After), // (deserialize stack is called in reverse)
+ stack.Deserialize.Insert(&smithyhttp.InterceptAfterDeserialization{
+ Interceptors: opts.Interceptors.AfterDeserialization,
+ }, "OperationDeserializer", middleware.Before),
+ )
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go
index df5dc1674f34..c0b961fcf180 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go
@@ -153,40 +153,7 @@ func (c *Client) addOperationGetRoleCredentialsMiddlewares(stack *middleware.Sta
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go
index 2a3b2ad90212..f5ca09ac7d8d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go
@@ -158,40 +158,7 @@ func (c *Client) addOperationListAccountRolesMiddlewares(stack *middleware.Stack
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go
index f6114a7c105e..54511d34a6ec 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go
@@ -157,40 +157,7 @@ func (c *Client) addOperationListAccountsMiddlewares(stack *middleware.Stack, op
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go
index 2c7f181c344e..a21116e96c1e 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go
@@ -152,40 +152,7 @@ func (c *Client) addOperationLogoutMiddlewares(stack *middleware.Stack, options
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go
index 53c6bc756124..dfeacc10766c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go
@@ -217,11 +217,15 @@ func resolveBaseEndpoint(cfg aws.Config, o *Options) {
}
}
-func bindRegion(region string) *string {
+func bindRegion(region string) (*string, error) {
if region == "" {
- return nil
+ return nil, nil
+ }
+ if !smithyhttp.ValidHostLabel(region) {
+ return nil, fmt.Errorf("invalid input region %s", region)
}
- return aws.String(endpoints.MapFIPSRegion(region))
+
+ return aws.String(endpoints.MapFIPSRegion(region)), nil
}
// EndpointParameters provides the parameters that influence how endpoints are
@@ -328,7 +332,9 @@ func (r *resolver) ResolveEndpoint(
return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err)
}
_UseDualStack := *params.UseDualStack
+ _ = _UseDualStack
_UseFIPS := *params.UseFIPS
+ _ = _UseFIPS
if exprVal := params.Endpoint; exprVal != nil {
_Endpoint := *exprVal
@@ -385,8 +391,8 @@ func (r *resolver) ResolveEndpoint(
}
}
if _UseFIPS == true {
- if true == _PartitionResult.SupportsFIPS {
- if "aws-us-gov" == _PartitionResult.Name {
+ if _PartitionResult.SupportsFIPS == true {
+ if _PartitionResult.Name == "aws-us-gov" {
uriString := func() string {
var out strings.Builder
out.WriteString("https://portal.sso.")
@@ -477,10 +483,15 @@ type endpointParamsBinder interface {
bindEndpointParams(*EndpointParameters)
}
-func bindEndpointParams(ctx context.Context, input interface{}, options Options) *EndpointParameters {
+func bindEndpointParams(ctx context.Context, input interface{}, options Options) (*EndpointParameters, error) {
params := &EndpointParameters{}
- params.Region = bindRegion(options.Region)
+ region, err := bindRegion(options.Region)
+ if err != nil {
+ return nil, err
+ }
+ params.Region = region
+
params.UseDualStack = aws.Bool(options.EndpointOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled)
params.UseFIPS = aws.Bool(options.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled)
params.Endpoint = options.BaseEndpoint
@@ -489,7 +500,7 @@ func bindEndpointParams(ctx context.Context, input interface{}, options Options)
b.bindEndpointParams(params)
}
- return params
+ return params, nil
}
type resolveEndpointV2Middleware struct {
@@ -519,7 +530,10 @@ func (m *resolveEndpointV2Middleware) HandleFinalize(ctx context.Context, in mid
return out, metadata, fmt.Errorf("expected endpoint resolver to not be nil")
}
- params := bindEndpointParams(ctx, getOperationInput(ctx), m.options)
+ params, err := bindEndpointParams(ctx, getOperationInput(ctx), m.options)
+ if err != nil {
+ return out, metadata, fmt.Errorf("failed to bind endpoint params, %w", err)
+ }
endpt, err := timeOperationMetric(ctx, "client.call.resolve_endpoint_duration",
func() (smithyendpoints.Endpoint, error) {
return m.options.EndpointResolverV2.ResolveEndpoint(ctx, *params)
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json
index 1a88fe4df8e4..1499c0a95911 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json
@@ -30,7 +30,7 @@
"types/types.go",
"validators.go"
],
- "go": "1.22",
+ "go": "1.23",
"module": "github.com/aws/aws-sdk-go-v2/service/sso",
"unstable": false
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go
index def5652fd9f3..b189a07b2912 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go
@@ -3,4 +3,4 @@
package sso
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.28.2"
+const goModuleVersion = "1.30.3"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go
index 04416606be06..8bb8730be076 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go
@@ -237,6 +237,9 @@ var defaultPartitions = endpoints.Partitions{
Region: "ap-southeast-5",
},
},
+ endpoints.EndpointKey{
+ Region: "ap-southeast-7",
+ }: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ca-central-1",
}: endpoints.Endpoint{
@@ -341,6 +344,9 @@ var defaultPartitions = endpoints.Partitions{
Region: "me-south-1",
},
},
+ endpoints.EndpointKey{
+ Region: "mx-central-1",
+ }: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "sa-east-1",
}: endpoints.Endpoint{
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md
index 35085b7fa8f9..a6818ae6db0d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md
@@ -1,3 +1,61 @@
+# v1.35.7 (2025-11-12)
+
+* **Bug Fix**: Further reduce allocation overhead when the metrics system isn't in-use.
+* **Bug Fix**: Reduce allocation overhead when the client doesn't have any HTTP interceptors configured.
+* **Bug Fix**: Remove blank trace spans towards the beginning of the request that added no additional information. This conveys a slight reduction in overall allocations.
+
+# v1.35.6 (2025-11-11)
+
+* **Bug Fix**: Return validation error if input region is not a valid host label.
+
+# v1.35.5 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.35.4 (2025-10-30)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.35.3 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.35.2 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.35.1 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.35.0 (2025-09-23)
+
+* **Feature**: This release includes exception definition and documentation updates.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.34.5 (2025-09-22)
+
+* No change notes available for this release.
+
+# v1.34.4 (2025-09-10)
+
+* No change notes available for this release.
+
+# v1.34.3 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.34.2 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.34.1 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.34.0 (2025-08-26)
* **Feature**: Remove incorrect endpoint tests
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go
index 12ad2f5d9d57..8e8508fa349a 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go
@@ -65,7 +65,12 @@ func timeOperationMetric[T any](
ctx context.Context, metric string, fn func() (T, error),
opts ...metrics.RecordMetricOption,
) (T, error) {
- instr := getOperationMetrics(ctx).histogramFor(metric)
+ mm := getOperationMetrics(ctx)
+ if mm == nil { // not using the metrics system
+ return fn()
+ }
+
+ instr := mm.histogramFor(metric)
opts = append([]metrics.RecordMetricOption{withOperationMetadata(ctx)}, opts...)
start := time.Now()
@@ -78,7 +83,12 @@ func timeOperationMetric[T any](
}
func startMetricTimer(ctx context.Context, metric string, opts ...metrics.RecordMetricOption) func() {
- instr := getOperationMetrics(ctx).histogramFor(metric)
+ mm := getOperationMetrics(ctx)
+ if mm == nil { // not using the metrics system
+ return func() {}
+ }
+
+ instr := mm.histogramFor(metric)
opts = append([]metrics.RecordMetricOption{withOperationMetadata(ctx)}, opts...)
var ended bool
@@ -106,6 +116,12 @@ func withOperationMetadata(ctx context.Context) metrics.RecordMetricOption {
type operationMetricsKey struct{}
func withOperationMetrics(parent context.Context, mp metrics.MeterProvider) (context.Context, error) {
+ if _, ok := mp.(metrics.NopMeterProvider); ok {
+ // not using the metrics system - setting up the metrics context is a memory-intensive operation
+ // so we should skip it in this case
+ return parent, nil
+ }
+
meter := mp.Meter("github.com/aws/aws-sdk-go-v2/service/ssooidc")
om := &operationMetrics{}
@@ -153,7 +169,10 @@ func operationMetricTimer(m metrics.Meter, name, desc string) (metrics.Float64Hi
}
func getOperationMetrics(ctx context.Context) *operationMetrics {
- return ctx.Value(operationMetricsKey{}).(*operationMetrics)
+ if v := ctx.Value(operationMetricsKey{}); v != nil {
+ return v.(*operationMetrics)
+ }
+ return nil
}
func operationTracer(p tracing.TracerProvider) tracing.Tracer {
@@ -882,138 +901,49 @@ func addInterceptAttempt(stack *middleware.Stack, opts Options) error {
}, "Retry", middleware.After)
}
-func addInterceptExecution(stack *middleware.Stack, opts Options) error {
- return stack.Initialize.Add(&smithyhttp.InterceptExecution{
- BeforeExecution: opts.Interceptors.BeforeExecution,
- AfterExecution: opts.Interceptors.AfterExecution,
- }, middleware.Before)
-}
-
-func addInterceptBeforeSerialization(stack *middleware.Stack, opts Options) error {
- return stack.Serialize.Insert(&smithyhttp.InterceptBeforeSerialization{
- Interceptors: opts.Interceptors.BeforeSerialization,
- }, "OperationSerializer", middleware.Before)
-}
-
-func addInterceptAfterSerialization(stack *middleware.Stack, opts Options) error {
- return stack.Serialize.Insert(&smithyhttp.InterceptAfterSerialization{
- Interceptors: opts.Interceptors.AfterSerialization,
- }, "OperationSerializer", middleware.After)
-}
-
-func addInterceptBeforeSigning(stack *middleware.Stack, opts Options) error {
- return stack.Finalize.Insert(&smithyhttp.InterceptBeforeSigning{
- Interceptors: opts.Interceptors.BeforeSigning,
- }, "Signing", middleware.Before)
-}
-
-func addInterceptAfterSigning(stack *middleware.Stack, opts Options) error {
- return stack.Finalize.Insert(&smithyhttp.InterceptAfterSigning{
- Interceptors: opts.Interceptors.AfterSigning,
- }, "Signing", middleware.After)
-}
-
-func addInterceptTransmit(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Add(&smithyhttp.InterceptTransmit{
- BeforeTransmit: opts.Interceptors.BeforeTransmit,
- AfterTransmit: opts.Interceptors.AfterTransmit,
- }, middleware.After)
-}
-
-func addInterceptBeforeDeserialization(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Insert(&smithyhttp.InterceptBeforeDeserialization{
- Interceptors: opts.Interceptors.BeforeDeserialization,
- }, "OperationDeserializer", middleware.After) // (deserialize stack is called in reverse)
-}
-
-func addInterceptAfterDeserialization(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Insert(&smithyhttp.InterceptAfterDeserialization{
- Interceptors: opts.Interceptors.AfterDeserialization,
- }, "OperationDeserializer", middleware.Before)
-}
-
-type spanInitializeStart struct {
-}
-
-func (*spanInitializeStart) ID() string {
- return "spanInitializeStart"
-}
-
-func (m *spanInitializeStart) HandleInitialize(
- ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
-) (
- middleware.InitializeOutput, middleware.Metadata, error,
-) {
- ctx, _ = tracing.StartSpan(ctx, "Initialize")
-
- return next.HandleInitialize(ctx, in)
-}
-
-type spanInitializeEnd struct {
-}
-
-func (*spanInitializeEnd) ID() string {
- return "spanInitializeEnd"
-}
-
-func (m *spanInitializeEnd) HandleInitialize(
- ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
-) (
- middleware.InitializeOutput, middleware.Metadata, error,
-) {
- ctx, span := tracing.PopSpan(ctx)
- span.End()
-
- return next.HandleInitialize(ctx, in)
-}
-
-type spanBuildRequestStart struct {
-}
-
-func (*spanBuildRequestStart) ID() string {
- return "spanBuildRequestStart"
-}
-
-func (m *spanBuildRequestStart) HandleSerialize(
- ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler,
-) (
- middleware.SerializeOutput, middleware.Metadata, error,
-) {
- ctx, _ = tracing.StartSpan(ctx, "BuildRequest")
-
- return next.HandleSerialize(ctx, in)
-}
-
-type spanBuildRequestEnd struct {
-}
-
-func (*spanBuildRequestEnd) ID() string {
- return "spanBuildRequestEnd"
-}
-
-func (m *spanBuildRequestEnd) HandleBuild(
- ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
-) (
- middleware.BuildOutput, middleware.Metadata, error,
-) {
- ctx, span := tracing.PopSpan(ctx)
- span.End()
-
- return next.HandleBuild(ctx, in)
-}
-
-func addSpanInitializeStart(stack *middleware.Stack) error {
- return stack.Initialize.Add(&spanInitializeStart{}, middleware.Before)
-}
-
-func addSpanInitializeEnd(stack *middleware.Stack) error {
- return stack.Initialize.Add(&spanInitializeEnd{}, middleware.After)
-}
-
-func addSpanBuildRequestStart(stack *middleware.Stack) error {
- return stack.Serialize.Add(&spanBuildRequestStart{}, middleware.Before)
-}
+func addInterceptors(stack *middleware.Stack, opts Options) error {
+ // middlewares are expensive, don't add all of these interceptor ones unless the caller
+ // actually has at least one interceptor configured
+ //
+ // at the moment it's all-or-nothing because some of the middlewares here are responsible for
+ // setting fields in the interceptor context for future ones
+ if len(opts.Interceptors.BeforeExecution) == 0 &&
+ len(opts.Interceptors.BeforeSerialization) == 0 && len(opts.Interceptors.AfterSerialization) == 0 &&
+ len(opts.Interceptors.BeforeRetryLoop) == 0 &&
+ len(opts.Interceptors.BeforeAttempt) == 0 &&
+ len(opts.Interceptors.BeforeSigning) == 0 && len(opts.Interceptors.AfterSigning) == 0 &&
+ len(opts.Interceptors.BeforeTransmit) == 0 && len(opts.Interceptors.AfterTransmit) == 0 &&
+ len(opts.Interceptors.BeforeDeserialization) == 0 && len(opts.Interceptors.AfterDeserialization) == 0 &&
+ len(opts.Interceptors.AfterAttempt) == 0 && len(opts.Interceptors.AfterExecution) == 0 {
+ return nil
+ }
-func addSpanBuildRequestEnd(stack *middleware.Stack) error {
- return stack.Build.Add(&spanBuildRequestEnd{}, middleware.After)
+ return errors.Join(
+ stack.Initialize.Add(&smithyhttp.InterceptExecution{
+ BeforeExecution: opts.Interceptors.BeforeExecution,
+ AfterExecution: opts.Interceptors.AfterExecution,
+ }, middleware.Before),
+ stack.Serialize.Insert(&smithyhttp.InterceptBeforeSerialization{
+ Interceptors: opts.Interceptors.BeforeSerialization,
+ }, "OperationSerializer", middleware.Before),
+ stack.Serialize.Insert(&smithyhttp.InterceptAfterSerialization{
+ Interceptors: opts.Interceptors.AfterSerialization,
+ }, "OperationSerializer", middleware.After),
+ stack.Finalize.Insert(&smithyhttp.InterceptBeforeSigning{
+ Interceptors: opts.Interceptors.BeforeSigning,
+ }, "Signing", middleware.Before),
+ stack.Finalize.Insert(&smithyhttp.InterceptAfterSigning{
+ Interceptors: opts.Interceptors.AfterSigning,
+ }, "Signing", middleware.After),
+ stack.Deserialize.Add(&smithyhttp.InterceptTransmit{
+ BeforeTransmit: opts.Interceptors.BeforeTransmit,
+ AfterTransmit: opts.Interceptors.AfterTransmit,
+ }, middleware.After),
+ stack.Deserialize.Insert(&smithyhttp.InterceptBeforeDeserialization{
+ Interceptors: opts.Interceptors.BeforeDeserialization,
+ }, "OperationDeserializer", middleware.After), // (deserialize stack is called in reverse)
+ stack.Deserialize.Insert(&smithyhttp.InterceptAfterDeserialization{
+ Interceptors: opts.Interceptors.AfterDeserialization,
+ }, "OperationDeserializer", middleware.Before),
+ )
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go
index b3875eeabeb3..3f622dbcb952 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go
@@ -85,10 +85,9 @@ type CreateTokenInput struct {
// [IAM Identity Center OIDC API Reference]: https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/Welcome.html
RefreshToken *string
- // The list of scopes for which authorization is requested. The access token that
- // is issued is limited to the scopes that are granted. If this value is not
- // specified, IAM Identity Center authorizes all scopes that are configured for the
- // client during the call to RegisterClient.
+ // The list of scopes for which authorization is requested. This parameter has no
+ // effect; the access token will always include all scopes configured during client
+ // registration.
Scope []string
noSmithyDocumentSerde
@@ -224,40 +223,7 @@ func (c *Client) addOperationCreateTokenMiddlewares(stack *middleware.Stack, opt
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go
index 78b37b5eafde..24cb2fac8db6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go
@@ -11,10 +11,19 @@ import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)
-// Creates and returns access and refresh tokens for clients and applications that
-// are authenticated using IAM entities. The access token can be used to fetch
-// short-lived credentials for the assigned Amazon Web Services accounts or to
-// access application APIs using bearer authentication.
+// Creates and returns access and refresh tokens for authorized client
+// applications that are authenticated using any IAM entity, such as a service role
+// or user. These tokens might contain defined scopes that specify permissions such
+// as read:profile or write:data . Through downscoping, you can use the scopes
+// parameter to request tokens with reduced permissions compared to the original
+// client application's permissions or, if applicable, the refresh token's scopes.
+// The access token can be used to fetch short-lived credentials for the assigned
+// Amazon Web Services accounts or to access application APIs using bearer
+// authentication.
+//
+// This API is used with Signature Version 4. For more information, see [Amazon Web Services Signature Version 4 for API Requests].
+//
+// [Amazon Web Services Signature Version 4 for API Requests]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html
func (c *Client) CreateTokenWithIAM(ctx context.Context, params *CreateTokenWithIAMInput, optFns ...func(*Options)) (*CreateTokenWithIAMOutput, error) {
if params == nil {
params = &CreateTokenWithIAMInput{}
@@ -124,9 +133,8 @@ type CreateTokenWithIAMOutput struct {
// to a user.
AccessToken *string
- // A structure containing information from the idToken . Only the identityContext
- // is in it, which is a value extracted from the idToken . This provides direct
- // access to identity information without requiring JWT parsing.
+ // A structure containing information from IAM Identity Center managed user and
+ // group information.
AwsAdditionalDetails *types.AwsAdditionalDetails
// Indicates the time in seconds when an access token will expire.
@@ -262,40 +270,7 @@ func (c *Client) addOperationCreateTokenWithIAMMiddlewares(stack *middleware.Sta
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go
index 8d50092fb15b..14472ee3be68 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go
@@ -194,40 +194,7 @@ func (c *Client) addOperationRegisterClientMiddlewares(stack *middleware.Stack,
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go
index 7242ac82b68b..92a6854a776b 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go
@@ -176,40 +176,7 @@ func (c *Client) addOperationStartDeviceAuthorizationMiddlewares(stack *middlewa
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/deserializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/deserializers.go
index 17712c6dc7ca..fb9a0df51942 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/deserializers.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/deserializers.go
@@ -611,6 +611,9 @@ func awsRestjson1_deserializeOpErrorRegisterClient(response *smithyhttp.Response
case strings.EqualFold("InvalidScopeException", errorCode):
return awsRestjson1_deserializeErrorInvalidScopeException(response, errorBody)
+ case strings.EqualFold("SlowDownException", errorCode):
+ return awsRestjson1_deserializeErrorSlowDownException(response, errorBody)
+
case strings.EqualFold("UnsupportedGrantTypeException", errorCode):
return awsRestjson1_deserializeErrorUnsupportedGrantTypeException(response, errorBody)
@@ -1482,6 +1485,15 @@ func awsRestjson1_deserializeDocumentAccessDeniedException(v **types.AccessDenie
sv.Error_description = ptr.String(jtv)
}
+ case "reason":
+ if value != nil {
+ jtv, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("expected AccessDeniedExceptionReason to be of type string, got %T instead", value)
+ }
+ sv.Reason = types.AccessDeniedExceptionReason(jtv)
+ }
+
default:
_, _ = key, value
@@ -1914,6 +1926,15 @@ func awsRestjson1_deserializeDocumentInvalidRequestException(v **types.InvalidRe
sv.Error_description = ptr.String(jtv)
}
+ case "reason":
+ if value != nil {
+ jtv, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("expected InvalidRequestExceptionReason to be of type string, got %T instead", value)
+ }
+ sv.Reason = types.InvalidRequestExceptionReason(jtv)
+ }
+
default:
_, _ = key, value
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/doc.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/doc.go
index f3510b18c546..aa9cf731d4c6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/doc.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/doc.go
@@ -11,7 +11,7 @@
// # API namespaces
//
// IAM Identity Center uses the sso and identitystore API namespaces. IAM Identity
-// Center OpenID Connect uses the sso-oidc namespace.
+// Center OpenID Connect uses the sso-oauth namespace.
//
// # Considerations for using this guide
//
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/endpoints.go
index 6feea0c9fec4..3deb443b2896 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/endpoints.go
@@ -217,11 +217,15 @@ func resolveBaseEndpoint(cfg aws.Config, o *Options) {
}
}
-func bindRegion(region string) *string {
+func bindRegion(region string) (*string, error) {
if region == "" {
- return nil
+ return nil, nil
+ }
+ if !smithyhttp.ValidHostLabel(region) {
+ return nil, fmt.Errorf("invalid input region %s", region)
}
- return aws.String(endpoints.MapFIPSRegion(region))
+
+ return aws.String(endpoints.MapFIPSRegion(region)), nil
}
// EndpointParameters provides the parameters that influence how endpoints are
@@ -328,7 +332,9 @@ func (r *resolver) ResolveEndpoint(
return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err)
}
_UseDualStack := *params.UseDualStack
+ _ = _UseDualStack
_UseFIPS := *params.UseFIPS
+ _ = _UseFIPS
if exprVal := params.Endpoint; exprVal != nil {
_Endpoint := *exprVal
@@ -477,10 +483,15 @@ type endpointParamsBinder interface {
bindEndpointParams(*EndpointParameters)
}
-func bindEndpointParams(ctx context.Context, input interface{}, options Options) *EndpointParameters {
+func bindEndpointParams(ctx context.Context, input interface{}, options Options) (*EndpointParameters, error) {
params := &EndpointParameters{}
- params.Region = bindRegion(options.Region)
+ region, err := bindRegion(options.Region)
+ if err != nil {
+ return nil, err
+ }
+ params.Region = region
+
params.UseDualStack = aws.Bool(options.EndpointOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled)
params.UseFIPS = aws.Bool(options.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled)
params.Endpoint = options.BaseEndpoint
@@ -489,7 +500,7 @@ func bindEndpointParams(ctx context.Context, input interface{}, options Options)
b.bindEndpointParams(params)
}
- return params
+ return params, nil
}
type resolveEndpointV2Middleware struct {
@@ -519,7 +530,10 @@ func (m *resolveEndpointV2Middleware) HandleFinalize(ctx context.Context, in mid
return out, metadata, fmt.Errorf("expected endpoint resolver to not be nil")
}
- params := bindEndpointParams(ctx, getOperationInput(ctx), m.options)
+ params, err := bindEndpointParams(ctx, getOperationInput(ctx), m.options)
+ if err != nil {
+ return out, metadata, fmt.Errorf("failed to bind endpoint params, %w", err)
+ }
endpt, err := timeOperationMetric(ctx, "client.call.resolve_endpoint_duration",
func() (smithyendpoints.Endpoint, error) {
return m.options.EndpointResolverV2.ResolveEndpoint(ctx, *params)
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json
index 35f180975a8c..ee79b48eaa57 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json
@@ -26,11 +26,12 @@
"serializers.go",
"snapshot_test.go",
"sra_operation_order_test.go",
+ "types/enums.go",
"types/errors.go",
"types/types.go",
"validators.go"
],
- "go": "1.22",
+ "go": "1.23",
"module": "github.com/aws/aws-sdk-go-v2/service/ssooidc",
"unstable": false
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go
index d0758f943579..aa850b99d144 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go
@@ -3,4 +3,4 @@
package ssooidc
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.34.0"
+const goModuleVersion = "1.35.7"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints/endpoints.go
index ba7b4f9eb01d..f15c1a3ff52f 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints/endpoints.go
@@ -237,6 +237,9 @@ var defaultPartitions = endpoints.Partitions{
Region: "ap-southeast-5",
},
},
+ endpoints.EndpointKey{
+ Region: "ap-southeast-7",
+ }: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ca-central-1",
}: endpoints.Endpoint{
@@ -341,6 +344,9 @@ var defaultPartitions = endpoints.Partitions{
Region: "me-south-1",
},
},
+ endpoints.EndpointKey{
+ Region: "mx-central-1",
+ }: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "sa-east-1",
}: endpoints.Endpoint{
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/enums.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/enums.go
new file mode 100644
index 000000000000..b14a3c05810a
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/enums.go
@@ -0,0 +1,44 @@
+// Code generated by smithy-go-codegen DO NOT EDIT.
+
+package types
+
+type AccessDeniedExceptionReason string
+
+// Enum values for AccessDeniedExceptionReason
+const (
+ AccessDeniedExceptionReasonKmsAccessDenied AccessDeniedExceptionReason = "KMS_AccessDeniedException"
+)
+
+// Values returns all known values for AccessDeniedExceptionReason. Note that this
+// can be expanded in the future, and so it is only as up to date as the client.
+//
+// The ordering of this slice is not guaranteed to be stable across updates.
+func (AccessDeniedExceptionReason) Values() []AccessDeniedExceptionReason {
+ return []AccessDeniedExceptionReason{
+ "KMS_AccessDeniedException",
+ }
+}
+
+type InvalidRequestExceptionReason string
+
+// Enum values for InvalidRequestExceptionReason
+const (
+ InvalidRequestExceptionReasonKmsKeyNotFound InvalidRequestExceptionReason = "KMS_NotFoundException"
+ InvalidRequestExceptionReasonKmsInvalidKeyUsage InvalidRequestExceptionReason = "KMS_InvalidKeyUsageException"
+ InvalidRequestExceptionReasonKmsInvalidState InvalidRequestExceptionReason = "KMS_InvalidStateException"
+ InvalidRequestExceptionReasonKmsDisabledKey InvalidRequestExceptionReason = "KMS_DisabledException"
+)
+
+// Values returns all known values for InvalidRequestExceptionReason. Note that
+// this can be expanded in the future, and so it is only as up to date as the
+// client.
+//
+// The ordering of this slice is not guaranteed to be stable across updates.
+func (InvalidRequestExceptionReason) Values() []InvalidRequestExceptionReason {
+ return []InvalidRequestExceptionReason{
+ "KMS_NotFoundException",
+ "KMS_InvalidKeyUsageException",
+ "KMS_InvalidStateException",
+ "KMS_DisabledException",
+ }
+}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/errors.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/errors.go
index 2cfe7b48fed6..a1a3c7ef0da7 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/errors.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/errors.go
@@ -14,6 +14,7 @@ type AccessDeniedException struct {
ErrorCodeOverride *string
Error_ *string
+ Reason AccessDeniedExceptionReason
Error_description *string
noSmithyDocumentSerde
@@ -255,6 +256,7 @@ type InvalidRequestException struct {
ErrorCodeOverride *string
Error_ *string
+ Reason InvalidRequestExceptionReason
Error_description *string
noSmithyDocumentSerde
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/types.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/types.go
index 2e8f3ea031c7..de15e8f05140 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/types.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/types.go
@@ -6,14 +6,17 @@ import (
smithydocument "github.com/aws/smithy-go/document"
)
-// This structure contains Amazon Web Services-specific parameter extensions for
-// the token endpoint responses and includes the identity context.
+// This structure contains Amazon Web Services-specific parameter extensions and
+// the [identity context].
+//
+// [identity context]: https://docs.aws.amazon.com/singlesignon/latest/userguide/trustedidentitypropagation-overview.html
type AwsAdditionalDetails struct {
- // STS context assertion that carries a user identifier to the Amazon Web Services
- // service that it calls and can be used to obtain an identity-enhanced IAM role
- // session. This value corresponds to the sts:identity_context claim in the ID
- // token.
+ // The trusted context assertion is signed and encrypted by STS. It provides
+ // access to sts:identity_context claim in the idToken without JWT parsing
+ //
+ // Identity context comprises information that Amazon Web Services services use to
+ // make authorization decisions when they receive requests.
IdentityContext *string
noSmithyDocumentSerde
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md
index ca18a1e9f2c3..ac1346ff9b88 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md
@@ -1,3 +1,65 @@
+# v1.40.2 (2025-11-12)
+
+* **Bug Fix**: Further reduce allocation overhead when the metrics system isn't in-use.
+* **Bug Fix**: Reduce allocation overhead when the client doesn't have any HTTP interceptors configured.
+* **Bug Fix**: Remove blank trace spans towards the beginning of the request that added no additional information. This conveys a slight reduction in overall allocations.
+
+# v1.40.1 (2025-11-11)
+
+* **Bug Fix**: Return validation error if input region is not a valid host label.
+
+# v1.40.0 (2025-11-10)
+
+* **Feature**: Added GetDelegatedAccessToken API, which is not available for general use at this time.
+
+# v1.39.1 (2025-11-04)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+* **Dependency Update**: Upgrade to smithy-go v1.23.2 which should convey some passive reduction of overall allocations, especially when not using the metrics system.
+
+# v1.39.0 (2025-10-30)
+
+* **Feature**: Update endpoint ruleset parameters casing
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.9 (2025-10-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.8 (2025-10-22)
+
+* No change notes available for this release.
+
+# v1.38.7 (2025-10-16)
+
+* **Dependency Update**: Bump minimum Go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.6 (2025-09-26)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.5 (2025-09-23)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.4 (2025-09-10)
+
+* No change notes available for this release.
+
+# v1.38.3 (2025-09-08)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.2 (2025-08-29)
+
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# v1.38.1 (2025-08-27)
+
+* **Dependency Update**: Update to smithy-go v1.23.0.
+* **Dependency Update**: Updated to the latest SDK module versions
+
# v1.38.0 (2025-08-21)
* **Feature**: Remove incorrect endpoint tests
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go
index 6658babc95f6..70228d0dfa77 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go
@@ -68,7 +68,12 @@ func timeOperationMetric[T any](
ctx context.Context, metric string, fn func() (T, error),
opts ...metrics.RecordMetricOption,
) (T, error) {
- instr := getOperationMetrics(ctx).histogramFor(metric)
+ mm := getOperationMetrics(ctx)
+ if mm == nil { // not using the metrics system
+ return fn()
+ }
+
+ instr := mm.histogramFor(metric)
opts = append([]metrics.RecordMetricOption{withOperationMetadata(ctx)}, opts...)
start := time.Now()
@@ -81,7 +86,12 @@ func timeOperationMetric[T any](
}
func startMetricTimer(ctx context.Context, metric string, opts ...metrics.RecordMetricOption) func() {
- instr := getOperationMetrics(ctx).histogramFor(metric)
+ mm := getOperationMetrics(ctx)
+ if mm == nil { // not using the metrics system
+ return func() {}
+ }
+
+ instr := mm.histogramFor(metric)
opts = append([]metrics.RecordMetricOption{withOperationMetadata(ctx)}, opts...)
var ended bool
@@ -109,6 +119,12 @@ func withOperationMetadata(ctx context.Context) metrics.RecordMetricOption {
type operationMetricsKey struct{}
func withOperationMetrics(parent context.Context, mp metrics.MeterProvider) (context.Context, error) {
+ if _, ok := mp.(metrics.NopMeterProvider); ok {
+ // not using the metrics system - setting up the metrics context is a memory-intensive operation
+ // so we should skip it in this case
+ return parent, nil
+ }
+
meter := mp.Meter("github.com/aws/aws-sdk-go-v2/service/sts")
om := &operationMetrics{}
@@ -156,7 +172,10 @@ func operationMetricTimer(m metrics.Meter, name, desc string) (metrics.Float64Hi
}
func getOperationMetrics(ctx context.Context) *operationMetrics {
- return ctx.Value(operationMetricsKey{}).(*operationMetrics)
+ if v := ctx.Value(operationMetricsKey{}); v != nil {
+ return v.(*operationMetrics)
+ }
+ return nil
}
func operationTracer(p tracing.TracerProvider) tracing.Tracer {
@@ -1034,138 +1053,49 @@ func addInterceptAttempt(stack *middleware.Stack, opts Options) error {
}, "Retry", middleware.After)
}
-func addInterceptExecution(stack *middleware.Stack, opts Options) error {
- return stack.Initialize.Add(&smithyhttp.InterceptExecution{
- BeforeExecution: opts.Interceptors.BeforeExecution,
- AfterExecution: opts.Interceptors.AfterExecution,
- }, middleware.Before)
-}
-
-func addInterceptBeforeSerialization(stack *middleware.Stack, opts Options) error {
- return stack.Serialize.Insert(&smithyhttp.InterceptBeforeSerialization{
- Interceptors: opts.Interceptors.BeforeSerialization,
- }, "OperationSerializer", middleware.Before)
-}
-
-func addInterceptAfterSerialization(stack *middleware.Stack, opts Options) error {
- return stack.Serialize.Insert(&smithyhttp.InterceptAfterSerialization{
- Interceptors: opts.Interceptors.AfterSerialization,
- }, "OperationSerializer", middleware.After)
-}
-
-func addInterceptBeforeSigning(stack *middleware.Stack, opts Options) error {
- return stack.Finalize.Insert(&smithyhttp.InterceptBeforeSigning{
- Interceptors: opts.Interceptors.BeforeSigning,
- }, "Signing", middleware.Before)
-}
-
-func addInterceptAfterSigning(stack *middleware.Stack, opts Options) error {
- return stack.Finalize.Insert(&smithyhttp.InterceptAfterSigning{
- Interceptors: opts.Interceptors.AfterSigning,
- }, "Signing", middleware.After)
-}
-
-func addInterceptTransmit(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Add(&smithyhttp.InterceptTransmit{
- BeforeTransmit: opts.Interceptors.BeforeTransmit,
- AfterTransmit: opts.Interceptors.AfterTransmit,
- }, middleware.After)
-}
-
-func addInterceptBeforeDeserialization(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Insert(&smithyhttp.InterceptBeforeDeserialization{
- Interceptors: opts.Interceptors.BeforeDeserialization,
- }, "OperationDeserializer", middleware.After) // (deserialize stack is called in reverse)
-}
-
-func addInterceptAfterDeserialization(stack *middleware.Stack, opts Options) error {
- return stack.Deserialize.Insert(&smithyhttp.InterceptAfterDeserialization{
- Interceptors: opts.Interceptors.AfterDeserialization,
- }, "OperationDeserializer", middleware.Before)
-}
-
-type spanInitializeStart struct {
-}
-
-func (*spanInitializeStart) ID() string {
- return "spanInitializeStart"
-}
-
-func (m *spanInitializeStart) HandleInitialize(
- ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
-) (
- middleware.InitializeOutput, middleware.Metadata, error,
-) {
- ctx, _ = tracing.StartSpan(ctx, "Initialize")
-
- return next.HandleInitialize(ctx, in)
-}
-
-type spanInitializeEnd struct {
-}
-
-func (*spanInitializeEnd) ID() string {
- return "spanInitializeEnd"
-}
-
-func (m *spanInitializeEnd) HandleInitialize(
- ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
-) (
- middleware.InitializeOutput, middleware.Metadata, error,
-) {
- ctx, span := tracing.PopSpan(ctx)
- span.End()
-
- return next.HandleInitialize(ctx, in)
-}
-
-type spanBuildRequestStart struct {
-}
-
-func (*spanBuildRequestStart) ID() string {
- return "spanBuildRequestStart"
-}
-
-func (m *spanBuildRequestStart) HandleSerialize(
- ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler,
-) (
- middleware.SerializeOutput, middleware.Metadata, error,
-) {
- ctx, _ = tracing.StartSpan(ctx, "BuildRequest")
-
- return next.HandleSerialize(ctx, in)
-}
-
-type spanBuildRequestEnd struct {
-}
-
-func (*spanBuildRequestEnd) ID() string {
- return "spanBuildRequestEnd"
-}
-
-func (m *spanBuildRequestEnd) HandleBuild(
- ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
-) (
- middleware.BuildOutput, middleware.Metadata, error,
-) {
- ctx, span := tracing.PopSpan(ctx)
- span.End()
-
- return next.HandleBuild(ctx, in)
-}
-
-func addSpanInitializeStart(stack *middleware.Stack) error {
- return stack.Initialize.Add(&spanInitializeStart{}, middleware.Before)
-}
-
-func addSpanInitializeEnd(stack *middleware.Stack) error {
- return stack.Initialize.Add(&spanInitializeEnd{}, middleware.After)
-}
-
-func addSpanBuildRequestStart(stack *middleware.Stack) error {
- return stack.Serialize.Add(&spanBuildRequestStart{}, middleware.Before)
-}
+func addInterceptors(stack *middleware.Stack, opts Options) error {
+ // middlewares are expensive, don't add all of these interceptor ones unless the caller
+ // actually has at least one interceptor configured
+ //
+ // at the moment it's all-or-nothing because some of the middlewares here are responsible for
+ // setting fields in the interceptor context for future ones
+ if len(opts.Interceptors.BeforeExecution) == 0 &&
+ len(opts.Interceptors.BeforeSerialization) == 0 && len(opts.Interceptors.AfterSerialization) == 0 &&
+ len(opts.Interceptors.BeforeRetryLoop) == 0 &&
+ len(opts.Interceptors.BeforeAttempt) == 0 &&
+ len(opts.Interceptors.BeforeSigning) == 0 && len(opts.Interceptors.AfterSigning) == 0 &&
+ len(opts.Interceptors.BeforeTransmit) == 0 && len(opts.Interceptors.AfterTransmit) == 0 &&
+ len(opts.Interceptors.BeforeDeserialization) == 0 && len(opts.Interceptors.AfterDeserialization) == 0 &&
+ len(opts.Interceptors.AfterAttempt) == 0 && len(opts.Interceptors.AfterExecution) == 0 {
+ return nil
+ }
-func addSpanBuildRequestEnd(stack *middleware.Stack) error {
- return stack.Build.Add(&spanBuildRequestEnd{}, middleware.After)
+ return errors.Join(
+ stack.Initialize.Add(&smithyhttp.InterceptExecution{
+ BeforeExecution: opts.Interceptors.BeforeExecution,
+ AfterExecution: opts.Interceptors.AfterExecution,
+ }, middleware.Before),
+ stack.Serialize.Insert(&smithyhttp.InterceptBeforeSerialization{
+ Interceptors: opts.Interceptors.BeforeSerialization,
+ }, "OperationSerializer", middleware.Before),
+ stack.Serialize.Insert(&smithyhttp.InterceptAfterSerialization{
+ Interceptors: opts.Interceptors.AfterSerialization,
+ }, "OperationSerializer", middleware.After),
+ stack.Finalize.Insert(&smithyhttp.InterceptBeforeSigning{
+ Interceptors: opts.Interceptors.BeforeSigning,
+ }, "Signing", middleware.Before),
+ stack.Finalize.Insert(&smithyhttp.InterceptAfterSigning{
+ Interceptors: opts.Interceptors.AfterSigning,
+ }, "Signing", middleware.After),
+ stack.Deserialize.Add(&smithyhttp.InterceptTransmit{
+ BeforeTransmit: opts.Interceptors.BeforeTransmit,
+ AfterTransmit: opts.Interceptors.AfterTransmit,
+ }, middleware.After),
+ stack.Deserialize.Insert(&smithyhttp.InterceptBeforeDeserialization{
+ Interceptors: opts.Interceptors.BeforeDeserialization,
+ }, "OperationDeserializer", middleware.After), // (deserialize stack is called in reverse)
+ stack.Deserialize.Insert(&smithyhttp.InterceptAfterDeserialization{
+ Interceptors: opts.Interceptors.AfterDeserialization,
+ }, "OperationDeserializer", middleware.Before),
+ )
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go
index f3a93418fa01..0ddd3623ae56 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go
@@ -147,7 +147,7 @@ type AssumeRoleInput struct {
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can also
- // include underscores or any of the following characters: =,.@-
+ // include underscores or any of the following characters: +=,.@-
//
// [CloudTrail logs]: https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-integration.html#cloudtrail-integration_signin-tempcreds
// [sts:RoleSessionName]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#ck_rolesessionname
@@ -196,7 +196,7 @@ type AssumeRoleInput struct {
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can also
- // include underscores or any of the following characters: =,.@:/-
+ // include underscores or any of the following characters: +=,.@:\/-
//
// [How to Use an External ID When Granting Access to Your Amazon Web Services Resources to a Third Party]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html
ExternalId *string
@@ -279,7 +279,7 @@ type AssumeRoleInput struct {
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can also
- // include underscores or any of the following characters: =,.@-
+ // include underscores or any of the following characters: +=/:,.@-
SerialNumber *string
// The source identity specified by the principal that is calling the AssumeRole
@@ -508,40 +508,7 @@ func (c *Client) addOperationAssumeRoleMiddlewares(stack *middleware.Stack, opti
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go
index 9dcceec12a25..15f1dd91d295 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go
@@ -23,6 +23,9 @@ import (
// these temporary security credentials to sign calls to Amazon Web Services
// services.
//
+// AssumeRoleWithSAML will not work on IAM Identity Center managed roles. These
+// roles' names start with AWSReservedSSO_ .
+//
// # Session Duration
//
// By default, the temporary security credentials created by AssumeRoleWithSAML
@@ -440,40 +443,7 @@ func (c *Client) addOperationAssumeRoleWithSAMLMiddlewares(stack *middleware.Sta
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go
index 5975a0cdee86..7006eb3b7fb4 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go
@@ -75,7 +75,7 @@ import (
//
// (Optional) You can configure your IdP to pass attributes into your web identity
// token as session tags. Each session tag consists of a key name and an associated
-// value. For more information about session tags, see [Passing Session Tags in STS]in the IAM User Guide.
+// value. For more information about session tags, see [Passing session tags using AssumeRoleWithWebIdentity]in the IAM User Guide.
//
// You can pass up to 50 session tags. The plaintext session tag keys can’t exceed
// 128 characters and the values can’t exceed 256 characters. For these and
@@ -123,6 +123,7 @@ import (
// providers to get and use temporary security credentials.
//
// [Amazon Web Services SDK for iOS Developer Guide]: http://aws.amazon.com/sdkforios/
+// [Passing session tags using AssumeRoleWithWebIdentity]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_adding-assume-role-idp
// [Amazon Web Services SDK for Android Developer Guide]: http://aws.amazon.com/sdkforandroid/
// [IAM and STS Character Limits]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length
// [session policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session
@@ -135,7 +136,6 @@ import (
// [Using IAM Roles]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html
// [Session Policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session
// [Amazon Cognito federated identities]: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html
-// [Passing Session Tags in STS]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html
// [Chaining Roles with Session Tags]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_role-chaining
// [Update the maximum session duration for a role]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-settings.html#id_roles_update-session-duration
// [Using Web Identity Federation API Operations for Mobile Apps]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual.html
@@ -460,40 +460,7 @@ func (c *Client) addOperationAssumeRoleWithWebIdentityMiddlewares(stack *middlew
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go
index 571f06728a5b..009c40558387 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go
@@ -12,7 +12,9 @@ import (
)
// Returns a set of short term credentials you can use to perform privileged tasks
-// on a member account in your organization.
+// on a member account in your organization. You must use credentials from an
+// Organizations management account or a delegated administrator account for IAM to
+// call AssumeRoot . You cannot use root user credentials to make this call.
//
// Before you can launch a privileged session, you must have centralized root
// access in your organization. For steps to enable this feature, see [Centralize root access for member accounts]in the IAM
@@ -24,8 +26,16 @@ import (
// You can track AssumeRoot in CloudTrail logs to determine what actions were
// performed in a session. For more information, see [Track privileged tasks in CloudTrail]in the IAM User Guide.
//
+// When granting access to privileged tasks you should only grant the necessary
+// permissions required to perform that task. For more information, see [Security best practices in IAM]. In
+// addition, you can use [service control policies](SCPs) to manage and limit permissions in your
+// organization. See [General examples]in the Organizations User Guide for more information on SCPs.
+//
// [Endpoints]: https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html#sts-endpoints
+// [Security best practices in IAM]: https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html
// [Track privileged tasks in CloudTrail]: https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-track-privileged-tasks.html
+// [General examples]: https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples_general.html
+// [service control policies]: https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html
// [Centralize root access for member accounts]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-enable-root-access.html
func (c *Client) AssumeRoot(ctx context.Context, params *AssumeRootInput, optFns ...func(*Options)) (*AssumeRootOutput, error) {
if params == nil {
@@ -50,8 +60,10 @@ type AssumeRootInput struct {
TargetPrincipal *string
// The identity based policy that scopes the session to the privileged tasks that
- // can be performed. You can use one of following Amazon Web Services managed
- // policies to scope root session actions.
+ // can be performed. You must
+ //
+ // use one of following Amazon Web Services managed policies to scope root session
+ // actions:
//
// [IAMAuditRootUserCredentials]
//
@@ -205,40 +217,7 @@ func (c *Client) addOperationAssumeRootMiddlewares(stack *middleware.Stack, opti
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go
index 786bac89b8ac..b00b0c4096c6 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go
@@ -177,40 +177,7 @@ func (c *Client) addOperationDecodeAuthorizationMessageMiddlewares(stack *middle
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go
index 6c1f878981cf..887bb081f3b0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go
@@ -168,40 +168,7 @@ func (c *Client) addOperationGetAccessKeyInfoMiddlewares(stack *middleware.Stack
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go
index 7d0653398b31..2c8d8867013c 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go
@@ -156,40 +156,7 @@ func (c *Client) addOperationGetCallerIdentityMiddlewares(stack *middleware.Stac
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go
new file mode 100644
index 000000000000..fbc9b46f83af
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go
@@ -0,0 +1,163 @@
+// Code generated by smithy-go-codegen DO NOT EDIT.
+
+package sts
+
+import (
+ "context"
+ "fmt"
+ awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
+ "github.com/aws/aws-sdk-go-v2/service/sts/types"
+ "github.com/aws/smithy-go/middleware"
+ smithyhttp "github.com/aws/smithy-go/transport/http"
+)
+
+// This API is currently unavailable for general use.
+func (c *Client) GetDelegatedAccessToken(ctx context.Context, params *GetDelegatedAccessTokenInput, optFns ...func(*Options)) (*GetDelegatedAccessTokenOutput, error) {
+ if params == nil {
+ params = &GetDelegatedAccessTokenInput{}
+ }
+
+ result, metadata, err := c.invokeOperation(ctx, "GetDelegatedAccessToken", params, optFns, c.addOperationGetDelegatedAccessTokenMiddlewares)
+ if err != nil {
+ return nil, err
+ }
+
+ out := result.(*GetDelegatedAccessTokenOutput)
+ out.ResultMetadata = metadata
+ return out, nil
+}
+
+type GetDelegatedAccessTokenInput struct {
+
+ //
+ //
+ // This member is required.
+ TradeInToken *string
+
+ noSmithyDocumentSerde
+}
+
+type GetDelegatedAccessTokenOutput struct {
+
+ //
+ AssumedPrincipal *string
+
+ // Amazon Web Services credentials for API authentication.
+ Credentials *types.Credentials
+
+ //
+ PackedPolicySize *int32
+
+ // Metadata pertaining to the operation's result.
+ ResultMetadata middleware.Metadata
+
+ noSmithyDocumentSerde
+}
+
+func (c *Client) addOperationGetDelegatedAccessTokenMiddlewares(stack *middleware.Stack, options Options) (err error) {
+ if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil {
+ return err
+ }
+ err = stack.Serialize.Add(&awsAwsquery_serializeOpGetDelegatedAccessToken{}, middleware.After)
+ if err != nil {
+ return err
+ }
+ err = stack.Deserialize.Add(&awsAwsquery_deserializeOpGetDelegatedAccessToken{}, middleware.After)
+ if err != nil {
+ return err
+ }
+ if err := addProtocolFinalizerMiddlewares(stack, options, "GetDelegatedAccessToken"); err != nil {
+ return fmt.Errorf("add protocol finalizers: %v", err)
+ }
+
+ if err = addlegacyEndpointContextSetter(stack, options); err != nil {
+ return err
+ }
+ if err = addSetLoggerMiddleware(stack, options); err != nil {
+ return err
+ }
+ if err = addClientRequestID(stack); err != nil {
+ return err
+ }
+ if err = addComputeContentLength(stack); err != nil {
+ return err
+ }
+ if err = addResolveEndpointMiddleware(stack, options); err != nil {
+ return err
+ }
+ if err = addComputePayloadSHA256(stack); err != nil {
+ return err
+ }
+ if err = addRetry(stack, options); err != nil {
+ return err
+ }
+ if err = addRawResponseToMetadata(stack); err != nil {
+ return err
+ }
+ if err = addRecordResponseTiming(stack); err != nil {
+ return err
+ }
+ if err = addSpanRetryLoop(stack, options); err != nil {
+ return err
+ }
+ if err = addClientUserAgent(stack, options); err != nil {
+ return err
+ }
+ if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
+ return err
+ }
+ if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
+ return err
+ }
+ if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil {
+ return err
+ }
+ if err = addTimeOffsetBuild(stack, c); err != nil {
+ return err
+ }
+ if err = addUserAgentRetryMode(stack, options); err != nil {
+ return err
+ }
+ if err = addCredentialSource(stack, options); err != nil {
+ return err
+ }
+ if err = addOpGetDelegatedAccessTokenValidationMiddleware(stack); err != nil {
+ return err
+ }
+ if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetDelegatedAccessToken(options.Region), middleware.Before); err != nil {
+ return err
+ }
+ if err = addRecursionDetection(stack); err != nil {
+ return err
+ }
+ if err = addRequestIDRetrieverMiddleware(stack); err != nil {
+ return err
+ }
+ if err = addResponseErrorMiddleware(stack); err != nil {
+ return err
+ }
+ if err = addRequestResponseLogging(stack, options); err != nil {
+ return err
+ }
+ if err = addDisableHTTPSMiddleware(stack, options); err != nil {
+ return err
+ }
+ if err = addInterceptBeforeRetryLoop(stack, options); err != nil {
+ return err
+ }
+ if err = addInterceptAttempt(stack, options); err != nil {
+ return err
+ }
+ if err = addInterceptors(stack, options); err != nil {
+ return err
+ }
+ return nil
+}
+
+func newServiceMetadataMiddleware_opGetDelegatedAccessToken(region string) *awsmiddleware.RegisterServiceMetadata {
+ return &awsmiddleware.RegisterServiceMetadata{
+ Region: region,
+ ServiceID: ServiceID,
+ OperationName: "GetDelegatedAccessToken",
+ }
+}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go
index 1c2f28e519c3..e0fc9a548484 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go
@@ -381,40 +381,7 @@ func (c *Client) addOperationGetFederationTokenMiddlewares(stack *middleware.Sta
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go
index 25604699009d..2f931f4446d0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go
@@ -227,40 +227,7 @@ func (c *Client) addOperationGetSessionTokenMiddlewares(stack *middleware.Stack,
if err = addInterceptAttempt(stack, options); err != nil {
return err
}
- if err = addInterceptExecution(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSerialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterSigning(stack, options); err != nil {
- return err
- }
- if err = addInterceptTransmit(stack, options); err != nil {
- return err
- }
- if err = addInterceptBeforeDeserialization(stack, options); err != nil {
- return err
- }
- if err = addInterceptAfterDeserialization(stack, options); err != nil {
- return err
- }
- if err = addSpanInitializeStart(stack); err != nil {
- return err
- }
- if err = addSpanInitializeEnd(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestStart(stack); err != nil {
- return err
- }
- if err = addSpanBuildRequestEnd(stack); err != nil {
+ if err = addInterceptors(stack, options); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/deserializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/deserializers.go
index a1ac917ec6a0..aa42a1312652 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/deserializers.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/deserializers.go
@@ -846,6 +846,121 @@ func awsAwsquery_deserializeOpErrorGetCallerIdentity(response *smithyhttp.Respon
}
}
+type awsAwsquery_deserializeOpGetDelegatedAccessToken struct {
+}
+
+func (*awsAwsquery_deserializeOpGetDelegatedAccessToken) ID() string {
+ return "OperationDeserializer"
+}
+
+func (m *awsAwsquery_deserializeOpGetDelegatedAccessToken) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
+ out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
+) {
+ out, metadata, err = next.HandleDeserialize(ctx, in)
+ if err != nil {
+ return out, metadata, err
+ }
+
+ _, span := tracing.StartSpan(ctx, "OperationDeserializer")
+ endTimer := startMetricTimer(ctx, "client.call.deserialization_duration")
+ defer endTimer()
+ defer span.End()
+ response, ok := out.RawResponse.(*smithyhttp.Response)
+ if !ok {
+ return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)}
+ }
+
+ if response.StatusCode < 200 || response.StatusCode >= 300 {
+ return out, metadata, awsAwsquery_deserializeOpErrorGetDelegatedAccessToken(response, &metadata)
+ }
+ output := &GetDelegatedAccessTokenOutput{}
+ out.Result = output
+
+ var buff [1024]byte
+ ringBuffer := smithyio.NewRingBuffer(buff[:])
+ body := io.TeeReader(response.Body, ringBuffer)
+ rootDecoder := xml.NewDecoder(body)
+ t, err := smithyxml.FetchRootElement(rootDecoder)
+ if err == io.EOF {
+ return out, metadata, nil
+ }
+ if err != nil {
+ var snapshot bytes.Buffer
+ io.Copy(&snapshot, ringBuffer)
+ return out, metadata, &smithy.DeserializationError{
+ Err: fmt.Errorf("failed to decode response body, %w", err),
+ Snapshot: snapshot.Bytes(),
+ }
+ }
+
+ decoder := smithyxml.WrapNodeDecoder(rootDecoder, t)
+ t, err = decoder.GetElement("GetDelegatedAccessTokenResult")
+ if err != nil {
+ var snapshot bytes.Buffer
+ io.Copy(&snapshot, ringBuffer)
+ err = &smithy.DeserializationError{
+ Err: fmt.Errorf("failed to decode response body, %w", err),
+ Snapshot: snapshot.Bytes(),
+ }
+ return out, metadata, err
+ }
+
+ decoder = smithyxml.WrapNodeDecoder(decoder.Decoder, t)
+ err = awsAwsquery_deserializeOpDocumentGetDelegatedAccessTokenOutput(&output, decoder)
+ if err != nil {
+ var snapshot bytes.Buffer
+ io.Copy(&snapshot, ringBuffer)
+ err = &smithy.DeserializationError{
+ Err: fmt.Errorf("failed to decode response body, %w", err),
+ Snapshot: snapshot.Bytes(),
+ }
+ return out, metadata, err
+ }
+
+ return out, metadata, err
+}
+
+func awsAwsquery_deserializeOpErrorGetDelegatedAccessToken(response *smithyhttp.Response, metadata *middleware.Metadata) error {
+ var errorBuffer bytes.Buffer
+ if _, err := io.Copy(&errorBuffer, response.Body); err != nil {
+ return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)}
+ }
+ errorBody := bytes.NewReader(errorBuffer.Bytes())
+
+ errorCode := "UnknownError"
+ errorMessage := errorCode
+
+ errorComponents, err := awsxml.GetErrorResponseComponents(errorBody, false)
+ if err != nil {
+ return err
+ }
+ if reqID := errorComponents.RequestID; len(reqID) != 0 {
+ awsmiddleware.SetRequestIDMetadata(metadata, reqID)
+ }
+ if len(errorComponents.Code) != 0 {
+ errorCode = errorComponents.Code
+ }
+ if len(errorComponents.Message) != 0 {
+ errorMessage = errorComponents.Message
+ }
+ errorBody.Seek(0, io.SeekStart)
+ switch {
+ case strings.EqualFold("ExpiredTradeInTokenException", errorCode):
+ return awsAwsquery_deserializeErrorExpiredTradeInTokenException(response, errorBody)
+
+ case strings.EqualFold("RegionDisabledException", errorCode):
+ return awsAwsquery_deserializeErrorRegionDisabledException(response, errorBody)
+
+ default:
+ genericError := &smithy.GenericAPIError{
+ Code: errorCode,
+ Message: errorMessage,
+ }
+ return genericError
+
+ }
+}
+
type awsAwsquery_deserializeOpGetFederationToken struct {
}
@@ -1120,6 +1235,50 @@ func awsAwsquery_deserializeErrorExpiredTokenException(response *smithyhttp.Resp
return output
}
+func awsAwsquery_deserializeErrorExpiredTradeInTokenException(response *smithyhttp.Response, errorBody *bytes.Reader) error {
+ output := &types.ExpiredTradeInTokenException{}
+ var buff [1024]byte
+ ringBuffer := smithyio.NewRingBuffer(buff[:])
+ body := io.TeeReader(errorBody, ringBuffer)
+ rootDecoder := xml.NewDecoder(body)
+ t, err := smithyxml.FetchRootElement(rootDecoder)
+ if err == io.EOF {
+ return output
+ }
+ if err != nil {
+ var snapshot bytes.Buffer
+ io.Copy(&snapshot, ringBuffer)
+ return &smithy.DeserializationError{
+ Err: fmt.Errorf("failed to decode response body, %w", err),
+ Snapshot: snapshot.Bytes(),
+ }
+ }
+
+ decoder := smithyxml.WrapNodeDecoder(rootDecoder, t)
+ t, err = decoder.GetElement("Error")
+ if err != nil {
+ var snapshot bytes.Buffer
+ io.Copy(&snapshot, ringBuffer)
+ return &smithy.DeserializationError{
+ Err: fmt.Errorf("failed to decode response body, %w", err),
+ Snapshot: snapshot.Bytes(),
+ }
+ }
+
+ decoder = smithyxml.WrapNodeDecoder(decoder.Decoder, t)
+ err = awsAwsquery_deserializeDocumentExpiredTradeInTokenException(&output, decoder)
+ if err != nil {
+ var snapshot bytes.Buffer
+ io.Copy(&snapshot, ringBuffer)
+ return &smithy.DeserializationError{
+ Err: fmt.Errorf("failed to decode response body, %w", err),
+ Snapshot: snapshot.Bytes(),
+ }
+ }
+
+ return output
+}
+
func awsAwsquery_deserializeErrorIDPCommunicationErrorException(response *smithyhttp.Response, errorBody *bytes.Reader) error {
output := &types.IDPCommunicationErrorException{}
var buff [1024]byte
@@ -1631,6 +1790,55 @@ func awsAwsquery_deserializeDocumentExpiredTokenException(v **types.ExpiredToken
return nil
}
+func awsAwsquery_deserializeDocumentExpiredTradeInTokenException(v **types.ExpiredTradeInTokenException, decoder smithyxml.NodeDecoder) error {
+ if v == nil {
+ return fmt.Errorf("unexpected nil of type %T", v)
+ }
+ var sv *types.ExpiredTradeInTokenException
+ if *v == nil {
+ sv = &types.ExpiredTradeInTokenException{}
+ } else {
+ sv = *v
+ }
+
+ for {
+ t, done, err := decoder.Token()
+ if err != nil {
+ return err
+ }
+ if done {
+ break
+ }
+ originalDecoder := decoder
+ decoder = smithyxml.WrapNodeDecoder(originalDecoder.Decoder, t)
+ switch {
+ case strings.EqualFold("message", t.Name.Local):
+ val, err := decoder.Value()
+ if err != nil {
+ return err
+ }
+ if val == nil {
+ break
+ }
+ {
+ xtv := string(val)
+ sv.Message = ptr.String(xtv)
+ }
+
+ default:
+ // Do nothing and ignore the unexpected tag element
+ err = decoder.Decoder.Skip()
+ if err != nil {
+ return err
+ }
+
+ }
+ decoder = originalDecoder
+ }
+ *v = sv
+ return nil
+}
+
func awsAwsquery_deserializeDocumentFederatedUser(v **types.FederatedUser, decoder smithyxml.NodeDecoder) error {
if v == nil {
return fmt.Errorf("unexpected nil of type %T", v)
@@ -2602,6 +2810,78 @@ func awsAwsquery_deserializeOpDocumentGetCallerIdentityOutput(v **GetCallerIdent
return nil
}
+func awsAwsquery_deserializeOpDocumentGetDelegatedAccessTokenOutput(v **GetDelegatedAccessTokenOutput, decoder smithyxml.NodeDecoder) error {
+ if v == nil {
+ return fmt.Errorf("unexpected nil of type %T", v)
+ }
+ var sv *GetDelegatedAccessTokenOutput
+ if *v == nil {
+ sv = &GetDelegatedAccessTokenOutput{}
+ } else {
+ sv = *v
+ }
+
+ for {
+ t, done, err := decoder.Token()
+ if err != nil {
+ return err
+ }
+ if done {
+ break
+ }
+ originalDecoder := decoder
+ decoder = smithyxml.WrapNodeDecoder(originalDecoder.Decoder, t)
+ switch {
+ case strings.EqualFold("AssumedPrincipal", t.Name.Local):
+ val, err := decoder.Value()
+ if err != nil {
+ return err
+ }
+ if val == nil {
+ break
+ }
+ {
+ xtv := string(val)
+ sv.AssumedPrincipal = ptr.String(xtv)
+ }
+
+ case strings.EqualFold("Credentials", t.Name.Local):
+ nodeDecoder := smithyxml.WrapNodeDecoder(decoder.Decoder, t)
+ if err := awsAwsquery_deserializeDocumentCredentials(&sv.Credentials, nodeDecoder); err != nil {
+ return err
+ }
+
+ case strings.EqualFold("PackedPolicySize", t.Name.Local):
+ val, err := decoder.Value()
+ if err != nil {
+ return err
+ }
+ if val == nil {
+ break
+ }
+ {
+ xtv := string(val)
+ i64, err := strconv.ParseInt(xtv, 10, 64)
+ if err != nil {
+ return err
+ }
+ sv.PackedPolicySize = ptr.Int32(int32(i64))
+ }
+
+ default:
+ // Do nothing and ignore the unexpected tag element
+ err = decoder.Decoder.Skip()
+ if err != nil {
+ return err
+ }
+
+ }
+ decoder = originalDecoder
+ }
+ *v = sv
+ return nil
+}
+
func awsAwsquery_deserializeOpDocumentGetFederationTokenOutput(v **GetFederationTokenOutput, decoder smithyxml.NodeDecoder) error {
if v == nil {
return fmt.Errorf("unexpected nil of type %T", v)
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/endpoints.go
index dca2ce3599e4..962596a6ef9d 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/endpoints.go
@@ -218,11 +218,15 @@ func resolveBaseEndpoint(cfg aws.Config, o *Options) {
}
}
-func bindRegion(region string) *string {
+func bindRegion(region string) (*string, error) {
if region == "" {
- return nil
+ return nil, nil
+ }
+ if !smithyhttp.ValidHostLabel(region) {
+ return nil, fmt.Errorf("invalid input region %s", region)
}
- return aws.String(endpoints.MapFIPSRegion(region))
+
+ return aws.String(endpoints.MapFIPSRegion(region)), nil
}
// EndpointParameters provides the parameters that influence how endpoints are
@@ -346,8 +350,11 @@ func (r *resolver) ResolveEndpoint(
return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err)
}
_UseDualStack := *params.UseDualStack
+ _ = _UseDualStack
_UseFIPS := *params.UseFIPS
+ _ = _UseFIPS
_UseGlobalEndpoint := *params.UseGlobalEndpoint
+ _ = _UseGlobalEndpoint
if _UseGlobalEndpoint == true {
if !(params.Endpoint != nil) {
@@ -1057,10 +1064,15 @@ type endpointParamsBinder interface {
bindEndpointParams(*EndpointParameters)
}
-func bindEndpointParams(ctx context.Context, input interface{}, options Options) *EndpointParameters {
+func bindEndpointParams(ctx context.Context, input interface{}, options Options) (*EndpointParameters, error) {
params := &EndpointParameters{}
- params.Region = bindRegion(options.Region)
+ region, err := bindRegion(options.Region)
+ if err != nil {
+ return nil, err
+ }
+ params.Region = region
+
params.UseDualStack = aws.Bool(options.EndpointOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled)
params.UseFIPS = aws.Bool(options.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled)
params.Endpoint = options.BaseEndpoint
@@ -1069,7 +1081,7 @@ func bindEndpointParams(ctx context.Context, input interface{}, options Options)
b.bindEndpointParams(params)
}
- return params
+ return params, nil
}
type resolveEndpointV2Middleware struct {
@@ -1099,7 +1111,10 @@ func (m *resolveEndpointV2Middleware) HandleFinalize(ctx context.Context, in mid
return out, metadata, fmt.Errorf("expected endpoint resolver to not be nil")
}
- params := bindEndpointParams(ctx, getOperationInput(ctx), m.options)
+ params, err := bindEndpointParams(ctx, getOperationInput(ctx), m.options)
+ if err != nil {
+ return out, metadata, fmt.Errorf("failed to bind endpoint params, %w", err)
+ }
endpt, err := timeOperationMetric(ctx, "client.call.resolve_endpoint_duration",
func() (smithyendpoints.Endpoint, error) {
return m.options.EndpointResolverV2.ResolveEndpoint(ctx, *params)
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json
index 86bb3b79be49..6e05b2097b42 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json
@@ -17,6 +17,7 @@
"api_op_DecodeAuthorizationMessage.go",
"api_op_GetAccessKeyInfo.go",
"api_op_GetCallerIdentity.go",
+ "api_op_GetDelegatedAccessToken.go",
"api_op_GetFederationToken.go",
"api_op_GetSessionToken.go",
"auth.go",
@@ -37,7 +38,7 @@
"types/types.go",
"validators.go"
],
- "go": "1.22",
+ "go": "1.23",
"module": "github.com/aws/aws-sdk-go-v2/service/sts",
"unstable": false
}
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go
index 931a5d81e11e..5fde44100dc0 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go
@@ -3,4 +3,4 @@
package sts
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.38.0"
+const goModuleVersion = "1.40.2"
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints/endpoints.go
index 3dfa51e5f4b2..1ec1ecf65250 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints/endpoints.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints/endpoints.go
@@ -180,6 +180,9 @@ var defaultPartitions = endpoints.Partitions{
endpoints.EndpointKey{
Region: "ap-southeast-5",
}: endpoints.Endpoint{},
+ endpoints.EndpointKey{
+ Region: "ap-southeast-6",
+ }: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-southeast-7",
}: endpoints.Endpoint{},
@@ -427,6 +430,9 @@ var defaultPartitions = endpoints.Partitions{
endpoints.EndpointKey{
Region: "us-isob-east-1",
}: endpoints.Endpoint{},
+ endpoints.EndpointKey{
+ Region: "us-isob-west-1",
+ }: endpoints.Endpoint{},
},
},
{
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/serializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/serializers.go
index 96b222136bf0..be7cc851b520 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/serializers.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/serializers.go
@@ -502,6 +502,76 @@ func (m *awsAwsquery_serializeOpGetCallerIdentity) HandleSerialize(ctx context.C
return next.HandleSerialize(ctx, in)
}
+type awsAwsquery_serializeOpGetDelegatedAccessToken struct {
+}
+
+func (*awsAwsquery_serializeOpGetDelegatedAccessToken) ID() string {
+ return "OperationSerializer"
+}
+
+func (m *awsAwsquery_serializeOpGetDelegatedAccessToken) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) (
+ out middleware.SerializeOutput, metadata middleware.Metadata, err error,
+) {
+ _, span := tracing.StartSpan(ctx, "OperationSerializer")
+ endTimer := startMetricTimer(ctx, "client.call.serialization_duration")
+ defer endTimer()
+ defer span.End()
+ request, ok := in.Request.(*smithyhttp.Request)
+ if !ok {
+ return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)}
+ }
+
+ input, ok := in.Parameters.(*GetDelegatedAccessTokenInput)
+ _ = input
+ if !ok {
+ return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)}
+ }
+
+ operationPath := "/"
+ if len(request.Request.URL.Path) == 0 {
+ request.Request.URL.Path = operationPath
+ } else {
+ request.Request.URL.Path = path.Join(request.Request.URL.Path, operationPath)
+ if request.Request.URL.Path != "/" && operationPath[len(operationPath)-1] == '/' {
+ request.Request.URL.Path += "/"
+ }
+ }
+ request.Request.Method = "POST"
+ httpBindingEncoder, err := httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header)
+ if err != nil {
+ return out, metadata, &smithy.SerializationError{Err: err}
+ }
+ httpBindingEncoder.SetHeader("Content-Type").String("application/x-www-form-urlencoded")
+
+ bodyWriter := bytes.NewBuffer(nil)
+ bodyEncoder := query.NewEncoder(bodyWriter)
+ body := bodyEncoder.Object()
+ body.Key("Action").String("GetDelegatedAccessToken")
+ body.Key("Version").String("2011-06-15")
+
+ if err := awsAwsquery_serializeOpDocumentGetDelegatedAccessTokenInput(input, bodyEncoder.Value); err != nil {
+ return out, metadata, &smithy.SerializationError{Err: err}
+ }
+
+ err = bodyEncoder.Encode()
+ if err != nil {
+ return out, metadata, &smithy.SerializationError{Err: err}
+ }
+
+ if request, err = request.SetStream(bytes.NewReader(bodyWriter.Bytes())); err != nil {
+ return out, metadata, &smithy.SerializationError{Err: err}
+ }
+
+ if request.Request, err = httpBindingEncoder.Encode(request.Request); err != nil {
+ return out, metadata, &smithy.SerializationError{Err: err}
+ }
+ in.Request = request
+
+ endTimer()
+ span.End()
+ return next.HandleSerialize(ctx, in)
+}
+
type awsAwsquery_serializeOpGetFederationToken struct {
}
@@ -946,6 +1016,18 @@ func awsAwsquery_serializeOpDocumentGetCallerIdentityInput(v *GetCallerIdentityI
return nil
}
+func awsAwsquery_serializeOpDocumentGetDelegatedAccessTokenInput(v *GetDelegatedAccessTokenInput, value query.Value) error {
+ object := value.Object()
+ _ = object
+
+ if v.TradeInToken != nil {
+ objectKey := object.Key("TradeInToken")
+ objectKey.String(*v.TradeInToken)
+ }
+
+ return nil
+}
+
func awsAwsquery_serializeOpDocumentGetFederationTokenInput(v *GetFederationTokenInput, value query.Value) error {
object := value.Object()
_ = object
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/errors.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/errors.go
index 041629bba2cb..c7fc70e4db66 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/errors.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/errors.go
@@ -34,6 +34,31 @@ func (e *ExpiredTokenException) ErrorCode() string {
}
func (e *ExpiredTokenException) ErrorFault() smithy.ErrorFault { return smithy.FaultClient }
+type ExpiredTradeInTokenException struct {
+ Message *string
+
+ ErrorCodeOverride *string
+
+ noSmithyDocumentSerde
+}
+
+func (e *ExpiredTradeInTokenException) Error() string {
+ return fmt.Sprintf("%s: %s", e.ErrorCode(), e.ErrorMessage())
+}
+func (e *ExpiredTradeInTokenException) ErrorMessage() string {
+ if e.Message == nil {
+ return ""
+ }
+ return *e.Message
+}
+func (e *ExpiredTradeInTokenException) ErrorCode() string {
+ if e == nil || e.ErrorCodeOverride == nil {
+ return "ExpiredTradeInTokenException"
+ }
+ return *e.ErrorCodeOverride
+}
+func (e *ExpiredTradeInTokenException) ErrorFault() smithy.ErrorFault { return smithy.FaultClient }
+
// The request could not be fulfilled because the identity provider (IDP) that was
// asked to verify the incoming identity token could not be reached. This is often
// a transient error caused by network conditions. Retry the request a limited
@@ -221,7 +246,7 @@ func (e *PackedPolicyTooLargeException) ErrorFault() smithy.ErrorFault { return
// console to activate STS in that region. For more information, see [Activating and Deactivating STS in an Amazon Web Services Region]in the IAM
// User Guide.
//
-// [Activating and Deactivating STS in an Amazon Web Services Region]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html
+// [Activating and Deactivating STS in an Amazon Web Services Region]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html#sts-regions-activate-deactivate
type RegionDisabledException struct {
Message *string
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/validators.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/validators.go
index 1026e22118d0..da0370ef9bc5 100644
--- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/validators.go
+++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/validators.go
@@ -130,6 +130,26 @@ func (m *validateOpGetAccessKeyInfo) HandleInitialize(ctx context.Context, in mi
return next.HandleInitialize(ctx, in)
}
+type validateOpGetDelegatedAccessToken struct {
+}
+
+func (*validateOpGetDelegatedAccessToken) ID() string {
+ return "OperationInputValidation"
+}
+
+func (m *validateOpGetDelegatedAccessToken) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) (
+ out middleware.InitializeOutput, metadata middleware.Metadata, err error,
+) {
+ input, ok := in.Parameters.(*GetDelegatedAccessTokenInput)
+ if !ok {
+ return out, metadata, fmt.Errorf("unknown input parameters type %T", in.Parameters)
+ }
+ if err := validateOpGetDelegatedAccessTokenInput(input); err != nil {
+ return out, metadata, err
+ }
+ return next.HandleInitialize(ctx, in)
+}
+
type validateOpGetFederationToken struct {
}
@@ -174,6 +194,10 @@ func addOpGetAccessKeyInfoValidationMiddleware(stack *middleware.Stack) error {
return stack.Initialize.Add(&validateOpGetAccessKeyInfo{}, middleware.After)
}
+func addOpGetDelegatedAccessTokenValidationMiddleware(stack *middleware.Stack) error {
+ return stack.Initialize.Add(&validateOpGetDelegatedAccessToken{}, middleware.After)
+}
+
func addOpGetFederationTokenValidationMiddleware(stack *middleware.Stack) error {
return stack.Initialize.Add(&validateOpGetFederationToken{}, middleware.After)
}
@@ -326,6 +350,21 @@ func validateOpGetAccessKeyInfoInput(v *GetAccessKeyInfoInput) error {
}
}
+func validateOpGetDelegatedAccessTokenInput(v *GetDelegatedAccessTokenInput) error {
+ if v == nil {
+ return nil
+ }
+ invalidParams := smithy.InvalidParamsError{Context: "GetDelegatedAccessTokenInput"}
+ if v.TradeInToken == nil {
+ invalidParams.Add(smithy.NewErrParamRequired("TradeInToken"))
+ }
+ if invalidParams.Len() > 0 {
+ return invalidParams
+ } else {
+ return nil
+ }
+}
+
func validateOpGetFederationTokenInput(v *GetFederationTokenInput) error {
if v == nil {
return nil
diff --git a/vendor/github.com/aws/smithy-go/CHANGELOG.md b/vendor/github.com/aws/smithy-go/CHANGELOG.md
index 1d60def6d1b3..8193f4b3964a 100644
--- a/vendor/github.com/aws/smithy-go/CHANGELOG.md
+++ b/vendor/github.com/aws/smithy-go/CHANGELOG.md
@@ -1,3 +1,34 @@
+# Release (2025-11-03)
+
+## General Highlights
+* **Dependency Update**: Updated to the latest SDK module versions
+
+## Module Highlights
+* `github.com/aws/smithy-go`: v1.23.2
+ * **Bug Fix**: Adjust the initial sizes of each middleware phase to avoid some unnecessary reallocation.
+ * **Bug Fix**: Avoid unnecessary allocation overhead from the metrics system when not in use.
+
+# Release (2025-10-15)
+
+## General Highlights
+* **Dependency Update**: Bump minimum go version to 1.23.
+* **Dependency Update**: Updated to the latest SDK module versions
+
+# Release (2025-09-18)
+
+## Module Highlights
+* `github.com/aws/smithy-go/aws-http-auth`: [v1.1.0](aws-http-auth/CHANGELOG.md#v110-2025-09-18)
+ * **Feature**: Added support for SIG4/SIGV4A querystring authentication.
+
+# Release (2025-08-27)
+
+## General Highlights
+* **Dependency Update**: Updated to the latest SDK module versions
+
+## Module Highlights
+* `github.com/aws/smithy-go`: v1.23.0
+ * **Feature**: Sort map keys in JSON Document types.
+
# Release (2025-07-24)
## General Highlights
@@ -5,8 +36,7 @@
## Module Highlights
* `github.com/aws/smithy-go`: v1.22.5
- * **Bug Fix**: Fix HTTP metrics data race.
- * **Bug Fix**: Replace usages of deprecated ioutil package.
+ * **Feature**: Add HTTP interceptors.
# Release (2025-06-16)
diff --git a/vendor/github.com/aws/smithy-go/Makefile b/vendor/github.com/aws/smithy-go/Makefile
index 34b17ab2fe09..a12b124d5050 100644
--- a/vendor/github.com/aws/smithy-go/Makefile
+++ b/vendor/github.com/aws/smithy-go/Makefile
@@ -13,6 +13,7 @@ REPOTOOLS_CMD_GENERATE_CHANGELOG = ${REPOTOOLS_MODULE}/cmd/generatechangelog@${R
REPOTOOLS_CMD_CHANGELOG = ${REPOTOOLS_MODULE}/cmd/changelog@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_TAG_RELEASE = ${REPOTOOLS_MODULE}/cmd/tagrelease@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_MODULE_VERSION = ${REPOTOOLS_MODULE}/cmd/moduleversion@${REPOTOOLS_VERSION}
+REPOTOOLS_CMD_EACHMODULE = ${REPOTOOLS_MODULE}/cmd/eachmodule@${REPOTOOLS_VERSION}
UNIT_TEST_TAGS=
BUILD_TAGS=
@@ -55,8 +56,11 @@ ensure-gradle-up:
verify: vet
-vet:
- go vet ${BUILD_TAGS} --all ./...
+vet: vet-modules-.
+
+vet-modules-%:
+ go run ${REPOTOOLS_CMD_EACHMODULE} -p $(subst vet-modules-,,$@) \
+ "go vet ${BUILD_TAGS} --all ./..."
cover:
go test ${BUILD_TAGS} -coverprofile c.out ./...
@@ -66,21 +70,22 @@ cover:
################
# Unit Testing #
################
-.PHONY: unit unit-race unit-test unit-race-test
+.PHONY: test unit unit-race
+
+test: unit-race
+
+unit: verify unit-modules-.
-unit: verify
- go test ${BUILD_TAGS} ${RUN_NONE} ./... && \
- go test -timeout=1m ${UNIT_TEST_TAGS} ./...
+unit-modules-%:
+ go run ${REPOTOOLS_CMD_EACHMODULE} -p $(subst unit-modules-,,$@) \
+ "go test -timeout=1m ${UNIT_TEST_TAGS} ./..."
-unit-race: verify
- go test ${BUILD_TAGS} ${RUN_NONE} ./... && \
- go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./...
+unit-race: verify unit-race-modules-.
-unit-test: verify
- go test -timeout=1m ${UNIT_TEST_TAGS} ./...
+unit-race-modules-%:
+ go run ${REPOTOOLS_CMD_EACHMODULE} -p $(subst unit-race-modules-,,$@) \
+ "go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./..."
-unit-race-test: verify
- go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./...
#####################
# Release Process #
diff --git a/vendor/github.com/aws/smithy-go/README.md b/vendor/github.com/aws/smithy-go/README.md
index c9ba5ea5e4b0..ddce37b99ef0 100644
--- a/vendor/github.com/aws/smithy-go/README.md
+++ b/vendor/github.com/aws/smithy-go/README.md
@@ -4,19 +4,21 @@
[Smithy](https://smithy.io/) code generators for Go and the accompanying smithy-go runtime.
-The smithy-go runtime requires a minimum version of Go 1.22.
+The smithy-go runtime requires a minimum version of Go 1.23.
**WARNING: All interfaces are subject to change.**
-## Can I use the code generators?
+## :no_entry_sign: DO NOT use the code generators in this repository
+
+**The code generators in this repository do not generate working clients at
+this time.**
In order to generate a usable smithy client you must provide a [protocol definition](https://github.com/aws/smithy-go/blob/main/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/integration/ProtocolGenerator.java),
such as [AWS restJson1](https://smithy.io/2.0/aws/protocols/aws-restjson1-protocol.html),
in order to generate transport mechanisms and serialization/deserialization
code ("serde") accordingly.
-The code generator does not currently support any protocols out of the box other than the new `smithy.protocols#rpcv2Cbor`,
-therefore the useability of this project on its own is currently limited.
+The code generator does not currently support any protocols out of the box.
Support for all [AWS protocols](https://smithy.io/2.0/aws/protocols/index.html)
exists in [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2). We are
tracking the movement of those out of the SDK into smithy-go in
@@ -31,6 +33,7 @@ This repository implements the following Smithy build plugins:
|----|------------|-------------|
| `go-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go client code generation for Smithy models. |
| `go-server-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go server code generation for Smithy models. |
+| `go-shape-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go shape code generation (types only) for Smithy models. |
**NOTE: Build plugins are not currently published to mavenCentral. You must publish to mavenLocal to make the build plugins visible to the Smithy CLI. The artifact version is currently fixed at 0.1.0.**
@@ -77,7 +80,7 @@ example created from `smithy init`:
"service": "example.weather#Weather",
"module": "github.com/example/weather",
"generateGoMod": true,
- "goDirective": "1.22"
+ "goDirective": "1.23"
}
}
}
@@ -87,6 +90,10 @@ example created from `smithy init`:
This plugin is a work-in-progress and is currently undocumented.
+## `go-shape-codegen`
+
+This plugin is a work-in-progress and is currently undocumented.
+
## License
This project is licensed under the Apache-2.0 License.
diff --git a/vendor/github.com/aws/smithy-go/go_module_metadata.go b/vendor/github.com/aws/smithy-go/go_module_metadata.go
index cbbaabee9ef8..263059014b85 100644
--- a/vendor/github.com/aws/smithy-go/go_module_metadata.go
+++ b/vendor/github.com/aws/smithy-go/go_module_metadata.go
@@ -3,4 +3,4 @@
package smithy
// goModuleVersion is the tagged release for this module
-const goModuleVersion = "1.22.5"
+const goModuleVersion = "1.23.2"
diff --git a/vendor/github.com/aws/smithy-go/metrics/nop.go b/vendor/github.com/aws/smithy-go/metrics/nop.go
index fb374e1fb850..444126df5a06 100644
--- a/vendor/github.com/aws/smithy-go/metrics/nop.go
+++ b/vendor/github.com/aws/smithy-go/metrics/nop.go
@@ -9,54 +9,82 @@ var _ MeterProvider = (*NopMeterProvider)(nil)
// Meter returns a meter which creates no-op instruments.
func (NopMeterProvider) Meter(string, ...MeterOption) Meter {
- return nopMeter{}
+ return NopMeter{}
}
-type nopMeter struct{}
+// NopMeter creates no-op instruments.
+type NopMeter struct{}
-var _ Meter = (*nopMeter)(nil)
+var _ Meter = (*NopMeter)(nil)
-func (nopMeter) Int64Counter(string, ...InstrumentOption) (Int64Counter, error) {
- return nopInstrument[int64]{}, nil
+// Int64Counter creates a no-op instrument.
+func (NopMeter) Int64Counter(string, ...InstrumentOption) (Int64Counter, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Int64UpDownCounter(string, ...InstrumentOption) (Int64UpDownCounter, error) {
- return nopInstrument[int64]{}, nil
+
+// Int64UpDownCounter creates a no-op instrument.
+func (NopMeter) Int64UpDownCounter(string, ...InstrumentOption) (Int64UpDownCounter, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Int64Gauge(string, ...InstrumentOption) (Int64Gauge, error) {
- return nopInstrument[int64]{}, nil
+
+// Int64Gauge creates a no-op instrument.
+func (NopMeter) Int64Gauge(string, ...InstrumentOption) (Int64Gauge, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Int64Histogram(string, ...InstrumentOption) (Int64Histogram, error) {
- return nopInstrument[int64]{}, nil
+
+// Int64Histogram creates a no-op instrument.
+func (NopMeter) Int64Histogram(string, ...InstrumentOption) (Int64Histogram, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Int64AsyncCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
- return nopInstrument[int64]{}, nil
+
+// Int64AsyncCounter creates a no-op instrument.
+func (NopMeter) Int64AsyncCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Int64AsyncUpDownCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
- return nopInstrument[int64]{}, nil
+
+// Int64AsyncUpDownCounter creates a no-op instrument.
+func (NopMeter) Int64AsyncUpDownCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Int64AsyncGauge(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
- return nopInstrument[int64]{}, nil
+
+// Int64AsyncGauge creates a no-op instrument.
+func (NopMeter) Int64AsyncGauge(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
+ return nopInstrumentInt64, nil
}
-func (nopMeter) Float64Counter(string, ...InstrumentOption) (Float64Counter, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64Counter creates a no-op instrument.
+func (NopMeter) Float64Counter(string, ...InstrumentOption) (Float64Counter, error) {
+ return nopInstrumentFloat64, nil
}
-func (nopMeter) Float64UpDownCounter(string, ...InstrumentOption) (Float64UpDownCounter, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64UpDownCounter creates a no-op instrument.
+func (NopMeter) Float64UpDownCounter(string, ...InstrumentOption) (Float64UpDownCounter, error) {
+ return nopInstrumentFloat64, nil
}
-func (nopMeter) Float64Gauge(string, ...InstrumentOption) (Float64Gauge, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64Gauge creates a no-op instrument.
+func (NopMeter) Float64Gauge(string, ...InstrumentOption) (Float64Gauge, error) {
+ return nopInstrumentFloat64, nil
}
-func (nopMeter) Float64Histogram(string, ...InstrumentOption) (Float64Histogram, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64Histogram creates a no-op instrument.
+func (NopMeter) Float64Histogram(string, ...InstrumentOption) (Float64Histogram, error) {
+ return nopInstrumentFloat64, nil
}
-func (nopMeter) Float64AsyncCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64AsyncCounter creates a no-op instrument.
+func (NopMeter) Float64AsyncCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
+ return nopInstrumentFloat64, nil
}
-func (nopMeter) Float64AsyncUpDownCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64AsyncUpDownCounter creates a no-op instrument.
+func (NopMeter) Float64AsyncUpDownCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
+ return nopInstrumentFloat64, nil
}
-func (nopMeter) Float64AsyncGauge(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
- return nopInstrument[float64]{}, nil
+
+// Float64AsyncGauge creates a no-op instrument.
+func (NopMeter) Float64AsyncGauge(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
+ return nopInstrumentFloat64, nil
}
type nopInstrument[N any] struct{}
@@ -65,3 +93,6 @@ func (nopInstrument[N]) Add(context.Context, N, ...RecordMetricOption) {}
func (nopInstrument[N]) Sample(context.Context, N, ...RecordMetricOption) {}
func (nopInstrument[N]) Record(context.Context, N, ...RecordMetricOption) {}
func (nopInstrument[_]) Stop() {}
+
+var nopInstrumentInt64 = nopInstrument[int64]{}
+var nopInstrumentFloat64 = nopInstrument[float64]{}
diff --git a/vendor/github.com/aws/smithy-go/middleware/ordered_group.go b/vendor/github.com/aws/smithy-go/middleware/ordered_group.go
index 4b195308c599..daf90136e96c 100644
--- a/vendor/github.com/aws/smithy-go/middleware/ordered_group.go
+++ b/vendor/github.com/aws/smithy-go/middleware/ordered_group.go
@@ -23,12 +23,14 @@ type orderedIDs struct {
items map[string]ider
}
-const baseOrderedItems = 5
+// selected based on the general upper bound of # of middlewares in each step
+// in the downstream aws-sdk-go-v2
+const baseOrderedItems = 8
-func newOrderedIDs() *orderedIDs {
+func newOrderedIDs(cap int) *orderedIDs {
return &orderedIDs{
- order: newRelativeOrder(),
- items: make(map[string]ider, baseOrderedItems),
+ order: newRelativeOrder(cap),
+ items: make(map[string]ider, cap),
}
}
@@ -141,9 +143,9 @@ type relativeOrder struct {
order []string
}
-func newRelativeOrder() *relativeOrder {
+func newRelativeOrder(cap int) *relativeOrder {
return &relativeOrder{
- order: make([]string, 0, baseOrderedItems),
+ order: make([]string, 0, cap),
}
}
diff --git a/vendor/github.com/aws/smithy-go/middleware/step_build.go b/vendor/github.com/aws/smithy-go/middleware/step_build.go
index 7e1d94caeef9..cc7fe89c94a6 100644
--- a/vendor/github.com/aws/smithy-go/middleware/step_build.go
+++ b/vendor/github.com/aws/smithy-go/middleware/step_build.go
@@ -79,7 +79,7 @@ type BuildStep struct {
// initialization added to it.
func NewBuildStep() *BuildStep {
return &BuildStep{
- ids: newOrderedIDs(),
+ ids: newOrderedIDs(baseOrderedItems),
}
}
diff --git a/vendor/github.com/aws/smithy-go/middleware/step_deserialize.go b/vendor/github.com/aws/smithy-go/middleware/step_deserialize.go
index 44860721571c..9a6679a59b3e 100644
--- a/vendor/github.com/aws/smithy-go/middleware/step_deserialize.go
+++ b/vendor/github.com/aws/smithy-go/middleware/step_deserialize.go
@@ -85,7 +85,8 @@ type DeserializeStep struct {
// initialization added to it.
func NewDeserializeStep() *DeserializeStep {
return &DeserializeStep{
- ids: newOrderedIDs(),
+ // downstream SDK typically has larger Deserialize step
+ ids: newOrderedIDs(baseOrderedItems * 2),
}
}
diff --git a/vendor/github.com/aws/smithy-go/middleware/step_finalize.go b/vendor/github.com/aws/smithy-go/middleware/step_finalize.go
index 065e3885de92..76eab2490934 100644
--- a/vendor/github.com/aws/smithy-go/middleware/step_finalize.go
+++ b/vendor/github.com/aws/smithy-go/middleware/step_finalize.go
@@ -79,7 +79,8 @@ type FinalizeStep struct {
// initialization added to it.
func NewFinalizeStep() *FinalizeStep {
return &FinalizeStep{
- ids: newOrderedIDs(),
+ // downstream SDK typically has larger Finalize step
+ ids: newOrderedIDs(baseOrderedItems * 2),
}
}
diff --git a/vendor/github.com/aws/smithy-go/middleware/step_initialize.go b/vendor/github.com/aws/smithy-go/middleware/step_initialize.go
index fe359144d243..312be3a331ea 100644
--- a/vendor/github.com/aws/smithy-go/middleware/step_initialize.go
+++ b/vendor/github.com/aws/smithy-go/middleware/step_initialize.go
@@ -79,7 +79,7 @@ type InitializeStep struct {
// initialization added to it.
func NewInitializeStep() *InitializeStep {
return &InitializeStep{
- ids: newOrderedIDs(),
+ ids: newOrderedIDs(baseOrderedItems),
}
}
diff --git a/vendor/github.com/aws/smithy-go/middleware/step_serialize.go b/vendor/github.com/aws/smithy-go/middleware/step_serialize.go
index 114bafcedea8..a4ce4bee3b7a 100644
--- a/vendor/github.com/aws/smithy-go/middleware/step_serialize.go
+++ b/vendor/github.com/aws/smithy-go/middleware/step_serialize.go
@@ -85,7 +85,7 @@ type SerializeStep struct {
// serialize the input parameters into.
func NewSerializeStep(newRequest func() interface{}) *SerializeStep {
return &SerializeStep{
- ids: newOrderedIDs(),
+ ids: newOrderedIDs(baseOrderedItems),
newRequest: newRequest,
}
}
diff --git a/vendor/github.com/aws/smithy-go/transport/http/metrics.go b/vendor/github.com/aws/smithy-go/transport/http/metrics.go
index d1beaa595d97..b4cd4a47e363 100644
--- a/vendor/github.com/aws/smithy-go/transport/http/metrics.go
+++ b/vendor/github.com/aws/smithy-go/transport/http/metrics.go
@@ -17,6 +17,12 @@ var now = time.Now
func withMetrics(parent context.Context, client ClientDo, meter metrics.Meter) (
context.Context, ClientDo, error,
) {
+ // WithClientTrace is an expensive operation - avoid calling it if we're
+ // not actually using a metrics sink.
+ if _, ok := meter.(metrics.NopMeter); ok {
+ return parent, client, nil
+ }
+
hm, err := newHTTPMetrics(meter)
if err != nil {
return nil, nil, err
diff --git a/vendor/github.com/blang/semver/.travis.yml b/vendor/github.com/blang/semver/.travis.yml
new file mode 100644
index 000000000000..102fb9a691b6
--- /dev/null
+++ b/vendor/github.com/blang/semver/.travis.yml
@@ -0,0 +1,21 @@
+language: go
+matrix:
+ include:
+ - go: 1.4.3
+ - go: 1.5.4
+ - go: 1.6.3
+ - go: 1.7
+ - go: tip
+ allow_failures:
+ - go: tip
+install:
+- go get golang.org/x/tools/cmd/cover
+- go get github.com/mattn/goveralls
+script:
+- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
+ -repotoken $COVERALLS_TOKEN
+- echo "Build examples" ; cd examples && go build
+- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
+env:
+ global:
+ secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/LICENSE
new file mode 100644
index 000000000000..5ba5c86fcb02
--- /dev/null
+++ b/vendor/github.com/blang/semver/LICENSE
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2014 Benedikt Lang
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md
new file mode 100644
index 000000000000..08b2e4a3d76e
--- /dev/null
+++ b/vendor/github.com/blang/semver/README.md
@@ -0,0 +1,194 @@
+semver for golang [](https://travis-ci.org/blang/semver) [](https://godoc.org/github.com/blang/semver) [](https://coveralls.io/r/blang/semver?branch=master)
+======
+
+semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
+
+Usage
+-----
+```bash
+$ go get github.com/blang/semver
+```
+Note: Always vendor your dependencies or fix on a specific version tag.
+
+```go
+import github.com/blang/semver
+v1, err := semver.Make("1.0.0-beta")
+v2, err := semver.Make("2.0.0-beta")
+v1.Compare(v2)
+```
+
+Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
+
+Why should I use this lib?
+-----
+
+- Fully spec compatible
+- No reflection
+- No regex
+- Fully tested (Coverage >99%)
+- Readable parsing/validation errors
+- Fast (See [Benchmarks](#benchmarks))
+- Only Stdlib
+- Uses values instead of pointers
+- Many features, see below
+
+
+Features
+-----
+
+- Parsing and validation at all levels
+- Comparator-like comparisons
+- Compare Helper Methods
+- InPlace manipulation
+- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
+- Wildcards `>=1.x`, `<=2.5.x`
+- Sortable (implements sort.Interface)
+- database/sql compatible (sql.Scanner/Valuer)
+- encoding/json compatible (json.Marshaler/Unmarshaler)
+
+Ranges
+------
+
+A `Range` is a set of conditions which specify which versions satisfy the range.
+
+A condition is composed of an operator and a version. The supported operators are:
+
+- `<1.0.0` Less than `1.0.0`
+- `<=1.0.0` Less than or equal to `1.0.0`
+- `>1.0.0` Greater than `1.0.0`
+- `>=1.0.0` Greater than or equal to `1.0.0`
+- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
+- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
+
+Note that spaces between the operator and the version will be gracefully tolerated.
+
+A `Range` can link multiple `Ranges` separated by space:
+
+Ranges can be linked by logical AND:
+
+ - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
+ - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
+
+Ranges can also be linked by logical OR:
+
+ - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
+
+AND has a higher precedence than OR. It's not possible to use brackets.
+
+Ranges can be combined by both AND and OR
+
+ - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
+
+Range usage:
+
+```
+v, err := semver.Parse("1.2.3")
+range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
+if range(v) {
+ //valid
+}
+
+```
+
+Example
+-----
+
+Have a look at full examples in [examples/main.go](examples/main.go)
+
+```go
+import github.com/blang/semver
+
+v, err := semver.Make("0.0.1-alpha.preview+123.github")
+fmt.Printf("Major: %d\n", v.Major)
+fmt.Printf("Minor: %d\n", v.Minor)
+fmt.Printf("Patch: %d\n", v.Patch)
+fmt.Printf("Pre: %s\n", v.Pre)
+fmt.Printf("Build: %s\n", v.Build)
+
+// Prerelease versions array
+if len(v.Pre) > 0 {
+ fmt.Println("Prerelease versions:")
+ for i, pre := range v.Pre {
+ fmt.Printf("%d: %q\n", i, pre)
+ }
+}
+
+// Build meta data array
+if len(v.Build) > 0 {
+ fmt.Println("Build meta data:")
+ for i, build := range v.Build {
+ fmt.Printf("%d: %q\n", i, build)
+ }
+}
+
+v001, err := semver.Make("0.0.1")
+// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
+v001.GT(v) == true
+v.LT(v001) == true
+v.GTE(v) == true
+v.LTE(v) == true
+
+// Or use v.Compare(v2) for comparisons (-1, 0, 1):
+v001.Compare(v) == 1
+v.Compare(v001) == -1
+v.Compare(v) == 0
+
+// Manipulate Version in place:
+v.Pre[0], err = semver.NewPRVersion("beta")
+if err != nil {
+ fmt.Printf("Error parsing pre release version: %q", err)
+}
+
+fmt.Println("\nValidate versions:")
+v.Build[0] = "?"
+
+err = v.Validate()
+if err != nil {
+ fmt.Printf("Validation failed: %s\n", err)
+}
+```
+
+
+Benchmarks
+-----
+
+ BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
+ BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
+ BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
+ BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
+ BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
+ BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
+ BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
+ BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
+ BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
+ BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
+ BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
+ BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
+ BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
+ BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
+ BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
+ BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
+ BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
+ BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
+ BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
+ BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
+
+See benchmark cases at [semver_test.go](semver_test.go)
+
+
+Motivation
+-----
+
+I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
+
+
+Contribution
+-----
+
+Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
+
+
+License
+-----
+
+See [LICENSE](LICENSE) file.
diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/json.go
new file mode 100644
index 000000000000..a74bf7c44940
--- /dev/null
+++ b/vendor/github.com/blang/semver/json.go
@@ -0,0 +1,23 @@
+package semver
+
+import (
+ "encoding/json"
+)
+
+// MarshalJSON implements the encoding/json.Marshaler interface.
+func (v Version) MarshalJSON() ([]byte, error) {
+ return json.Marshal(v.String())
+}
+
+// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
+func (v *Version) UnmarshalJSON(data []byte) (err error) {
+ var versionString string
+
+ if err = json.Unmarshal(data, &versionString); err != nil {
+ return
+ }
+
+ *v, err = Parse(versionString)
+
+ return
+}
diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json
new file mode 100644
index 000000000000..1cf8ebdd9c18
--- /dev/null
+++ b/vendor/github.com/blang/semver/package.json
@@ -0,0 +1,17 @@
+{
+ "author": "blang",
+ "bugs": {
+ "URL": "https://github.com/blang/semver/issues",
+ "url": "https://github.com/blang/semver/issues"
+ },
+ "gx": {
+ "dvcsimport": "github.com/blang/semver"
+ },
+ "gxVersion": "0.10.0",
+ "language": "go",
+ "license": "MIT",
+ "name": "semver",
+ "releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
+ "version": "3.5.1"
+}
+
diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go
new file mode 100644
index 000000000000..fca406d47939
--- /dev/null
+++ b/vendor/github.com/blang/semver/range.go
@@ -0,0 +1,416 @@
+package semver
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+type wildcardType int
+
+const (
+ noneWildcard wildcardType = iota
+ majorWildcard wildcardType = 1
+ minorWildcard wildcardType = 2
+ patchWildcard wildcardType = 3
+)
+
+func wildcardTypefromInt(i int) wildcardType {
+ switch i {
+ case 1:
+ return majorWildcard
+ case 2:
+ return minorWildcard
+ case 3:
+ return patchWildcard
+ default:
+ return noneWildcard
+ }
+}
+
+type comparator func(Version, Version) bool
+
+var (
+ compEQ comparator = func(v1 Version, v2 Version) bool {
+ return v1.Compare(v2) == 0
+ }
+ compNE = func(v1 Version, v2 Version) bool {
+ return v1.Compare(v2) != 0
+ }
+ compGT = func(v1 Version, v2 Version) bool {
+ return v1.Compare(v2) == 1
+ }
+ compGE = func(v1 Version, v2 Version) bool {
+ return v1.Compare(v2) >= 0
+ }
+ compLT = func(v1 Version, v2 Version) bool {
+ return v1.Compare(v2) == -1
+ }
+ compLE = func(v1 Version, v2 Version) bool {
+ return v1.Compare(v2) <= 0
+ }
+)
+
+type versionRange struct {
+ v Version
+ c comparator
+}
+
+// rangeFunc creates a Range from the given versionRange.
+func (vr *versionRange) rangeFunc() Range {
+ return Range(func(v Version) bool {
+ return vr.c(v, vr.v)
+ })
+}
+
+// Range represents a range of versions.
+// A Range can be used to check if a Version satisfies it:
+//
+// range, err := semver.ParseRange(">1.0.0 <2.0.0")
+// range(semver.MustParse("1.1.1") // returns true
+type Range func(Version) bool
+
+// OR combines the existing Range with another Range using logical OR.
+func (rf Range) OR(f Range) Range {
+ return Range(func(v Version) bool {
+ return rf(v) || f(v)
+ })
+}
+
+// AND combines the existing Range with another Range using logical AND.
+func (rf Range) AND(f Range) Range {
+ return Range(func(v Version) bool {
+ return rf(v) && f(v)
+ })
+}
+
+// ParseRange parses a range and returns a Range.
+// If the range could not be parsed an error is returned.
+//
+// Valid ranges are:
+// - "<1.0.0"
+// - "<=1.0.0"
+// - ">1.0.0"
+// - ">=1.0.0"
+// - "1.0.0", "=1.0.0", "==1.0.0"
+// - "!1.0.0", "!=1.0.0"
+//
+// A Range can consist of multiple ranges separated by space:
+// Ranges can be linked by logical AND:
+// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
+// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
+//
+// Ranges can also be linked by logical OR:
+// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
+//
+// AND has a higher precedence than OR. It's not possible to use brackets.
+//
+// Ranges can be combined by both AND and OR
+//
+// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
+func ParseRange(s string) (Range, error) {
+ parts := splitAndTrim(s)
+ orParts, err := splitORParts(parts)
+ if err != nil {
+ return nil, err
+ }
+ expandedParts, err := expandWildcardVersion(orParts)
+ if err != nil {
+ return nil, err
+ }
+ var orFn Range
+ for _, p := range expandedParts {
+ var andFn Range
+ for _, ap := range p {
+ opStr, vStr, err := splitComparatorVersion(ap)
+ if err != nil {
+ return nil, err
+ }
+ vr, err := buildVersionRange(opStr, vStr)
+ if err != nil {
+ return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
+ }
+ rf := vr.rangeFunc()
+
+ // Set function
+ if andFn == nil {
+ andFn = rf
+ } else { // Combine with existing function
+ andFn = andFn.AND(rf)
+ }
+ }
+ if orFn == nil {
+ orFn = andFn
+ } else {
+ orFn = orFn.OR(andFn)
+ }
+
+ }
+ return orFn, nil
+}
+
+// splitORParts splits the already cleaned parts by '||'.
+// Checks for invalid positions of the operator and returns an
+// error if found.
+func splitORParts(parts []string) ([][]string, error) {
+ var ORparts [][]string
+ last := 0
+ for i, p := range parts {
+ if p == "||" {
+ if i == 0 {
+ return nil, fmt.Errorf("First element in range is '||'")
+ }
+ ORparts = append(ORparts, parts[last:i])
+ last = i + 1
+ }
+ }
+ if last == len(parts) {
+ return nil, fmt.Errorf("Last element in range is '||'")
+ }
+ ORparts = append(ORparts, parts[last:])
+ return ORparts, nil
+}
+
+// buildVersionRange takes a slice of 2: operator and version
+// and builds a versionRange, otherwise an error.
+func buildVersionRange(opStr, vStr string) (*versionRange, error) {
+ c := parseComparator(opStr)
+ if c == nil {
+ return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
+ }
+ v, err := Parse(vStr)
+ if err != nil {
+ return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
+ }
+
+ return &versionRange{
+ v: v,
+ c: c,
+ }, nil
+
+}
+
+// inArray checks if a byte is contained in an array of bytes
+func inArray(s byte, list []byte) bool {
+ for _, el := range list {
+ if el == s {
+ return true
+ }
+ }
+ return false
+}
+
+// splitAndTrim splits a range string by spaces and cleans whitespaces
+func splitAndTrim(s string) (result []string) {
+ last := 0
+ var lastChar byte
+ excludeFromSplit := []byte{'>', '<', '='}
+ for i := 0; i < len(s); i++ {
+ if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
+ if last < i-1 {
+ result = append(result, s[last:i])
+ }
+ last = i + 1
+ } else if s[i] != ' ' {
+ lastChar = s[i]
+ }
+ }
+ if last < len(s)-1 {
+ result = append(result, s[last:])
+ }
+
+ for i, v := range result {
+ result[i] = strings.Replace(v, " ", "", -1)
+ }
+
+ // parts := strings.Split(s, " ")
+ // for _, x := range parts {
+ // if s := strings.TrimSpace(x); len(s) != 0 {
+ // result = append(result, s)
+ // }
+ // }
+ return
+}
+
+// splitComparatorVersion splits the comparator from the version.
+// Input must be free of leading or trailing spaces.
+func splitComparatorVersion(s string) (string, string, error) {
+ i := strings.IndexFunc(s, unicode.IsDigit)
+ if i == -1 {
+ return "", "", fmt.Errorf("Could not get version from string: %q", s)
+ }
+ return strings.TrimSpace(s[0:i]), s[i:], nil
+}
+
+// getWildcardType will return the type of wildcard that the
+// passed version contains
+func getWildcardType(vStr string) wildcardType {
+ parts := strings.Split(vStr, ".")
+ nparts := len(parts)
+ wildcard := parts[nparts-1]
+
+ possibleWildcardType := wildcardTypefromInt(nparts)
+ if wildcard == "x" {
+ return possibleWildcardType
+ }
+
+ return noneWildcard
+}
+
+// createVersionFromWildcard will convert a wildcard version
+// into a regular version, replacing 'x's with '0's, handling
+// special cases like '1.x.x' and '1.x'
+func createVersionFromWildcard(vStr string) string {
+ // handle 1.x.x
+ vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
+ vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
+ parts := strings.Split(vStr2, ".")
+
+ // handle 1.x
+ if len(parts) == 2 {
+ return vStr2 + ".0"
+ }
+
+ return vStr2
+}
+
+// incrementMajorVersion will increment the major version
+// of the passed version
+func incrementMajorVersion(vStr string) (string, error) {
+ parts := strings.Split(vStr, ".")
+ i, err := strconv.Atoi(parts[0])
+ if err != nil {
+ return "", err
+ }
+ parts[0] = strconv.Itoa(i + 1)
+
+ return strings.Join(parts, "."), nil
+}
+
+// incrementMajorVersion will increment the minor version
+// of the passed version
+func incrementMinorVersion(vStr string) (string, error) {
+ parts := strings.Split(vStr, ".")
+ i, err := strconv.Atoi(parts[1])
+ if err != nil {
+ return "", err
+ }
+ parts[1] = strconv.Itoa(i + 1)
+
+ return strings.Join(parts, "."), nil
+}
+
+// expandWildcardVersion will expand wildcards inside versions
+// following these rules:
+//
+// * when dealing with patch wildcards:
+// >= 1.2.x will become >= 1.2.0
+// <= 1.2.x will become < 1.3.0
+// > 1.2.x will become >= 1.3.0
+// < 1.2.x will become < 1.2.0
+// != 1.2.x will become < 1.2.0 >= 1.3.0
+//
+// * when dealing with minor wildcards:
+// >= 1.x will become >= 1.0.0
+// <= 1.x will become < 2.0.0
+// > 1.x will become >= 2.0.0
+// < 1.0 will become < 1.0.0
+// != 1.x will become < 1.0.0 >= 2.0.0
+//
+// * when dealing with wildcards without
+// version operator:
+// 1.2.x will become >= 1.2.0 < 1.3.0
+// 1.x will become >= 1.0.0 < 2.0.0
+func expandWildcardVersion(parts [][]string) ([][]string, error) {
+ var expandedParts [][]string
+ for _, p := range parts {
+ var newParts []string
+ for _, ap := range p {
+ if strings.Index(ap, "x") != -1 {
+ opStr, vStr, err := splitComparatorVersion(ap)
+ if err != nil {
+ return nil, err
+ }
+
+ versionWildcardType := getWildcardType(vStr)
+ flatVersion := createVersionFromWildcard(vStr)
+
+ var resultOperator string
+ var shouldIncrementVersion bool
+ switch opStr {
+ case ">":
+ resultOperator = ">="
+ shouldIncrementVersion = true
+ case ">=":
+ resultOperator = ">="
+ case "<":
+ resultOperator = "<"
+ case "<=":
+ resultOperator = "<"
+ shouldIncrementVersion = true
+ case "", "=", "==":
+ newParts = append(newParts, ">="+flatVersion)
+ resultOperator = "<"
+ shouldIncrementVersion = true
+ case "!=", "!":
+ newParts = append(newParts, "<"+flatVersion)
+ resultOperator = ">="
+ shouldIncrementVersion = true
+ }
+
+ var resultVersion string
+ if shouldIncrementVersion {
+ switch versionWildcardType {
+ case patchWildcard:
+ resultVersion, _ = incrementMinorVersion(flatVersion)
+ case minorWildcard:
+ resultVersion, _ = incrementMajorVersion(flatVersion)
+ }
+ } else {
+ resultVersion = flatVersion
+ }
+
+ ap = resultOperator + resultVersion
+ }
+ newParts = append(newParts, ap)
+ }
+ expandedParts = append(expandedParts, newParts)
+ }
+
+ return expandedParts, nil
+}
+
+func parseComparator(s string) comparator {
+ switch s {
+ case "==":
+ fallthrough
+ case "":
+ fallthrough
+ case "=":
+ return compEQ
+ case ">":
+ return compGT
+ case ">=":
+ return compGE
+ case "<":
+ return compLT
+ case "<=":
+ return compLE
+ case "!":
+ fallthrough
+ case "!=":
+ return compNE
+ }
+
+ return nil
+}
+
+// MustParseRange is like ParseRange but panics if the range cannot be parsed.
+func MustParseRange(s string) Range {
+ r, err := ParseRange(s)
+ if err != nil {
+ panic(`semver: ParseRange(` + s + `): ` + err.Error())
+ }
+ return r
+}
diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go
new file mode 100644
index 000000000000..8ee0842e6ac7
--- /dev/null
+++ b/vendor/github.com/blang/semver/semver.go
@@ -0,0 +1,418 @@
+package semver
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+const (
+ numbers string = "0123456789"
+ alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
+ alphanum = alphas + numbers
+)
+
+// SpecVersion is the latest fully supported spec version of semver
+var SpecVersion = Version{
+ Major: 2,
+ Minor: 0,
+ Patch: 0,
+}
+
+// Version represents a semver compatible version
+type Version struct {
+ Major uint64
+ Minor uint64
+ Patch uint64
+ Pre []PRVersion
+ Build []string //No Precendence
+}
+
+// Version to string
+func (v Version) String() string {
+ b := make([]byte, 0, 5)
+ b = strconv.AppendUint(b, v.Major, 10)
+ b = append(b, '.')
+ b = strconv.AppendUint(b, v.Minor, 10)
+ b = append(b, '.')
+ b = strconv.AppendUint(b, v.Patch, 10)
+
+ if len(v.Pre) > 0 {
+ b = append(b, '-')
+ b = append(b, v.Pre[0].String()...)
+
+ for _, pre := range v.Pre[1:] {
+ b = append(b, '.')
+ b = append(b, pre.String()...)
+ }
+ }
+
+ if len(v.Build) > 0 {
+ b = append(b, '+')
+ b = append(b, v.Build[0]...)
+
+ for _, build := range v.Build[1:] {
+ b = append(b, '.')
+ b = append(b, build...)
+ }
+ }
+
+ return string(b)
+}
+
+// Equals checks if v is equal to o.
+func (v Version) Equals(o Version) bool {
+ return (v.Compare(o) == 0)
+}
+
+// EQ checks if v is equal to o.
+func (v Version) EQ(o Version) bool {
+ return (v.Compare(o) == 0)
+}
+
+// NE checks if v is not equal to o.
+func (v Version) NE(o Version) bool {
+ return (v.Compare(o) != 0)
+}
+
+// GT checks if v is greater than o.
+func (v Version) GT(o Version) bool {
+ return (v.Compare(o) == 1)
+}
+
+// GTE checks if v is greater than or equal to o.
+func (v Version) GTE(o Version) bool {
+ return (v.Compare(o) >= 0)
+}
+
+// GE checks if v is greater than or equal to o.
+func (v Version) GE(o Version) bool {
+ return (v.Compare(o) >= 0)
+}
+
+// LT checks if v is less than o.
+func (v Version) LT(o Version) bool {
+ return (v.Compare(o) == -1)
+}
+
+// LTE checks if v is less than or equal to o.
+func (v Version) LTE(o Version) bool {
+ return (v.Compare(o) <= 0)
+}
+
+// LE checks if v is less than or equal to o.
+func (v Version) LE(o Version) bool {
+ return (v.Compare(o) <= 0)
+}
+
+// Compare compares Versions v to o:
+// -1 == v is less than o
+// 0 == v is equal to o
+// 1 == v is greater than o
+func (v Version) Compare(o Version) int {
+ if v.Major != o.Major {
+ if v.Major > o.Major {
+ return 1
+ }
+ return -1
+ }
+ if v.Minor != o.Minor {
+ if v.Minor > o.Minor {
+ return 1
+ }
+ return -1
+ }
+ if v.Patch != o.Patch {
+ if v.Patch > o.Patch {
+ return 1
+ }
+ return -1
+ }
+
+ // Quick comparison if a version has no prerelease versions
+ if len(v.Pre) == 0 && len(o.Pre) == 0 {
+ return 0
+ } else if len(v.Pre) == 0 && len(o.Pre) > 0 {
+ return 1
+ } else if len(v.Pre) > 0 && len(o.Pre) == 0 {
+ return -1
+ }
+
+ i := 0
+ for ; i < len(v.Pre) && i < len(o.Pre); i++ {
+ if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
+ continue
+ } else if comp == 1 {
+ return 1
+ } else {
+ return -1
+ }
+ }
+
+ // If all pr versions are the equal but one has further prversion, this one greater
+ if i == len(v.Pre) && i == len(o.Pre) {
+ return 0
+ } else if i == len(v.Pre) && i < len(o.Pre) {
+ return -1
+ } else {
+ return 1
+ }
+
+}
+
+// Validate validates v and returns error in case
+func (v Version) Validate() error {
+ // Major, Minor, Patch already validated using uint64
+
+ for _, pre := range v.Pre {
+ if !pre.IsNum { //Numeric prerelease versions already uint64
+ if len(pre.VersionStr) == 0 {
+ return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
+ }
+ if !containsOnly(pre.VersionStr, alphanum) {
+ return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
+ }
+ }
+ }
+
+ for _, build := range v.Build {
+ if len(build) == 0 {
+ return fmt.Errorf("Build meta data can not be empty %q", build)
+ }
+ if !containsOnly(build, alphanum) {
+ return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
+ }
+ }
+
+ return nil
+}
+
+// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
+func New(s string) (vp *Version, err error) {
+ v, err := Parse(s)
+ vp = &v
+ return
+}
+
+// Make is an alias for Parse, parses version string and returns a validated Version or error
+func Make(s string) (Version, error) {
+ return Parse(s)
+}
+
+// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
+// specs to be parsed by this library. It does so by normalizing versions before passing them to
+// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
+// with only major and minor components specified
+func ParseTolerant(s string) (Version, error) {
+ s = strings.TrimSpace(s)
+ s = strings.TrimPrefix(s, "v")
+
+ // Split into major.minor.(patch+pr+meta)
+ parts := strings.SplitN(s, ".", 3)
+ if len(parts) < 3 {
+ if strings.ContainsAny(parts[len(parts)-1], "+-") {
+ return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
+ }
+ for len(parts) < 3 {
+ parts = append(parts, "0")
+ }
+ s = strings.Join(parts, ".")
+ }
+
+ return Parse(s)
+}
+
+// Parse parses version string and returns a validated Version or error
+func Parse(s string) (Version, error) {
+ if len(s) == 0 {
+ return Version{}, errors.New("Version string empty")
+ }
+
+ // Split into major.minor.(patch+pr+meta)
+ parts := strings.SplitN(s, ".", 3)
+ if len(parts) != 3 {
+ return Version{}, errors.New("No Major.Minor.Patch elements found")
+ }
+
+ // Major
+ if !containsOnly(parts[0], numbers) {
+ return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
+ }
+ if hasLeadingZeroes(parts[0]) {
+ return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
+ }
+ major, err := strconv.ParseUint(parts[0], 10, 64)
+ if err != nil {
+ return Version{}, err
+ }
+
+ // Minor
+ if !containsOnly(parts[1], numbers) {
+ return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
+ }
+ if hasLeadingZeroes(parts[1]) {
+ return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
+ }
+ minor, err := strconv.ParseUint(parts[1], 10, 64)
+ if err != nil {
+ return Version{}, err
+ }
+
+ v := Version{}
+ v.Major = major
+ v.Minor = minor
+
+ var build, prerelease []string
+ patchStr := parts[2]
+
+ if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
+ build = strings.Split(patchStr[buildIndex+1:], ".")
+ patchStr = patchStr[:buildIndex]
+ }
+
+ if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
+ prerelease = strings.Split(patchStr[preIndex+1:], ".")
+ patchStr = patchStr[:preIndex]
+ }
+
+ if !containsOnly(patchStr, numbers) {
+ return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
+ }
+ if hasLeadingZeroes(patchStr) {
+ return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
+ }
+ patch, err := strconv.ParseUint(patchStr, 10, 64)
+ if err != nil {
+ return Version{}, err
+ }
+
+ v.Patch = patch
+
+ // Prerelease
+ for _, prstr := range prerelease {
+ parsedPR, err := NewPRVersion(prstr)
+ if err != nil {
+ return Version{}, err
+ }
+ v.Pre = append(v.Pre, parsedPR)
+ }
+
+ // Build meta data
+ for _, str := range build {
+ if len(str) == 0 {
+ return Version{}, errors.New("Build meta data is empty")
+ }
+ if !containsOnly(str, alphanum) {
+ return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
+ }
+ v.Build = append(v.Build, str)
+ }
+
+ return v, nil
+}
+
+// MustParse is like Parse but panics if the version cannot be parsed.
+func MustParse(s string) Version {
+ v, err := Parse(s)
+ if err != nil {
+ panic(`semver: Parse(` + s + `): ` + err.Error())
+ }
+ return v
+}
+
+// PRVersion represents a PreRelease Version
+type PRVersion struct {
+ VersionStr string
+ VersionNum uint64
+ IsNum bool
+}
+
+// NewPRVersion creates a new valid prerelease version
+func NewPRVersion(s string) (PRVersion, error) {
+ if len(s) == 0 {
+ return PRVersion{}, errors.New("Prerelease is empty")
+ }
+ v := PRVersion{}
+ if containsOnly(s, numbers) {
+ if hasLeadingZeroes(s) {
+ return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
+ }
+ num, err := strconv.ParseUint(s, 10, 64)
+
+ // Might never be hit, but just in case
+ if err != nil {
+ return PRVersion{}, err
+ }
+ v.VersionNum = num
+ v.IsNum = true
+ } else if containsOnly(s, alphanum) {
+ v.VersionStr = s
+ v.IsNum = false
+ } else {
+ return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
+ }
+ return v, nil
+}
+
+// IsNumeric checks if prerelease-version is numeric
+func (v PRVersion) IsNumeric() bool {
+ return v.IsNum
+}
+
+// Compare compares two PreRelease Versions v and o:
+// -1 == v is less than o
+// 0 == v is equal to o
+// 1 == v is greater than o
+func (v PRVersion) Compare(o PRVersion) int {
+ if v.IsNum && !o.IsNum {
+ return -1
+ } else if !v.IsNum && o.IsNum {
+ return 1
+ } else if v.IsNum && o.IsNum {
+ if v.VersionNum == o.VersionNum {
+ return 0
+ } else if v.VersionNum > o.VersionNum {
+ return 1
+ } else {
+ return -1
+ }
+ } else { // both are Alphas
+ if v.VersionStr == o.VersionStr {
+ return 0
+ } else if v.VersionStr > o.VersionStr {
+ return 1
+ } else {
+ return -1
+ }
+ }
+}
+
+// PreRelease version to string
+func (v PRVersion) String() string {
+ if v.IsNum {
+ return strconv.FormatUint(v.VersionNum, 10)
+ }
+ return v.VersionStr
+}
+
+func containsOnly(s string, set string) bool {
+ return strings.IndexFunc(s, func(r rune) bool {
+ return !strings.ContainsRune(set, r)
+ }) == -1
+}
+
+func hasLeadingZeroes(s string) bool {
+ return len(s) > 1 && s[0] == '0'
+}
+
+// NewBuildVersion creates a new valid build version
+func NewBuildVersion(s string) (string, error) {
+ if len(s) == 0 {
+ return "", errors.New("Buildversion is empty")
+ }
+ if !containsOnly(s, alphanum) {
+ return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
+ }
+ return s, nil
+}
diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/sort.go
new file mode 100644
index 000000000000..e18f880826ab
--- /dev/null
+++ b/vendor/github.com/blang/semver/sort.go
@@ -0,0 +1,28 @@
+package semver
+
+import (
+ "sort"
+)
+
+// Versions represents multiple versions.
+type Versions []Version
+
+// Len returns length of version collection
+func (s Versions) Len() int {
+ return len(s)
+}
+
+// Swap swaps two versions inside the collection by its indices
+func (s Versions) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+// Less checks if version at index i is less than version at index j
+func (s Versions) Less(i, j int) bool {
+ return s[i].LT(s[j])
+}
+
+// Sort sorts a slice of versions
+func Sort(versions []Version) {
+ sort.Sort(Versions(versions))
+}
diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/sql.go
new file mode 100644
index 000000000000..eb4d802666e0
--- /dev/null
+++ b/vendor/github.com/blang/semver/sql.go
@@ -0,0 +1,30 @@
+package semver
+
+import (
+ "database/sql/driver"
+ "fmt"
+)
+
+// Scan implements the database/sql.Scanner interface.
+func (v *Version) Scan(src interface{}) (err error) {
+ var str string
+ switch src := src.(type) {
+ case string:
+ str = src
+ case []byte:
+ str = string(src)
+ default:
+ return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
+ }
+
+ if t, err := Parse(str); err == nil {
+ *v = t
+ }
+
+ return
+}
+
+// Value implements the database/sql/driver.Valuer interface.
+func (v Version) Value() (driver.Value, error) {
+ return v.String(), nil
+}
diff --git a/vendor/github.com/cyberphone/json-canonicalization/LICENSE b/vendor/github.com/cyberphone/json-canonicalization/LICENSE
new file mode 100644
index 000000000000..591211595aaa
--- /dev/null
+++ b/vendor/github.com/cyberphone/json-canonicalization/LICENSE
@@ -0,0 +1,13 @@
+ Copyright 2018 Anders Rundgren
+
+ 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
+
+ https://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/github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer/es6numfmt.go b/vendor/github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer/es6numfmt.go
new file mode 100644
index 000000000000..92574a3f4f30
--- /dev/null
+++ b/vendor/github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer/es6numfmt.go
@@ -0,0 +1,71 @@
+//
+// Copyright 2006-2019 WebPKI.org (http://webpki.org).
+//
+// 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
+//
+// https://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.
+//
+
+// This package converts numbers in IEEE-754 double precision into the
+// format specified for JSON in EcmaScript Version 6 and forward.
+// The core application for this is canonicalization:
+// https://tools.ietf.org/html/draft-rundgren-json-canonicalization-scheme-02
+
+package jsoncanonicalizer
+
+import (
+ "errors"
+ "math"
+ "strconv"
+ "strings"
+)
+
+const invalidPattern uint64 = 0x7ff0000000000000
+
+func NumberToJSON(ieeeF64 float64) (res string, err error) {
+ ieeeU64 := math.Float64bits(ieeeF64)
+
+ // Special case: NaN and Infinity are invalid in JSON
+ if (ieeeU64 & invalidPattern) == invalidPattern {
+ return "null", errors.New("Invalid JSON number: " + strconv.FormatUint(ieeeU64, 16))
+ }
+
+ // Special case: eliminate "-0" as mandated by the ES6-JSON/JCS specifications
+ if ieeeF64 == 0 { // Right, this line takes both -0 and 0
+ return "0", nil
+ }
+
+ // Deal with the sign separately
+ var sign string = ""
+ if ieeeF64 < 0 {
+ ieeeF64 =-ieeeF64
+ sign = "-"
+ }
+
+ // ES6 has a unique "g" format
+ var format byte = 'e'
+ if ieeeF64 < 1e+21 && ieeeF64 >= 1e-6 {
+ format = 'f'
+ }
+
+ // The following should do the trick:
+ es6Formatted := strconv.FormatFloat(ieeeF64, format, -1, 64)
+
+ // Minor cleanup
+ exponent := strings.IndexByte(es6Formatted, 'e')
+ if exponent > 0 {
+ // Go outputs "1e+09" which must be rewritten as "1e+9"
+ if es6Formatted[exponent + 2] == '0' {
+ es6Formatted = es6Formatted[:exponent + 2] + es6Formatted[exponent + 3:]
+ }
+ }
+ return sign + es6Formatted, nil
+}
diff --git a/vendor/github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer/jsoncanonicalizer.go b/vendor/github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer/jsoncanonicalizer.go
new file mode 100644
index 000000000000..661f41055e46
--- /dev/null
+++ b/vendor/github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer/jsoncanonicalizer.go
@@ -0,0 +1,378 @@
+//
+// Copyright 2006-2019 WebPKI.org (http://webpki.org).
+//
+// 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
+//
+// https://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.
+//
+
+// This package transforms JSON data in UTF-8 according to:
+// https://tools.ietf.org/html/draft-rundgren-json-canonicalization-scheme-02
+
+package jsoncanonicalizer
+
+import (
+ "errors"
+ "container/list"
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode/utf16"
+)
+
+type nameValueType struct {
+ name string
+ sortKey []uint16
+ value string
+}
+
+// JSON standard escapes (modulo \u)
+var asciiEscapes = []byte{'\\', '"', 'b', 'f', 'n', 'r', 't'}
+var binaryEscapes = []byte{'\\', '"', '\b', '\f', '\n', '\r', '\t'}
+
+// JSON literals
+var literals = []string{"true", "false", "null"}
+
+func Transform(jsonData []byte) (result []byte, e error) {
+
+ // JSON data MUST be UTF-8 encoded
+ var jsonDataLength int = len(jsonData)
+
+ // Current pointer in jsonData
+ var index int = 0
+
+ // "Forward" declarations are needed for closures referring each other
+ var parseElement func() string
+ var parseSimpleType func() string
+ var parseQuotedString func() string
+ var parseObject func() string
+ var parseArray func() string
+
+ var globalError error = nil
+
+ checkError := func(e error) {
+ // We only honor the first reported error
+ if globalError == nil {
+ globalError = e
+ }
+ }
+
+ setError := func(msg string) {
+ checkError(errors.New(msg))
+ }
+
+ isWhiteSpace := func(c byte) bool {
+ return c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09
+ }
+
+ nextChar := func() byte {
+ if index < jsonDataLength {
+ c := jsonData[index]
+ if c > 0x7f {
+ setError("Unexpected non-ASCII character")
+ }
+ index++
+ return c
+ }
+ setError("Unexpected EOF reached")
+ return '"'
+ }
+
+ scan := func() byte {
+ for {
+ c := nextChar()
+ if isWhiteSpace(c) {
+ continue;
+ }
+ return c
+ }
+ }
+
+ scanFor := func(expected byte) {
+ c := scan()
+ if c != expected {
+ setError("Expected '" + string(expected) + "' but got '" + string(c) + "'")
+ }
+ }
+
+ getUEscape := func() rune {
+ start := index
+ nextChar()
+ nextChar()
+ nextChar()
+ nextChar()
+ if globalError != nil {
+ return 0
+ }
+ u16, err := strconv.ParseUint(string(jsonData[start:index]), 16, 64)
+ checkError(err)
+ return rune(u16)
+ }
+
+ testNextNonWhiteSpaceChar := func() byte {
+ save := index
+ c := scan()
+ index = save
+ return c
+ }
+
+ decorateString := func(rawUTF8 string) string {
+ var quotedString strings.Builder
+ quotedString.WriteByte('"')
+ CoreLoop:
+ for _, c := range []byte(rawUTF8) {
+ // Is this within the JSON standard escapes?
+ for i, esc := range binaryEscapes {
+ if esc == c {
+ quotedString.WriteByte('\\')
+ quotedString.WriteByte(asciiEscapes[i])
+ continue CoreLoop
+ }
+ }
+ if c < 0x20 {
+ // Other ASCII control characters must be escaped with \uhhhh
+ quotedString.WriteString(fmt.Sprintf("\\u%04x", c))
+ } else {
+ quotedString.WriteByte(c)
+ }
+ }
+ quotedString.WriteByte('"')
+ return quotedString.String()
+ }
+
+ parseQuotedString = func() string {
+ var rawString strings.Builder
+ CoreLoop:
+ for globalError == nil {
+ var c byte
+ if index < jsonDataLength {
+ c = jsonData[index]
+ index++
+ } else {
+ nextChar()
+ break
+ }
+ if (c == '"') {
+ break;
+ }
+ if c < ' ' {
+ setError("Unterminated string literal")
+ } else if c == '\\' {
+ // Escape sequence
+ c = nextChar()
+ if c == 'u' {
+ // The \u escape
+ firstUTF16 := getUEscape()
+ if utf16.IsSurrogate(firstUTF16) {
+ // If the first UTF-16 code unit has a certain value there must be
+ // another succeeding UTF-16 code unit as well
+ if nextChar() != '\\' || nextChar() != 'u' {
+ setError("Missing surrogate")
+ } else {
+ // Output the UTF-32 code point as UTF-8
+ rawString.WriteRune(utf16.DecodeRune(firstUTF16, getUEscape()))
+ }
+ } else {
+ // Single UTF-16 code identical to UTF-32. Output as UTF-8
+ rawString.WriteRune(firstUTF16)
+ }
+ } else if c == '/' {
+ // Benign but useless escape
+ rawString.WriteByte('/')
+ } else {
+ // The JSON standard escapes
+ for i, esc := range asciiEscapes {
+ if esc == c {
+ rawString.WriteByte(binaryEscapes[i])
+ continue CoreLoop
+ }
+ }
+ setError("Unexpected escape: \\" + string(c))
+ }
+ } else {
+ // Just an ordinary ASCII character alternatively a UTF-8 byte
+ // outside of ASCII.
+ // Note that properly formatted UTF-8 never clashes with ASCII
+ // making byte per byte search for ASCII break characters work
+ // as expected.
+ rawString.WriteByte(c)
+ }
+ }
+ return rawString.String()
+ }
+
+ parseSimpleType = func() string {
+ var token strings.Builder
+ index--
+ for globalError == nil {
+ c := testNextNonWhiteSpaceChar()
+ if c == ',' || c == ']' || c == '}' {
+ break;
+ }
+ c = nextChar()
+ if isWhiteSpace(c) {
+ break
+ }
+ token.WriteByte(c)
+ }
+ if token.Len() == 0 {
+ setError("Missing argument")
+ }
+ value := token.String()
+ // Is it a JSON literal?
+ for _, literal := range literals {
+ if literal == value {
+ return literal
+ }
+ }
+ // Apparently not so we assume that it is a I-JSON number
+ ieeeF64, err := strconv.ParseFloat(value, 64)
+ checkError(err)
+ value, err = NumberToJSON(ieeeF64)
+ checkError(err)
+ return value
+ }
+
+ parseElement = func() string {
+ switch scan() {
+ case '{':
+ return parseObject()
+ case '"':
+ return decorateString(parseQuotedString())
+ case '[':
+ return parseArray()
+ default:
+ return parseSimpleType()
+ }
+ }
+
+ parseArray = func() string {
+ var arrayData strings.Builder
+ arrayData.WriteByte('[')
+ var next bool = false
+ for globalError == nil && testNextNonWhiteSpaceChar() != ']' {
+ if next {
+ scanFor(',')
+ arrayData.WriteByte(',')
+ } else {
+ next = true
+ }
+ arrayData.WriteString(parseElement())
+ }
+ scan()
+ arrayData.WriteByte(']')
+ return arrayData.String()
+ }
+
+ lexicographicallyPrecedes := func(sortKey []uint16, e *list.Element) bool {
+ // Find the minimum length of the sortKeys
+ oldSortKey := e.Value.(nameValueType).sortKey
+ minLength := len(oldSortKey)
+ if minLength > len(sortKey) {
+ minLength = len(sortKey)
+ }
+ for q := 0; q < minLength; q++ {
+ diff := int(sortKey[q]) - int(oldSortKey[q])
+ if diff < 0 {
+ // Smaller => Precedes
+ return true
+ } else if diff > 0 {
+ // Bigger => No match
+ return false
+ }
+ // Still equal => Continue
+ }
+ // The sortKeys compared equal up to minLength
+ if len(sortKey) < len(oldSortKey) {
+ // Shorter => Precedes
+ return true
+ }
+ if len(sortKey) == len(oldSortKey) {
+ setError("Duplicate key: " + e.Value.(nameValueType).name)
+ }
+ // Longer => No match
+ return false
+ }
+
+ parseObject = func() string {
+ nameValueList := list.New()
+ var next bool = false
+ CoreLoop:
+ for globalError == nil && testNextNonWhiteSpaceChar() != '}' {
+ if next {
+ scanFor(',')
+ }
+ next = true
+ scanFor('"')
+ rawUTF8 := parseQuotedString()
+ if globalError != nil {
+ break;
+ }
+ // Sort keys on UTF-16 code units
+ // Since UTF-8 doesn't have endianess this is just a value transformation
+ // In the Go case the transformation is UTF-8 => UTF-32 => UTF-16
+ sortKey := utf16.Encode([]rune(rawUTF8))
+ scanFor(':')
+ nameValue := nameValueType{rawUTF8, sortKey, parseElement()}
+ for e := nameValueList.Front(); e != nil; e = e.Next() {
+ // Check if the key is smaller than a previous key
+ if lexicographicallyPrecedes(sortKey, e) {
+ // Precedes => Insert before and exit sorting
+ nameValueList.InsertBefore(nameValue, e)
+ continue CoreLoop
+ }
+ // Continue searching for a possibly succeeding sortKey
+ // (which is straightforward since the list is ordered)
+ }
+ // The sortKey is either the first or is succeeding all previous sortKeys
+ nameValueList.PushBack(nameValue)
+ }
+ // Scan away '}'
+ scan()
+ // Now everything is sorted so we can properly serialize the object
+ var objectData strings.Builder
+ objectData.WriteByte('{')
+ next = false
+ for e := nameValueList.Front(); e != nil; e = e.Next() {
+ if next {
+ objectData.WriteByte(',')
+ }
+ next = true
+ nameValue := e.Value.(nameValueType)
+ objectData.WriteString(decorateString(nameValue.name))
+ objectData.WriteByte(':')
+ objectData.WriteString(nameValue.value)
+ }
+ objectData.WriteByte('}')
+ return objectData.String()
+ }
+
+ /////////////////////////////////////////////////
+ // This is where Transform actually begins... //
+ /////////////////////////////////////////////////
+ var transformed string
+
+ if testNextNonWhiteSpaceChar() == '[' {
+ scan()
+ transformed = parseArray()
+ } else {
+ scanFor('{')
+ transformed = parseObject()
+ }
+ for index < jsonDataLength {
+ if !isWhiteSpace(jsonData[index]) {
+ setError("Improperly terminated JSON object")
+ break;
+ }
+ index++
+ }
+ return []byte(transformed), globalError
+}
\ No newline at end of file
diff --git a/vendor/github.com/digitorus/pkcs7/.gitignore b/vendor/github.com/digitorus/pkcs7/.gitignore
new file mode 100644
index 000000000000..daf913b1b347
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/.gitignore
@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
diff --git a/vendor/github.com/digitorus/pkcs7/LICENSE b/vendor/github.com/digitorus/pkcs7/LICENSE
new file mode 100644
index 000000000000..75f3209085b8
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew Smith
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/digitorus/pkcs7/Makefile b/vendor/github.com/digitorus/pkcs7/Makefile
new file mode 100644
index 000000000000..07c78e14c040
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/Makefile
@@ -0,0 +1,20 @@
+all: vet staticcheck test
+
+test:
+ GODEBUG=x509sha1=1 go test -covermode=count -coverprofile=coverage.out .
+
+showcoverage: test
+ go tool cover -html=coverage.out
+
+vet:
+ go vet .
+
+lint:
+ golint .
+
+staticcheck:
+ staticcheck .
+
+gettools:
+ go get -u honnef.co/go/tools/...
+ go get -u golang.org/x/lint/golint
diff --git a/vendor/github.com/digitorus/pkcs7/README.md b/vendor/github.com/digitorus/pkcs7/README.md
new file mode 100644
index 000000000000..a55d117c682c
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/README.md
@@ -0,0 +1,69 @@
+# pkcs7
+
+[](https://godoc.org/go.mozilla.org/pkcs7)
+[](https://github.com/mozilla-services/pkcs7/actions/workflows/ci.yml?query=branch%3Amaster+event%3Apush)
+
+pkcs7 implements parsing and creating signed and enveloped messages.
+
+```go
+package main
+
+import (
+ "bytes"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "os"
+
+ "go.mozilla.org/pkcs7"
+)
+
+func SignAndDetach(content []byte, cert *x509.Certificate, privkey *rsa.PrivateKey) (signed []byte, err error) {
+ toBeSigned, err := NewSignedData(content)
+ if err != nil {
+ err = fmt.Errorf("Cannot initialize signed data: %s", err)
+ return
+ }
+ if err = toBeSigned.AddSigner(cert, privkey, SignerInfoConfig{}); err != nil {
+ err = fmt.Errorf("Cannot add signer: %s", err)
+ return
+ }
+
+ // Detach signature, omit if you want an embedded signature
+ toBeSigned.Detach()
+
+ signed, err = toBeSigned.Finish()
+ if err != nil {
+ err = fmt.Errorf("Cannot finish signing data: %s", err)
+ return
+ }
+
+ // Verify the signature
+ pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: signed})
+ p7, err := pkcs7.Parse(signed)
+ if err != nil {
+ err = fmt.Errorf("Cannot parse our signed data: %s", err)
+ return
+ }
+
+ // since the signature was detached, reattach the content here
+ p7.Content = content
+
+ if bytes.Compare(content, p7.Content) != 0 {
+ err = fmt.Errorf("Our content was not in the parsed data:\n\tExpected: %s\n\tActual: %s", content, p7.Content)
+ return
+ }
+ if err = p7.Verify(); err != nil {
+ err = fmt.Errorf("Cannot verify our signed data: %s", err)
+ return
+ }
+
+ return signed, nil
+}
+```
+
+
+
+## Credits
+This is a fork of [fullsailor/pkcs7](https://github.com/fullsailor/pkcs7)
diff --git a/vendor/github.com/digitorus/pkcs7/ber.go b/vendor/github.com/digitorus/pkcs7/ber.go
new file mode 100644
index 000000000000..31963b119f74
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/ber.go
@@ -0,0 +1,269 @@
+package pkcs7
+
+import (
+ "bytes"
+ "errors"
+)
+
+type asn1Object interface {
+ EncodeTo(writer *bytes.Buffer) error
+}
+
+type asn1Structured struct {
+ tagBytes []byte
+ content []asn1Object
+}
+
+func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
+ //fmt.Printf("%s--> tag: % X\n", strings.Repeat("| ", encodeIndent), s.tagBytes)
+ inner := new(bytes.Buffer)
+ for _, obj := range s.content {
+ err := obj.EncodeTo(inner)
+ if err != nil {
+ return err
+ }
+ }
+ out.Write(s.tagBytes)
+ encodeLength(out, inner.Len())
+ out.Write(inner.Bytes())
+ return nil
+}
+
+type asn1Primitive struct {
+ tagBytes []byte
+ length int
+ content []byte
+}
+
+func (p asn1Primitive) EncodeTo(out *bytes.Buffer) error {
+ _, err := out.Write(p.tagBytes)
+ if err != nil {
+ return err
+ }
+ if err = encodeLength(out, p.length); err != nil {
+ return err
+ }
+ //fmt.Printf("%s--> tag: % X length: %d\n", strings.Repeat("| ", encodeIndent), p.tagBytes, p.length)
+ //fmt.Printf("%s--> content length: %d\n", strings.Repeat("| ", encodeIndent), len(p.content))
+ out.Write(p.content)
+
+ return nil
+}
+
+func ber2der(ber []byte) ([]byte, error) {
+ if len(ber) == 0 {
+ return nil, errors.New("ber2der: input ber is empty")
+ }
+ //fmt.Printf("--> ber2der: Transcoding %d bytes\n", len(ber))
+ out := new(bytes.Buffer)
+
+ obj, _, err := readObject(ber, 0)
+ if err != nil {
+ return nil, err
+ }
+ obj.EncodeTo(out)
+
+ return out.Bytes(), nil
+}
+
+// encodes lengths that are longer than 127 into string of bytes
+func marshalLongLength(out *bytes.Buffer, i int) (err error) {
+ n := lengthLength(i)
+
+ for ; n > 0; n-- {
+ err = out.WriteByte(byte(i >> uint((n-1)*8)))
+ if err != nil {
+ return
+ }
+ }
+
+ return nil
+}
+
+// computes the byte length of an encoded length value
+func lengthLength(i int) (numBytes int) {
+ numBytes = 1
+ for i > 255 {
+ numBytes++
+ i >>= 8
+ }
+ return
+}
+
+// encodes the length in DER format
+// If the length fits in 7 bits, the value is encoded directly.
+//
+// Otherwise, the number of bytes to encode the length is first determined.
+// This number is likely to be 4 or less for a 32bit length. This number is
+// added to 0x80. The length is encoded in big endian encoding follow after
+//
+// Examples:
+// length | byte 1 | bytes n
+// 0 | 0x00 | -
+// 120 | 0x78 | -
+// 200 | 0x81 | 0xC8
+// 500 | 0x82 | 0x01 0xF4
+//
+func encodeLength(out *bytes.Buffer, length int) (err error) {
+ if length >= 128 {
+ l := lengthLength(length)
+ err = out.WriteByte(0x80 | byte(l))
+ if err != nil {
+ return
+ }
+ err = marshalLongLength(out, length)
+ if err != nil {
+ return
+ }
+ } else {
+ err = out.WriteByte(byte(length))
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+func readObject(ber []byte, offset int) (asn1Object, int, error) {
+ berLen := len(ber)
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: offset is after end of ber data")
+ }
+ tagStart := offset
+ b := ber[offset]
+ offset++
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
+ tag := b & 0x1F // last 5 bits
+ if tag == 0x1F {
+ tag = 0
+ for ber[offset] >= 0x80 {
+ tag = tag*128 + ber[offset] - 0x80
+ offset++
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
+ }
+ // jvehent 20170227: this doesn't appear to be used anywhere...
+ //tag = tag*128 + ber[offset] - 0x80
+ offset++
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
+ }
+ tagEnd := offset
+
+ kind := b & 0x20
+ if kind == 0 {
+ debugprint("--> Primitive\n")
+ } else {
+ debugprint("--> Constructed\n")
+ }
+ // read length
+ var length int
+ l := ber[offset]
+ offset++
+ if l >= 0x80 && offset >= berLen {
+ // if indefinite or multibyte length, we need to verify there is at least one more byte available
+ // otherwise we need to be flexible here for length == 0 conditions
+ // validation that the length is available is done after the length is correctly parsed
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
+ indefinite := false
+ if l > 0x80 {
+ numberOfBytes := (int)(l & 0x7F)
+ if numberOfBytes > 4 { // int is only guaranteed to be 32bit
+ return nil, 0, errors.New("ber2der: BER tag length too long")
+ }
+ if numberOfBytes == 4 && (int)(ber[offset]) > 0x7F {
+ return nil, 0, errors.New("ber2der: BER tag length is negative")
+ }
+ if offset + numberOfBytes > berLen {
+ // == condition is not checked here, this allows for a more descreptive error when the parsed length is
+ // compared with the remaining available bytes (`contentEnd > berLen`)
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
+ if (int)(ber[offset]) == 0x0 && (numberOfBytes == 1 || ber[offset+1] <= 0x7F) {
+ // `numberOfBytes == 1` is an important conditional to avoid a potential out of bounds panic with `ber[offset+1]`
+ return nil, 0, errors.New("ber2der: BER tag length has leading zero")
+ }
+ debugprint("--> (compute length) indicator byte: %x\n", l)
+ //debugprint("--> (compute length) length bytes: %x\n", ber[offset:offset+numberOfBytes])
+ for i := 0; i < numberOfBytes; i++ {
+ length = length*256 + (int)(ber[offset])
+ offset++
+ }
+ } else if l == 0x80 {
+ indefinite = true
+ } else {
+ length = (int)(l)
+ }
+ if length < 0 {
+ return nil, 0, errors.New("ber2der: invalid negative value found in BER tag length")
+ }
+ //fmt.Printf("--> length : %d\n", length)
+ contentEnd := offset + length
+ if contentEnd > berLen {
+ return nil, 0, errors.New("ber2der: BER tag length is more than available data")
+ }
+ debugprint("--> content start : %d\n", offset)
+ debugprint("--> content end : %d\n", contentEnd)
+ //debugprint("--> content : %x\n", ber[offset:contentEnd])
+ var obj asn1Object
+ if indefinite && kind == 0 {
+ return nil, 0, errors.New("ber2der: Indefinite form tag must have constructed encoding")
+ }
+ if kind == 0 {
+ obj = asn1Primitive{
+ tagBytes: ber[tagStart:tagEnd],
+ length: length,
+ content: ber[offset:contentEnd],
+ }
+ } else {
+ var subObjects []asn1Object
+ for (offset < contentEnd) || indefinite {
+ var subObj asn1Object
+ var err error
+ subObj, offset, err = readObject(ber, offset)
+ if err != nil {
+ return nil, 0, err
+ }
+ subObjects = append(subObjects, subObj)
+
+ if indefinite {
+ terminated, err := isIndefiniteTermination(ber, offset)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ if terminated {
+ break
+ }
+ }
+ }
+ obj = asn1Structured{
+ tagBytes: ber[tagStart:tagEnd],
+ content: subObjects,
+ }
+ }
+
+ // Apply indefinite form length with 0x0000 terminator.
+ if indefinite {
+ contentEnd = offset + 2
+ }
+
+ return obj, contentEnd, nil
+}
+
+func isIndefiniteTermination(ber []byte, offset int) (bool, error) {
+ if len(ber) - offset < 2 {
+ return false, errors.New("ber2der: Invalid BER format")
+ }
+
+ return bytes.Index(ber[offset:], []byte{0x0, 0x0}) == 0, nil
+}
+
+func debugprint(format string, a ...interface{}) {
+ //fmt.Printf(format, a)
+}
diff --git a/vendor/github.com/digitorus/pkcs7/decrypt.go b/vendor/github.com/digitorus/pkcs7/decrypt.go
new file mode 100644
index 000000000000..0d088d6287c9
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/decrypt.go
@@ -0,0 +1,177 @@
+package pkcs7
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+)
+
+// ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed
+var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported")
+
+// ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data
+var ErrNotEncryptedContent = errors.New("pkcs7: content data is a decryptable data type")
+
+// Decrypt decrypts encrypted content info for recipient cert and private key
+func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pkey crypto.PrivateKey) ([]byte, error) {
+ data, ok := p7.raw.(envelopedData)
+ if !ok {
+ return nil, ErrNotEncryptedContent
+ }
+ recipient := selectRecipientForCertificate(data.RecipientInfos, cert)
+ if recipient.EncryptedKey == nil {
+ return nil, errors.New("pkcs7: no enveloped recipient for provided certificate")
+ }
+ switch pkey := pkey.(type) {
+ case *rsa.PrivateKey:
+ var contentKey []byte
+ contentKey, err := rsa.DecryptPKCS1v15(rand.Reader, pkey, recipient.EncryptedKey)
+ if err != nil {
+ return nil, err
+ }
+ return data.EncryptedContentInfo.decrypt(contentKey)
+ }
+ return nil, ErrUnsupportedAlgorithm
+}
+
+// DecryptUsingPSK decrypts encrypted data using caller provided
+// pre-shared secret
+func (p7 *PKCS7) DecryptUsingPSK(key []byte) ([]byte, error) {
+ data, ok := p7.raw.(encryptedData)
+ if !ok {
+ return nil, ErrNotEncryptedContent
+ }
+ return data.EncryptedContentInfo.decrypt(key)
+}
+
+func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
+ alg := eci.ContentEncryptionAlgorithm.Algorithm
+ if !alg.Equal(OIDEncryptionAlgorithmDESCBC) &&
+ !alg.Equal(OIDEncryptionAlgorithmDESEDE3CBC) &&
+ !alg.Equal(OIDEncryptionAlgorithmAES256CBC) &&
+ !alg.Equal(OIDEncryptionAlgorithmAES128CBC) &&
+ !alg.Equal(OIDEncryptionAlgorithmAES128GCM) &&
+ !alg.Equal(OIDEncryptionAlgorithmAES256GCM) {
+ fmt.Printf("Unsupported Content Encryption Algorithm: %s\n", alg)
+ return nil, ErrUnsupportedAlgorithm
+ }
+
+ // EncryptedContent can either be constructed of multple OCTET STRINGs
+ // or _be_ a tagged OCTET STRING
+ var cyphertext []byte
+ if eci.EncryptedContent.IsCompound {
+ // Complex case to concat all of the children OCTET STRINGs
+ var buf bytes.Buffer
+ cypherbytes := eci.EncryptedContent.Bytes
+ for {
+ var part []byte
+ cypherbytes, _ = asn1.Unmarshal(cypherbytes, &part)
+ buf.Write(part)
+ if cypherbytes == nil {
+ break
+ }
+ }
+ cyphertext = buf.Bytes()
+ } else {
+ // Simple case, the bytes _are_ the cyphertext
+ cyphertext = eci.EncryptedContent.Bytes
+ }
+
+ var block cipher.Block
+ var err error
+
+ switch {
+ case alg.Equal(OIDEncryptionAlgorithmDESCBC):
+ block, err = des.NewCipher(key)
+ case alg.Equal(OIDEncryptionAlgorithmDESEDE3CBC):
+ block, err = des.NewTripleDESCipher(key)
+ case alg.Equal(OIDEncryptionAlgorithmAES256CBC), alg.Equal(OIDEncryptionAlgorithmAES256GCM):
+ fallthrough
+ case alg.Equal(OIDEncryptionAlgorithmAES128GCM), alg.Equal(OIDEncryptionAlgorithmAES128CBC):
+ block, err = aes.NewCipher(key)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ if alg.Equal(OIDEncryptionAlgorithmAES128GCM) || alg.Equal(OIDEncryptionAlgorithmAES256GCM) {
+ params := aesGCMParameters{}
+ paramBytes := eci.ContentEncryptionAlgorithm.Parameters.Bytes
+
+ _, err := asn1.Unmarshal(paramBytes, ¶ms)
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(params.Nonce) != gcm.NonceSize() {
+ return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
+ }
+ if params.ICVLen != gcm.Overhead() {
+ return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
+ }
+
+ plaintext, err := gcm.Open(nil, params.Nonce, cyphertext, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return plaintext, nil
+ }
+
+ iv := eci.ContentEncryptionAlgorithm.Parameters.Bytes
+ if len(iv) != block.BlockSize() {
+ return nil, errors.New("pkcs7: encryption algorithm parameters are malformed")
+ }
+ mode := cipher.NewCBCDecrypter(block, iv)
+ plaintext := make([]byte, len(cyphertext))
+ mode.CryptBlocks(plaintext, cyphertext)
+ if plaintext, err = unpad(plaintext, mode.BlockSize()); err != nil {
+ return nil, err
+ }
+ return plaintext, nil
+}
+
+func unpad(data []byte, blocklen int) ([]byte, error) {
+ if blocklen < 1 {
+ return nil, fmt.Errorf("invalid blocklen %d", blocklen)
+ }
+ if len(data)%blocklen != 0 || len(data) == 0 {
+ return nil, fmt.Errorf("invalid data len %d", len(data))
+ }
+
+ // the last byte is the length of padding
+ padlen := int(data[len(data)-1])
+
+ // check padding integrity, all bytes should be the same
+ pad := data[len(data)-padlen:]
+ for _, padbyte := range pad {
+ if padbyte != byte(padlen) {
+ return nil, errors.New("invalid padding")
+ }
+ }
+
+ return data[:len(data)-padlen], nil
+}
+
+func selectRecipientForCertificate(recipients []recipientInfo, cert *x509.Certificate) recipientInfo {
+ for _, recp := range recipients {
+ if isCertMatchForIssuerAndSerial(cert, recp.IssuerAndSerialNumber) {
+ return recp
+ }
+ }
+ return recipientInfo{}
+}
diff --git a/vendor/github.com/digitorus/pkcs7/encrypt.go b/vendor/github.com/digitorus/pkcs7/encrypt.go
new file mode 100644
index 000000000000..6b2655708c68
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/encrypt.go
@@ -0,0 +1,399 @@
+package pkcs7
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+)
+
+type envelopedData struct {
+ Version int
+ RecipientInfos []recipientInfo `asn1:"set"`
+ EncryptedContentInfo encryptedContentInfo
+}
+
+type encryptedData struct {
+ Version int
+ EncryptedContentInfo encryptedContentInfo
+}
+
+type recipientInfo struct {
+ Version int
+ IssuerAndSerialNumber issuerAndSerial
+ KeyEncryptionAlgorithm pkix.AlgorithmIdentifier
+ EncryptedKey []byte
+}
+
+type encryptedContentInfo struct {
+ ContentType asn1.ObjectIdentifier
+ ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
+ EncryptedContent asn1.RawValue `asn1:"tag:0,optional"`
+}
+
+const (
+ // EncryptionAlgorithmDESCBC is the DES CBC encryption algorithm
+ EncryptionAlgorithmDESCBC = iota
+
+ // EncryptionAlgorithmAES128CBC is the AES 128 bits with CBC encryption algorithm
+ // Avoid this algorithm unless required for interoperability; use AES GCM instead.
+ EncryptionAlgorithmAES128CBC
+
+ // EncryptionAlgorithmAES256CBC is the AES 256 bits with CBC encryption algorithm
+ // Avoid this algorithm unless required for interoperability; use AES GCM instead.
+ EncryptionAlgorithmAES256CBC
+
+ // EncryptionAlgorithmAES128GCM is the AES 128 bits with GCM encryption algorithm
+ EncryptionAlgorithmAES128GCM
+
+ // EncryptionAlgorithmAES256GCM is the AES 256 bits with GCM encryption algorithm
+ EncryptionAlgorithmAES256GCM
+)
+
+// ContentEncryptionAlgorithm determines the algorithm used to encrypt the
+// plaintext message. Change the value of this variable to change which
+// algorithm is used in the Encrypt() function.
+var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
+
+// ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt
+// content with an unsupported algorithm.
+var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC, AES-CBC, and AES-GCM supported")
+
+// ErrPSKNotProvided is returned when attempting to encrypt
+// using a PSK without actually providing the PSK.
+var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided")
+
+const nonceSize = 12
+
+type aesGCMParameters struct {
+ Nonce []byte `asn1:"tag:4"`
+ ICVLen int
+}
+
+func encryptAESGCM(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
+ var keyLen int
+ var algID asn1.ObjectIdentifier
+ switch ContentEncryptionAlgorithm {
+ case EncryptionAlgorithmAES128GCM:
+ keyLen = 16
+ algID = OIDEncryptionAlgorithmAES128GCM
+ case EncryptionAlgorithmAES256GCM:
+ keyLen = 32
+ algID = OIDEncryptionAlgorithmAES256GCM
+ default:
+ return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESGCM: %d", ContentEncryptionAlgorithm)
+ }
+ if key == nil {
+ // Create AES key
+ key = make([]byte, keyLen)
+
+ _, err := rand.Read(key)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ // Create nonce
+ nonce := make([]byte, nonceSize)
+
+ _, err := rand.Read(nonce)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Encrypt content
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ ciphertext := gcm.Seal(nil, nonce, content, nil)
+
+ // Prepare ASN.1 Encrypted Content Info
+ paramSeq := aesGCMParameters{
+ Nonce: nonce,
+ ICVLen: gcm.Overhead(),
+ }
+
+ paramBytes, err := asn1.Marshal(paramSeq)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ eci := encryptedContentInfo{
+ ContentType: OIDData,
+ ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: algID,
+ Parameters: asn1.RawValue{
+ Tag: asn1.TagSequence,
+ Bytes: paramBytes,
+ },
+ },
+ EncryptedContent: marshalEncryptedContent(ciphertext),
+ }
+
+ return key, &eci, nil
+}
+
+func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
+ if key == nil {
+ // Create DES key
+ key = make([]byte, 8)
+
+ _, err := rand.Read(key)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ // Create CBC IV
+ iv := make([]byte, des.BlockSize)
+ _, err := rand.Read(iv)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Encrypt padded content
+ block, err := des.NewCipher(key)
+ if err != nil {
+ return nil, nil, err
+ }
+ mode := cipher.NewCBCEncrypter(block, iv)
+ plaintext, err := pad(content, mode.BlockSize())
+ if err != nil {
+ return nil, nil, err
+ }
+ cyphertext := make([]byte, len(plaintext))
+ mode.CryptBlocks(cyphertext, plaintext)
+
+ // Prepare ASN.1 Encrypted Content Info
+ eci := encryptedContentInfo{
+ ContentType: OIDData,
+ ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: OIDEncryptionAlgorithmDESCBC,
+ Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
+ },
+ EncryptedContent: marshalEncryptedContent(cyphertext),
+ }
+
+ return key, &eci, nil
+}
+
+func encryptAESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
+ var keyLen int
+ var algID asn1.ObjectIdentifier
+ switch ContentEncryptionAlgorithm {
+ case EncryptionAlgorithmAES128CBC:
+ keyLen = 16
+ algID = OIDEncryptionAlgorithmAES128CBC
+ case EncryptionAlgorithmAES256CBC:
+ keyLen = 32
+ algID = OIDEncryptionAlgorithmAES256CBC
+ default:
+ return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESCBC: %d", ContentEncryptionAlgorithm)
+ }
+
+ if key == nil {
+ // Create AES key
+ key = make([]byte, keyLen)
+
+ _, err := rand.Read(key)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ // Create CBC IV
+ iv := make([]byte, aes.BlockSize)
+ _, err := rand.Read(iv)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Encrypt padded content
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, nil, err
+ }
+ mode := cipher.NewCBCEncrypter(block, iv)
+ plaintext, err := pad(content, mode.BlockSize())
+ if err != nil {
+ return nil, nil, err
+ }
+ cyphertext := make([]byte, len(plaintext))
+ mode.CryptBlocks(cyphertext, plaintext)
+
+ // Prepare ASN.1 Encrypted Content Info
+ eci := encryptedContentInfo{
+ ContentType: OIDData,
+ ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: algID,
+ Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
+ },
+ EncryptedContent: marshalEncryptedContent(cyphertext),
+ }
+
+ return key, &eci, nil
+}
+
+// Encrypt creates and returns an envelope data PKCS7 structure with encrypted
+// recipient keys for each recipient public key.
+//
+// The algorithm used to perform encryption is determined by the current value
+// of the global ContentEncryptionAlgorithm package variable. By default, the
+// value is EncryptionAlgorithmDESCBC. To use a different algorithm, change the
+// value before calling Encrypt(). For example:
+//
+// ContentEncryptionAlgorithm = EncryptionAlgorithmAES128GCM
+//
+// TODO(fullsailor): Add support for encrypting content with other algorithms
+func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
+ var eci *encryptedContentInfo
+ var key []byte
+ var err error
+
+ // Apply chosen symmetric encryption method
+ switch ContentEncryptionAlgorithm {
+ case EncryptionAlgorithmDESCBC:
+ key, eci, err = encryptDESCBC(content, nil)
+ case EncryptionAlgorithmAES128CBC:
+ fallthrough
+ case EncryptionAlgorithmAES256CBC:
+ key, eci, err = encryptAESCBC(content, nil)
+ case EncryptionAlgorithmAES128GCM:
+ fallthrough
+ case EncryptionAlgorithmAES256GCM:
+ key, eci, err = encryptAESGCM(content, nil)
+
+ default:
+ return nil, ErrUnsupportedEncryptionAlgorithm
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ // Prepare each recipient's encrypted cipher key
+ recipientInfos := make([]recipientInfo, len(recipients))
+ for i, recipient := range recipients {
+ encrypted, err := encryptKey(key, recipient)
+ if err != nil {
+ return nil, err
+ }
+ ias, err := cert2issuerAndSerial(recipient)
+ if err != nil {
+ return nil, err
+ }
+ info := recipientInfo{
+ Version: 0,
+ IssuerAndSerialNumber: ias,
+ KeyEncryptionAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: OIDEncryptionAlgorithmRSA,
+ },
+ EncryptedKey: encrypted,
+ }
+ recipientInfos[i] = info
+ }
+
+ // Prepare envelope content
+ envelope := envelopedData{
+ EncryptedContentInfo: *eci,
+ Version: 0,
+ RecipientInfos: recipientInfos,
+ }
+ innerContent, err := asn1.Marshal(envelope)
+ if err != nil {
+ return nil, err
+ }
+
+ // Prepare outer payload structure
+ wrapper := contentInfo{
+ ContentType: OIDEnvelopedData,
+ Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
+ }
+
+ return asn1.Marshal(wrapper)
+}
+
+// EncryptUsingPSK creates and returns an encrypted data PKCS7 structure,
+// encrypted using caller provided pre-shared secret.
+func EncryptUsingPSK(content []byte, key []byte) ([]byte, error) {
+ var eci *encryptedContentInfo
+ var err error
+
+ if key == nil {
+ return nil, ErrPSKNotProvided
+ }
+
+ // Apply chosen symmetric encryption method
+ switch ContentEncryptionAlgorithm {
+ case EncryptionAlgorithmDESCBC:
+ _, eci, err = encryptDESCBC(content, key)
+
+ case EncryptionAlgorithmAES128GCM:
+ fallthrough
+ case EncryptionAlgorithmAES256GCM:
+ _, eci, err = encryptAESGCM(content, key)
+
+ default:
+ return nil, ErrUnsupportedEncryptionAlgorithm
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ // Prepare encrypted-data content
+ ed := encryptedData{
+ Version: 0,
+ EncryptedContentInfo: *eci,
+ }
+ innerContent, err := asn1.Marshal(ed)
+ if err != nil {
+ return nil, err
+ }
+
+ // Prepare outer payload structure
+ wrapper := contentInfo{
+ ContentType: OIDEncryptedData,
+ Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
+ }
+
+ return asn1.Marshal(wrapper)
+}
+
+func marshalEncryptedContent(content []byte) asn1.RawValue {
+ asn1Content, _ := asn1.Marshal(content)
+ return asn1.RawValue{Tag: 0, Class: 2, Bytes: asn1Content, IsCompound: true}
+}
+
+func encryptKey(key []byte, recipient *x509.Certificate) ([]byte, error) {
+ if pub := recipient.PublicKey.(*rsa.PublicKey); pub != nil {
+ return rsa.EncryptPKCS1v15(rand.Reader, pub, key)
+ }
+ return nil, ErrUnsupportedAlgorithm
+}
+
+func pad(data []byte, blocklen int) ([]byte, error) {
+ if blocklen < 1 {
+ return nil, fmt.Errorf("invalid blocklen %d", blocklen)
+ }
+ padlen := blocklen - (len(data) % blocklen)
+ if padlen == 0 {
+ padlen = blocklen
+ }
+ pad := bytes.Repeat([]byte{byte(padlen)}, padlen)
+ return append(data, pad...), nil
+}
diff --git a/vendor/github.com/digitorus/pkcs7/pkcs7.go b/vendor/github.com/digitorus/pkcs7/pkcs7.go
new file mode 100644
index 000000000000..aca3c53f4322
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/pkcs7.go
@@ -0,0 +1,302 @@
+// Package pkcs7 implements parsing and generation of some PKCS#7 structures.
+package pkcs7
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/ed25519"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "sort"
+
+ _ "crypto/sha1" // for crypto.SHA1
+)
+
+// PKCS7 Represents a PKCS7 structure
+type PKCS7 struct {
+ Content []byte
+ Certificates []*x509.Certificate
+ CRLs []pkix.CertificateList
+ Signers []signerInfo
+ raw interface{}
+}
+
+type contentInfo struct {
+ ContentType asn1.ObjectIdentifier
+ Content asn1.RawValue `asn1:"explicit,optional,tag:0"`
+}
+
+// ErrUnsupportedContentType is returned when a PKCS7 content is not supported.
+// Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2),
+// and Enveloped Data are supported (1.2.840.113549.1.7.3)
+var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")
+
+type unsignedData []byte
+
+var (
+ // Signed Data OIDs
+ OIDData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
+ OIDSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
+ OIDEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3}
+ OIDEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}
+ OIDAttributeContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3}
+ OIDAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4}
+ OIDAttributeSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5}
+
+ // Digest Algorithms
+ OIDDigestAlgorithmSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
+ OIDDigestAlgorithmSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
+ OIDDigestAlgorithmSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
+ OIDDigestAlgorithmSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
+
+ OIDDigestAlgorithmDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+ OIDDigestAlgorithmDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+
+ OIDDigestAlgorithmECDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+ OIDDigestAlgorithmECDSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+ OIDDigestAlgorithmECDSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+ OIDDigestAlgorithmECDSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
+
+ // Signature Algorithms
+ OIDEncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
+ OIDEncryptionAlgorithmRSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+ OIDEncryptionAlgorithmRSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+ OIDEncryptionAlgorithmRSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+ OIDEncryptionAlgorithmRSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+
+ OIDEncryptionAlgorithmECDSAP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
+ OIDEncryptionAlgorithmECDSAP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
+ OIDEncryptionAlgorithmECDSAP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
+
+ OIDEncryptionAlgorithmEDDSA25519 = asn1.ObjectIdentifier{1, 3, 101, 112}
+
+ // Encryption Algorithms
+ OIDEncryptionAlgorithmDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7}
+ OIDEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}
+ OIDEncryptionAlgorithmAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
+ OIDEncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6}
+ OIDEncryptionAlgorithmAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
+ OIDEncryptionAlgorithmAES256GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 46}
+)
+
+func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) {
+ switch {
+ case oid.Equal(OIDDigestAlgorithmSHA1), oid.Equal(OIDDigestAlgorithmECDSASHA1),
+ oid.Equal(OIDDigestAlgorithmDSA), oid.Equal(OIDDigestAlgorithmDSASHA1),
+ oid.Equal(OIDEncryptionAlgorithmRSA):
+ return crypto.SHA1, nil
+ case oid.Equal(OIDDigestAlgorithmSHA256), oid.Equal(OIDDigestAlgorithmECDSASHA256):
+ return crypto.SHA256, nil
+ case oid.Equal(OIDDigestAlgorithmSHA384), oid.Equal(OIDDigestAlgorithmECDSASHA384):
+ return crypto.SHA384, nil
+ case oid.Equal(OIDDigestAlgorithmSHA512), oid.Equal(OIDDigestAlgorithmECDSASHA512):
+ return crypto.SHA512, nil
+ }
+ return crypto.Hash(0), ErrUnsupportedAlgorithm
+}
+
+// GetDigestOIDForSignatureAlgorithm takes an x509.SignatureAlgorithm
+// and returns the corresponding OID digest algorithm
+func GetDigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error) {
+ switch digestAlg {
+ case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
+ return OIDDigestAlgorithmSHA1, nil
+ case x509.SHA256WithRSA, x509.ECDSAWithSHA256:
+ return OIDDigestAlgorithmSHA256, nil
+ case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
+ return OIDDigestAlgorithmSHA384, nil
+ case x509.SHA512WithRSA, x509.ECDSAWithSHA512, x509.PureEd25519:
+ return OIDDigestAlgorithmSHA512, nil
+ }
+ return nil, fmt.Errorf("pkcs7: cannot convert hash to oid, unknown hash algorithm")
+}
+
+// getOIDForEncryptionAlgorithm takes a private key or signer and
+// the OID of a digest algorithm to return the appropriate signerInfo.DigestEncryptionAlgorithm
+func getOIDForEncryptionAlgorithm(keyOrSigner interface{}, OIDDigestAlg asn1.ObjectIdentifier) (asn1.ObjectIdentifier, error) {
+ _, ok := keyOrSigner.(*dsa.PrivateKey)
+ if ok {
+ return OIDDigestAlgorithmDSA, nil
+ }
+
+ signer, ok := keyOrSigner.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("pkcs7: key does not implement crypto.Signer")
+ }
+ switch signer.Public().(type) {
+ case *rsa.PublicKey:
+ switch {
+ default:
+ return OIDEncryptionAlgorithmRSA, nil
+ case OIDDigestAlg.Equal(OIDEncryptionAlgorithmRSA):
+ return OIDEncryptionAlgorithmRSA, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA1):
+ return OIDEncryptionAlgorithmRSASHA1, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA256):
+ return OIDEncryptionAlgorithmRSASHA256, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA384):
+ return OIDEncryptionAlgorithmRSASHA384, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA512):
+ return OIDEncryptionAlgorithmRSASHA512, nil
+ }
+ case *ecdsa.PublicKey:
+ switch {
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA1):
+ return OIDDigestAlgorithmECDSASHA1, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA256):
+ return OIDDigestAlgorithmECDSASHA256, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA384):
+ return OIDDigestAlgorithmECDSASHA384, nil
+ case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA512):
+ return OIDDigestAlgorithmECDSASHA512, nil
+ }
+ case ed25519.PublicKey:
+ return OIDEncryptionAlgorithmEDDSA25519, nil
+ }
+ return nil, fmt.Errorf("pkcs7: cannot convert encryption algorithm to oid, unknown key type %T", signer.Public())
+}
+
+// Parse decodes a DER encoded PKCS7 package
+func Parse(data []byte) (p7 *PKCS7, err error) {
+ if len(data) == 0 {
+ return nil, errors.New("pkcs7: input data is empty")
+ }
+ var info contentInfo
+ der, err := ber2der(data)
+ if err != nil {
+ return nil, err
+ }
+ rest, err := asn1.Unmarshal(der, &info)
+ if len(rest) > 0 {
+ err = asn1.SyntaxError{Msg: "trailing data"}
+ return
+ }
+ if err != nil {
+ return
+ }
+
+ // fmt.Printf("--> Content Type: %s", info.ContentType)
+ switch {
+ case info.ContentType.Equal(OIDSignedData):
+ return parseSignedData(info.Content.Bytes)
+ case info.ContentType.Equal(OIDEnvelopedData):
+ return parseEnvelopedData(info.Content.Bytes)
+ case info.ContentType.Equal(OIDEncryptedData):
+ return parseEncryptedData(info.Content.Bytes)
+ }
+ return nil, ErrUnsupportedContentType
+}
+
+func parseEnvelopedData(data []byte) (*PKCS7, error) {
+ var ed envelopedData
+ if _, err := asn1.Unmarshal(data, &ed); err != nil {
+ return nil, err
+ }
+ return &PKCS7{
+ raw: ed,
+ }, nil
+}
+
+func parseEncryptedData(data []byte) (*PKCS7, error) {
+ var ed encryptedData
+ if _, err := asn1.Unmarshal(data, &ed); err != nil {
+ return nil, err
+ }
+ return &PKCS7{
+ raw: ed,
+ }, nil
+}
+
+func (raw rawCertificates) Parse() ([]*x509.Certificate, error) {
+ if len(raw.Raw) == 0 {
+ return nil, nil
+ }
+
+ var val asn1.RawValue
+ if _, err := asn1.Unmarshal(raw.Raw, &val); err != nil {
+ return nil, err
+ }
+
+ return x509.ParseCertificates(val.Bytes)
+}
+
+func isCertMatchForIssuerAndSerial(cert *x509.Certificate, ias issuerAndSerial) bool {
+ return cert.SerialNumber.Cmp(ias.SerialNumber) == 0 && bytes.Equal(cert.RawIssuer, ias.IssuerName.FullBytes)
+}
+
+// Attribute represents a key value pair attribute. Value must be marshalable byte
+// `encoding/asn1`
+type Attribute struct {
+ Type asn1.ObjectIdentifier
+ Value interface{}
+}
+
+type attributes struct {
+ types []asn1.ObjectIdentifier
+ values []interface{}
+}
+
+// Add adds the attribute, maintaining insertion order
+func (attrs *attributes) Add(attrType asn1.ObjectIdentifier, value interface{}) {
+ attrs.types = append(attrs.types, attrType)
+ attrs.values = append(attrs.values, value)
+}
+
+type sortableAttribute struct {
+ SortKey []byte
+ Attribute attribute
+}
+
+type attributeSet []sortableAttribute
+
+func (sa attributeSet) Len() int {
+ return len(sa)
+}
+
+func (sa attributeSet) Less(i, j int) bool {
+ return bytes.Compare(sa[i].SortKey, sa[j].SortKey) < 0
+}
+
+func (sa attributeSet) Swap(i, j int) {
+ sa[i], sa[j] = sa[j], sa[i]
+}
+
+func (sa attributeSet) Attributes() []attribute {
+ attrs := make([]attribute, len(sa))
+ for i, attr := range sa {
+ attrs[i] = attr.Attribute
+ }
+ return attrs
+}
+
+func (attrs *attributes) ForMarshalling() ([]attribute, error) {
+ sortables := make(attributeSet, len(attrs.types))
+ for i := range sortables {
+ attrType := attrs.types[i]
+ attrValue := attrs.values[i]
+ asn1Value, err := asn1.Marshal(attrValue)
+ if err != nil {
+ return nil, err
+ }
+ attr := attribute{
+ Type: attrType,
+ Value: asn1.RawValue{Tag: 17, IsCompound: true, Bytes: asn1Value}, // 17 == SET tag
+ }
+ encoded, err := asn1.Marshal(attr)
+ if err != nil {
+ return nil, err
+ }
+ sortables[i] = sortableAttribute{
+ SortKey: encoded,
+ Attribute: attr,
+ }
+ }
+ sort.Sort(sortables)
+ return sortables.Attributes(), nil
+}
diff --git a/vendor/github.com/digitorus/pkcs7/sign.go b/vendor/github.com/digitorus/pkcs7/sign.go
new file mode 100644
index 000000000000..6cfd2ab9c263
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/sign.go
@@ -0,0 +1,456 @@
+package pkcs7
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ed25519"
+ "crypto/rand"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "math/big"
+ "time"
+)
+
+// SignedData is an opaque data structure for creating signed data payloads
+type SignedData struct {
+ sd signedData
+ certs []*x509.Certificate
+ data, messageDigest []byte
+ digestOid asn1.ObjectIdentifier
+ encryptionOid asn1.ObjectIdentifier
+}
+
+// NewSignedData takes data and initializes a PKCS7 SignedData struct that is
+// ready to be signed via AddSigner. The digest algorithm is set to SHA1 by default
+// and can be changed by calling SetDigestAlgorithm.
+func NewSignedData(data []byte) (*SignedData, error) {
+ content, err := asn1.Marshal(data)
+ if err != nil {
+ return nil, err
+ }
+ ci := contentInfo{
+ ContentType: OIDData,
+ Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
+ }
+ sd := signedData{
+ ContentInfo: ci,
+ Version: 1,
+ }
+ return &SignedData{sd: sd, data: data, digestOid: OIDDigestAlgorithmSHA1}, nil
+}
+
+// SignerInfoConfig are optional values to include when adding a signer
+type SignerInfoConfig struct {
+ ExtraSignedAttributes []Attribute
+ ExtraUnsignedAttributes []Attribute
+ SkipCertificates bool
+}
+
+type signedData struct {
+ Version int `asn1:"default:1"`
+ DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"`
+ ContentInfo contentInfo
+ Certificates rawCertificates `asn1:"optional,tag:0"`
+ CRLs []pkix.CertificateList `asn1:"optional,tag:1"`
+ SignerInfos []signerInfo `asn1:"set"`
+}
+
+type signerInfo struct {
+ Version int `asn1:"default:1"`
+ IssuerAndSerialNumber issuerAndSerial
+ DigestAlgorithm pkix.AlgorithmIdentifier
+ AuthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:0"`
+ DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
+ EncryptedDigest []byte
+ UnauthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:1"`
+}
+
+type attribute struct {
+ Type asn1.ObjectIdentifier
+ Value asn1.RawValue `asn1:"set"`
+}
+
+func marshalAttributes(attrs []attribute) ([]byte, error) {
+ encodedAttributes, err := asn1.Marshal(struct {
+ A []attribute `asn1:"set"`
+ }{A: attrs})
+ if err != nil {
+ return nil, err
+ }
+
+ // Remove the leading sequence octets
+ var raw asn1.RawValue
+ asn1.Unmarshal(encodedAttributes, &raw)
+ return raw.Bytes, nil
+}
+
+type rawCertificates struct {
+ Raw asn1.RawContent
+}
+
+type issuerAndSerial struct {
+ IssuerName asn1.RawValue
+ SerialNumber *big.Int
+}
+
+// SetDigestAlgorithm sets the digest algorithm to be used in the signing process.
+//
+// This should be called before adding signers
+func (sd *SignedData) SetDigestAlgorithm(d asn1.ObjectIdentifier) {
+ sd.digestOid = d
+}
+
+// SetEncryptionAlgorithm sets the encryption algorithm to be used in the signing process.
+//
+// This should be called before adding signers
+func (sd *SignedData) SetEncryptionAlgorithm(d asn1.ObjectIdentifier) {
+ sd.encryptionOid = d
+}
+
+// AddSigner is a wrapper around AddSignerChain() that adds a signer without any parent. The signer can
+// either be a crypto.Signer or crypto.PrivateKey.
+func (sd *SignedData) AddSigner(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error {
+ var parents []*x509.Certificate
+ return sd.AddSignerChain(ee, keyOrSigner, parents, config)
+}
+
+// AddSignerChain signs attributes about the content and adds certificates
+// and signers infos to the Signed Data. The certificate and private key
+// of the end-entity signer are used to issue the signature, and any
+// parent of that end-entity that need to be added to the list of
+// certifications can be specified in the parents slice.
+//
+// The signature algorithm used to hash the data is the one of the end-entity
+// certificate. The signer can be either a crypto.Signer or crypto.PrivateKey.
+func (sd *SignedData) AddSignerChain(ee *x509.Certificate, keyOrSigner interface{}, parents []*x509.Certificate, config SignerInfoConfig) error {
+ // Following RFC 2315, 9.2 SignerInfo type, the distinguished name of
+ // the issuer of the end-entity signer is stored in the issuerAndSerialNumber
+ // section of the SignedData.SignerInfo, alongside the serial number of
+ // the end-entity.
+ var ias issuerAndSerial
+ ias.SerialNumber = ee.SerialNumber
+ if len(parents) == 0 {
+ // no parent, the issuer is the end-entity cert itself
+ ias.IssuerName = asn1.RawValue{FullBytes: ee.RawIssuer}
+ } else {
+ err := verifyPartialChain(ee, parents)
+ if err != nil {
+ return err
+ }
+ // the first parent is the issuer
+ ias.IssuerName = asn1.RawValue{FullBytes: parents[0].RawSubject}
+ }
+ sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers,
+ pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
+ )
+ hash, err := getHashForOID(sd.digestOid)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
+ h.Write(sd.data)
+ sd.messageDigest = h.Sum(nil)
+ encryptionOid, err := getOIDForEncryptionAlgorithm(keyOrSigner, sd.digestOid)
+ if err != nil {
+ return err
+ }
+ attrs := &attributes{}
+ attrs.Add(OIDAttributeContentType, sd.sd.ContentInfo.ContentType)
+ attrs.Add(OIDAttributeMessageDigest, sd.messageDigest)
+ attrs.Add(OIDAttributeSigningTime, time.Now().UTC())
+ for _, attr := range config.ExtraSignedAttributes {
+ attrs.Add(attr.Type, attr.Value)
+ }
+ finalAttrs, err := attrs.ForMarshalling()
+ if err != nil {
+ return err
+ }
+ unsignedAttrs := &attributes{}
+ for _, attr := range config.ExtraUnsignedAttributes {
+ unsignedAttrs.Add(attr.Type, attr.Value)
+ }
+ finalUnsignedAttrs, err := unsignedAttrs.ForMarshalling()
+ if err != nil {
+ return err
+ }
+ // create signature of signed attributes
+ signature, err := signAttributes(finalAttrs, keyOrSigner, hash)
+ if err != nil {
+ return err
+ }
+ signerInfo := signerInfo{
+ AuthenticatedAttributes: finalAttrs,
+ UnauthenticatedAttributes: finalUnsignedAttrs,
+ DigestAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
+ DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: encryptionOid},
+ IssuerAndSerialNumber: ias,
+ EncryptedDigest: signature,
+ Version: 1,
+ }
+ if !config.SkipCertificates {
+ sd.certs = append(sd.certs, ee)
+ if len(parents) > 0 {
+ sd.certs = append(sd.certs, parents...)
+ }
+ }
+ sd.sd.SignerInfos = append(sd.sd.SignerInfos, signerInfo)
+ return nil
+}
+
+// SignWithoutAttr issues a signature on the content of the pkcs7 SignedData.
+// Unlike AddSigner/AddSignerChain, it calculates the digest on the data alone
+// and does not include any signed attributes like timestamp and so on.
+//
+// This function is needed to sign old Android APKs, something you probably
+// shouldn't do unless you're maintaining backward compatibility for old
+// applications. The signer can be either a crypto.Signer or crypto.PrivateKey.
+func (sd *SignedData) SignWithoutAttr(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error {
+ var signature []byte
+ sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers, pkix.AlgorithmIdentifier{Algorithm: sd.digestOid})
+ hash, err := getHashForOID(sd.digestOid)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
+ h.Write(sd.data)
+ sd.messageDigest = h.Sum(nil)
+
+ switch pkey := keyOrSigner.(type) {
+ case *dsa.PrivateKey:
+ // dsa doesn't implement crypto.Signer so we make a special case
+ // https://github.com/golang/go/issues/27889
+ r, s, err := dsa.Sign(rand.Reader, pkey, sd.messageDigest)
+ if err != nil {
+ return err
+ }
+ signature, err = asn1.Marshal(dsaSignature{r, s})
+ if err != nil {
+ return err
+ }
+ default:
+ signer, ok := keyOrSigner.(crypto.Signer)
+ if !ok {
+ return errors.New("pkcs7: private key does not implement crypto.Signer")
+ }
+
+ // special case for Ed25519, which hashes as part of the signing algorithm
+ _, ok = signer.Public().(ed25519.PublicKey)
+ if ok {
+ signature, err = signer.Sign(rand.Reader, sd.data, crypto.Hash(0))
+ } else {
+ signature, err = signer.Sign(rand.Reader, sd.messageDigest, hash)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ var ias issuerAndSerial
+ ias.SerialNumber = ee.SerialNumber
+ // no parent, the issue is the end-entity cert itself
+ ias.IssuerName = asn1.RawValue{FullBytes: ee.RawIssuer}
+ if sd.encryptionOid == nil {
+ // if the encryption algorithm wasn't set by SetEncryptionAlgorithm,
+ // infer it from the digest algorithm
+ sd.encryptionOid, err = getOIDForEncryptionAlgorithm(keyOrSigner, sd.digestOid)
+ }
+ if err != nil {
+ return err
+ }
+ signerInfo := signerInfo{
+ DigestAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
+ DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.encryptionOid},
+ IssuerAndSerialNumber: ias,
+ EncryptedDigest: signature,
+ Version: 1,
+ }
+ // create signature of signed attributes
+ sd.certs = append(sd.certs, ee)
+ sd.sd.SignerInfos = append(sd.sd.SignerInfos, signerInfo)
+ return nil
+}
+
+func (si *signerInfo) SetUnauthenticatedAttributes(extraUnsignedAttrs []Attribute) error {
+ unsignedAttrs := &attributes{}
+ for _, attr := range extraUnsignedAttrs {
+ unsignedAttrs.Add(attr.Type, attr.Value)
+ }
+ finalUnsignedAttrs, err := unsignedAttrs.ForMarshalling()
+ if err != nil {
+ return err
+ }
+
+ si.UnauthenticatedAttributes = finalUnsignedAttrs
+
+ return nil
+}
+
+// AddCertificate adds the certificate to the payload. Useful for parent certificates
+func (sd *SignedData) AddCertificate(cert *x509.Certificate) {
+ sd.certs = append(sd.certs, cert)
+}
+
+// SetContentType sets the content type of the SignedData. For example to specify the
+// content type of a time-stamp token according to RFC 3161 section 2.4.2.
+func (sd *SignedData) SetContentType(contentType asn1.ObjectIdentifier) {
+ sd.sd.ContentInfo.ContentType = contentType
+}
+
+// Detach removes content from the signed data struct to make it a detached signature.
+// This must be called right before Finish()
+func (sd *SignedData) Detach() {
+ sd.sd.ContentInfo = contentInfo{ContentType: OIDData}
+}
+
+// GetSignedData returns the private Signed Data
+func (sd *SignedData) GetSignedData() *signedData {
+ return &sd.sd
+}
+
+// Finish marshals the content and its signers
+func (sd *SignedData) Finish() ([]byte, error) {
+ sd.sd.Certificates = marshalCertificates(sd.certs)
+ inner, err := asn1.Marshal(sd.sd)
+ if err != nil {
+ return nil, err
+ }
+ outer := contentInfo{
+ ContentType: OIDSignedData,
+ Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
+ }
+ return asn1.Marshal(outer)
+}
+
+// RemoveAuthenticatedAttributes removes authenticated attributes from signedData
+// similar to OpenSSL's PKCS7_NOATTR or -noattr flags
+func (sd *SignedData) RemoveAuthenticatedAttributes() {
+ for i := range sd.sd.SignerInfos {
+ sd.sd.SignerInfos[i].AuthenticatedAttributes = nil
+ }
+}
+
+// RemoveUnauthenticatedAttributes removes unauthenticated attributes from signedData
+func (sd *SignedData) RemoveUnauthenticatedAttributes() {
+ for i := range sd.sd.SignerInfos {
+ sd.sd.SignerInfos[i].UnauthenticatedAttributes = nil
+ }
+}
+
+// verifyPartialChain checks that a given cert is issued by the first parent in the list,
+// then continue down the path. It doesn't require the last parent to be a root CA,
+// or to be trusted in any truststore. It simply verifies that the chain provided, albeit
+// partial, makes sense.
+func verifyPartialChain(cert *x509.Certificate, parents []*x509.Certificate) error {
+ if len(parents) == 0 {
+ return fmt.Errorf("pkcs7: zero parents provided to verify the signature of certificate %q", cert.Subject.CommonName)
+ }
+ err := cert.CheckSignatureFrom(parents[0])
+ if err != nil {
+ return fmt.Errorf("pkcs7: certificate signature from parent is invalid: %v", err)
+ }
+ if len(parents) == 1 {
+ // there is no more parent to check, return
+ return nil
+ }
+ return verifyPartialChain(parents[0], parents[1:])
+}
+
+func cert2issuerAndSerial(cert *x509.Certificate) (issuerAndSerial, error) {
+ var ias issuerAndSerial
+ // The issuer RDNSequence has to match exactly the sequence in the certificate
+ // We cannot use cert.Issuer.ToRDNSequence() here since it mangles the sequence
+ ias.IssuerName = asn1.RawValue{FullBytes: cert.RawIssuer}
+ ias.SerialNumber = cert.SerialNumber
+
+ return ias, nil
+}
+
+// signs the DER encoded form of the attributes with the private key
+func signAttributes(attrs []attribute, keyOrSigner interface{}, digestAlg crypto.Hash) ([]byte, error) {
+ attrBytes, err := marshalAttributes(attrs)
+ if err != nil {
+ return nil, err
+ }
+ h := digestAlg.New()
+ h.Write(attrBytes)
+ hash := h.Sum(nil)
+
+ // dsa doesn't implement crypto.Signer so we make a special case
+ // https://github.com/golang/go/issues/27889
+ switch pkey := keyOrSigner.(type) {
+ case *dsa.PrivateKey:
+ r, s, err := dsa.Sign(rand.Reader, pkey, hash)
+ if err != nil {
+ return nil, err
+ }
+ return asn1.Marshal(dsaSignature{r, s})
+ }
+
+ signer, ok := keyOrSigner.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("pkcs7: private key does not implement crypto.Signer")
+ }
+
+ // special case for Ed25519, which hashes as part of the signing algorithm
+ _, ok = signer.Public().(ed25519.PublicKey)
+ if ok {
+ return signer.Sign(rand.Reader, attrBytes, crypto.Hash(0))
+ }
+
+ return signer.Sign(rand.Reader, hash, digestAlg)
+}
+
+type dsaSignature struct {
+ R, S *big.Int
+}
+
+// concats and wraps the certificates in the RawValue structure
+func marshalCertificates(certs []*x509.Certificate) rawCertificates {
+ var buf bytes.Buffer
+ for _, cert := range certs {
+ buf.Write(cert.Raw)
+ }
+ rawCerts, _ := marshalCertificateBytes(buf.Bytes())
+ return rawCerts
+}
+
+// Even though, the tag & length are stripped out during marshalling the
+// RawContent, we have to encode it into the RawContent. If its missing,
+// then `asn1.Marshal()` will strip out the certificate wrapper instead.
+func marshalCertificateBytes(certs []byte) (rawCertificates, error) {
+ var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true}
+ b, err := asn1.Marshal(val)
+ if err != nil {
+ return rawCertificates{}, err
+ }
+ return rawCertificates{Raw: b}, nil
+}
+
+// DegenerateCertificate creates a signed data structure containing only the
+// provided certificate or certificate chain.
+func DegenerateCertificate(cert []byte) ([]byte, error) {
+ rawCert, err := marshalCertificateBytes(cert)
+ if err != nil {
+ return nil, err
+ }
+ emptyContent := contentInfo{ContentType: OIDData}
+ sd := signedData{
+ Version: 1,
+ ContentInfo: emptyContent,
+ Certificates: rawCert,
+ CRLs: []pkix.CertificateList{},
+ }
+ content, err := asn1.Marshal(sd)
+ if err != nil {
+ return nil, err
+ }
+ signedContent := contentInfo{
+ ContentType: OIDSignedData,
+ Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
+ }
+ return asn1.Marshal(signedContent)
+}
diff --git a/vendor/github.com/digitorus/pkcs7/verify.go b/vendor/github.com/digitorus/pkcs7/verify.go
new file mode 100644
index 000000000000..d0e4f0429d6d
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/verify.go
@@ -0,0 +1,370 @@
+package pkcs7
+
+import (
+ "crypto/subtle"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "time"
+)
+
+// Verify is a wrapper around VerifyWithChain() that initializes an empty
+// trust store, effectively disabling certificate verification when validating
+// a signature.
+func (p7 *PKCS7) Verify() (err error) {
+ return p7.VerifyWithChain(nil)
+}
+
+// VerifyWithChain checks the signatures of a PKCS7 object.
+//
+// If truststore is not nil, it also verifies the chain of trust of
+// the end-entity signer cert to one of the roots in the
+// truststore. When the PKCS7 object includes the signing time
+// authenticated attr it verifies the chain at that time and UTC now
+// otherwise.
+func (p7 *PKCS7) VerifyWithChain(truststore *x509.CertPool) (err error) {
+ intermediates := x509.NewCertPool()
+ for _, cert := range(p7.Certificates) {
+ intermediates.AddCert(cert)
+ }
+
+ opts := x509.VerifyOptions{
+ Roots: truststore,
+ Intermediates: intermediates,
+ }
+
+ return p7.VerifyWithOpts(opts)
+}
+
+// VerifyWithChainAtTime checks the signatures of a PKCS7 object.
+//
+// If truststore is not nil, it also verifies the chain of trust of
+// the end-entity signer cert to a root in the truststore at
+// currentTime. It does not use the signing time authenticated
+// attribute.
+func (p7 *PKCS7) VerifyWithChainAtTime(truststore *x509.CertPool, currentTime time.Time) (err error) {
+ intermediates := x509.NewCertPool()
+ for _, cert := range(p7.Certificates) {
+ intermediates.AddCert(cert)
+ }
+
+ opts := x509.VerifyOptions{
+ Roots: truststore,
+ Intermediates: intermediates,
+ CurrentTime: currentTime,
+ }
+
+ return p7.VerifyWithOpts(opts)
+}
+
+// VerifyWithOpts checks the signatures of a PKCS7 object.
+//
+// It accepts x509.VerifyOptions as a parameter.
+// This struct contains a root certificate pool, an intermedate certificate pool,
+// an optional list of EKUs, and an optional time that certificates should be
+// checked as being valid during.
+
+// If VerifyOpts.Roots is not nil it verifies the chain of trust of
+// the end-entity signer cert to one of the roots in the
+// truststore. When the PKCS7 object includes the signing time
+// authenticated attr it verifies the chain at that time and UTC now
+// otherwise.
+func (p7 *PKCS7) VerifyWithOpts(opts x509.VerifyOptions) (err error) {
+ // if KeyUsage isn't set, default to ExtKeyUsageAny
+ if opts.KeyUsages == nil {
+ opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
+ }
+
+ if len(p7.Signers) == 0 {
+ return errors.New("pkcs7: Message has no signers")
+ }
+
+ // if opts.CurrentTime is not set, call verifySignature,
+ // which will verify the leaf certificate with the current time
+ if opts.CurrentTime.IsZero() {
+ for _, signer := range p7.Signers {
+ if err := verifySignature(p7, signer, opts); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ // if opts.CurrentTime is set, call verifySignatureAtTime,
+ // which will verify the leaf certificate with opts.CurrentTime
+ for _, signer := range p7.Signers {
+ if err := verifySignatureAtTime(p7, signer, opts); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func verifySignatureAtTime(p7 *PKCS7, signer signerInfo, opts x509.VerifyOptions) (err error) {
+ signedData := p7.Content
+ ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
+ if ee == nil {
+ return errors.New("pkcs7: No certificate for signer")
+ }
+ if len(signer.AuthenticatedAttributes) > 0 {
+ // TODO(fullsailor): First check the content type match
+ var (
+ digest []byte
+ signingTime time.Time
+ )
+ err := unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeMessageDigest, &digest)
+ if err != nil {
+ return err
+ }
+ hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
+ h.Write(p7.Content)
+ computed := h.Sum(nil)
+ if subtle.ConstantTimeCompare(digest, computed) != 1 {
+ return &MessageDigestMismatchError{
+ ExpectedDigest: digest,
+ ActualDigest: computed,
+ }
+ }
+ signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
+ if err != nil {
+ return err
+ }
+ err = unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeSigningTime, &signingTime)
+ if err == nil {
+ // signing time found, performing validity check
+ if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) {
+ return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q",
+ signingTime.Format(time.RFC3339),
+ ee.NotBefore.Format(time.RFC3339),
+ ee.NotAfter.Format(time.RFC3339))
+ }
+ }
+ }
+ if opts.Roots != nil {
+ _, err = ee.Verify(opts)
+ if err != nil {
+ return fmt.Errorf("pkcs7: failed to verify certificate chain: %v", err)
+ }
+ }
+ sigalg, err := getSignatureAlgorithm(signer.DigestEncryptionAlgorithm, signer.DigestAlgorithm)
+ if err != nil {
+ return err
+ }
+ return ee.CheckSignature(sigalg, signedData, signer.EncryptedDigest)
+}
+
+func verifySignature(p7 *PKCS7, signer signerInfo, opts x509.VerifyOptions) (err error) {
+ signedData := p7.Content
+ ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
+ if ee == nil {
+ return errors.New("pkcs7: No certificate for signer")
+ }
+ signingTime := time.Now().UTC()
+ if len(signer.AuthenticatedAttributes) > 0 {
+ // TODO(fullsailor): First check the content type match
+ var digest []byte
+ err := unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeMessageDigest, &digest)
+ if err != nil {
+ return err
+ }
+ hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
+ h.Write(p7.Content)
+ computed := h.Sum(nil)
+ if subtle.ConstantTimeCompare(digest, computed) != 1 {
+ return &MessageDigestMismatchError{
+ ExpectedDigest: digest,
+ ActualDigest: computed,
+ }
+ }
+ signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
+ if err != nil {
+ return err
+ }
+ err = unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeSigningTime, &signingTime)
+ if err == nil {
+ // signing time found, performing validity check
+ if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) {
+ return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q",
+ signingTime.Format(time.RFC3339),
+ ee.NotBefore.Format(time.RFC3339),
+ ee.NotAfter.Format(time.RFC3339))
+ }
+ }
+ }
+ if opts.Roots != nil {
+ opts.CurrentTime = signingTime
+ _, err = ee.Verify(opts)
+ if err != nil {
+ return fmt.Errorf("pkcs7: failed to verify certificate chain: %v", err)
+ }
+ }
+ sigalg, err := getSignatureAlgorithm(signer.DigestEncryptionAlgorithm, signer.DigestAlgorithm)
+ if err != nil {
+ return err
+ }
+ return ee.CheckSignature(sigalg, signedData, signer.EncryptedDigest)
+}
+
+// GetOnlySigner returns an x509.Certificate for the first signer of the signed
+// data payload. If there are more or less than one signer, nil is returned
+func (p7 *PKCS7) GetOnlySigner() *x509.Certificate {
+ if len(p7.Signers) != 1 {
+ return nil
+ }
+ signer := p7.Signers[0]
+ return getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
+}
+
+// UnmarshalSignedAttribute decodes a single attribute from the signer info
+func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error {
+ sd, ok := p7.raw.(signedData)
+ if !ok {
+ return errors.New("pkcs7: payload is not signedData content")
+ }
+ if len(sd.SignerInfos) < 1 {
+ return errors.New("pkcs7: payload has no signers")
+ }
+ attributes := sd.SignerInfos[0].AuthenticatedAttributes
+ return unmarshalAttribute(attributes, attributeType, out)
+}
+
+func parseSignedData(data []byte) (*PKCS7, error) {
+ var sd signedData
+ asn1.Unmarshal(data, &sd)
+ certs, err := sd.Certificates.Parse()
+ if err != nil {
+ return nil, err
+ }
+ // fmt.Printf("--> Signed Data Version %d\n", sd.Version)
+
+ var compound asn1.RawValue
+ var content unsignedData
+
+ // The Content.Bytes maybe empty on PKI responses.
+ if len(sd.ContentInfo.Content.Bytes) > 0 {
+ if _, err := asn1.Unmarshal(sd.ContentInfo.Content.Bytes, &compound); err != nil {
+ return nil, err
+ }
+ }
+ // Compound octet string
+ if compound.IsCompound {
+ if compound.Tag == 4 {
+ if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil {
+ return nil, err
+ }
+ } else {
+ content = compound.Bytes
+ }
+ } else {
+ // assuming this is tag 04
+ content = compound.Bytes
+ }
+ return &PKCS7{
+ Content: content,
+ Certificates: certs,
+ CRLs: sd.CRLs,
+ Signers: sd.SignerInfos,
+ raw: sd}, nil
+}
+
+// MessageDigestMismatchError is returned when the signer data digest does not
+// match the computed digest for the contained content
+type MessageDigestMismatchError struct {
+ ExpectedDigest []byte
+ ActualDigest []byte
+}
+
+func (err *MessageDigestMismatchError) Error() string {
+ return fmt.Sprintf("pkcs7: Message digest mismatch\n\tExpected: %X\n\tActual : %X", err.ExpectedDigest, err.ActualDigest)
+}
+
+func getSignatureAlgorithm(digestEncryption, digest pkix.AlgorithmIdentifier) (x509.SignatureAlgorithm, error) {
+ switch {
+ case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA1):
+ return x509.ECDSAWithSHA1, nil
+ case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA256):
+ return x509.ECDSAWithSHA256, nil
+ case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA384):
+ return x509.ECDSAWithSHA384, nil
+ case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA512):
+ return x509.ECDSAWithSHA512, nil
+ case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSA),
+ digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA1),
+ digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA256),
+ digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA384),
+ digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA512):
+ switch {
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
+ return x509.SHA1WithRSA, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
+ return x509.SHA256WithRSA, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA384):
+ return x509.SHA384WithRSA, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA512):
+ return x509.SHA512WithRSA, nil
+ default:
+ return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
+ digest.Algorithm.String(), digestEncryption.Algorithm.String())
+ }
+ case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmDSA),
+ digestEncryption.Algorithm.Equal(OIDDigestAlgorithmDSASHA1):
+ switch {
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
+ return x509.DSAWithSHA1, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
+ return x509.DSAWithSHA256, nil
+ default:
+ return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
+ digest.Algorithm.String(), digestEncryption.Algorithm.String())
+ }
+ case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP256),
+ digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP384),
+ digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP521):
+ switch {
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
+ return x509.ECDSAWithSHA1, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
+ return x509.ECDSAWithSHA256, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA384):
+ return x509.ECDSAWithSHA384, nil
+ case digest.Algorithm.Equal(OIDDigestAlgorithmSHA512):
+ return x509.ECDSAWithSHA512, nil
+ default:
+ return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
+ digest.Algorithm.String(), digestEncryption.Algorithm.String())
+ }
+ case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmEDDSA25519):
+ return x509.PureEd25519, nil
+ default:
+ return -1, fmt.Errorf("pkcs7: unsupported algorithm %q",
+ digestEncryption.Algorithm.String())
+ }
+}
+
+func getCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate {
+ for _, cert := range certs {
+ if isCertMatchForIssuerAndSerial(cert, ias) {
+ return cert
+ }
+ }
+ return nil
+}
+
+func unmarshalAttribute(attrs []attribute, attributeType asn1.ObjectIdentifier, out interface{}) error {
+ for _, attr := range attrs {
+ if attr.Type.Equal(attributeType) {
+ _, err := asn1.Unmarshal(attr.Value.Bytes, out)
+ return err
+ }
+ }
+ return errors.New("pkcs7: attribute type not in attributes")
+}
diff --git a/vendor/github.com/digitorus/pkcs7/verify_test_dsa.go b/vendor/github.com/digitorus/pkcs7/verify_test_dsa.go
new file mode 100644
index 000000000000..1eb05bc3eae6
--- /dev/null
+++ b/vendor/github.com/digitorus/pkcs7/verify_test_dsa.go
@@ -0,0 +1,182 @@
+// +build go1.11 go1.12 go1.13 go1.14 go1.15
+
+package pkcs7
+
+import (
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "testing"
+)
+
+func TestVerifyEC2(t *testing.T) {
+ fixture := UnmarshalDSATestFixture(EC2IdentityDocumentFixture)
+ p7, err := Parse(fixture.Input)
+ if err != nil {
+ t.Errorf("Parse encountered unexpected error: %v", err)
+ }
+ p7.Certificates = []*x509.Certificate{fixture.Certificate}
+ if err := p7.Verify(); err != nil {
+ t.Errorf("Verify failed with error: %v", err)
+ }
+}
+
+var EC2IdentityDocumentFixture = `
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA
+JIAEggGmewogICJwcml2YXRlSXAiIDogIjE3Mi4zMC4wLjI1MiIsCiAgImRldnBh
+eVByb2R1Y3RDb2RlcyIgOiBudWxsLAogICJhdmFpbGFiaWxpdHlab25lIiA6ICJ1
+cy1lYXN0LTFhIiwKICAidmVyc2lvbiIgOiAiMjAxMC0wOC0zMSIsCiAgImluc3Rh
+bmNlSWQiIDogImktZjc5ZmU1NmMiLAogICJiaWxsaW5nUHJvZHVjdHMiIDogbnVs
+bCwKICAiaW5zdGFuY2VUeXBlIiA6ICJ0Mi5taWNybyIsCiAgImFjY291bnRJZCIg
+OiAiMTIxNjU5MDE0MzM0IiwKICAiaW1hZ2VJZCIgOiAiYW1pLWZjZTNjNjk2IiwK
+ICAicGVuZGluZ1RpbWUiIDogIjIwMTYtMDQtMDhUMDM6MDE6MzhaIiwKICAiYXJj
+aGl0ZWN0dXJlIiA6ICJ4ODZfNjQiLAogICJrZXJuZWxJZCIgOiBudWxsLAogICJy
+YW1kaXNrSWQiIDogbnVsbCwKICAicmVnaW9uIiA6ICJ1cy1lYXN0LTEiCn0AAAAA
+AAAxggEYMIIBFAIBATBpMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5n
+dG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2Vi
+IFNlcnZpY2VzIExMQwIJAJa6SNnlXhpnMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0B
+CQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNjA0MDgwMzAxNDRaMCMG
+CSqGSIb3DQEJBDEWBBTuUc28eBXmImAautC+wOjqcFCBVjAJBgcqhkjOOAQDBC8w
+LQIVAKA54NxGHWWCz5InboDmY/GHs33nAhQ6O/ZI86NwjA9Vz3RNMUJrUPU5tAAA
+AAAAAA==
+-----END PKCS7-----
+-----BEGIN CERTIFICATE-----
+MIIC7TCCAq0CCQCWukjZ5V4aZzAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw
+FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD
+VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xMjAxMDUxMjU2MTJaFw0z
+ODAxMDUxMjU2MTJaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u
+IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl
+cnZpY2VzIExMQzCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCjkvcS2bb1VQ4yt/5e
+ih5OO6kK/n1Lzllr7D8ZwtQP8fOEpp5E2ng+D6Ud1Z1gYipr58Kj3nssSNpI6bX3
+VyIQzK7wLclnd/YozqNNmgIyZecN7EglK9ITHJLP+x8FtUpt3QbyYXJdmVMegN6P
+hviYt5JH/nYl4hh3Pa1HJdskgQIVALVJ3ER11+Ko4tP6nwvHwh6+ERYRAoGBAI1j
+k+tkqMVHuAFcvAGKocTgsjJem6/5qomzJuKDmbJNu9Qxw3rAotXau8Qe+MBcJl/U
+hhy1KHVpCGl9fueQ2s6IL0CaO/buycU1CiYQk40KNHCcHfNiZbdlx1E9rpUp7bnF
+lRa2v1ntMX3caRVDdbtPEWmdxSCYsYFDk4mZrOLBA4GEAAKBgEbmeve5f8LIE/Gf
+MNmP9CM5eovQOGx5ho8WqD+aTebs+k2tn92BBPqeZqpWRa5P/+jrdKml1qx4llHW
+MXrs3IgIb6+hUIB+S8dz8/mmO0bpr76RoZVCXYab2CZedFut7qc3WUH9+EUAH5mw
+vSeDCOUMYQR7R9LINYwouHIziqQYMAkGByqGSM44BAMDLwAwLAIUWXBlk40xTwSw
+7HX32MxXYruse9ACFBNGmdX2ZBrVNGrN9N2f6ROk0k9K
+-----END CERTIFICATE-----`
+
+func TestDSASignWithOpenSSLAndVerify(t *testing.T) {
+ content := []byte(`
+A ship in port is safe,
+but that's not what ships are built for.
+-- Grace Hopper`)
+ // write the content to a temp file
+ tmpContentFile, err := ioutil.TempFile("", "TestDSASignWithOpenSSLAndVerify_content")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ioutil.WriteFile(tmpContentFile.Name(), content, 0755)
+
+ // write the signer cert to a temp file
+ tmpSignerCertFile, err := ioutil.TempFile("", "TestDSASignWithOpenSSLAndVerify_signer")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ioutil.WriteFile(tmpSignerCertFile.Name(), dsaPublicCert, 0755)
+
+ // write the signer key to a temp file
+ tmpSignerKeyFile, err := ioutil.TempFile("", "TestDSASignWithOpenSSLAndVerify_key")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ioutil.WriteFile(tmpSignerKeyFile.Name(), dsaPrivateKey, 0755)
+
+ tmpSignedFile, err := ioutil.TempFile("", "TestDSASignWithOpenSSLAndVerify_signature")
+ if err != nil {
+ t.Fatal(err)
+ }
+ // call openssl to sign the content
+ opensslCMD := exec.Command("openssl", "smime", "-sign", "-nodetach", "-md", "sha1",
+ "-in", tmpContentFile.Name(), "-out", tmpSignedFile.Name(),
+ "-signer", tmpSignerCertFile.Name(), "-inkey", tmpSignerKeyFile.Name(),
+ "-certfile", tmpSignerCertFile.Name(), "-outform", "PEM")
+ out, err := opensslCMD.CombinedOutput()
+ if err != nil {
+ t.Fatalf("openssl command failed with %s: %s", err, out)
+ }
+
+ // verify the signed content
+ pemSignature, err := ioutil.ReadFile(tmpSignedFile.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+ fmt.Printf("%s\n", pemSignature)
+ derBlock, _ := pem.Decode(pemSignature)
+ if derBlock == nil {
+ t.Fatalf("failed to read DER block from signature PEM %s", tmpSignedFile.Name())
+ }
+ p7, err := Parse(derBlock.Bytes)
+ if err != nil {
+ t.Fatalf("Parse encountered unexpected error: %v", err)
+ }
+ if err := p7.Verify(); err != nil {
+ t.Fatalf("Verify failed with error: %v", err)
+ }
+ os.Remove(tmpSignerCertFile.Name()) // clean up
+ os.Remove(tmpSignerKeyFile.Name()) // clean up
+ os.Remove(tmpContentFile.Name()) // clean up
+}
+
+var dsaPrivateKey = []byte(`-----BEGIN PRIVATE KEY-----
+MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdS
+PO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVCl
+pJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith
+1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7L
+vKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3
+zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
+g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUfW4aPdQBn9gJZp2KuNpzgHzvfsE=
+-----END PRIVATE KEY-----`)
+
+var dsaPublicCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIDOjCCAvWgAwIBAgIEPCY/UDANBglghkgBZQMEAwIFADBsMRAwDgYDVQQGEwdV
+bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD
+VQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3du
+MB4XDTE4MTAyMjEzNDMwN1oXDTQ2MDMwOTEzNDMwN1owbDEQMA4GA1UEBhMHVW5r
+bm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UE
+ChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCC
+AbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADD
+Hj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gE
+exAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/Ii
+Axmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4
+V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozI
+puE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4Vrl
+nwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDCriMPbEVBoRK4SOUeFwg7+VRf4TTp
+rcOQC9IVVoCjXzuWEGrp3ZI7YWJSpFnSch4lk29RH8O0HpI/NOzKnOBtnKr782pt
+1k/bJVMH9EaLd6MKnAVjrCDMYBB0MhebZ8QHY2elZZCWoqDYAcIDOsEx+m4NLErT
+ypPnjS5M0jm1PKMhMB8wHQYDVR0OBBYEFC0Yt5XdM0Kc95IX8NQ8XRssGPx7MA0G
+CWCGSAFlAwQDAgUAAzAAMC0CFQCIgQtrZZ9hdZG1ROhR5hc8nYEmbgIUAIlgC688
+qzy/7yePTlhlpj+ahMM=
+-----END CERTIFICATE-----`)
+
+type DSATestFixture struct {
+ Input []byte
+ Certificate *x509.Certificate
+}
+
+func UnmarshalDSATestFixture(testPEMBlock string) DSATestFixture {
+ var result DSATestFixture
+ var derBlock *pem.Block
+ var pemBlock = []byte(testPEMBlock)
+ for {
+ derBlock, pemBlock = pem.Decode(pemBlock)
+ if derBlock == nil {
+ break
+ }
+ switch derBlock.Type {
+ case "PKCS7":
+ result.Input = derBlock.Bytes
+ case "CERTIFICATE":
+ result.Certificate, _ = x509.ParseCertificate(derBlock.Bytes)
+ }
+ }
+
+ return result
+}
diff --git a/vendor/github.com/digitorus/timestamp/LICENSE b/vendor/github.com/digitorus/timestamp/LICENSE
new file mode 100644
index 000000000000..dac8634ce7be
--- /dev/null
+++ b/vendor/github.com/digitorus/timestamp/LICENSE
@@ -0,0 +1,25 @@
+BSD 2-Clause License
+
+Copyright (c) 2017, Digitorus B.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/digitorus/timestamp/README.md b/vendor/github.com/digitorus/timestamp/README.md
new file mode 100644
index 000000000000..d475e03f9931
--- /dev/null
+++ b/vendor/github.com/digitorus/timestamp/README.md
@@ -0,0 +1,13 @@
+# RFC3161 Time-Stamp Protocol (TSP) package for Go
+
+[](https://github.com/digitorus/timestamp/actions?query=workflow%3Abuild-and-test)
+[](https://github.com/digitorus/timestamp/actions?query=workflow%3Agolangci-lint)
+[](https://github.com/digitorus/timestamp/actions?query=workflow%3Acodeql)
+[](https://goreportcard.com/report/github.com/digitorus/timestamp)
+[](https://codecov.io/gh/digitorus/timestamp)
+[](https://pkg.go.dev/github.com/digitorus/timestamp)
+
+Time-Stamp Protocol (TSP) package for Go
+
+#### General
+The package timestamp implements the Time-Stamp Protocol (TSP) as specified in RFC3161 (Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)).
diff --git a/vendor/github.com/digitorus/timestamp/borrowed.go b/vendor/github.com/digitorus/timestamp/borrowed.go
new file mode 100644
index 000000000000..b379b7167f6f
--- /dev/null
+++ b/vendor/github.com/digitorus/timestamp/borrowed.go
@@ -0,0 +1,56 @@
+package timestamp
+
+import (
+ "crypto"
+ "encoding/asn1"
+)
+
+// TODO(vanbroup): taken from "golang.org/x/crypto/ocsp"
+// use directly from crypto/x509 when exported as suggested below.
+
+var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
+ crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
+ crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
+ crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
+ crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
+}
+
+// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form.
+func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
+ for hash, oid := range hashOIDs {
+ if oid.Equal(target) {
+ return hash
+ }
+ }
+ return crypto.Hash(0)
+}
+
+func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
+ for hash, oid := range hashOIDs {
+ if hash == target {
+ return oid
+ }
+ }
+ return nil
+}
+
+// TODO(vanbroup): taken from golang.org/x/crypto/x509
+// asn1BitLength returns the bit-length of bitString by considering the
+// most-significant bit in a byte to be the "first" bit. This convention
+// matches ASN.1, but differs from almost everything else.
+func asn1BitLength(bitString []byte) int {
+ bitLen := len(bitString) * 8
+
+ for i := range bitString {
+ b := bitString[len(bitString)-i-1]
+
+ for bit := uint(0); bit < 8; bit++ {
+ if (b>>bit)&1 == 1 {
+ return bitLen
+ }
+ bitLen--
+ }
+ }
+
+ return 0
+}
diff --git a/vendor/github.com/digitorus/timestamp/rfc3161_struct.go b/vendor/github.com/digitorus/timestamp/rfc3161_struct.go
new file mode 100644
index 000000000000..c5692253c53f
--- /dev/null
+++ b/vendor/github.com/digitorus/timestamp/rfc3161_struct.go
@@ -0,0 +1,75 @@
+package timestamp
+
+import (
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "math/big"
+ "time"
+)
+
+// http://www.ietf.org/rfc/rfc3161.txt
+// 2.4.1. Request Format
+type request struct {
+ Version int
+ MessageImprint messageImprint
+ ReqPolicy asn1.ObjectIdentifier `asn1:"optional"`
+ Nonce *big.Int `asn1:"optional"`
+ CertReq bool `asn1:"optional,default:false"`
+ Extensions []pkix.Extension `asn1:"tag:0,optional"`
+}
+
+type messageImprint struct {
+ HashAlgorithm pkix.AlgorithmIdentifier
+ HashedMessage []byte
+}
+
+// 2.4.2. Response Format
+type response struct {
+ Status pkiStatusInfo
+ TimeStampToken asn1.RawValue `asn1:"optional"`
+}
+
+type pkiStatusInfo struct {
+ Status Status
+ StatusString []string `asn1:"optional,utf8"`
+ FailInfo asn1.BitString `asn1:"optional"`
+}
+
+func (s pkiStatusInfo) FailureInfo() FailureInfo {
+ fi := []FailureInfo{BadAlgorithm, BadRequest, BadDataFormat, TimeNotAvailable,
+ UnacceptedPolicy, UnacceptedExtension, AddInfoNotAvailable, SystemFailure}
+
+ for _, f := range fi {
+ if s.FailInfo.At(int(f)) != 0 {
+ return f
+ }
+ }
+
+ return UnknownFailureInfo
+}
+
+// eContent within SignedData is TSTInfo
+type tstInfo struct {
+ Version int
+ Policy asn1.ObjectIdentifier
+ MessageImprint messageImprint
+ SerialNumber *big.Int
+ Time time.Time `asn1:"generalized"`
+ Accuracy accuracy `asn1:"optional"`
+ Ordering bool `asn1:"optional,default:false"`
+ Nonce *big.Int `asn1:"optional"`
+ TSA asn1.RawValue `asn1:"tag:0,optional"`
+ Extensions []pkix.Extension `asn1:"tag:1,optional"`
+}
+
+// accuracy within TSTInfo
+type accuracy struct {
+ Seconds int64 `asn1:"optional"`
+ Milliseconds int64 `asn1:"tag:0,optional"`
+ Microseconds int64 `asn1:"tag:1,optional"`
+}
+
+type qcStatement struct {
+ StatementID asn1.ObjectIdentifier
+ StatementInfo asn1.RawValue `asn1:"optional"`
+}
diff --git a/vendor/github.com/digitorus/timestamp/signing_cert_v2_struct.go b/vendor/github.com/digitorus/timestamp/signing_cert_v2_struct.go
new file mode 100644
index 000000000000..0507c56e511d
--- /dev/null
+++ b/vendor/github.com/digitorus/timestamp/signing_cert_v2_struct.go
@@ -0,0 +1,26 @@
+package timestamp
+
+import (
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "math/big"
+)
+
+type issuerAndSerial struct {
+ IssuerName generalNames
+ SerialNumber *big.Int
+}
+
+type generalNames struct {
+ Name asn1.RawValue `asn1:"optional,tag:4"`
+}
+
+type essCertIDv2 struct {
+ HashAlgorithm pkix.AlgorithmIdentifier `asn1:"optional"` // default sha256
+ CertHash []byte
+ IssuerSerial issuerAndSerial `asn1:"optional"`
+}
+
+type signingCertificateV2 struct {
+ Certs []essCertIDv2
+}
diff --git a/vendor/github.com/digitorus/timestamp/timestamp.go b/vendor/github.com/digitorus/timestamp/timestamp.go
new file mode 100644
index 000000000000..e4f26903e5f2
--- /dev/null
+++ b/vendor/github.com/digitorus/timestamp/timestamp.go
@@ -0,0 +1,680 @@
+// Package timestamp implements the Time-Stamp Protocol (TSP) as specified in
+// RFC3161 (Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)).
+package timestamp
+
+import (
+ "crypto"
+ "crypto/rand"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "fmt"
+ "io"
+ "math/big"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/digitorus/pkcs7"
+)
+
+// FailureInfo contains the failure details of an Time-Stamp request. See
+// https://tools.ietf.org/html/rfc3161#section-2.4.2
+type FailureInfo int
+
+const (
+ // UnknownFailureInfo mean that no known failure info was provided
+ UnknownFailureInfo FailureInfo = -1
+ // BadAlgorithm defines an unrecognized or unsupported Algorithm Identifier
+ BadAlgorithm FailureInfo = 0
+ // BadRequest indicates that the transaction not permitted or supported
+ BadRequest FailureInfo = 2
+ // BadDataFormat means tha data submitted has the wrong format
+ BadDataFormat FailureInfo = 5
+ // TimeNotAvailable indicates that TSA's time source is not available
+ TimeNotAvailable FailureInfo = 14
+ // UnacceptedPolicy indicates that the requested TSA policy is not supported
+ // by the TSA
+ UnacceptedPolicy FailureInfo = 15
+ // UnacceptedExtension indicates that the requested extension is not supported
+ // by the TSA
+ UnacceptedExtension FailureInfo = 16
+ // AddInfoNotAvailable means that the information requested could not be
+ // understood or is not available
+ AddInfoNotAvailable FailureInfo = 17
+ // SystemFailure indicates that the request cannot be handled due to system
+ // failure
+ SystemFailure FailureInfo = 25
+)
+
+func (f FailureInfo) String() string {
+ switch f {
+ case BadAlgorithm:
+ return "unrecognized or unsupported Algorithm Identifier"
+ case BadRequest:
+ return "transaction not permitted or supported"
+ case BadDataFormat:
+ return "the data submitted has the wrong format"
+ case TimeNotAvailable:
+ return "the TSA's time source is not available"
+ case UnacceptedPolicy:
+ return "the requested TSA policy is not supported by the TSA"
+ case UnacceptedExtension:
+ return "the requested extension is not supported by the TSA"
+ case AddInfoNotAvailable:
+ return "the additional information requested could not be understood or is not available"
+ case SystemFailure:
+ return "the request cannot be handled due to system failure"
+ default:
+ return "unknown failure"
+ }
+}
+
+// Status contains the status of an Time-Stamp request. See
+// https://tools.ietf.org/html/rfc3161#section-2.4.2
+type Status int
+
+const (
+ // Granted PKIStatus contains the value zero a TimeStampToken, as requested,
+ // is present.
+ Granted Status = 0
+ // GrantedWithMods PKIStatus contains the value one a TimeStampToken, with
+ // modifications, is present.
+ GrantedWithMods Status = 1
+ // Rejection PKIStatus
+ Rejection Status = 2
+ // Waiting PKIStatus
+ Waiting Status = 3
+ // RevocationWarning PKIStatus
+ RevocationWarning Status = 4
+ // RevocationNotification PKIStatus
+ RevocationNotification Status = 5
+)
+
+func (s Status) String() string {
+ switch s {
+ case Granted:
+ return "the request is granted"
+ case GrantedWithMods:
+ return "the request is granted with modifications"
+ case Rejection:
+ return "the request is rejected"
+ case Waiting:
+ return "the request is waiting"
+ case RevocationWarning:
+ return "revocation is imminent"
+ case RevocationNotification:
+ return "revocation has occurred"
+ default:
+ return "unknown status: " + strconv.Itoa(int(s))
+ }
+}
+
+// ParseError results from an invalid Time-Stamp request or response.
+type ParseError string
+
+func (p ParseError) Error() string {
+ return string(p)
+}
+
+// Request represents an Time-Stamp request. See
+// https://tools.ietf.org/html/rfc3161#section-2.4.1
+type Request struct {
+ HashAlgorithm crypto.Hash
+ HashedMessage []byte
+
+ // Certificates indicates if the TSA needs to return the signing certificate
+ // and optionally any other certificates of the chain as part of the response.
+ Certificates bool
+
+ // The TSAPolicyOID field, if provided, indicates the TSA policy under
+ // which the TimeStampToken SHOULD be provided
+ TSAPolicyOID asn1.ObjectIdentifier
+
+ // The nonce, if provided, allows the client to verify the timeliness of
+ // the response.
+ Nonce *big.Int
+
+ // Extensions contains raw X.509 extensions from the Extensions field of the
+ // Time-Stamp request. When parsing requests, this can be used to extract
+ // non-critical extensions that are not parsed by this package. When
+ // marshaling OCSP requests, the Extensions field is ignored, see
+ // ExtraExtensions.
+ Extensions []pkix.Extension
+
+ // ExtraExtensions contains extensions to be copied, raw, into any marshaled
+ // OCSP response (in the singleExtensions field). Values override any
+ // extensions that would otherwise be produced based on the other fields. The
+ // ExtraExtensions field is not populated when parsing Time-Stamp requests,
+ // see Extensions.
+ ExtraExtensions []pkix.Extension
+}
+
+// ParseRequest parses an timestamp request in DER form.
+func ParseRequest(bytes []byte) (*Request, error) {
+ var err error
+ var rest []byte
+ var req request
+
+ if rest, err = asn1.Unmarshal(bytes, &req); err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 {
+ return nil, ParseError("trailing data in Time-Stamp request")
+ }
+
+ if len(req.MessageImprint.HashedMessage) == 0 {
+ return nil, ParseError("Time-Stamp request contains no hashed message")
+ }
+
+ hashFunc := getHashAlgorithmFromOID(req.MessageImprint.HashAlgorithm.Algorithm)
+ if hashFunc == crypto.Hash(0) {
+ return nil, ParseError("Time-Stamp request uses unknown hash function")
+ }
+
+ return &Request{
+ HashAlgorithm: hashFunc,
+ HashedMessage: req.MessageImprint.HashedMessage,
+ Certificates: req.CertReq,
+ Nonce: req.Nonce,
+ TSAPolicyOID: req.ReqPolicy,
+ Extensions: req.Extensions,
+ }, nil
+}
+
+// Marshal marshals the Time-Stamp request to ASN.1 DER encoded form.
+func (req *Request) Marshal() ([]byte, error) {
+ request := request{
+ Version: 1,
+ MessageImprint: messageImprint{
+ HashAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: getOIDFromHashAlgorithm(req.HashAlgorithm),
+ Parameters: asn1.RawValue{
+ Tag: 5, /* ASN.1 NULL */
+ },
+ },
+ HashedMessage: req.HashedMessage,
+ },
+ CertReq: req.Certificates,
+ Extensions: req.ExtraExtensions,
+ }
+
+ if req.TSAPolicyOID != nil {
+ request.ReqPolicy = req.TSAPolicyOID
+ }
+ if req.Nonce != nil {
+ request.Nonce = req.Nonce
+ }
+ reqBytes, err := asn1.Marshal(request)
+ if err != nil {
+ return nil, err
+ }
+ return reqBytes, nil
+}
+
+// Timestamp represents an Time-Stamp. See:
+// https://tools.ietf.org/html/rfc3161#section-2.4.1
+type Timestamp struct {
+ // Timestamp token part of raw ASN.1 DER content.
+ RawToken []byte
+
+ HashAlgorithm crypto.Hash
+ HashedMessage []byte
+
+ Time time.Time
+ Accuracy time.Duration
+ SerialNumber *big.Int
+ Policy asn1.ObjectIdentifier
+ Ordering bool
+ Nonce *big.Int
+ Qualified bool
+
+ Certificates []*x509.Certificate
+
+ // If set to true, includes TSA certificate in timestamp response
+ AddTSACertificate bool
+
+ // Extensions contains raw X.509 extensions from the Extensions field of the
+ // Time-Stamp. When parsing time-stamps, this can be used to extract
+ // non-critical extensions that are not parsed by this package. When
+ // marshaling time-stamps, the Extensions field is ignored, see
+ // ExtraExtensions.
+ Extensions []pkix.Extension
+
+ // ExtraExtensions contains extensions to be copied, raw, into any marshaled
+ // Time-Stamp response. Values override any extensions that would otherwise
+ // be produced based on the other fields. The ExtraExtensions field is not
+ // populated when parsing Time-Stamp responses, see Extensions.
+ ExtraExtensions []pkix.Extension
+}
+
+// ParseResponse parses an Time-Stamp response in DER form containing a
+// TimeStampToken.
+//
+// Invalid signatures or parse failures will result in a ParseError. Error
+// responses will result in a ResponseError.
+func ParseResponse(bytes []byte) (*Timestamp, error) {
+ var err error
+ var rest []byte
+ var resp response
+
+ if rest, err = asn1.Unmarshal(bytes, &resp); err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 {
+ return nil, ParseError("trailing data in Time-Stamp response")
+ }
+
+ if resp.Status.Status > 0 {
+ var fis string
+ fi := resp.Status.FailureInfo()
+ if fi != UnknownFailureInfo {
+ fis = fi.String()
+ }
+ return nil, fmt.Errorf("%s: %s (%v)",
+ resp.Status.Status.String(),
+ strings.Join(resp.Status.StatusString, ","),
+ fis)
+ }
+
+ if len(resp.TimeStampToken.Bytes) == 0 {
+ return nil, ParseError("no pkcs7 data in Time-Stamp response")
+ }
+
+ return Parse(resp.TimeStampToken.FullBytes)
+}
+
+// Parse parses an Time-Stamp in DER form. If the time-stamp contains a
+// certificate then the signature over the response is checked.
+//
+// Invalid signatures or parse failures will result in a ParseError. Error
+// responses will result in a ResponseError.
+func Parse(bytes []byte) (*Timestamp, error) {
+ var addTSACertificate bool
+ p7, err := pkcs7.Parse(bytes)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(p7.Certificates) > 0 {
+ if err = p7.Verify(); err != nil {
+ return nil, err
+ }
+ addTSACertificate = true
+ } else {
+ addTSACertificate = false
+ }
+
+ var inf tstInfo
+ if _, err = asn1.Unmarshal(p7.Content, &inf); err != nil {
+ return nil, err
+ }
+
+ if len(inf.MessageImprint.HashedMessage) == 0 {
+ return nil, ParseError("Time-Stamp response contains no hashed message")
+ }
+
+ ret := &Timestamp{
+ RawToken: bytes,
+ HashedMessage: inf.MessageImprint.HashedMessage,
+ Time: inf.Time,
+ Accuracy: time.Duration((time.Second * time.Duration(inf.Accuracy.Seconds)) +
+ (time.Millisecond * time.Duration(inf.Accuracy.Milliseconds)) +
+ (time.Microsecond * time.Duration(inf.Accuracy.Microseconds))),
+ SerialNumber: inf.SerialNumber,
+ Policy: inf.Policy,
+ Ordering: inf.Ordering,
+ Nonce: inf.Nonce,
+ Certificates: p7.Certificates,
+ AddTSACertificate: addTSACertificate,
+ Extensions: inf.Extensions,
+ }
+
+ ret.HashAlgorithm = getHashAlgorithmFromOID(inf.MessageImprint.HashAlgorithm.Algorithm)
+ if ret.HashAlgorithm == crypto.Hash(0) {
+ return nil, ParseError("Time-Stamp response uses unknown hash function")
+ }
+
+ if oidInExtensions(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3}, inf.Extensions) {
+ ret.Qualified = true
+ }
+ return ret, nil
+}
+
+// RequestOptions contains options for constructing timestamp requests.
+type RequestOptions struct {
+ // Hash contains the hash function that should be used when
+ // constructing the timestamp request. If zero, SHA-256 will be used.
+ Hash crypto.Hash
+
+ // Certificates sets Request.Certificates
+ Certificates bool
+
+ // The TSAPolicyOID field, if provided, indicates the TSA policy under
+ // which the TimeStampToken SHOULD be provided
+ TSAPolicyOID asn1.ObjectIdentifier
+
+ // The nonce, if provided, allows the client to verify the timeliness of
+ // the response.
+ Nonce *big.Int
+}
+
+func (opts *RequestOptions) hash() crypto.Hash {
+ if opts == nil || opts.Hash == 0 {
+ return crypto.SHA256
+ }
+ return opts.Hash
+}
+
+// CreateRequest returns a DER-encoded, timestamp request for the status of cert. If
+// opts is nil then sensible defaults are used.
+func CreateRequest(r io.Reader, opts *RequestOptions) ([]byte, error) {
+ hashFunc := opts.hash()
+
+ if !hashFunc.Available() {
+ return nil, x509.ErrUnsupportedAlgorithm
+ }
+ h := opts.hash().New()
+
+ b := make([]byte, h.Size())
+ for {
+ n, err := r.Read(b)
+ if err == io.EOF {
+ break
+ }
+
+ _, err = h.Write(b[:n])
+ if err != nil {
+ return nil, fmt.Errorf("failed to create hash")
+ }
+ }
+
+ req := &Request{
+ HashAlgorithm: opts.hash(),
+ HashedMessage: h.Sum(nil),
+ }
+ if opts != nil {
+ req.Certificates = opts.Certificates
+ }
+ if opts != nil && opts.TSAPolicyOID != nil {
+ req.TSAPolicyOID = opts.TSAPolicyOID
+ }
+ if opts != nil && opts.Nonce != nil {
+ req.Nonce = opts.Nonce
+ }
+ return req.Marshal()
+}
+
+// CreateResponseWithOpts returns a DER-encoded timestamp response with the specified contents.
+// The fields in the response are populated as follows:
+//
+// The responder cert is used to populate the responder's name field, and the
+// certificate itself is provided alongside the timestamp response signature.
+func (t *Timestamp) CreateResponseWithOpts(signingCert *x509.Certificate, priv crypto.Signer, opts crypto.SignerOpts) ([]byte, error) {
+ messageImprint := getMessageImprint(t.HashAlgorithm, t.HashedMessage)
+
+ tsaSerialNumber, err := generateTSASerialNumber()
+ if err != nil {
+ return nil, err
+ }
+ tstInfo, err := t.populateTSTInfo(messageImprint, t.Policy, tsaSerialNumber, signingCert)
+ if err != nil {
+ return nil, err
+ }
+ signature, err := t.generateSignedData(tstInfo, priv, signingCert, opts)
+ if err != nil {
+ return nil, err
+ }
+ timestampRes := response{
+ Status: pkiStatusInfo{
+ Status: Granted,
+ },
+ TimeStampToken: asn1.RawValue{FullBytes: signature},
+ }
+ tspResponseBytes, err := asn1.Marshal(timestampRes)
+ if err != nil {
+ return nil, err
+ }
+ return tspResponseBytes, nil
+}
+
+// CreateResponse returns a DER-encoded timestamp response with the specified contents.
+// The fields in the response are populated as follows:
+//
+// The responder cert is used to populate the responder's name field, and the
+// certificate itself is provided alongside the timestamp response signature.
+//
+// This function is equivalent to CreateResponseWithOpts, using a SHA256 hash.
+//
+// Deprecated: Use CreateResponseWithOpts instead.
+func (t *Timestamp) CreateResponse(signingCert *x509.Certificate, priv crypto.Signer) ([]byte, error) {
+ return t.CreateResponseWithOpts(signingCert, priv, crypto.SHA256)
+}
+
+// CreateErrorResponse is used to create response other than granted and granted with mod status
+func CreateErrorResponse(pkiStatus Status, pkiFailureInfo FailureInfo) ([]byte, error) {
+ var bs asn1.BitString
+ setFlag(&bs, int(pkiFailureInfo))
+
+ timestampRes := response{
+ Status: pkiStatusInfo{
+ Status: pkiStatus,
+ FailInfo: bs,
+ },
+ }
+ tspResponseBytes, err := asn1.Marshal(timestampRes)
+ if err != nil {
+ return nil, err
+ }
+ return tspResponseBytes, nil
+}
+
+func setFlag(bs *asn1.BitString, i int) {
+ for l := len(bs.Bytes); l < 4; l++ {
+ (*bs).Bytes = append((*bs).Bytes, byte(0))
+ (*bs).BitLength = len((*bs).Bytes) * 8
+ }
+ b := i / 8
+ p := uint(7 - (i - 8*b))
+ (*bs).Bytes[b] = (*bs).Bytes[b] | (1 << p)
+ bs.BitLength = asn1BitLength(bs.Bytes)
+ bs.Bytes = bs.Bytes[0 : (bs.BitLength/8)+1]
+}
+
+func getMessageImprint(hashAlgorithm crypto.Hash, hashedMessage []byte) messageImprint {
+ messageImprint := messageImprint{
+ HashAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: getOIDFromHashAlgorithm(hashAlgorithm),
+ Parameters: asn1.NullRawValue,
+ },
+ HashedMessage: hashedMessage,
+ }
+ return messageImprint
+}
+
+func generateTSASerialNumber() (*big.Int, error) {
+ randomBytes := make([]byte, 20)
+ _, err := rand.Read(randomBytes)
+ if err != nil {
+ return nil, err
+ }
+ serialNumber := big.NewInt(0)
+ serialNumber = serialNumber.SetBytes(randomBytes)
+ return serialNumber, nil
+}
+
+func (t *Timestamp) populateTSTInfo(messageImprint messageImprint, policyOID asn1.ObjectIdentifier, tsaSerialNumber *big.Int, tsaCert *x509.Certificate) ([]byte, error) {
+ dirGeneralName, err := asn1.Marshal(asn1.RawValue{Tag: 4, Class: 2, IsCompound: true, Bytes: tsaCert.RawSubject})
+ if err != nil {
+ return nil, err
+ }
+ tstInfo := tstInfo{
+ Version: 1,
+ Policy: policyOID,
+ MessageImprint: messageImprint,
+ SerialNumber: tsaSerialNumber,
+ Time: t.Time,
+ TSA: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: dirGeneralName},
+ Ordering: t.Ordering,
+ }
+ if t.Nonce != nil {
+ tstInfo.Nonce = t.Nonce
+ }
+ if t.Accuracy != 0 {
+ if t.Accuracy < time.Microsecond {
+ // Round up to 1 microsecond if accuracy is lower than 1 microsecond but greater than 0 nanosecond
+ tstInfo.Accuracy.Microseconds = 1
+ } else {
+ seconds := t.Accuracy.Truncate(time.Second)
+ tstInfo.Accuracy.Seconds = int64(seconds.Seconds())
+ ms := (t.Accuracy - seconds).Truncate(time.Millisecond)
+ if ms != 0 {
+ tstInfo.Accuracy.Milliseconds = int64(ms.Milliseconds())
+ }
+ microSeconds := (t.Accuracy - seconds - ms).Truncate(time.Microsecond)
+ if microSeconds != 0 {
+ tstInfo.Accuracy.Microseconds = int64(microSeconds.Microseconds())
+ }
+ }
+ }
+ if len(t.ExtraExtensions) != 0 {
+ tstInfo.Extensions = t.ExtraExtensions
+ }
+ if t.Qualified && !oidInExtensions(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3}, t.ExtraExtensions) {
+ qcStatements := []qcStatement{{
+ StatementID: asn1.ObjectIdentifier{0, 4, 0, 19422, 1, 1},
+ }}
+ asn1QcStats, err := asn1.Marshal(qcStatements)
+ if err != nil {
+ return nil, err
+ }
+ tstInfo.Extensions = append(tstInfo.Extensions, pkix.Extension{
+ Id: []int{1, 3, 6, 1, 5, 5, 7, 1, 3},
+ Value: asn1QcStats,
+ Critical: false,
+ })
+ }
+ tstInfoBytes, err := asn1.Marshal(tstInfo)
+ if err != nil {
+ return nil, err
+ }
+ return tstInfoBytes, nil
+}
+
+func (t *Timestamp) populateSigningCertificateV2Ext(certificate *x509.Certificate) ([]byte, error) {
+ if !t.HashAlgorithm.Available() {
+ return nil, x509.ErrUnsupportedAlgorithm
+ }
+ if t.HashAlgorithm.HashFunc() == crypto.SHA1 {
+ return nil, fmt.Errorf("for SHA1 use ESSCertID instead of ESSCertIDv2")
+ }
+
+ h := t.HashAlgorithm.HashFunc().New()
+ _, err := h.Write(certificate.Raw)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create hash")
+ }
+
+ var hashAlg pkix.AlgorithmIdentifier
+
+ // HashAlgorithm defaults to SHA256
+ if t.HashAlgorithm.HashFunc() != crypto.SHA256 {
+ hashAlg = pkix.AlgorithmIdentifier{
+ Algorithm: hashOIDs[t.HashAlgorithm.HashFunc()],
+ Parameters: asn1.NullRawValue,
+ }
+ }
+
+ signingCertificateV2 := signingCertificateV2{
+ Certs: []essCertIDv2{{
+ HashAlgorithm: hashAlg,
+ CertHash: h.Sum(nil),
+ IssuerSerial: issuerAndSerial{
+ IssuerName: generalNames{
+ Name: asn1.RawValue{Tag: 4, Class: 2, IsCompound: true, Bytes: certificate.RawIssuer},
+ },
+ SerialNumber: certificate.SerialNumber,
+ },
+ }},
+ }
+ signingCertV2Bytes, err := asn1.Marshal(signingCertificateV2)
+ if err != nil {
+ return nil, err
+ }
+ return signingCertV2Bytes, nil
+}
+
+// digestAlgorithmToOID converts the hash func to the corresponding OID.
+// This should have parity with [pkcs7.getHashForOID].
+func digestAlgorithmToOID(hash crypto.Hash) (asn1.ObjectIdentifier, error) {
+ switch hash {
+ case crypto.SHA1:
+ return pkcs7.OIDDigestAlgorithmSHA1, nil
+ case crypto.SHA256:
+ return pkcs7.OIDDigestAlgorithmSHA256, nil
+ case crypto.SHA384:
+ return pkcs7.OIDDigestAlgorithmSHA384, nil
+ case crypto.SHA512:
+ return pkcs7.OIDDigestAlgorithmSHA512, nil
+ }
+ return nil, pkcs7.ErrUnsupportedAlgorithm
+}
+
+func (t *Timestamp) generateSignedData(tstInfo []byte, signer crypto.Signer, certificate *x509.Certificate, opts crypto.SignerOpts) ([]byte, error) {
+ signedData, err := pkcs7.NewSignedData(tstInfo)
+ if err != nil {
+ return nil, err
+ }
+
+ alg, err := digestAlgorithmToOID(opts.HashFunc())
+ if err != nil {
+ return nil, err
+ }
+ signedData.SetDigestAlgorithm(alg)
+ signedData.SetContentType(asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 4})
+ signedData.GetSignedData().Version = 3
+
+ signingCertV2Bytes, err := t.populateSigningCertificateV2Ext(certificate)
+ if err != nil {
+ return nil, err
+ }
+
+ signerInfoConfig := pkcs7.SignerInfoConfig{
+ ExtraSignedAttributes: []pkcs7.Attribute{
+ {
+ Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 47},
+ Value: asn1.RawValue{FullBytes: signingCertV2Bytes},
+ },
+ },
+ }
+ if !t.AddTSACertificate {
+ signerInfoConfig.SkipCertificates = true
+ }
+
+ if len(t.Certificates) > 0 {
+ err = signedData.AddSignerChain(certificate, signer, t.Certificates, signerInfoConfig)
+ } else {
+ err = signedData.AddSigner(certificate, signer, signerInfoConfig)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ signature, err := signedData.Finish()
+ if err != nil {
+ return nil, err
+ }
+ return signature, nil
+}
+
+// copied from crypto/x509 package
+// oidNotInExtensions reports whether an extension with the given oid exists in
+// extensions.
+func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool {
+ for _, e := range extensions {
+ if e.Id.Equal(oid) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/go-openapi/analysis/.codecov.yml b/vendor/github.com/go-openapi/analysis/.codecov.yml
new file mode 100644
index 000000000000..841c4281e23d
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/.codecov.yml
@@ -0,0 +1,5 @@
+coverage:
+ status:
+ patch:
+ default:
+ target: 80%
diff --git a/vendor/github.com/go-openapi/analysis/.gitattributes b/vendor/github.com/go-openapi/analysis/.gitattributes
new file mode 100644
index 000000000000..d020be8ea4e7
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/.gitattributes
@@ -0,0 +1,2 @@
+*.go text eol=lf
+
diff --git a/vendor/github.com/go-openapi/analysis/.gitignore b/vendor/github.com/go-openapi/analysis/.gitignore
new file mode 100644
index 000000000000..87c3bd3e66e0
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/.gitignore
@@ -0,0 +1,5 @@
+secrets.yml
+coverage.out
+coverage.txt
+*.cov
+.idea
diff --git a/vendor/github.com/go-openapi/analysis/.golangci.yml b/vendor/github.com/go-openapi/analysis/.golangci.yml
new file mode 100644
index 000000000000..06190ac055fd
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ - intrange
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - noinlineerr
+ - nonamedreturns
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/analysis/LICENSE b/vendor/github.com/go-openapi/analysis/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/analysis/README.md b/vendor/github.com/go-openapi/analysis/README.md
new file mode 100644
index 000000000000..e005d4b37b7f
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/README.md
@@ -0,0 +1,27 @@
+# OpenAPI analysis [](https://github.com/go-openapi/analysis/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/analysis)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/analysis/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/analysis)
+[](https://goreportcard.com/report/github.com/go-openapi/analysis)
+
+
+A foundational library to analyze an OAI specification document for easier reasoning about the content.
+
+## What's inside?
+
+* An analyzer providing methods to walk the functional content of a specification
+* A spec flattener producing a self-contained document bundle, while preserving `$ref`s
+* A spec merger ("mixin") to merge several spec documents into a primary spec
+* A spec "fixer" ensuring that response descriptions are non empty
+
+[Documentation](https://pkg.go.dev/github.com/go-openapi/analysis)
+
+## FAQ
+
+* Does this library support OpenAPI 3?
+
+> No.
+> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
+> There is no plan to make it evolve toward supporting OpenAPI 3.x.
+> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
diff --git a/vendor/github.com/go-openapi/analysis/analyzer.go b/vendor/github.com/go-openapi/analysis/analyzer.go
new file mode 100644
index 000000000000..4870ad07beb9
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/analyzer.go
@@ -0,0 +1,1054 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "fmt"
+ "maps"
+ slashpath "path"
+ "strconv"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/swag/mangling"
+)
+
+const (
+ allocLargeMap = 150
+ allocMediumMap = 64
+ allocSmallMap = 10
+)
+
+type referenceAnalysis struct {
+ schemas map[string]spec.Ref
+ responses map[string]spec.Ref
+ parameters map[string]spec.Ref
+ items map[string]spec.Ref
+ headerItems map[string]spec.Ref
+ parameterItems map[string]spec.Ref
+ allRefs map[string]spec.Ref
+ pathItems map[string]spec.Ref
+}
+
+func (r *referenceAnalysis) addRef(key string, ref spec.Ref) {
+ r.allRefs["#"+key] = ref
+}
+
+func (r *referenceAnalysis) addItemsRef(key string, items *spec.Items, location string) {
+ r.items["#"+key] = items.Ref
+ r.addRef(key, items.Ref)
+ if location == "header" {
+ // NOTE: in swagger 2.0, headers and parameters (but not body param schemas) are simple schemas
+ // and $ref are not supported here. However it is possible to analyze this.
+ r.headerItems["#"+key] = items.Ref
+ } else {
+ r.parameterItems["#"+key] = items.Ref
+ }
+}
+
+func (r *referenceAnalysis) addSchemaRef(key string, ref SchemaRef) {
+ r.schemas["#"+key] = ref.Schema.Ref
+ r.addRef(key, ref.Schema.Ref)
+}
+
+func (r *referenceAnalysis) addResponseRef(key string, resp *spec.Response) {
+ r.responses["#"+key] = resp.Ref
+ r.addRef(key, resp.Ref)
+}
+
+func (r *referenceAnalysis) addParamRef(key string, param *spec.Parameter) {
+ r.parameters["#"+key] = param.Ref
+ r.addRef(key, param.Ref)
+}
+
+func (r *referenceAnalysis) addPathItemRef(key string, pathItem *spec.PathItem) {
+ r.pathItems["#"+key] = pathItem.Ref
+ r.addRef(key, pathItem.Ref)
+}
+
+type patternAnalysis struct {
+ parameters map[string]string
+ headers map[string]string
+ items map[string]string
+ schemas map[string]string
+ allPatterns map[string]string
+}
+
+func (p *patternAnalysis) addPattern(key, pattern string) {
+ p.allPatterns["#"+key] = pattern
+}
+
+func (p *patternAnalysis) addParameterPattern(key, pattern string) {
+ p.parameters["#"+key] = pattern
+ p.addPattern(key, pattern)
+}
+
+func (p *patternAnalysis) addHeaderPattern(key, pattern string) {
+ p.headers["#"+key] = pattern
+ p.addPattern(key, pattern)
+}
+
+func (p *patternAnalysis) addItemsPattern(key, pattern string) {
+ p.items["#"+key] = pattern
+ p.addPattern(key, pattern)
+}
+
+func (p *patternAnalysis) addSchemaPattern(key, pattern string) {
+ p.schemas["#"+key] = pattern
+ p.addPattern(key, pattern)
+}
+
+type enumAnalysis struct {
+ parameters map[string][]any
+ headers map[string][]any
+ items map[string][]any
+ schemas map[string][]any
+ allEnums map[string][]any
+}
+
+func (p *enumAnalysis) addEnum(key string, enum []any) {
+ p.allEnums["#"+key] = enum
+}
+
+func (p *enumAnalysis) addParameterEnum(key string, enum []any) {
+ p.parameters["#"+key] = enum
+ p.addEnum(key, enum)
+}
+
+func (p *enumAnalysis) addHeaderEnum(key string, enum []any) {
+ p.headers["#"+key] = enum
+ p.addEnum(key, enum)
+}
+
+func (p *enumAnalysis) addItemsEnum(key string, enum []any) {
+ p.items["#"+key] = enum
+ p.addEnum(key, enum)
+}
+
+func (p *enumAnalysis) addSchemaEnum(key string, enum []any) {
+ p.schemas["#"+key] = enum
+ p.addEnum(key, enum)
+}
+
+// Spec is an analyzed specification object. It takes a swagger spec object and turns it into a registry
+// with a bunch of utility methods to act on the information in the spec.
+type Spec struct {
+ spec *spec.Swagger
+ consumes map[string]struct{}
+ produces map[string]struct{}
+ authSchemes map[string]struct{}
+ operations map[string]map[string]*spec.Operation
+ references referenceAnalysis
+ patterns patternAnalysis
+ enums enumAnalysis
+ allSchemas map[string]SchemaRef
+ allOfs map[string]SchemaRef
+}
+
+// New takes a swagger spec object and returns an analyzed spec document.
+// The analyzed document contains a number of indices that make it easier to
+// reason about semantics of a swagger specification for use in code generation
+// or validation etc.
+func New(doc *spec.Swagger) *Spec {
+ a := &Spec{
+ spec: doc,
+ references: referenceAnalysis{},
+ patterns: patternAnalysis{},
+ enums: enumAnalysis{},
+ }
+ a.reset()
+ a.initialize()
+
+ return a
+}
+
+// SecurityRequirement is a representation of a security requirement for an operation
+type SecurityRequirement struct {
+ Name string
+ Scopes []string
+}
+
+// SecurityRequirementsFor gets the security requirements for the operation
+func (s *Spec) SecurityRequirementsFor(operation *spec.Operation) [][]SecurityRequirement {
+ if s.spec.Security == nil && operation.Security == nil {
+ return nil
+ }
+
+ schemes := s.spec.Security
+ if operation.Security != nil {
+ schemes = operation.Security
+ }
+
+ result := [][]SecurityRequirement{}
+ for _, scheme := range schemes {
+ if len(scheme) == 0 {
+ // append a zero object for anonymous
+ result = append(result, []SecurityRequirement{{}})
+
+ continue
+ }
+
+ var reqs []SecurityRequirement
+ for k, v := range scheme {
+ if v == nil {
+ v = []string{}
+ }
+ reqs = append(reqs, SecurityRequirement{Name: k, Scopes: v})
+ }
+
+ result = append(result, reqs)
+ }
+
+ return result
+}
+
+// SecurityDefinitionsForRequirements gets the matching security definitions for a set of requirements
+func (s *Spec) SecurityDefinitionsForRequirements(requirements []SecurityRequirement) map[string]spec.SecurityScheme {
+ result := make(map[string]spec.SecurityScheme)
+
+ for _, v := range requirements {
+ if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
+ if definition != nil {
+ result[v.Name] = *definition
+ }
+ }
+ }
+
+ return result
+}
+
+// SecurityDefinitionsFor gets the matching security definitions for a set of requirements
+func (s *Spec) SecurityDefinitionsFor(operation *spec.Operation) map[string]spec.SecurityScheme {
+ requirements := s.SecurityRequirementsFor(operation)
+ if len(requirements) == 0 {
+ return nil
+ }
+
+ result := make(map[string]spec.SecurityScheme)
+ for _, reqs := range requirements {
+ for _, v := range reqs {
+ if v.Name == "" {
+ // optional requirement
+ continue
+ }
+
+ if _, ok := result[v.Name]; ok {
+ // duplicate requirement
+ continue
+ }
+
+ if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
+ if definition != nil {
+ result[v.Name] = *definition
+ }
+ }
+ }
+ }
+
+ return result
+}
+
+// ConsumesFor gets the mediatypes for the operation
+func (s *Spec) ConsumesFor(operation *spec.Operation) []string {
+ if len(operation.Consumes) == 0 {
+ cons := make(map[string]struct{}, len(s.spec.Consumes))
+ for _, k := range s.spec.Consumes {
+ cons[k] = struct{}{}
+ }
+
+ return s.structMapKeys(cons)
+ }
+
+ cons := make(map[string]struct{}, len(operation.Consumes))
+ for _, c := range operation.Consumes {
+ cons[c] = struct{}{}
+ }
+
+ return s.structMapKeys(cons)
+}
+
+// ProducesFor gets the mediatypes for the operation
+func (s *Spec) ProducesFor(operation *spec.Operation) []string {
+ if len(operation.Produces) == 0 {
+ prod := make(map[string]struct{}, len(s.spec.Produces))
+ for _, k := range s.spec.Produces {
+ prod[k] = struct{}{}
+ }
+
+ return s.structMapKeys(prod)
+ }
+
+ prod := make(map[string]struct{}, len(operation.Produces))
+ for _, c := range operation.Produces {
+ prod[c] = struct{}{}
+ }
+
+ return s.structMapKeys(prod)
+}
+
+func mapKeyFromParam(param *spec.Parameter) string {
+ return fmt.Sprintf("%s#%s", param.In, fieldNameFromParam(param))
+}
+
+func fieldNameFromParam(param *spec.Parameter) string {
+ // TODO: this should be x-go-name
+ if nm, ok := param.Extensions.GetString("go-name"); ok {
+ return nm
+ }
+ mangler := mangling.NewNameMangler()
+
+ return mangler.ToGoName(param.Name)
+}
+
+// ErrorOnParamFunc is a callback function to be invoked
+// whenever an error is encountered while resolving references
+// on parameters.
+//
+// This function takes as input the spec.Parameter which triggered the
+// error and the error itself.
+//
+// If the callback function returns false, the calling function should bail.
+//
+// If it returns true, the calling function should continue evaluating parameters.
+// A nil ErrorOnParamFunc must be evaluated as equivalent to panic().
+type ErrorOnParamFunc func(spec.Parameter, error) bool
+
+// ParametersFor the specified operation id.
+//
+// Assumes parameters properly resolve references if any and that
+// such references actually resolve to a parameter object.
+// Otherwise, panics.
+func (s *Spec) ParametersFor(operationID string) []spec.Parameter {
+ return s.SafeParametersFor(operationID, nil)
+}
+
+// SafeParametersFor the specified operation id.
+//
+// Does not assume parameters properly resolve references or that
+// such references actually resolve to a parameter object.
+//
+// Upon error, invoke a ErrorOnParamFunc callback with the erroneous
+// parameters. If the callback is set to nil, panics upon errors.
+func (s *Spec) SafeParametersFor(operationID string, callmeOnError ErrorOnParamFunc) []spec.Parameter {
+ gatherParams := func(pi *spec.PathItem, op *spec.Operation) []spec.Parameter {
+ bag := make(map[string]spec.Parameter)
+ s.paramsAsMap(pi.Parameters, bag, callmeOnError)
+ s.paramsAsMap(op.Parameters, bag, callmeOnError)
+
+ var res []spec.Parameter
+ for _, v := range bag {
+ res = append(res, v)
+ }
+
+ return res
+ }
+
+ for _, pi := range s.spec.Paths.Paths {
+ if pi.Get != nil && pi.Get.ID == operationID {
+ return gatherParams(&pi, pi.Get) //#nosec
+ }
+ if pi.Head != nil && pi.Head.ID == operationID {
+ return gatherParams(&pi, pi.Head) //#nosec
+ }
+ if pi.Options != nil && pi.Options.ID == operationID {
+ return gatherParams(&pi, pi.Options) //#nosec
+ }
+ if pi.Post != nil && pi.Post.ID == operationID {
+ return gatherParams(&pi, pi.Post) //#nosec
+ }
+ if pi.Patch != nil && pi.Patch.ID == operationID {
+ return gatherParams(&pi, pi.Patch) //#nosec
+ }
+ if pi.Put != nil && pi.Put.ID == operationID {
+ return gatherParams(&pi, pi.Put) //#nosec
+ }
+ if pi.Delete != nil && pi.Delete.ID == operationID {
+ return gatherParams(&pi, pi.Delete) //#nosec
+ }
+ }
+
+ return nil
+}
+
+// ParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that
+// apply for the method and path.
+//
+// Assumes parameters properly resolve references if any and that
+// such references actually resolve to a parameter object.
+// Otherwise, panics.
+func (s *Spec) ParamsFor(method, path string) map[string]spec.Parameter {
+ return s.SafeParamsFor(method, path, nil)
+}
+
+// SafeParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that
+// apply for the method and path.
+//
+// Does not assume parameters properly resolve references or that
+// such references actually resolve to a parameter object.
+//
+// Upon error, invoke a ErrorOnParamFunc callback with the erroneous
+// parameters. If the callback is set to nil, panics upon errors.
+func (s *Spec) SafeParamsFor(method, path string, callmeOnError ErrorOnParamFunc) map[string]spec.Parameter {
+ res := make(map[string]spec.Parameter)
+ if pi, ok := s.spec.Paths.Paths[path]; ok {
+ s.paramsAsMap(pi.Parameters, res, callmeOnError)
+ s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res, callmeOnError)
+ }
+
+ return res
+}
+
+// OperationForName gets the operation for the given id
+func (s *Spec) OperationForName(operationID string) (string, string, *spec.Operation, bool) {
+ for method, pathItem := range s.operations {
+ for path, op := range pathItem {
+ if operationID == op.ID {
+ return method, path, op, true
+ }
+ }
+ }
+
+ return "", "", nil, false
+}
+
+// OperationFor the given method and path
+func (s *Spec) OperationFor(method, path string) (*spec.Operation, bool) {
+ if mp, ok := s.operations[strings.ToUpper(method)]; ok {
+ op, fn := mp[path]
+
+ return op, fn
+ }
+
+ return nil, false
+}
+
+// Operations gathers all the operations specified in the spec document
+func (s *Spec) Operations() map[string]map[string]*spec.Operation {
+ return s.operations
+}
+
+// AllPaths returns all the paths in the swagger spec
+func (s *Spec) AllPaths() map[string]spec.PathItem {
+ if s.spec == nil || s.spec.Paths == nil {
+ return nil
+ }
+
+ return s.spec.Paths.Paths
+}
+
+// OperationIDs gets all the operation ids based on method an dpath
+func (s *Spec) OperationIDs() []string {
+ if len(s.operations) == 0 {
+ return nil
+ }
+
+ result := make([]string, 0, len(s.operations))
+ for method, v := range s.operations {
+ for p, o := range v {
+ if o.ID != "" {
+ result = append(result, o.ID)
+ } else {
+ result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
+ }
+ }
+ }
+
+ return result
+}
+
+// OperationMethodPaths gets all the operation ids based on method an dpath
+func (s *Spec) OperationMethodPaths() []string {
+ if len(s.operations) == 0 {
+ return nil
+ }
+
+ result := make([]string, 0, len(s.operations))
+ for method, v := range s.operations {
+ for p := range v {
+ result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
+ }
+ }
+
+ return result
+}
+
+// RequiredConsumes gets all the distinct consumes that are specified in the specification document
+func (s *Spec) RequiredConsumes() []string {
+ return s.structMapKeys(s.consumes)
+}
+
+// RequiredProduces gets all the distinct produces that are specified in the specification document
+func (s *Spec) RequiredProduces() []string {
+ return s.structMapKeys(s.produces)
+}
+
+// RequiredSecuritySchemes gets all the distinct security schemes that are specified in the swagger spec
+func (s *Spec) RequiredSecuritySchemes() []string {
+ return s.structMapKeys(s.authSchemes)
+}
+
+// SchemaRef is a reference to a schema
+type SchemaRef struct {
+ Name string
+ Ref spec.Ref
+ Schema *spec.Schema
+ TopLevel bool
+}
+
+// SchemasWithAllOf returns schema references to all schemas that are defined
+// with an allOf key
+func (s *Spec) SchemasWithAllOf() (result []SchemaRef) {
+ for _, v := range s.allOfs {
+ result = append(result, v)
+ }
+
+ return
+}
+
+// AllDefinitions returns schema references for all the definitions that were discovered
+func (s *Spec) AllDefinitions() (result []SchemaRef) {
+ for _, v := range s.allSchemas {
+ result = append(result, v)
+ }
+
+ return
+}
+
+// AllDefinitionReferences returns json refs for all the discovered schemas
+func (s *Spec) AllDefinitionReferences() (result []string) {
+ for _, v := range s.references.schemas {
+ result = append(result, v.String())
+ }
+
+ return
+}
+
+// AllParameterReferences returns json refs for all the discovered parameters
+func (s *Spec) AllParameterReferences() (result []string) {
+ for _, v := range s.references.parameters {
+ result = append(result, v.String())
+ }
+
+ return
+}
+
+// AllResponseReferences returns json refs for all the discovered responses
+func (s *Spec) AllResponseReferences() (result []string) {
+ for _, v := range s.references.responses {
+ result = append(result, v.String())
+ }
+
+ return
+}
+
+// AllPathItemReferences returns the references for all the items
+func (s *Spec) AllPathItemReferences() (result []string) {
+ for _, v := range s.references.pathItems {
+ result = append(result, v.String())
+ }
+
+ return
+}
+
+// AllItemsReferences returns the references for all the items in simple schemas (parameters or headers).
+//
+// NOTE: since Swagger 2.0 forbids $ref in simple params, this should always yield an empty slice for a valid
+// Swagger 2.0 spec.
+func (s *Spec) AllItemsReferences() (result []string) {
+ for _, v := range s.references.items {
+ result = append(result, v.String())
+ }
+
+ return
+}
+
+// AllReferences returns all the references found in the document, with possible duplicates
+func (s *Spec) AllReferences() (result []string) {
+ for _, v := range s.references.allRefs {
+ result = append(result, v.String())
+ }
+
+ return
+}
+
+// AllRefs returns all the unique references found in the document
+func (s *Spec) AllRefs() (result []spec.Ref) {
+ set := make(map[string]struct{})
+ for _, v := range s.references.allRefs {
+ a := v.String()
+ if a == "" {
+ continue
+ }
+
+ if _, ok := set[a]; !ok {
+ set[a] = struct{}{}
+ result = append(result, v)
+ }
+ }
+
+ return
+}
+
+// ParameterPatterns returns all the patterns found in parameters
+// the map is cloned to avoid accidental changes
+func (s *Spec) ParameterPatterns() map[string]string {
+ return cloneStringMap(s.patterns.parameters)
+}
+
+// HeaderPatterns returns all the patterns found in response headers
+// the map is cloned to avoid accidental changes
+func (s *Spec) HeaderPatterns() map[string]string {
+ return cloneStringMap(s.patterns.headers)
+}
+
+// ItemsPatterns returns all the patterns found in simple array items
+// the map is cloned to avoid accidental changes
+func (s *Spec) ItemsPatterns() map[string]string {
+ return cloneStringMap(s.patterns.items)
+}
+
+// SchemaPatterns returns all the patterns found in schemas
+// the map is cloned to avoid accidental changes
+func (s *Spec) SchemaPatterns() map[string]string {
+ return cloneStringMap(s.patterns.schemas)
+}
+
+// AllPatterns returns all the patterns found in the spec
+// the map is cloned to avoid accidental changes
+func (s *Spec) AllPatterns() map[string]string {
+ return cloneStringMap(s.patterns.allPatterns)
+}
+
+// ParameterEnums returns all the enums found in parameters
+// the map is cloned to avoid accidental changes
+func (s *Spec) ParameterEnums() map[string][]any {
+ return cloneEnumMap(s.enums.parameters)
+}
+
+// HeaderEnums returns all the enums found in response headers
+// the map is cloned to avoid accidental changes
+func (s *Spec) HeaderEnums() map[string][]any {
+ return cloneEnumMap(s.enums.headers)
+}
+
+// ItemsEnums returns all the enums found in simple array items
+// the map is cloned to avoid accidental changes
+func (s *Spec) ItemsEnums() map[string][]any {
+ return cloneEnumMap(s.enums.items)
+}
+
+// SchemaEnums returns all the enums found in schemas
+// the map is cloned to avoid accidental changes
+func (s *Spec) SchemaEnums() map[string][]any {
+ return cloneEnumMap(s.enums.schemas)
+}
+
+// AllEnums returns all the enums found in the spec
+// the map is cloned to avoid accidental changes
+func (s *Spec) AllEnums() map[string][]any {
+ return cloneEnumMap(s.enums.allEnums)
+}
+
+func (s *Spec) structMapKeys(mp map[string]struct{}) []string {
+ if len(mp) == 0 {
+ return nil
+ }
+
+ result := make([]string, 0, len(mp))
+ for k := range mp {
+ result = append(result, k)
+ }
+
+ return result
+}
+
+func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Parameter, callmeOnError ErrorOnParamFunc) {
+ for _, param := range parameters {
+ pr := param
+ if pr.Ref.String() == "" {
+ res[mapKeyFromParam(&pr)] = pr
+
+ continue
+ }
+
+ // resolve $ref
+ if callmeOnError == nil {
+ callmeOnError = func(_ spec.Parameter, err error) bool {
+ panic(err)
+ }
+ }
+
+ obj, _, err := pr.Ref.GetPointer().Get(s.spec)
+ if err != nil {
+ if callmeOnError(param, ErrInvalidRef(pr.Ref.String())) {
+ continue
+ }
+
+ break
+ }
+
+ objAsParam, ok := obj.(spec.Parameter)
+ if !ok {
+ if callmeOnError(param, ErrInvalidParameterRef(pr.Ref.String())) {
+ continue
+ }
+
+ break
+ }
+
+ pr = objAsParam
+ res[mapKeyFromParam(&pr)] = pr
+ }
+}
+
+func (s *Spec) reset() {
+ s.consumes = make(map[string]struct{}, allocLargeMap)
+ s.produces = make(map[string]struct{}, allocLargeMap)
+ s.authSchemes = make(map[string]struct{}, allocLargeMap)
+ s.operations = make(map[string]map[string]*spec.Operation, allocLargeMap)
+ s.allSchemas = make(map[string]SchemaRef, allocLargeMap)
+ s.allOfs = make(map[string]SchemaRef, allocLargeMap)
+ s.references.schemas = make(map[string]spec.Ref, allocLargeMap)
+ s.references.pathItems = make(map[string]spec.Ref, allocLargeMap)
+ s.references.responses = make(map[string]spec.Ref, allocLargeMap)
+ s.references.parameters = make(map[string]spec.Ref, allocLargeMap)
+ s.references.items = make(map[string]spec.Ref, allocLargeMap)
+ s.references.headerItems = make(map[string]spec.Ref, allocLargeMap)
+ s.references.parameterItems = make(map[string]spec.Ref, allocLargeMap)
+ s.references.allRefs = make(map[string]spec.Ref, allocLargeMap)
+ s.patterns.parameters = make(map[string]string, allocLargeMap)
+ s.patterns.headers = make(map[string]string, allocLargeMap)
+ s.patterns.items = make(map[string]string, allocLargeMap)
+ s.patterns.schemas = make(map[string]string, allocLargeMap)
+ s.patterns.allPatterns = make(map[string]string, allocLargeMap)
+ s.enums.parameters = make(map[string][]any, allocLargeMap)
+ s.enums.headers = make(map[string][]any, allocLargeMap)
+ s.enums.items = make(map[string][]any, allocLargeMap)
+ s.enums.schemas = make(map[string][]any, allocLargeMap)
+ s.enums.allEnums = make(map[string][]any, allocLargeMap)
+}
+
+func (s *Spec) reload() {
+ s.reset()
+ s.initialize()
+}
+
+func (s *Spec) initialize() {
+ for _, c := range s.spec.Consumes {
+ s.consumes[c] = struct{}{}
+ }
+ for _, c := range s.spec.Produces {
+ s.produces[c] = struct{}{}
+ }
+ for _, ss := range s.spec.Security {
+ for k := range ss {
+ s.authSchemes[k] = struct{}{}
+ }
+ }
+ for path, pathItem := range s.AllPaths() {
+ s.analyzeOperations(path, &pathItem) //#nosec
+ }
+
+ for name, parameter := range s.spec.Parameters {
+ refPref := slashpath.Join("/parameters", jsonpointer.Escape(name))
+ if parameter.Items != nil {
+ s.analyzeItems("items", parameter.Items, refPref, "parameter")
+ }
+ if parameter.In == "body" && parameter.Schema != nil {
+ s.analyzeSchema("schema", parameter.Schema, refPref)
+ }
+ if parameter.Pattern != "" {
+ s.patterns.addParameterPattern(refPref, parameter.Pattern)
+ }
+ if len(parameter.Enum) > 0 {
+ s.enums.addParameterEnum(refPref, parameter.Enum)
+ }
+ }
+
+ for name, response := range s.spec.Responses {
+ refPref := slashpath.Join("/responses", jsonpointer.Escape(name))
+ for k, v := range response.Headers {
+ hRefPref := slashpath.Join(refPref, "headers", k)
+ if v.Items != nil {
+ s.analyzeItems("items", v.Items, hRefPref, "header")
+ }
+ if v.Pattern != "" {
+ s.patterns.addHeaderPattern(hRefPref, v.Pattern)
+ }
+ if len(v.Enum) > 0 {
+ s.enums.addHeaderEnum(hRefPref, v.Enum)
+ }
+ }
+ if response.Schema != nil {
+ s.analyzeSchema("schema", response.Schema, refPref)
+ }
+ }
+
+ for name := range s.spec.Definitions {
+ schema := s.spec.Definitions[name]
+ s.analyzeSchema(name, &schema, "/definitions")
+ }
+ // TODO: after analyzing all things and flattening schemas etc
+ // resolve all the collected references to their final representations
+ // best put in a separate method because this could get expensive
+}
+
+func (s *Spec) analyzeOperations(path string, pi *spec.PathItem) {
+ // TODO: resolve refs here?
+ // Currently, operations declared via pathItem $ref are known only after expansion
+ op := pi
+ if pi.Ref.String() != "" {
+ key := slashpath.Join("/paths", jsonpointer.Escape(path))
+ s.references.addPathItemRef(key, pi)
+ }
+ s.analyzeOperation("GET", path, op.Get)
+ s.analyzeOperation("PUT", path, op.Put)
+ s.analyzeOperation("POST", path, op.Post)
+ s.analyzeOperation("PATCH", path, op.Patch)
+ s.analyzeOperation("DELETE", path, op.Delete)
+ s.analyzeOperation("HEAD", path, op.Head)
+ s.analyzeOperation("OPTIONS", path, op.Options)
+ for i, param := range op.Parameters {
+ refPref := slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i))
+ if param.Ref.String() != "" {
+ s.references.addParamRef(refPref, ¶m) //#nosec
+ }
+ if param.Pattern != "" {
+ s.patterns.addParameterPattern(refPref, param.Pattern)
+ }
+ if len(param.Enum) > 0 {
+ s.enums.addParameterEnum(refPref, param.Enum)
+ }
+ if param.Items != nil {
+ s.analyzeItems("items", param.Items, refPref, "parameter")
+ }
+ if param.Schema != nil {
+ s.analyzeSchema("schema", param.Schema, refPref)
+ }
+ }
+}
+
+func (s *Spec) analyzeItems(name string, items *spec.Items, prefix, location string) {
+ if items == nil {
+ return
+ }
+ refPref := slashpath.Join(prefix, name)
+ s.analyzeItems(name, items.Items, refPref, location)
+ if items.Ref.String() != "" {
+ s.references.addItemsRef(refPref, items, location)
+ }
+ if items.Pattern != "" {
+ s.patterns.addItemsPattern(refPref, items.Pattern)
+ }
+ if len(items.Enum) > 0 {
+ s.enums.addItemsEnum(refPref, items.Enum)
+ }
+}
+
+func (s *Spec) analyzeParameter(prefix string, i int, param spec.Parameter) {
+ refPref := slashpath.Join(prefix, "parameters", strconv.Itoa(i))
+ if param.Ref.String() != "" {
+ s.references.addParamRef(refPref, ¶m) //#nosec
+ }
+
+ if param.Pattern != "" {
+ s.patterns.addParameterPattern(refPref, param.Pattern)
+ }
+
+ if len(param.Enum) > 0 {
+ s.enums.addParameterEnum(refPref, param.Enum)
+ }
+
+ s.analyzeItems("items", param.Items, refPref, "parameter")
+ if param.In == "body" && param.Schema != nil {
+ s.analyzeSchema("schema", param.Schema, refPref)
+ }
+}
+
+func (s *Spec) analyzeOperation(method, path string, op *spec.Operation) {
+ if op == nil {
+ return
+ }
+
+ for _, c := range op.Consumes {
+ s.consumes[c] = struct{}{}
+ }
+
+ for _, c := range op.Produces {
+ s.produces[c] = struct{}{}
+ }
+
+ for _, ss := range op.Security {
+ for k := range ss {
+ s.authSchemes[k] = struct{}{}
+ }
+ }
+
+ if _, ok := s.operations[method]; !ok {
+ s.operations[method] = make(map[string]*spec.Operation)
+ }
+
+ s.operations[method][path] = op
+ prefix := slashpath.Join("/paths", jsonpointer.Escape(path), strings.ToLower(method))
+ for i, param := range op.Parameters {
+ s.analyzeParameter(prefix, i, param)
+ }
+
+ if op.Responses == nil {
+ return
+ }
+
+ if op.Responses.Default != nil {
+ s.analyzeDefaultResponse(prefix, op.Responses.Default)
+ }
+
+ for k, res := range op.Responses.StatusCodeResponses {
+ s.analyzeResponse(prefix, k, res)
+ }
+}
+
+func (s *Spec) analyzeDefaultResponse(prefix string, res *spec.Response) {
+ refPref := slashpath.Join(prefix, "responses", "default")
+ if res.Ref.String() != "" {
+ s.references.addResponseRef(refPref, res)
+ }
+
+ for k, v := range res.Headers {
+ hRefPref := slashpath.Join(refPref, "headers", k)
+ s.analyzeItems("items", v.Items, hRefPref, "header")
+ if v.Pattern != "" {
+ s.patterns.addHeaderPattern(hRefPref, v.Pattern)
+ }
+ }
+
+ if res.Schema != nil {
+ s.analyzeSchema("schema", res.Schema, refPref)
+ }
+}
+
+func (s *Spec) analyzeResponse(prefix string, k int, res spec.Response) {
+ refPref := slashpath.Join(prefix, "responses", strconv.Itoa(k))
+ if res.Ref.String() != "" {
+ s.references.addResponseRef(refPref, &res) //#nosec
+ }
+
+ for k, v := range res.Headers {
+ hRefPref := slashpath.Join(refPref, "headers", k)
+ s.analyzeItems("items", v.Items, hRefPref, "header")
+ if v.Pattern != "" {
+ s.patterns.addHeaderPattern(hRefPref, v.Pattern)
+ }
+
+ if len(v.Enum) > 0 {
+ s.enums.addHeaderEnum(hRefPref, v.Enum)
+ }
+ }
+
+ if res.Schema != nil {
+ s.analyzeSchema("schema", res.Schema, refPref)
+ }
+}
+
+func (s *Spec) analyzeSchema(name string, schema *spec.Schema, prefix string) {
+ refURI := slashpath.Join(prefix, jsonpointer.Escape(name))
+ schRef := SchemaRef{
+ Name: name,
+ Schema: schema,
+ Ref: spec.MustCreateRef("#" + refURI),
+ TopLevel: prefix == "/definitions",
+ }
+
+ s.allSchemas["#"+refURI] = schRef
+
+ if schema.Ref.String() != "" {
+ s.references.addSchemaRef(refURI, schRef)
+ }
+
+ if schema.Pattern != "" {
+ s.patterns.addSchemaPattern(refURI, schema.Pattern)
+ }
+
+ if len(schema.Enum) > 0 {
+ s.enums.addSchemaEnum(refURI, schema.Enum)
+ }
+
+ for k, v := range schema.Definitions {
+ s.analyzeSchema(k, &v, slashpath.Join(refURI, "definitions"))
+ }
+
+ for k, v := range schema.Properties {
+ s.analyzeSchema(k, &v, slashpath.Join(refURI, "properties"))
+ }
+
+ for k, v := range schema.PatternProperties {
+ // NOTE: swagger 2.0 does not support PatternProperties.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema(k, &v, slashpath.Join(refURI, "patternProperties"))
+ }
+
+ for i := range schema.AllOf {
+ v := &schema.AllOf[i]
+ s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "allOf"))
+ }
+
+ if len(schema.AllOf) > 0 {
+ s.allOfs["#"+refURI] = schRef
+ }
+
+ for i := range schema.AnyOf {
+ v := &schema.AnyOf[i]
+ // NOTE: swagger 2.0 does not support anyOf constructs.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "anyOf"))
+ }
+
+ for i := range schema.OneOf {
+ v := &schema.OneOf[i]
+ // NOTE: swagger 2.0 does not support oneOf constructs.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "oneOf"))
+ }
+
+ if schema.Not != nil {
+ // NOTE: swagger 2.0 does not support "not" constructs.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema("not", schema.Not, refURI)
+ }
+
+ if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
+ s.analyzeSchema("additionalProperties", schema.AdditionalProperties.Schema, refURI)
+ }
+
+ if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
+ // NOTE: swagger 2.0 does not support AdditionalItems.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema("additionalItems", schema.AdditionalItems.Schema, refURI)
+ }
+
+ if schema.Items != nil {
+ if schema.Items.Schema != nil {
+ s.analyzeSchema("items", schema.Items.Schema, refURI)
+ }
+
+ for i := range schema.Items.Schemas {
+ sch := &schema.Items.Schemas[i]
+ s.analyzeSchema(strconv.Itoa(i), sch, slashpath.Join(refURI, "items"))
+ }
+ }
+}
+
+func cloneStringMap(source map[string]string) map[string]string {
+ res := make(map[string]string, len(source))
+ maps.Copy(res, source)
+
+ return res
+}
+
+func cloneEnumMap(source map[string][]any) map[string][]any {
+ res := make(map[string][]any, len(source))
+ maps.Copy(res, source)
+
+ return res
+}
diff --git a/vendor/github.com/go-openapi/analysis/debug.go b/vendor/github.com/go-openapi/analysis/debug.go
new file mode 100644
index 000000000000..d490eab60636
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/debug.go
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "os"
+
+ "github.com/go-openapi/analysis/internal/debug"
+)
+
+var debugLog = debug.GetLogger("analysis", os.Getenv("SWAGGER_DEBUG") != "")
diff --git a/vendor/github.com/go-openapi/analysis/doc.go b/vendor/github.com/go-openapi/analysis/doc.go
new file mode 100644
index 000000000000..9d41371a9f07
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/doc.go
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+Package analysis provides methods to work with a Swagger specification document from
+package go-openapi/spec.
+
+## Analyzing a specification
+
+An analysed specification object (type Spec) provides methods to work with swagger definition.
+
+## Flattening or expanding a specification
+
+Flattening a specification bundles all remote $ref in the main spec document.
+Depending on flattening options, additional preprocessing may take place:
+ - full flattening: replacing all inline complex constructs by a named entry in #/definitions
+ - expand: replace all $ref's in the document by their expanded content
+
+## Merging several specifications
+
+Mixin several specifications merges all Swagger constructs, and warns about found conflicts.
+
+## Fixing a specification
+
+Unmarshalling a specification with golang json unmarshalling may lead to
+some unwanted result on present but empty fields.
+
+## Analyzing a Swagger schema
+
+Swagger schemas are analyzed to determine their complexity and qualify their content.
+*/
+package analysis
diff --git a/vendor/github.com/go-openapi/analysis/errors.go b/vendor/github.com/go-openapi/analysis/errors.go
new file mode 100644
index 000000000000..540e159a23ce
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/errors.go
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "errors"
+ "fmt"
+)
+
+type analysisError string
+
+const (
+ ErrAnalysis analysisError = "analysis error"
+ ErrNoSchema analysisError = "no schema to analyze"
+)
+
+func (e analysisError) Error() string {
+ return string(e)
+}
+
+func ErrAtKey(key string, err error) error {
+ return errors.Join(
+ fmt.Errorf("key %s: %w", key, err),
+ ErrAnalysis,
+ )
+}
+
+func ErrInvalidRef(key string) error {
+ return fmt.Errorf("invalid reference: %q: %w", key, ErrAnalysis)
+}
+
+func ErrInvalidParameterRef(key string) error {
+ return fmt.Errorf("resolved reference is not a parameter: %q: %w", key, ErrAnalysis)
+}
+
+func ErrResolveSchema(err error) error {
+ return errors.Join(
+ fmt.Errorf("could not resolve schema: %w", err),
+ ErrAnalysis,
+ )
+}
+
+func ErrRewriteRef(key string, target any, err error) error {
+ return errors.Join(
+ fmt.Errorf("failed to rewrite ref for key %q at %v: %w", key, target, err),
+ ErrAnalysis,
+ )
+}
+
+func ErrInlineDefinition(key string, err error) error {
+ return errors.Join(
+ fmt.Errorf("error while creating definition %q from inline schema: %w", key, err),
+ ErrAnalysis,
+ )
+}
diff --git a/vendor/github.com/go-openapi/analysis/fixer.go b/vendor/github.com/go-openapi/analysis/fixer.go
new file mode 100644
index 000000000000..74becbbe4962
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/fixer.go
@@ -0,0 +1,68 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import "github.com/go-openapi/spec"
+
+// FixEmptyResponseDescriptions replaces empty ("") response
+// descriptions in the input with "(empty)" to ensure that the
+// resulting Swagger is stays valid. The problem appears to arise
+// from reading in valid specs that have a explicit response
+// description of "" (valid, response.description is required), but
+// due to zero values being omitted upon re-serializing (omitempty) we
+// lose them unless we stick some chars in there.
+func FixEmptyResponseDescriptions(s *spec.Swagger) {
+ for k, v := range s.Responses {
+ FixEmptyDesc(&v) //#nosec
+ s.Responses[k] = v
+ }
+
+ if s.Paths == nil {
+ return
+ }
+
+ for _, v := range s.Paths.Paths {
+ if v.Get != nil {
+ FixEmptyDescs(v.Get.Responses)
+ }
+ if v.Put != nil {
+ FixEmptyDescs(v.Put.Responses)
+ }
+ if v.Post != nil {
+ FixEmptyDescs(v.Post.Responses)
+ }
+ if v.Delete != nil {
+ FixEmptyDescs(v.Delete.Responses)
+ }
+ if v.Options != nil {
+ FixEmptyDescs(v.Options.Responses)
+ }
+ if v.Head != nil {
+ FixEmptyDescs(v.Head.Responses)
+ }
+ if v.Patch != nil {
+ FixEmptyDescs(v.Patch.Responses)
+ }
+ }
+}
+
+// FixEmptyDescs adds "(empty)" as the description for any Response in
+// the given Responses object that doesn't already have one.
+func FixEmptyDescs(rs *spec.Responses) {
+ FixEmptyDesc(rs.Default)
+ for k, v := range rs.StatusCodeResponses {
+ FixEmptyDesc(&v) //#nosec
+ rs.StatusCodeResponses[k] = v
+ }
+}
+
+// FixEmptyDesc adds "(empty)" as the description to the given
+// Response object if it doesn't already have one and isn't a
+// ref. No-op on nil input.
+func FixEmptyDesc(rs *spec.Response) {
+ if rs == nil || rs.Description != "" || rs.Ref.GetURL() != nil {
+ return
+ }
+ rs.Description = "(empty)"
+}
diff --git a/vendor/github.com/go-openapi/analysis/flatten.go b/vendor/github.com/go-openapi/analysis/flatten.go
new file mode 100644
index 000000000000..1c7a49c034f2
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/flatten.go
@@ -0,0 +1,796 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "log"
+ "path"
+ "slices"
+ "sort"
+ "strings"
+
+ "github.com/go-openapi/analysis/internal/flatten/normalize"
+ "github.com/go-openapi/analysis/internal/flatten/operations"
+ "github.com/go-openapi/analysis/internal/flatten/replace"
+ "github.com/go-openapi/analysis/internal/flatten/schutils"
+ "github.com/go-openapi/analysis/internal/flatten/sortref"
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/spec"
+)
+
+const definitionsPath = "#/definitions"
+
+// newRef stores information about refs created during the flattening process
+type newRef struct {
+ key string
+ newName string
+ path string
+ isOAIGen bool
+ resolved bool
+ schema *spec.Schema
+ parents []string
+}
+
+// context stores intermediary results from flatten
+type context struct {
+ newRefs map[string]*newRef
+ warnings []string
+ resolved map[string]string
+}
+
+func newContext() *context {
+ return &context{
+ newRefs: make(map[string]*newRef, allocMediumMap),
+ warnings: make([]string, 0),
+ resolved: make(map[string]string, allocMediumMap),
+ }
+}
+
+// Flatten an analyzed spec and produce a self-contained spec bundle.
+//
+// There is a minimal and a full flattening mode.
+//
+// Minimally flattening a spec means:
+// - Expanding parameters, responses, path items, parameter items and header items (references to schemas are left
+// unscathed)
+// - Importing external (http, file) references so they become internal to the document
+// - Moving every JSON pointer to a $ref to a named definition (i.e. the reworked spec does not contain pointers
+// like "$ref": "#/definitions/myObject/allOfs/1")
+//
+// A minimally flattened spec thus guarantees the following properties:
+// - all $refs point to a local definition (i.e. '#/definitions/...')
+// - definitions are unique
+//
+// NOTE: arbitrary JSON pointers (other than $refs to top level definitions) are rewritten as definitions if they
+// represent a complex schema or express commonality in the spec.
+// Otherwise, they are simply expanded.
+// Self-referencing JSON pointers cannot resolve to a type and trigger an error.
+//
+// Minimal flattening is necessary and sufficient for codegen rendering using go-swagger.
+//
+// Fully flattening a spec means:
+// - Moving every complex inline schema to be a definition with an auto-generated name in a depth-first fashion.
+//
+// By complex, we mean every JSON object with some properties.
+// Arrays, when they do not define a tuple,
+// or empty objects with or without additionalProperties, are not considered complex and remain inline.
+//
+// NOTE: rewritten schemas get a vendor extension x-go-gen-location so we know from which part of the spec definitions
+// have been created.
+//
+// Available flattening options:
+// - Minimal: stops flattening after minimal $ref processing, leaving schema constructs untouched
+// - Expand: expand all $ref's in the document (inoperant if Minimal set to true)
+// - Verbose: croaks about name conflicts detected
+// - RemoveUnused: removes unused parameters, responses and definitions after expansion/flattening
+//
+// NOTE: expansion removes all $ref save circular $ref, which remain in place
+//
+// TODO: additional options
+// - ProgagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
+// x-go-name extension
+// - LiftAllOfs:
+// - limit the flattening of allOf members when simple objects
+// - merge allOf with validation only
+// - merge allOf with extensions only
+// - ...
+func Flatten(opts FlattenOpts) error {
+ debugLog("FlattenOpts: %#v", opts)
+
+ opts.flattenContext = newContext()
+
+ // 1. Recursively expand responses, parameters, path items and items in simple schemas.
+ //
+ // This simplifies the spec and leaves only the $ref's in schema objects.
+ if err := expand(&opts); err != nil {
+ return err
+ }
+
+ // 2. Strip the current document from absolute $ref's that actually a in the root,
+ // so we can recognize them as proper definitions
+ //
+ // In particular, this works around issue go-openapi/spec#76: leading absolute file in $ref is stripped
+ if err := normalizeRef(&opts); err != nil {
+ return err
+ }
+
+ // 3. Optionally remove shared parameters and responses already expanded (now unused).
+ //
+ // Operation parameters (i.e. under paths) remain.
+ if opts.RemoveUnused {
+ removeUnusedShared(&opts)
+ }
+
+ // 4. Import all remote references.
+ if err := importReferences(&opts); err != nil {
+ return err
+ }
+
+ // 5. full flattening: rewrite inline schemas (schemas that aren't simple types or arrays or maps)
+ if !opts.Minimal && !opts.Expand {
+ if err := nameInlinedSchemas(&opts); err != nil {
+ return err
+ }
+ }
+
+ // 6. Rewrite JSON pointers other than $ref to named definitions
+ // and attempt to resolve conflicting names whenever possible.
+ if err := stripPointersAndOAIGen(&opts); err != nil {
+ return err
+ }
+
+ // 7. Strip the spec from unused definitions
+ if opts.RemoveUnused {
+ removeUnused(&opts)
+ }
+
+ // 8. Issue warning notifications, if any
+ opts.croak()
+
+ // TODO: simplify known schema patterns to flat objects with properties
+ // examples:
+ // - lift simple allOf object,
+ // - empty allOf with validation only or extensions only
+ // - rework allOf arrays
+ // - rework allOf additionalProperties
+
+ return nil
+}
+
+func expand(opts *FlattenOpts) error {
+ if err := spec.ExpandSpec(opts.Swagger(), opts.ExpandOpts(!opts.Expand)); err != nil {
+ return err
+ }
+
+ opts.Spec.reload() // re-analyze
+
+ return nil
+}
+
+// normalizeRef strips the current file from any absolute file $ref. This works around issue go-openapi/spec#76:
+// leading absolute file in $ref is stripped
+func normalizeRef(opts *FlattenOpts) error {
+ debugLog("normalizeRef")
+
+ altered := false
+ for k, w := range opts.Spec.references.allRefs {
+ if !strings.HasPrefix(w.String(), opts.BasePath+definitionsPath) { // may be a mix of / and \, depending on OS
+ continue
+ }
+
+ altered = true
+ debugLog("stripping absolute path for: %s", w.String())
+
+ // strip the base path from definition
+ if err := replace.UpdateRef(opts.Swagger(), k,
+ spec.MustCreateRef(path.Join(definitionsPath, path.Base(w.String())))); err != nil {
+ return err
+ }
+ }
+
+ if altered {
+ opts.Spec.reload() // re-analyze
+ }
+
+ return nil
+}
+
+func removeUnusedShared(opts *FlattenOpts) {
+ opts.Swagger().Parameters = nil
+ opts.Swagger().Responses = nil
+
+ opts.Spec.reload() // re-analyze
+}
+
+func importReferences(opts *FlattenOpts) error {
+ var (
+ imported bool
+ err error
+ )
+
+ for !imported && err == nil {
+ // iteratively import remote references until none left.
+ // This inlining deals with name conflicts by introducing auto-generated names ("OAIGen")
+ imported, err = importExternalReferences(opts)
+
+ opts.Spec.reload() // re-analyze
+ }
+
+ return err
+}
+
+// nameInlinedSchemas replaces every complex inline construct by a named definition.
+func nameInlinedSchemas(opts *FlattenOpts) error {
+ debugLog("nameInlinedSchemas")
+
+ namer := &InlineSchemaNamer{
+ Spec: opts.Swagger(),
+ Operations: operations.AllOpRefsByRef(opts.Spec, nil),
+ flattenContext: opts.flattenContext,
+ opts: opts,
+ }
+
+ depthFirst := sortref.DepthFirst(opts.Spec.allSchemas)
+ for _, key := range depthFirst {
+ sch := opts.Spec.allSchemas[key]
+ if sch.Schema == nil || sch.Schema.Ref.String() != "" || sch.TopLevel {
+ continue
+ }
+
+ asch, err := Schema(SchemaOpts{Schema: sch.Schema, Root: opts.Swagger(), BasePath: opts.BasePath})
+ if err != nil {
+ return ErrAtKey(key, err)
+ }
+
+ if asch.isAnalyzedAsComplex() { // move complex schemas to definitions
+ if err := namer.Name(key, sch.Schema, asch); err != nil {
+ return err
+ }
+ }
+ }
+
+ opts.Spec.reload() // re-analyze
+
+ return nil
+}
+
+func removeUnused(opts *FlattenOpts) {
+ for removeUnusedSinglePass(opts) {
+ // continue until no unused definition remains
+ }
+}
+
+func removeUnusedSinglePass(opts *FlattenOpts) (hasRemoved bool) {
+ expected := make(map[string]struct{})
+ for k := range opts.Swagger().Definitions {
+ expected[path.Join(definitionsPath, jsonpointer.Escape(k))] = struct{}{}
+ }
+
+ for _, k := range opts.Spec.AllDefinitionReferences() {
+ delete(expected, k)
+ }
+
+ for k := range expected {
+ hasRemoved = true
+ debugLog("removing unused definition %s", path.Base(k))
+ if opts.Verbose {
+ log.Printf("info: removing unused definition: %s", path.Base(k))
+ }
+ delete(opts.Swagger().Definitions, path.Base(k))
+ }
+
+ opts.Spec.reload() // re-analyze
+
+ return hasRemoved
+}
+
+func importKnownRef(entry sortref.RefRevIdx, refStr, newName string, opts *FlattenOpts) error {
+ // rewrite ref with already resolved external ref (useful for cyclical refs):
+ // rewrite external refs to local ones
+ debugLog("resolving known ref [%s] to %s", refStr, newName)
+
+ for _, key := range entry.Keys {
+ if err := replace.UpdateRef(opts.Swagger(), key, spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func importNewRef(entry sortref.RefRevIdx, refStr string, opts *FlattenOpts) error {
+ var (
+ isOAIGen bool
+ newName string
+ )
+
+ debugLog("resolving schema from remote $ref [%s]", refStr)
+
+ sch, err := spec.ResolveRefWithBase(opts.Swagger(), &entry.Ref, opts.ExpandOpts(false))
+ if err != nil {
+ return ErrResolveSchema(err)
+ }
+
+ // at this stage only $ref analysis matters
+ partialAnalyzer := &Spec{
+ references: referenceAnalysis{},
+ patterns: patternAnalysis{},
+ enums: enumAnalysis{},
+ }
+ partialAnalyzer.reset()
+ partialAnalyzer.analyzeSchema("", sch, "/")
+
+ // now rewrite those refs with rebase
+ for key, ref := range partialAnalyzer.references.allRefs {
+ if err := replace.UpdateRef(sch, key, spec.MustCreateRef(normalize.RebaseRef(entry.Ref.String(), ref.String()))); err != nil {
+ return ErrRewriteRef(key, entry.Ref.String(), err)
+ }
+ }
+
+ // generate a unique name - isOAIGen means that a naming conflict was resolved by changing the name
+ newName, isOAIGen = uniqifyName(opts.Swagger().Definitions, nameFromRef(entry.Ref, opts))
+ debugLog("new name for [%s]: %s - with name conflict:%t", strings.Join(entry.Keys, ", "), newName, isOAIGen)
+
+ opts.flattenContext.resolved[refStr] = newName
+
+ // rewrite the external refs to local ones
+ for _, key := range entry.Keys {
+ if err := replace.UpdateRef(opts.Swagger(), key,
+ spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
+ return err
+ }
+
+ // keep track of created refs
+ resolved := false
+ if _, ok := opts.flattenContext.newRefs[key]; ok {
+ resolved = opts.flattenContext.newRefs[key].resolved
+ }
+
+ debugLog("keeping track of ref: %s (%s), resolved: %t", key, newName, resolved)
+ opts.flattenContext.newRefs[key] = &newRef{
+ key: key,
+ newName: newName,
+ path: path.Join(definitionsPath, newName),
+ isOAIGen: isOAIGen,
+ resolved: resolved,
+ schema: sch,
+ }
+ }
+
+ // add the resolved schema to the definitions
+ schutils.Save(opts.Swagger(), newName, sch)
+
+ return nil
+}
+
+// importExternalReferences iteratively digs remote references and imports them into the main schema.
+//
+// At every iteration, new remotes may be found when digging deeper: they are rebased to the current schema before being imported.
+//
+// This returns true when no more remote references can be found.
+func importExternalReferences(opts *FlattenOpts) (bool, error) {
+ debugLog("importExternalReferences")
+
+ groupedRefs := sortref.ReverseIndex(opts.Spec.references.schemas, opts.BasePath)
+ sortedRefStr := make([]string, 0, len(groupedRefs))
+ if opts.flattenContext == nil {
+ opts.flattenContext = newContext()
+ }
+
+ // sort $ref resolution to ensure deterministic name conflict resolution
+ for refStr := range groupedRefs {
+ sortedRefStr = append(sortedRefStr, refStr)
+ }
+ sort.Strings(sortedRefStr)
+
+ complete := true
+
+ for _, refStr := range sortedRefStr {
+ entry := groupedRefs[refStr]
+ if entry.Ref.HasFragmentOnly {
+ continue
+ }
+
+ complete = false
+
+ newName := opts.flattenContext.resolved[refStr]
+ if newName != "" {
+ if err := importKnownRef(entry, refStr, newName, opts); err != nil {
+ return false, err
+ }
+
+ continue
+ }
+
+ // resolve schemas
+ if err := importNewRef(entry, refStr, opts); err != nil {
+ return false, err
+ }
+ }
+
+ // maintains ref index entries
+ for k := range opts.flattenContext.newRefs {
+ r := opts.flattenContext.newRefs[k]
+
+ // update tracking with resolved schemas
+ if r.schema.Ref.String() != "" {
+ ref := spec.MustCreateRef(r.path)
+ sch, err := spec.ResolveRefWithBase(opts.Swagger(), &ref, opts.ExpandOpts(false))
+ if err != nil {
+ return false, ErrResolveSchema(err)
+ }
+
+ r.schema = sch
+ }
+
+ if r.path == k {
+ continue
+ }
+
+ // update tracking with renamed keys: got a cascade of refs
+ renamed := *r
+ renamed.key = r.path
+ opts.flattenContext.newRefs[renamed.path] = &renamed
+
+ // indirect ref
+ r.newName = path.Base(k)
+ r.schema = spec.RefSchema(r.path)
+ r.path = k
+ r.isOAIGen = strings.Contains(k, "OAIGen")
+ }
+
+ return complete, nil
+}
+
+// stripPointersAndOAIGen removes anonymous JSON pointers from spec and chain with name conflicts handler.
+// This loops until the spec has no such pointer and all name conflicts have been reduced as much as possible.
+func stripPointersAndOAIGen(opts *FlattenOpts) error {
+ // name all JSON pointers to anonymous documents
+ if err := namePointers(opts); err != nil {
+ return err
+ }
+
+ // remove unnecessary OAIGen ref (created when flattening external refs creates name conflicts)
+ hasIntroducedPointerOrInline, ers := stripOAIGen(opts)
+ if ers != nil {
+ return ers
+ }
+
+ // iterate as pointer or OAIGen resolution may introduce inline schemas or pointers
+ for hasIntroducedPointerOrInline {
+ if !opts.Minimal {
+ opts.Spec.reload() // re-analyze
+ if err := nameInlinedSchemas(opts); err != nil {
+ return err
+ }
+ }
+
+ if err := namePointers(opts); err != nil {
+ return err
+ }
+
+ // restrip and re-analyze
+ var err error
+ if hasIntroducedPointerOrInline, err = stripOAIGen(opts); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// stripOAIGen strips the spec from unnecessary OAIGen constructs, initially created to dedupe flattened definitions.
+//
+// A dedupe is deemed unnecessary whenever:
+// - the only conflict is with its (single) parent: OAIGen is merged into its parent (reinlining)
+// - there is a conflict with multiple parents: merge OAIGen in first parent, the rewrite other parents to point to
+// the first parent.
+//
+// This function returns true whenever it re-inlined a complex schema, so the caller may chose to iterate
+// pointer and name resolution again.
+func stripOAIGen(opts *FlattenOpts) (bool, error) {
+ debugLog("stripOAIGen")
+ replacedWithComplex := false
+
+ // figure out referers of OAIGen definitions (doing it before the ref start mutating)
+ for _, r := range opts.flattenContext.newRefs {
+ updateRefParents(opts.Spec.references.allRefs, r)
+ }
+
+ for k := range opts.flattenContext.newRefs {
+ r := opts.flattenContext.newRefs[k]
+ debugLog("newRefs[%s]: isOAIGen: %t, resolved: %t, name: %s, path:%s, #parents: %d, parents: %v, ref: %s",
+ k, r.isOAIGen, r.resolved, r.newName, r.path, len(r.parents), r.parents, r.schema.Ref.String())
+
+ if !r.isOAIGen || len(r.parents) == 0 {
+ continue
+ }
+
+ hasReplacedWithComplex, err := stripOAIGenForRef(opts, k, r)
+ if err != nil {
+ return replacedWithComplex, err
+ }
+
+ replacedWithComplex = replacedWithComplex || hasReplacedWithComplex
+ }
+
+ debugLog("replacedWithComplex: %t", replacedWithComplex)
+ opts.Spec.reload() // re-analyze
+
+ return replacedWithComplex, nil
+}
+
+// updateRefParents updates all parents of an updated $ref
+func updateRefParents(allRefs map[string]spec.Ref, r *newRef) {
+ if !r.isOAIGen || r.resolved { // bail on already resolved entries (avoid looping)
+ return
+ }
+ for k, v := range allRefs {
+ if r.path != v.String() {
+ continue
+ }
+
+ found := slices.Contains(r.parents, k)
+ if !found {
+ r.parents = append(r.parents, k)
+ }
+ }
+}
+
+func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) {
+ replacedWithComplex := false
+
+ pr := sortref.TopmostFirst(r.parents)
+
+ // rewrite first parent schema in hierarchical then lexicographical order
+ debugLog("rewrite first parent %s with schema", pr[0])
+ if err := replace.UpdateRefWithSchema(opts.Swagger(), pr[0], r.schema); err != nil {
+ return false, err
+ }
+
+ if pa, ok := opts.flattenContext.newRefs[pr[0]]; ok && pa.isOAIGen {
+ // update parent in ref index entry
+ debugLog("update parent entry: %s", pr[0])
+ pa.schema = r.schema
+ pa.resolved = false
+ replacedWithComplex = true
+ }
+
+ // rewrite other parents to point to first parent
+ if len(pr) > 1 {
+ for _, p := range pr[1:] {
+ replacingRef := spec.MustCreateRef(pr[0])
+
+ // set complex when replacing ref is an anonymous jsonpointer: further processing may be required
+ replacedWithComplex = replacedWithComplex || path.Dir(replacingRef.String()) != definitionsPath
+ debugLog("rewrite parent with ref: %s", replacingRef.String())
+
+ // NOTE: it is possible at this stage to introduce json pointers (to non-definitions places).
+ // Those are stripped later on.
+ if err := replace.UpdateRef(opts.Swagger(), p, replacingRef); err != nil {
+ return false, err
+ }
+
+ if pa, ok := opts.flattenContext.newRefs[p]; ok && pa.isOAIGen {
+ // update parent in ref index
+ debugLog("update parent entry: %s", p)
+ pa.schema = r.schema
+ pa.resolved = false
+ replacedWithComplex = true
+ }
+ }
+ }
+
+ // remove OAIGen definition
+ debugLog("removing definition %s", path.Base(r.path))
+ delete(opts.Swagger().Definitions, path.Base(r.path))
+
+ // propagate changes in ref index for keys which have this one as a parent
+ for kk, value := range opts.flattenContext.newRefs {
+ if kk == k || !value.isOAIGen || value.resolved {
+ continue
+ }
+
+ found := false
+ newParents := make([]string, 0, len(value.parents))
+ for _, parent := range value.parents {
+ switch {
+ case parent == r.path:
+ found = true
+ parent = pr[0]
+ case strings.HasPrefix(parent, r.path+"/"):
+ found = true
+ parent = path.Join(pr[0], strings.TrimPrefix(parent, r.path))
+ }
+
+ newParents = append(newParents, parent)
+ }
+
+ if found {
+ value.parents = newParents
+ }
+ }
+
+ // mark naming conflict as resolved
+ debugLog("marking naming conflict resolved for key: %s", r.key)
+ opts.flattenContext.newRefs[r.key].isOAIGen = false
+ opts.flattenContext.newRefs[r.key].resolved = true
+
+ // determine if the previous substitution did inline a complex schema
+ if r.schema != nil && r.schema.Ref.String() == "" { // inline schema
+ asch, err := Schema(SchemaOpts{Schema: r.schema, Root: opts.Swagger(), BasePath: opts.BasePath})
+ if err != nil {
+ return false, err
+ }
+
+ debugLog("re-inlined schema: parent: %s, %t", pr[0], asch.isAnalyzedAsComplex())
+ replacedWithComplex = replacedWithComplex || path.Dir(pr[0]) != definitionsPath && asch.isAnalyzedAsComplex()
+ }
+
+ return replacedWithComplex, nil
+}
+
+// namePointers replaces all JSON pointers to anonymous documents by a $ref to a new named definitions.
+//
+// This is carried on depth-first. Pointers to $refs which are top level definitions are replaced by the $ref itself.
+// Pointers to simple types are expanded, unless they express commonality (i.e. several such $ref are used).
+func namePointers(opts *FlattenOpts) error {
+ debugLog("name pointers")
+
+ refsToReplace := make(map[string]SchemaRef, len(opts.Spec.references.schemas))
+ for k, ref := range opts.Spec.references.allRefs {
+ debugLog("name pointers: %q => %#v", k, ref)
+ if path.Dir(ref.String()) == definitionsPath {
+ // this a ref to a top-level definition: ok
+ continue
+ }
+
+ result, err := replace.DeepestRef(opts.Swagger(), opts.ExpandOpts(false), ref)
+ if err != nil {
+ return ErrAtKey(k, err)
+ }
+
+ replacingRef := result.Ref
+ sch := result.Schema
+ if opts.flattenContext != nil {
+ opts.flattenContext.warnings = append(opts.flattenContext.warnings, result.Warnings...)
+ }
+
+ debugLog("planning pointer to replace at %s: %s, resolved to: %s", k, ref.String(), replacingRef.String())
+ refsToReplace[k] = SchemaRef{
+ Name: k, // caller
+ Ref: replacingRef, // called
+ Schema: sch,
+ TopLevel: path.Dir(replacingRef.String()) == definitionsPath,
+ }
+ }
+
+ depthFirst := sortref.DepthFirst(refsToReplace)
+ namer := &InlineSchemaNamer{
+ Spec: opts.Swagger(),
+ Operations: operations.AllOpRefsByRef(opts.Spec, nil),
+ flattenContext: opts.flattenContext,
+ opts: opts,
+ }
+
+ for _, key := range depthFirst {
+ v := refsToReplace[key]
+ // update current replacement, which may have been updated by previous changes of deeper elements
+ result, erd := replace.DeepestRef(opts.Swagger(), opts.ExpandOpts(false), v.Ref)
+ if erd != nil {
+ return ErrAtKey(key, erd)
+ }
+
+ if opts.flattenContext != nil {
+ opts.flattenContext.warnings = append(opts.flattenContext.warnings, result.Warnings...)
+ }
+
+ v.Ref = result.Ref
+ v.Schema = result.Schema
+ v.TopLevel = path.Dir(result.Ref.String()) == definitionsPath
+ debugLog("replacing pointer at %s: resolved to: %s", key, v.Ref.String())
+
+ if v.TopLevel {
+ debugLog("replace pointer %s by canonical definition: %s", key, v.Ref.String())
+
+ // if the schema is a $ref to a top level definition, just rewrite the pointer to this $ref
+ if err := replace.UpdateRef(opts.Swagger(), key, v.Ref); err != nil {
+ return err
+ }
+
+ continue
+ }
+
+ if err := flattenAnonPointer(key, v, refsToReplace, namer, opts); err != nil {
+ return err
+ }
+ }
+
+ opts.Spec.reload() // re-analyze
+
+ return nil
+}
+
+func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]SchemaRef, namer *InlineSchemaNamer, opts *FlattenOpts) error {
+ // this is a JSON pointer to an anonymous document (internal or external):
+ // create a definition for this schema when:
+ // - it is a complex schema
+ // - or it is pointed by more than one $ref (i.e. expresses commonality)
+ // otherwise, expand the pointer (single reference to a simple type)
+ //
+ // The named definition for this follows the target's key, not the caller's
+ debugLog("namePointers at %s for %s", key, v.Ref.String())
+
+ // qualify the expanded schema
+ asch, ers := Schema(SchemaOpts{Schema: v.Schema, Root: opts.Swagger(), BasePath: opts.BasePath})
+ if ers != nil {
+ return ErrAtKey(key, ers)
+ }
+ callers := make([]string, 0, allocMediumMap)
+
+ debugLog("looking for callers")
+
+ an := New(opts.Swagger())
+ for k, w := range an.references.allRefs {
+ r, err := replace.DeepestRef(opts.Swagger(), opts.ExpandOpts(false), w)
+ if err != nil {
+ return ErrAtKey(key, err)
+ }
+
+ if opts.flattenContext != nil {
+ opts.flattenContext.warnings = append(opts.flattenContext.warnings, r.Warnings...)
+ }
+
+ if r.Ref.String() == v.Ref.String() {
+ callers = append(callers, k)
+ }
+ }
+
+ debugLog("callers for %s: %d", v.Ref.String(), len(callers))
+ if len(callers) == 0 {
+ // has already been updated and resolved
+ return nil
+ }
+
+ parts := sortref.KeyParts(v.Ref.String())
+ debugLog("number of callers for %s: %d", v.Ref.String(), len(callers))
+
+ // identifying edge case when the namer did nothing because we point to a non-schema object
+ // no definition is created and we expand the $ref for all callers
+ debugLog("decide what to do with the schema pointed to: asch.IsSimpleSchema=%t, len(callers)=%d, parts.IsSharedParam=%t, parts.IsSharedResponse=%t",
+ asch.IsSimpleSchema, len(callers), parts.IsSharedParam(), parts.IsSharedResponse(),
+ )
+
+ if (!asch.IsSimpleSchema || len(callers) > 1) && !parts.IsSharedParam() && !parts.IsSharedResponse() {
+ debugLog("replace JSON pointer at [%s] by definition: %s", key, v.Ref.String())
+ if err := namer.Name(v.Ref.String(), v.Schema, asch); err != nil {
+ return err
+ }
+
+ // regular case: we named the $ref as a definition, and we move all callers to this new $ref
+ for _, caller := range callers {
+ if caller == key {
+ continue
+ }
+
+ // move $ref for next to resolve
+ debugLog("identified caller of %s at [%s]", v.Ref.String(), caller)
+ c := refsToReplace[caller]
+ c.Ref = v.Ref
+ refsToReplace[caller] = c
+ }
+
+ return nil
+ }
+
+ // everything that is a simple schema and not factorizable is expanded
+ debugLog("expand JSON pointer for key=%s", key)
+
+ if err := replace.UpdateRefWithSchema(opts.Swagger(), key, v.Schema); err != nil {
+ return err
+ }
+ // NOTE: there is no other caller to update
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/analysis/flatten_name.go b/vendor/github.com/go-openapi/analysis/flatten_name.go
new file mode 100644
index 000000000000..475b33c41366
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/flatten_name.go
@@ -0,0 +1,317 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "fmt"
+ "path"
+ "sort"
+ "strings"
+
+ "github.com/go-openapi/analysis/internal/flatten/operations"
+ "github.com/go-openapi/analysis/internal/flatten/replace"
+ "github.com/go-openapi/analysis/internal/flatten/schutils"
+ "github.com/go-openapi/analysis/internal/flatten/sortref"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/swag/mangling"
+)
+
+// InlineSchemaNamer finds a new name for an inlined type
+type InlineSchemaNamer struct {
+ Spec *spec.Swagger
+ Operations map[string]operations.OpRef
+ flattenContext *context
+ opts *FlattenOpts
+}
+
+// Name yields a new name for the inline schema
+func (isn *InlineSchemaNamer) Name(key string, schema *spec.Schema, aschema *AnalyzedSchema) error {
+ debugLog("naming inlined schema at %s", key)
+
+ parts := sortref.KeyParts(key)
+ for _, name := range namesFromKey(parts, aschema, isn.Operations) {
+ if name == "" {
+ continue
+ }
+
+ // create unique name
+ mangle := mangler(isn.opts)
+ newName, isOAIGen := uniqifyName(isn.Spec.Definitions, mangle(name))
+
+ // clone schema
+ sch := schutils.Clone(schema)
+
+ // replace values on schema
+ debugLog("rewriting schema to ref: key=%s with new name: %s", key, newName)
+ if err := replace.RewriteSchemaToRef(isn.Spec, key,
+ spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
+ return ErrInlineDefinition(newName, err)
+ }
+
+ // rewrite any dependent $ref pointing to this place,
+ // when not already pointing to a top-level definition.
+ //
+ // NOTE: this is important if such referers use arbitrary JSON pointers.
+ an := New(isn.Spec)
+ for k, v := range an.references.allRefs {
+ r, erd := replace.DeepestRef(isn.opts.Swagger(), isn.opts.ExpandOpts(false), v)
+ if erd != nil {
+ return ErrAtKey(k, erd)
+ }
+
+ if isn.opts.flattenContext != nil {
+ isn.opts.flattenContext.warnings = append(isn.opts.flattenContext.warnings, r.Warnings...)
+ }
+
+ if r.Ref.String() != key && (r.Ref.String() != path.Join(definitionsPath, newName) || path.Dir(v.String()) == definitionsPath) {
+ continue
+ }
+
+ debugLog("found a $ref to a rewritten schema: %s points to %s", k, v.String())
+
+ // rewrite $ref to the new target
+ if err := replace.UpdateRef(isn.Spec, k,
+ spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
+ return err
+ }
+ }
+
+ // NOTE: this extension is currently not used by go-swagger (provided for information only)
+ sch.AddExtension("x-go-gen-location", GenLocation(parts))
+
+ // save cloned schema to definitions
+ schutils.Save(isn.Spec, newName, sch)
+
+ // keep track of created refs
+ if isn.flattenContext == nil {
+ continue
+ }
+
+ debugLog("track created ref: key=%s, newName=%s, isOAIGen=%t", key, newName, isOAIGen)
+ resolved := false
+
+ if _, ok := isn.flattenContext.newRefs[key]; ok {
+ resolved = isn.flattenContext.newRefs[key].resolved
+ }
+
+ isn.flattenContext.newRefs[key] = &newRef{
+ key: key,
+ newName: newName,
+ path: path.Join(definitionsPath, newName),
+ isOAIGen: isOAIGen,
+ resolved: resolved,
+ schema: sch,
+ }
+ }
+
+ return nil
+}
+
+// uniqifyName yields a unique name for a definition
+func uniqifyName(definitions spec.Definitions, name string) (string, bool) {
+ isOAIGen := false
+ if name == "" {
+ name = "oaiGen"
+ isOAIGen = true
+ }
+
+ if len(definitions) == 0 {
+ return name, isOAIGen
+ }
+
+ unq := true
+ for k := range definitions {
+ if strings.EqualFold(k, name) {
+ unq = false
+
+ break
+ }
+ }
+
+ if unq {
+ return name, isOAIGen
+ }
+
+ name += "OAIGen"
+ isOAIGen = true
+ var idx int
+ unique := name
+ _, known := definitions[unique]
+
+ for known {
+ idx++
+ unique = fmt.Sprintf("%s%d", name, idx)
+ _, known = definitions[unique]
+ }
+
+ return unique, isOAIGen
+}
+
+func namesFromKey(parts sortref.SplitKey, aschema *AnalyzedSchema, operations map[string]operations.OpRef) []string {
+ var (
+ baseNames [][]string
+ startIndex int
+ )
+
+ switch {
+ case parts.IsOperation():
+ baseNames, startIndex = namesForOperation(parts, operations)
+ case parts.IsDefinition():
+ baseNames, startIndex = namesForDefinition(parts)
+ default:
+ // this a non-standard pointer: build a name by concatenating its parts
+ baseNames = [][]string{parts}
+ startIndex = len(baseNames) + 1
+ }
+
+ result := make([]string, 0, len(baseNames))
+ for _, segments := range baseNames {
+ nm := parts.BuildName(segments, startIndex, partAdder(aschema))
+ if nm == "" {
+ continue
+ }
+
+ result = append(result, nm)
+ }
+ sort.Strings(result)
+
+ debugLog("names from parts: %v => %v", parts, result)
+ return result
+}
+
+func namesForParam(parts sortref.SplitKey, operations map[string]operations.OpRef) ([][]string, int) {
+ var (
+ baseNames [][]string
+ startIndex int
+ )
+
+ piref := parts.PathItemRef()
+ if piref.String() != "" && parts.IsOperationParam() {
+ if op, ok := operations[piref.String()]; ok {
+ startIndex = 5
+ baseNames = append(baseNames, []string{op.ID, "params", "body"})
+ }
+ } else if parts.IsSharedOperationParam() {
+ pref := parts.PathRef()
+ for k, v := range operations {
+ if strings.HasPrefix(k, pref.String()) {
+ startIndex = 4
+ baseNames = append(baseNames, []string{v.ID, "params", "body"})
+ }
+ }
+ }
+
+ return baseNames, startIndex
+}
+
+func namesForOperation(parts sortref.SplitKey, operations map[string]operations.OpRef) ([][]string, int) {
+ var (
+ baseNames [][]string
+ startIndex int
+ )
+
+ // params
+ if parts.IsOperationParam() || parts.IsSharedOperationParam() {
+ baseNames, startIndex = namesForParam(parts, operations)
+ }
+
+ // responses
+ if parts.IsOperationResponse() {
+ piref := parts.PathItemRef()
+ if piref.String() != "" {
+ if op, ok := operations[piref.String()]; ok {
+ startIndex = 6
+ baseNames = append(baseNames, []string{op.ID, parts.ResponseName(), "body"})
+ }
+ }
+ }
+
+ return baseNames, startIndex
+}
+
+const (
+ minStartIndex = 2
+ minSegments = 2
+)
+
+func namesForDefinition(parts sortref.SplitKey) ([][]string, int) {
+ nm := parts.DefinitionName()
+ if nm != "" {
+ return [][]string{{parts.DefinitionName()}}, minStartIndex
+ }
+
+ return [][]string{}, 0
+}
+
+// partAdder knows how to interpret a schema when it comes to build a name from parts
+func partAdder(aschema *AnalyzedSchema) sortref.PartAdder {
+ return func(part string) []string {
+ segments := make([]string, 0, minSegments)
+
+ if part == "items" || part == "additionalItems" {
+ if aschema.IsTuple || aschema.IsTupleWithExtra {
+ segments = append(segments, "tuple")
+ } else {
+ segments = append(segments, "items")
+ }
+
+ if part == "additionalItems" {
+ segments = append(segments, part)
+ }
+
+ return segments
+ }
+
+ segments = append(segments, part)
+
+ return segments
+ }
+}
+
+func mangler(o *FlattenOpts) func(string) string {
+ if o.KeepNames {
+ return func(in string) string { return in }
+ }
+ mangler := mangling.NewNameMangler()
+
+ return mangler.ToJSONName
+}
+
+func nameFromRef(ref spec.Ref, o *FlattenOpts) string {
+ mangle := mangler(o)
+
+ u := ref.GetURL()
+ if u.Fragment != "" {
+ return mangle(path.Base(u.Fragment))
+ }
+
+ if u.Path != "" {
+ bn := path.Base(u.Path)
+ if bn != "" && bn != "/" {
+ ext := path.Ext(bn)
+ if ext != "" {
+ return mangle(bn[:len(bn)-len(ext)])
+ }
+
+ return mangle(bn)
+ }
+ }
+
+ return mangle(strings.ReplaceAll(u.Host, ".", " "))
+}
+
+// GenLocation indicates from which section of the specification (models or operations) a definition has been created.
+//
+// This is reflected in the output spec with a "x-go-gen-location" extension. At the moment, this is provided
+// for information only.
+func GenLocation(parts sortref.SplitKey) string {
+ switch {
+ case parts.IsOperation():
+ return "operations"
+ case parts.IsDefinition():
+ return "models"
+ default:
+ return ""
+ }
+}
diff --git a/vendor/github.com/go-openapi/analysis/flatten_options.go b/vendor/github.com/go-openapi/analysis/flatten_options.go
new file mode 100644
index 000000000000..d8fc25cf5861
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/flatten_options.go
@@ -0,0 +1,82 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "log"
+
+ "github.com/go-openapi/spec"
+)
+
+// FlattenOpts configuration for flattening a swagger specification.
+//
+// The BasePath parameter is used to locate remote relative $ref found in the specification.
+// This path is a file: it points to the location of the root document and may be either a local
+// file path or a URL.
+//
+// If none specified, relative references (e.g. "$ref": "folder/schema.yaml#/definitions/...")
+// found in the spec are searched from the current working directory.
+type FlattenOpts struct {
+ Spec *Spec // The analyzed spec to work with
+ flattenContext *context // Internal context to track flattening activity
+
+ BasePath string // The location of the root document for this spec to resolve relative $ref
+
+ // Flattening options
+ Expand bool // When true, skip flattening the spec and expand it instead (if Minimal is false)
+ Minimal bool // When true, do not decompose complex structures such as allOf
+ Verbose bool // enable some reporting on possible name conflicts detected
+ RemoveUnused bool // When true, remove unused parameters, responses and definitions after expansion/flattening
+ ContinueOnError bool // Continue when spec expansion issues are found
+ KeepNames bool // Do not attempt to jsonify names from references when flattening
+
+ /* Extra keys */
+ _ struct{} // require keys
+}
+
+// ExpandOpts creates a spec.ExpandOptions to configure expanding a specification document.
+func (f *FlattenOpts) ExpandOpts(skipSchemas bool) *spec.ExpandOptions {
+ return &spec.ExpandOptions{
+ RelativeBase: f.BasePath,
+ SkipSchemas: skipSchemas,
+ ContinueOnError: f.ContinueOnError,
+ }
+}
+
+// Swagger gets the swagger specification for this flatten operation
+func (f *FlattenOpts) Swagger() *spec.Swagger {
+ return f.Spec.spec
+}
+
+// croak logs notifications and warnings about valid, but possibly unwanted constructs resulting
+// from flattening a spec
+func (f *FlattenOpts) croak() {
+ if !f.Verbose {
+ return
+ }
+
+ reported := make(map[string]bool, len(f.flattenContext.newRefs))
+ for _, v := range f.Spec.references.allRefs {
+ // warns about duplicate handling
+ for _, r := range f.flattenContext.newRefs {
+ if r.isOAIGen && r.path == v.String() {
+ reported[r.newName] = true
+ }
+ }
+ }
+
+ for k := range reported {
+ log.Printf("warning: duplicate flattened definition name resolved as %s", k)
+ }
+
+ // warns about possible type mismatches
+ uniqueMsg := make(map[string]bool)
+ for _, msg := range f.flattenContext.warnings {
+ if _, ok := uniqueMsg[msg]; ok {
+ continue
+ }
+ log.Printf("warning: %s", msg)
+ uniqueMsg[msg] = true
+ }
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/debug/debug.go b/vendor/github.com/go-openapi/analysis/internal/debug/debug.go
new file mode 100644
index 000000000000..03e0d32e9eab
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/debug/debug.go
@@ -0,0 +1,30 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package debug
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+)
+
+var (
+ output = os.Stdout
+)
+
+// GetLogger provides a prefix debug logger
+func GetLogger(prefix string, debug bool) func(string, ...any) {
+ if debug {
+ logger := log.New(output, prefix+":", log.LstdFlags)
+
+ return func(msg string, args ...any) {
+ _, file1, pos1, _ := runtime.Caller(1)
+ logger.Printf("%s:%d: %s", filepath.Base(file1), pos1, fmt.Sprintf(msg, args...))
+ }
+ }
+
+ return func(_ string, _ ...any) {}
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go b/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go
new file mode 100644
index 000000000000..320a50bff859
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go
@@ -0,0 +1,90 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package normalize
+
+import (
+ "net/url"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "github.com/go-openapi/spec"
+)
+
+// RebaseRef rebases a remote ref relative to a base ref.
+//
+// NOTE: does not support JSONschema ID for $ref (we assume we are working with swagger specs here).
+//
+// NOTE(windows):
+// * refs are assumed to have been normalized with drive letter lower cased (from go-openapi/spec)
+// * "/ in paths may appear as escape sequences
+func RebaseRef(baseRef string, ref string) string {
+ baseRef, _ = url.PathUnescape(baseRef)
+ ref, _ = url.PathUnescape(ref)
+
+ if baseRef == "" || baseRef == "." || strings.HasPrefix(baseRef, "#") {
+ return ref
+ }
+
+ parts := strings.Split(ref, "#")
+
+ baseParts := strings.Split(baseRef, "#")
+ baseURL, _ := url.Parse(baseParts[0])
+ if strings.HasPrefix(ref, "#") {
+ if baseURL.Host == "" {
+ return strings.Join([]string{baseParts[0], parts[1]}, "#")
+ }
+
+ return strings.Join([]string{baseParts[0], parts[1]}, "#")
+ }
+
+ refURL, _ := url.Parse(parts[0])
+ if refURL.Host != "" || filepath.IsAbs(parts[0]) {
+ // not rebasing an absolute path
+ return ref
+ }
+
+ // there is a relative path
+ var basePath string
+ if baseURL.Host != "" {
+ // when there is a host, standard URI rules apply (with "/")
+ baseURL.Path = path.Dir(baseURL.Path)
+ baseURL.Path = path.Join(baseURL.Path, "/"+parts[0])
+
+ return baseURL.String()
+ }
+
+ // this is a local relative path
+ // basePart[0] and parts[0] are local filesystem directories/files
+ basePath = filepath.Dir(baseParts[0])
+ relPath := filepath.Join(basePath, string(filepath.Separator)+parts[0])
+ if len(parts) > 1 {
+ return strings.Join([]string{relPath, parts[1]}, "#")
+ }
+
+ return relPath
+}
+
+// Path renders absolute path on remote file refs
+//
+// NOTE(windows):
+// * refs are assumed to have been normalized with drive letter lower cased (from go-openapi/spec)
+// * "/ in paths may appear as escape sequences
+func Path(ref spec.Ref, basePath string) string {
+ uri, _ := url.PathUnescape(ref.String())
+ if ref.HasFragmentOnly || filepath.IsAbs(uri) {
+ return uri
+ }
+
+ refURL, _ := url.Parse(uri)
+ if refURL.Host != "" {
+ return uri
+ }
+
+ parts := strings.Split(uri, "#")
+ // BasePath, parts[0] are local filesystem directories, guaranteed to be absolute at this stage
+ parts[0] = filepath.Join(filepath.Dir(basePath), parts[0])
+
+ return strings.Join(parts, "#")
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go b/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go
new file mode 100644
index 000000000000..940c46a92563
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go
@@ -0,0 +1,95 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package operations
+
+import (
+ "path"
+ "slices"
+ "sort"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/swag/mangling"
+)
+
+// AllOpRefsByRef returns an index of sortable operations
+func AllOpRefsByRef(specDoc Provider, operationIDs []string) map[string]OpRef {
+ return OpRefsByRef(GatherOperations(specDoc, operationIDs))
+}
+
+// OpRefsByRef indexes a map of sortable operations
+func OpRefsByRef(oprefs map[string]OpRef) map[string]OpRef {
+ result := make(map[string]OpRef, len(oprefs))
+ for _, v := range oprefs {
+ result[v.Ref.String()] = v
+ }
+
+ return result
+}
+
+// OpRef is an indexable, sortable operation
+type OpRef struct {
+ Method string
+ Path string
+ Key string
+ ID string
+ Op *spec.Operation
+ Ref spec.Ref
+}
+
+// OpRefs is a sortable collection of operations
+type OpRefs []OpRef
+
+func (o OpRefs) Len() int { return len(o) }
+func (o OpRefs) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
+func (o OpRefs) Less(i, j int) bool { return o[i].Key < o[j].Key }
+
+// Provider knows how to collect operations from a spec
+type Provider interface {
+ Operations() map[string]map[string]*spec.Operation
+}
+
+// GatherOperations builds a map of sorted operations from a spec
+func GatherOperations(specDoc Provider, operationIDs []string) map[string]OpRef {
+ var oprefs OpRefs
+ mangler := mangling.NewNameMangler()
+
+ for method, pathItem := range specDoc.Operations() {
+ for pth, operation := range pathItem {
+ vv := *operation
+ oprefs = append(oprefs, OpRef{
+ Key: mangler.ToGoName(strings.ToLower(method) + " " + pth),
+ Method: method,
+ Path: pth,
+ ID: vv.ID,
+ Op: &vv,
+ Ref: spec.MustCreateRef("#" + path.Join("/paths", jsonpointer.Escape(pth), method)),
+ })
+ }
+ }
+
+ sort.Sort(oprefs)
+
+ operations := make(map[string]OpRef)
+ for _, opr := range oprefs {
+ nm := opr.ID
+ if nm == "" {
+ nm = opr.Key
+ }
+
+ oo, found := operations[nm]
+ if found && oo.Method != opr.Method && oo.Path != opr.Path {
+ nm = opr.Key
+ }
+
+ if len(operationIDs) == 0 || slices.Contains(operationIDs, opr.ID) || slices.Contains(operationIDs, nm) {
+ opr.ID = nm
+ opr.Op.ID = nm
+ operations[nm] = opr
+ }
+ }
+
+ return operations
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/replace/errors.go b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/errors.go
new file mode 100644
index 000000000000..d7c28b88571e
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/errors.go
@@ -0,0 +1,64 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package replace
+
+import (
+ "errors"
+ "fmt"
+)
+
+type replaceError string
+
+const (
+ ErrReplace replaceError = "flatten replace error"
+ ErrUnexpectedType replaceError = "unexpected type used in getPointerFromKey"
+)
+
+func (e replaceError) Error() string {
+ return string(e)
+}
+
+func ErrNoSchemaWithRef(key string, value any) error {
+ return fmt.Errorf("no schema with ref found at %s for %T: %w", key, value, ErrReplace)
+}
+
+func ErrNoSchema(key string) error {
+ return fmt.Errorf("no schema found at %s: %w", key, ErrReplace)
+}
+
+func ErrNotANumber(key string, err error) error {
+ return errors.Join(
+ ErrReplace,
+ fmt.Errorf("%s not a number: %w", key, err),
+ )
+}
+
+func ErrUnhandledParentRewrite(key string, value any) error {
+ return fmt.Errorf("unhandled parent schema rewrite %s: %T: %w", key, value, ErrReplace)
+}
+
+func ErrUnhandledParentType(key string, value any) error {
+ return fmt.Errorf("unhandled type for parent of %s: %T: %w", key, value, ErrReplace)
+}
+
+func ErrNoParent(key string, err error) error {
+ return errors.Join(
+ fmt.Errorf("can't get parent for %s: %w", key, err),
+ ErrReplace,
+ )
+}
+
+func ErrUnhandledContainerType(key string, value any) error {
+ return fmt.Errorf("unhandled container type at %s: %T: %w", key, value, ErrReplace)
+}
+
+func ErrCyclicChain(key string) error {
+ return fmt.Errorf("cannot resolve cyclic chain of pointers under %s: %w", key, ErrReplace)
+}
+
+func ErrInvalidPointerType(key string, value any, err error) error {
+ return fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T (%v): %w",
+ key, value, err, ErrReplace,
+ )
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go
new file mode 100644
index 000000000000..61c13f7ebaad
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go
@@ -0,0 +1,456 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package replace
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/url"
+ "os"
+ "path"
+ "strconv"
+
+ "github.com/go-openapi/analysis/internal/debug"
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/spec"
+)
+
+const (
+ definitionsPath = "#/definitions"
+ allocMediumMap = 64
+)
+
+var debugLog = debug.GetLogger("analysis/flatten/replace", os.Getenv("SWAGGER_DEBUG") != "")
+
+// RewriteSchemaToRef replaces a schema with a Ref
+func RewriteSchemaToRef(sp *spec.Swagger, key string, ref spec.Ref) error {
+ debugLog("rewriting schema to ref for %s with %s", key, ref.String())
+ _, value, err := getPointerFromKey(sp, key)
+ if err != nil {
+ return err
+ }
+
+ switch refable := value.(type) {
+ case *spec.Schema:
+ return rewriteParentRef(sp, key, ref)
+
+ case spec.Schema:
+ return rewriteParentRef(sp, key, ref)
+
+ case *spec.SchemaOrArray:
+ if refable.Schema != nil {
+ refable.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+ }
+
+ case *spec.SchemaOrBool:
+ if refable.Schema != nil {
+ refable.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+ }
+ case map[string]any: // this happens e.g. if a schema points to an extension unmarshaled as map[string]interface{}
+ return rewriteParentRef(sp, key, ref)
+ default:
+ return ErrNoSchemaWithRef(key, value)
+ }
+
+ return nil
+}
+
+func rewriteParentRef(sp *spec.Swagger, key string, ref spec.Ref) error {
+ parent, entry, pvalue, err := getParentFromKey(sp, key)
+ if err != nil {
+ return err
+ }
+
+ debugLog("rewriting holder for %T", pvalue)
+ switch container := pvalue.(type) {
+ case spec.Response:
+ if err := rewriteParentRef(sp, "#"+parent, ref); err != nil {
+ return err
+ }
+
+ case *spec.Response:
+ container.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case *spec.Responses:
+ statusCode, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(key[1:], err)
+ }
+ resp := container.StatusCodeResponses[statusCode]
+ resp.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+ container.StatusCodeResponses[statusCode] = resp
+
+ case map[string]spec.Response:
+ resp := container[entry]
+ resp.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+ container[entry] = resp
+
+ case spec.Parameter:
+ if err := rewriteParentRef(sp, "#"+parent, ref); err != nil {
+ return err
+ }
+
+ case map[string]spec.Parameter:
+ param := container[entry]
+ param.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+ container[entry] = param
+
+ case []spec.Parameter:
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(key[1:], err)
+ }
+ param := container[idx]
+ param.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+ container[idx] = param
+
+ case spec.Definitions:
+ container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case map[string]spec.Schema:
+ container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case []spec.Schema:
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(key[1:], err)
+ }
+ container[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case *spec.SchemaOrArray:
+ // NOTE: this is necessarily an array - otherwise, the parent would be *Schema
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(key[1:], err)
+ }
+ container.Schemas[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case spec.SchemaProperties:
+ container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case *any:
+ *container = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ // NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
+
+ default:
+ return ErrUnhandledParentRewrite(key, pvalue)
+ }
+
+ return nil
+}
+
+// getPointerFromKey retrieves the content of the JSON pointer "key"
+func getPointerFromKey(sp any, key string) (string, any, error) {
+ switch sp.(type) {
+ case *spec.Schema:
+ case *spec.Swagger:
+ default:
+ panic(ErrUnexpectedType)
+ }
+ if key == "#/" {
+ return "", sp, nil
+ }
+ // unescape chars in key, e.g. "{}" from path params
+ pth, _ := url.PathUnescape(key[1:])
+ ptr, err := jsonpointer.New(pth)
+ if err != nil {
+ return "", nil, errors.Join(err, ErrReplace)
+ }
+
+ value, _, err := ptr.Get(sp)
+ if err != nil {
+ debugLog("error when getting key: %s with path: %s", key, pth)
+
+ return "", nil, errors.Join(err, ErrReplace)
+ }
+
+ return pth, value, nil
+}
+
+// getParentFromKey retrieves the container of the JSON pointer "key"
+func getParentFromKey(sp any, key string) (string, string, any, error) {
+ switch sp.(type) {
+ case *spec.Schema:
+ case *spec.Swagger:
+ default:
+ panic(ErrUnexpectedType)
+ }
+ // unescape chars in key, e.g. "{}" from path params
+ pth, _ := url.PathUnescape(key[1:])
+
+ parent, entry := path.Dir(pth), path.Base(pth)
+ debugLog("getting schema holder at: %s, with entry: %s", parent, entry)
+
+ pptr, err := jsonpointer.New(parent)
+ if err != nil {
+ return "", "", nil, errors.Join(err, ErrReplace)
+ }
+ pvalue, _, err := pptr.Get(sp)
+ if err != nil {
+ return "", "", nil, ErrNoParent(parent, err)
+ }
+
+ return parent, entry, pvalue, nil
+}
+
+// UpdateRef replaces a ref by another one
+func UpdateRef(sp any, key string, ref spec.Ref) error {
+ switch sp.(type) {
+ case *spec.Schema:
+ case *spec.Swagger:
+ default:
+ panic(ErrUnexpectedType)
+ }
+ debugLog("updating ref for %s with %s", key, ref.String())
+ pth, value, err := getPointerFromKey(sp, key)
+ if err != nil {
+ return err
+ }
+
+ switch refable := value.(type) {
+ case *spec.Schema:
+ refable.Ref = ref
+ case *spec.SchemaOrArray:
+ if refable.Schema != nil {
+ refable.Schema.Ref = ref
+ }
+ case *spec.SchemaOrBool:
+ if refable.Schema != nil {
+ refable.Schema.Ref = ref
+ }
+ case spec.Schema:
+ debugLog("rewriting holder for %T", refable)
+ _, entry, pvalue, erp := getParentFromKey(sp, key)
+ if erp != nil {
+ return erp
+ }
+ switch container := pvalue.(type) {
+ case spec.Definitions:
+ container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case map[string]spec.Schema:
+ container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case []spec.Schema:
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(pth, err)
+ }
+ container[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case *spec.SchemaOrArray:
+ // NOTE: this is necessarily an array - otherwise, the parent would be *Schema
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(pth, err)
+ }
+ container.Schemas[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ case spec.SchemaProperties:
+ container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
+
+ // NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
+
+ default:
+ return ErrUnhandledContainerType(key, value)
+ }
+
+ default:
+ return ErrNoSchemaWithRef(key, value)
+ }
+
+ return nil
+}
+
+// UpdateRefWithSchema replaces a ref with a schema (i.e. re-inline schema)
+func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
+ debugLog("updating ref for %s with schema", key)
+ pth, value, err := getPointerFromKey(sp, key)
+ if err != nil {
+ return err
+ }
+
+ switch refable := value.(type) {
+ case *spec.Schema:
+ *refable = *sch
+ case spec.Schema:
+ _, entry, pvalue, erp := getParentFromKey(sp, key)
+ if erp != nil {
+ return erp
+ }
+
+ switch container := pvalue.(type) {
+ case spec.Definitions:
+ container[entry] = *sch
+
+ case map[string]spec.Schema:
+ container[entry] = *sch
+
+ case []spec.Schema:
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(pth, err)
+ }
+ container[idx] = *sch
+
+ case *spec.SchemaOrArray:
+ // NOTE: this is necessarily an array - otherwise, the parent would be *Schema
+ idx, err := strconv.Atoi(entry)
+ if err != nil {
+ return ErrNotANumber(pth, err)
+ }
+ container.Schemas[idx] = *sch
+
+ case spec.SchemaProperties:
+ container[entry] = *sch
+
+ // NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
+
+ default:
+ return ErrUnhandledParentType(key, value)
+ }
+ case *spec.SchemaOrArray:
+ *refable.Schema = *sch
+ // NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
+ case *spec.SchemaOrBool:
+ *refable.Schema = *sch
+ default:
+ return ErrNoSchemaWithRef(key, value)
+ }
+
+ return nil
+}
+
+// DeepestRefResult holds the results from DeepestRef analysis
+type DeepestRefResult struct {
+ Ref spec.Ref
+ Schema *spec.Schema
+ Warnings []string
+}
+
+// DeepestRef finds the first definition ref, from a cascade of nested refs which are not definitions.
+// - if no definition is found, returns the deepest ref.
+// - pointers to external files are expanded
+//
+// NOTE: all external $ref's are assumed to be already expanded at this stage.
+func DeepestRef(sp *spec.Swagger, opts *spec.ExpandOptions, ref spec.Ref) (*DeepestRefResult, error) {
+ if !ref.HasFragmentOnly {
+ // we found an external $ref, which is odd at this stage:
+ // do nothing on external $refs
+ return &DeepestRefResult{Ref: ref}, nil
+ }
+
+ currentRef := ref
+ visited := make(map[string]bool, allocMediumMap)
+ warnings := make([]string, 0)
+
+DOWNREF:
+ for currentRef.String() != "" {
+ if path.Dir(currentRef.String()) == definitionsPath {
+ // this is a top-level definition: stop here and return this ref
+ return &DeepestRefResult{Ref: currentRef}, nil
+ }
+
+ if _, beenThere := visited[currentRef.String()]; beenThere {
+ return nil, ErrCyclicChain(currentRef.String())
+ }
+
+ visited[currentRef.String()] = true
+ value, _, err := currentRef.GetPointer().Get(sp)
+ if err != nil {
+ return nil, err
+ }
+
+ switch refable := value.(type) {
+ case *spec.Schema:
+ if refable.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = refable.Ref
+
+ case spec.Schema:
+ if refable.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = refable.Ref
+
+ case *spec.SchemaOrArray:
+ if refable.Schema == nil || refable.Schema != nil && refable.Schema.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = refable.Schema.Ref
+
+ case *spec.SchemaOrBool:
+ if refable.Schema == nil || refable.Schema != nil && refable.Schema.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = refable.Schema.Ref
+
+ case spec.Response:
+ // a pointer points to a schema initially marshalled in responses section...
+ // Attempt to convert this to a schema. If this fails, the spec is invalid
+ asJSON, _ := refable.MarshalJSON()
+ var asSchema spec.Schema
+
+ err := asSchema.UnmarshalJSON(asJSON)
+ if err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
+ }
+ warnings = append(warnings, fmt.Sprintf("found $ref %q (response) interpreted as schema", currentRef.String()))
+
+ if asSchema.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = asSchema.Ref
+
+ case spec.Parameter:
+ // a pointer points to a schema initially marshalled in parameters section...
+ // Attempt to convert this to a schema. If this fails, the spec is invalid
+ asJSON, _ := refable.MarshalJSON()
+ var asSchema spec.Schema
+ if err := asSchema.UnmarshalJSON(asJSON); err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
+ }
+
+ warnings = append(warnings, fmt.Sprintf("found $ref %q (parameter) interpreted as schema", currentRef.String()))
+
+ if asSchema.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = asSchema.Ref
+
+ default:
+ // fallback: attempts to resolve the pointer as a schema
+ if refable == nil {
+ break DOWNREF
+ }
+
+ asJSON, _ := json.Marshal(refable)
+ var asSchema spec.Schema
+ if err := asSchema.UnmarshalJSON(asJSON); err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
+ }
+ warnings = append(warnings, fmt.Sprintf("found $ref %q (%T) interpreted as schema", currentRef.String(), refable))
+
+ if asSchema.Ref.String() == "" {
+ break DOWNREF
+ }
+ currentRef = asSchema.Ref
+ }
+ }
+
+ // assess what schema we're ending with
+ sch, erv := spec.ResolveRefWithBase(sp, ¤tRef, opts)
+ if erv != nil {
+ return nil, erv
+ }
+
+ if sch == nil {
+ return nil, ErrNoSchema(currentRef.String())
+ }
+
+ return &DeepestRefResult{Ref: currentRef, Schema: sch, Warnings: warnings}, nil
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go b/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go
new file mode 100644
index 000000000000..7e9fb9f0a5f8
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go
@@ -0,0 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package schutils provides tools to save or clone a schema
+// when flattening a spec.
+package schutils
+
+import (
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+const allocLargeMap = 150
+
+// Save registers a schema as an entry in spec #/definitions
+func Save(sp *spec.Swagger, name string, schema *spec.Schema) {
+ if schema == nil {
+ return
+ }
+
+ if sp.Definitions == nil {
+ sp.Definitions = make(map[string]spec.Schema, allocLargeMap)
+ }
+
+ sp.Definitions[name] = *schema
+}
+
+// Clone deep-clones a schema
+func Clone(schema *spec.Schema) *spec.Schema {
+ var sch spec.Schema
+ _ = jsonutils.FromDynamicJSON(schema, &sch)
+
+ return &sch
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go
new file mode 100644
index 000000000000..a5db0249ecca
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go
@@ -0,0 +1,205 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package sortref
+
+import (
+ "net/http"
+ "path"
+ "strconv"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/spec"
+)
+
+const (
+ paths = "paths"
+ responses = "responses"
+ parameters = "parameters"
+ definitions = "definitions"
+)
+
+var (
+ ignoredKeys map[string]struct{}
+ validMethods map[string]struct{}
+)
+
+func init() {
+ ignoredKeys = map[string]struct{}{
+ "schema": {},
+ "properties": {},
+ "not": {},
+ "anyOf": {},
+ "oneOf": {},
+ }
+
+ validMethods = map[string]struct{}{
+ "GET": {},
+ "HEAD": {},
+ "OPTIONS": {},
+ "PATCH": {},
+ "POST": {},
+ "PUT": {},
+ "DELETE": {},
+ }
+}
+
+// Key represent a key item constructed from /-separated segments
+type Key struct {
+ Segments int
+ Key string
+}
+
+// Keys is a sortable collable collection of Keys
+type Keys []Key
+
+func (k Keys) Len() int { return len(k) }
+func (k Keys) Swap(i, j int) { k[i], k[j] = k[j], k[i] }
+func (k Keys) Less(i, j int) bool {
+ return k[i].Segments > k[j].Segments || (k[i].Segments == k[j].Segments && k[i].Key < k[j].Key)
+}
+
+// KeyParts construct a SplitKey with all its /-separated segments decomposed. It is sortable.
+func KeyParts(key string) SplitKey {
+ var res []string
+ for part := range strings.SplitSeq(key[1:], "/") {
+ if part != "" {
+ res = append(res, jsonpointer.Unescape(part))
+ }
+ }
+
+ return res
+}
+
+// SplitKey holds of the parts of a /-separated key, so that their location may be determined.
+type SplitKey []string
+
+// IsDefinition is true when the split key is in the #/definitions section of a spec
+func (s SplitKey) IsDefinition() bool {
+ return len(s) > 1 && s[0] == definitions
+}
+
+// DefinitionName yields the name of the definition
+func (s SplitKey) DefinitionName() string {
+ if !s.IsDefinition() {
+ return ""
+ }
+
+ return s[1]
+}
+
+// PartAdder know how to construct the components of a new name
+type PartAdder func(string) []string
+
+// BuildName builds a name from segments
+func (s SplitKey) BuildName(segments []string, startIndex int, adder PartAdder) string {
+ for i, part := range s[startIndex:] {
+ if _, ignored := ignoredKeys[part]; !ignored || s.isKeyName(startIndex+i) {
+ segments = append(segments, adder(part)...)
+ }
+ }
+
+ return strings.Join(segments, " ")
+}
+
+// IsOperation is true when the split key is in the operations section
+func (s SplitKey) IsOperation() bool {
+ return len(s) > 1 && s[0] == paths
+}
+
+// IsSharedOperationParam is true when the split key is in the parameters section of a path
+func (s SplitKey) IsSharedOperationParam() bool {
+ return len(s) > 2 && s[0] == paths && s[2] == parameters
+}
+
+// IsSharedParam is true when the split key is in the #/parameters section of a spec
+func (s SplitKey) IsSharedParam() bool {
+ return len(s) > 1 && s[0] == parameters
+}
+
+// IsOperationParam is true when the split key is in the parameters section of an operation
+func (s SplitKey) IsOperationParam() bool {
+ return len(s) > 3 && s[0] == paths && s[3] == parameters
+}
+
+// IsOperationResponse is true when the split key is in the responses section of an operation
+func (s SplitKey) IsOperationResponse() bool {
+ return len(s) > 3 && s[0] == paths && s[3] == responses
+}
+
+// IsSharedResponse is true when the split key is in the #/responses section of a spec
+func (s SplitKey) IsSharedResponse() bool {
+ return len(s) > 1 && s[0] == responses
+}
+
+// IsDefaultResponse is true when the split key is the default response for an operation
+func (s SplitKey) IsDefaultResponse() bool {
+ return len(s) > 4 && s[0] == paths && s[3] == responses && s[4] == "default"
+}
+
+// IsStatusCodeResponse is true when the split key is an operation response with a status code
+func (s SplitKey) IsStatusCodeResponse() bool {
+ isInt := func() bool {
+ _, err := strconv.Atoi(s[4])
+
+ return err == nil
+ }
+
+ return len(s) > 4 && s[0] == paths && s[3] == responses && isInt()
+}
+
+// ResponseName yields either the status code or "Default" for a response
+func (s SplitKey) ResponseName() string {
+ if s.IsStatusCodeResponse() {
+ code, _ := strconv.Atoi(s[4])
+
+ return http.StatusText(code)
+ }
+
+ if s.IsDefaultResponse() {
+ return "Default"
+ }
+
+ return ""
+}
+
+// PathItemRef constructs a $ref object from a split key of the form /{path}/{method}
+func (s SplitKey) PathItemRef() spec.Ref {
+ const minValidPathItems = 3
+ if len(s) < minValidPathItems {
+ return spec.Ref{}
+ }
+
+ pth, method := s[1], s[2]
+ if _, isValidMethod := validMethods[strings.ToUpper(method)]; !isValidMethod && !strings.HasPrefix(method, "x-") {
+ return spec.Ref{}
+ }
+
+ return spec.MustCreateRef("#" + path.Join("/", paths, jsonpointer.Escape(pth), strings.ToUpper(method)))
+}
+
+// PathRef constructs a $ref object from a split key of the form /paths/{reference}
+func (s SplitKey) PathRef() spec.Ref {
+ if !s.IsOperation() {
+ return spec.Ref{}
+ }
+
+ return spec.MustCreateRef("#" + path.Join("/", paths, jsonpointer.Escape(s[1])))
+}
+
+func (s SplitKey) isKeyName(i int) bool {
+ if i <= 0 {
+ return false
+ }
+
+ count := 0
+ for idx := i - 1; idx > 0; idx-- {
+ if s[idx] != "properties" {
+ break
+ }
+ count++
+ }
+
+ return count%2 != 0
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go
new file mode 100644
index 000000000000..ceac71377287
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go
@@ -0,0 +1,144 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package sortref
+
+import (
+ "reflect"
+ "sort"
+ "strings"
+
+ "github.com/go-openapi/analysis/internal/flatten/normalize"
+ "github.com/go-openapi/spec"
+)
+
+var depthGroupOrder = []string{
+ "sharedParam", "sharedResponse", "sharedOpParam", "opParam", "codeResponse", "defaultResponse", "definition",
+}
+
+type mapIterator struct {
+ len int
+ mapIter *reflect.MapIter
+}
+
+func (i *mapIterator) Next() bool {
+ return i.mapIter.Next()
+}
+
+func (i *mapIterator) Len() int {
+ return i.len
+}
+
+func (i *mapIterator) Key() string {
+ return i.mapIter.Key().String()
+}
+
+func mustMapIterator(anyMap any) *mapIterator {
+ val := reflect.ValueOf(anyMap)
+
+ return &mapIterator{mapIter: val.MapRange(), len: val.Len()}
+}
+
+// DepthFirst sorts a map of anything. It groups keys by category
+// (shared params, op param, statuscode response, default response, definitions)
+// sort groups internally by number of parts in the key and lexical names
+// flatten groups into a single list of keys
+func DepthFirst(in any) []string {
+ iterator := mustMapIterator(in)
+ sorted := make([]string, 0, iterator.Len())
+ grouped := make(map[string]Keys, iterator.Len())
+
+ for iterator.Next() {
+ k := iterator.Key()
+ split := KeyParts(k)
+ var pk string
+
+ if split.IsSharedOperationParam() {
+ pk = "sharedOpParam"
+ }
+ if split.IsOperationParam() {
+ pk = "opParam"
+ }
+ if split.IsStatusCodeResponse() {
+ pk = "codeResponse"
+ }
+ if split.IsDefaultResponse() {
+ pk = "defaultResponse"
+ }
+ if split.IsDefinition() {
+ pk = "definition"
+ }
+ if split.IsSharedParam() {
+ pk = "sharedParam"
+ }
+ if split.IsSharedResponse() {
+ pk = "sharedResponse"
+ }
+ grouped[pk] = append(grouped[pk], Key{Segments: len(split), Key: k})
+ }
+
+ for _, pk := range depthGroupOrder {
+ res := grouped[pk]
+ sort.Sort(res)
+
+ for _, v := range res {
+ sorted = append(sorted, v.Key)
+ }
+ }
+
+ return sorted
+}
+
+// topMostRefs is able to sort refs by hierarchical then lexicographic order,
+// yielding refs ordered breadth-first.
+type topmostRefs []string
+
+func (k topmostRefs) Len() int { return len(k) }
+func (k topmostRefs) Swap(i, j int) { k[i], k[j] = k[j], k[i] }
+func (k topmostRefs) Less(i, j int) bool {
+ li, lj := len(strings.Split(k[i], "/")), len(strings.Split(k[j], "/"))
+ if li == lj {
+ return k[i] < k[j]
+ }
+
+ return li < lj
+}
+
+// TopmostFirst sorts references by depth
+func TopmostFirst(refs []string) []string {
+ res := topmostRefs(refs)
+ sort.Sort(res)
+
+ return res
+}
+
+// RefRevIdx is a reverse index for references
+type RefRevIdx struct {
+ Ref spec.Ref
+ Keys []string
+}
+
+// ReverseIndex builds a reverse index for references in schemas
+func ReverseIndex(schemas map[string]spec.Ref, basePath string) map[string]RefRevIdx {
+ collected := make(map[string]RefRevIdx)
+ for key, schRef := range schemas {
+ // normalize paths before sorting,
+ // so we get together keys that are from the same external file
+ normalizedPath := normalize.Path(schRef, basePath)
+
+ entry, ok := collected[normalizedPath]
+ if ok {
+ entry.Keys = append(entry.Keys, key)
+ collected[normalizedPath] = entry
+
+ continue
+ }
+
+ collected[normalizedPath] = RefRevIdx{
+ Ref: schRef,
+ Keys: []string{key},
+ }
+ }
+
+ return collected
+}
diff --git a/vendor/github.com/go-openapi/analysis/mixin.go b/vendor/github.com/go-openapi/analysis/mixin.go
new file mode 100644
index 000000000000..cc5c392334bf
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/mixin.go
@@ -0,0 +1,484 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "fmt"
+ "reflect"
+ "slices"
+
+ "github.com/go-openapi/spec"
+)
+
+// Mixin modifies the primary swagger spec by adding the paths and
+// definitions from the mixin specs. Top level parameters and
+// responses from the mixins are also carried over. Operation id
+// collisions are avoided by appending "Mixin" but only if
+// needed.
+//
+// The following parts of primary are subject to merge, filling empty details
+// - Info
+// - BasePath
+// - Host
+// - ExternalDocs
+//
+// Consider calling FixEmptyResponseDescriptions() on the modified primary
+// if you read them from storage and they are valid to start with.
+//
+// Entries in "paths", "definitions", "parameters" and "responses" are
+// added to the primary in the order of the given mixins. If the entry
+// already exists in primary it is skipped with a warning message.
+//
+// The count of skipped entries (from collisions) is returned so any
+// deviation from the number expected can flag a warning in your build
+// scripts. Carefully review the collisions before accepting them;
+// consider renaming things if possible.
+//
+// No key normalization takes place (paths, type defs,
+// etc). Ensure they are canonical if your downstream tools do
+// key normalization of any form.
+//
+// Merging schemes (http, https), and consumers/producers do not account for
+// collisions.
+func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string {
+ skipped := make([]string, 0, len(mixins))
+ opIDs := getOpIDs(primary)
+ initPrimary(primary)
+
+ for i, m := range mixins {
+ skipped = append(skipped, mergeSwaggerProps(primary, m)...)
+
+ skipped = append(skipped, mergeConsumes(primary, m)...)
+
+ skipped = append(skipped, mergeProduces(primary, m)...)
+
+ skipped = append(skipped, mergeTags(primary, m)...)
+
+ skipped = append(skipped, mergeSchemes(primary, m)...)
+
+ skipped = append(skipped, mergeSecurityDefinitions(primary, m)...)
+
+ skipped = append(skipped, mergeSecurityRequirements(primary, m)...)
+
+ skipped = append(skipped, mergeDefinitions(primary, m)...)
+
+ // merging paths requires a map of operationIDs to work with
+ skipped = append(skipped, mergePaths(primary, m, opIDs, i)...)
+
+ skipped = append(skipped, mergeParameters(primary, m)...)
+
+ skipped = append(skipped, mergeResponses(primary, m)...)
+ }
+
+ return skipped
+}
+
+// getOpIDs extracts all the paths..operationIds from the given
+// spec and returns them as the keys in a map with 'true' values.
+func getOpIDs(s *spec.Swagger) map[string]bool {
+ rv := make(map[string]bool)
+ if s.Paths == nil {
+ return rv
+ }
+
+ for _, v := range s.Paths.Paths {
+ piops := pathItemOps(v)
+
+ for _, op := range piops {
+ rv[op.ID] = true
+ }
+ }
+
+ return rv
+}
+
+func pathItemOps(p spec.PathItem) []*spec.Operation {
+ var rv []*spec.Operation
+ rv = appendOp(rv, p.Get)
+ rv = appendOp(rv, p.Put)
+ rv = appendOp(rv, p.Post)
+ rv = appendOp(rv, p.Delete)
+ rv = appendOp(rv, p.Head)
+ rv = appendOp(rv, p.Patch)
+
+ return rv
+}
+
+func appendOp(ops []*spec.Operation, op *spec.Operation) []*spec.Operation {
+ if op == nil {
+ return ops
+ }
+
+ return append(ops, op)
+}
+
+func mergeSecurityDefinitions(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
+ for k, v := range m.SecurityDefinitions {
+ if _, exists := primary.SecurityDefinitions[k]; exists {
+ warn := fmt.Sprintf(
+ "SecurityDefinitions entry '%v' already exists in primary or higher priority mixin, skipping\n", k)
+ skipped = append(skipped, warn)
+
+ continue
+ }
+
+ primary.SecurityDefinitions[k] = v
+ }
+
+ return
+}
+
+func mergeSecurityRequirements(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
+ for _, v := range m.Security {
+ found := false
+ for _, vv := range primary.Security {
+ if reflect.DeepEqual(v, vv) {
+ found = true
+
+ break
+ }
+ }
+
+ if found {
+ warn := fmt.Sprintf(
+ "Security requirement: '%v' already exists in primary or higher priority mixin, skipping\n", v)
+ skipped = append(skipped, warn)
+
+ continue
+ }
+ primary.Security = append(primary.Security, v)
+ }
+
+ return
+}
+
+func mergeDefinitions(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
+ for k, v := range m.Definitions {
+ // assume name collisions represent IDENTICAL type. careful.
+ if _, exists := primary.Definitions[k]; exists {
+ warn := fmt.Sprintf(
+ "definitions entry '%v' already exists in primary or higher priority mixin, skipping\n", k)
+ skipped = append(skipped, warn)
+
+ continue
+ }
+ primary.Definitions[k] = v
+ }
+
+ return
+}
+
+func mergePaths(primary *spec.Swagger, m *spec.Swagger, opIDs map[string]bool, mixIndex int) (skipped []string) {
+ if m.Paths != nil {
+ for k, v := range m.Paths.Paths {
+ if _, exists := primary.Paths.Paths[k]; exists {
+ warn := fmt.Sprintf(
+ "paths entry '%v' already exists in primary or higher priority mixin, skipping\n", k)
+ skipped = append(skipped, warn)
+
+ continue
+ }
+
+ // Swagger requires that operationIds be
+ // unique within a spec. If we find a
+ // collision we append "Mixin0" to the
+ // operatoinId we are adding, where 0 is mixin
+ // index. We assume that operationIds with
+ // all the proivded specs are already unique.
+ piops := pathItemOps(v)
+ for _, piop := range piops {
+ if opIDs[piop.ID] {
+ piop.ID = fmt.Sprintf("%v%v%v", piop.ID, "Mixin", mixIndex)
+ }
+ opIDs[piop.ID] = true
+ }
+ primary.Paths.Paths[k] = v
+ }
+ }
+
+ return
+}
+
+func mergeParameters(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
+ for k, v := range m.Parameters {
+ // could try to rename on conflict but would
+ // have to fix $refs in the mixin. Complain
+ // for now
+ if _, exists := primary.Parameters[k]; exists {
+ warn := fmt.Sprintf(
+ "top level parameters entry '%v' already exists in primary or higher priority mixin, skipping\n", k)
+ skipped = append(skipped, warn)
+
+ continue
+ }
+ primary.Parameters[k] = v
+ }
+
+ return
+}
+
+func mergeResponses(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
+ for k, v := range m.Responses {
+ // could try to rename on conflict but would
+ // have to fix $refs in the mixin. Complain
+ // for now
+ if _, exists := primary.Responses[k]; exists {
+ warn := fmt.Sprintf(
+ "top level responses entry '%v' already exists in primary or higher priority mixin, skipping\n", k)
+ skipped = append(skipped, warn)
+
+ continue
+ }
+ primary.Responses[k] = v
+ }
+
+ return skipped
+}
+
+func mergeConsumes(primary *spec.Swagger, m *spec.Swagger) []string {
+ for _, v := range m.Consumes {
+ found := slices.Contains(primary.Consumes, v)
+
+ if found {
+ // no warning here: we just skip it
+ continue
+ }
+ primary.Consumes = append(primary.Consumes, v)
+ }
+
+ return []string{}
+}
+
+func mergeProduces(primary *spec.Swagger, m *spec.Swagger) []string {
+ for _, v := range m.Produces {
+ found := slices.Contains(primary.Produces, v)
+
+ if found {
+ // no warning here: we just skip it
+ continue
+ }
+ primary.Produces = append(primary.Produces, v)
+ }
+
+ return []string{}
+}
+
+func mergeTags(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
+ for _, v := range m.Tags {
+ found := false
+ for _, vv := range primary.Tags {
+ if v.Name == vv.Name {
+ found = true
+
+ break
+ }
+ }
+
+ if found {
+ warn := fmt.Sprintf(
+ "top level tags entry with name '%v' already exists in primary or higher priority mixin, skipping\n",
+ v.Name,
+ )
+ skipped = append(skipped, warn)
+
+ continue
+ }
+
+ primary.Tags = append(primary.Tags, v)
+ }
+
+ return
+}
+
+func mergeSchemes(primary *spec.Swagger, m *spec.Swagger) []string {
+ for _, v := range m.Schemes {
+ found := slices.Contains(primary.Schemes, v)
+
+ if found {
+ // no warning here: we just skip it
+ continue
+ }
+ primary.Schemes = append(primary.Schemes, v)
+ }
+
+ return []string{}
+}
+
+func mergeSwaggerProps(primary *spec.Swagger, m *spec.Swagger) []string {
+ var skipped, skippedInfo, skippedDocs []string
+
+ primary.Extensions, skipped = mergeExtensions(primary.Extensions, m.Extensions)
+
+ // merging details in swagger top properties
+ if primary.Host == "" {
+ primary.Host = m.Host
+ }
+
+ if primary.BasePath == "" {
+ primary.BasePath = m.BasePath
+ }
+
+ if primary.Info == nil {
+ primary.Info = m.Info
+ } else if m.Info != nil {
+ skippedInfo = mergeInfo(primary.Info, m.Info)
+ skipped = append(skipped, skippedInfo...)
+ }
+
+ if primary.ExternalDocs == nil {
+ primary.ExternalDocs = m.ExternalDocs
+ } else if m != nil {
+ skippedDocs = mergeExternalDocs(primary.ExternalDocs, m.ExternalDocs)
+ skipped = append(skipped, skippedDocs...)
+ }
+
+ return skipped
+}
+
+//nolint:unparam
+func mergeExternalDocs(primary *spec.ExternalDocumentation, m *spec.ExternalDocumentation) []string {
+ if primary.Description == "" {
+ primary.Description = m.Description
+ }
+
+ if primary.URL == "" {
+ primary.URL = m.URL
+ }
+
+ return nil
+}
+
+func mergeInfo(primary *spec.Info, m *spec.Info) []string {
+ var sk, skipped []string
+
+ primary.Extensions, sk = mergeExtensions(primary.Extensions, m.Extensions)
+ skipped = append(skipped, sk...)
+
+ if primary.Description == "" {
+ primary.Description = m.Description
+ }
+
+ if primary.Title == "" {
+ primary.Title = m.Title
+ }
+
+ if primary.TermsOfService == "" {
+ primary.TermsOfService = m.TermsOfService
+ }
+
+ if primary.Version == "" {
+ primary.Version = m.Version
+ }
+
+ if primary.Contact == nil {
+ primary.Contact = m.Contact
+ } else if m.Contact != nil {
+ var csk []string
+ primary.Contact.Extensions, csk = mergeExtensions(primary.Contact.Extensions, m.Contact.Extensions)
+ skipped = append(skipped, csk...)
+
+ if primary.Contact.Name == "" {
+ primary.Contact.Name = m.Contact.Name
+ }
+
+ if primary.Contact.URL == "" {
+ primary.Contact.URL = m.Contact.URL
+ }
+
+ if primary.Contact.Email == "" {
+ primary.Contact.Email = m.Contact.Email
+ }
+ }
+
+ if primary.License == nil {
+ primary.License = m.License
+ } else if m.License != nil {
+ var lsk []string
+ primary.License.Extensions, lsk = mergeExtensions(primary.License.Extensions, m.License.Extensions)
+ skipped = append(skipped, lsk...)
+
+ if primary.License.Name == "" {
+ primary.License.Name = m.License.Name
+ }
+
+ if primary.License.URL == "" {
+ primary.License.URL = m.License.URL
+ }
+ }
+
+ return skipped
+}
+
+func mergeExtensions(primary spec.Extensions, m spec.Extensions) (result spec.Extensions, skipped []string) {
+ if primary == nil {
+ result = m
+
+ return
+ }
+
+ if m == nil {
+ result = primary
+
+ return
+ }
+
+ result = primary
+ for k, v := range m {
+ if _, found := primary[k]; found {
+ skipped = append(skipped, k)
+
+ continue
+ }
+
+ primary[k] = v
+ }
+
+ return
+}
+
+func initPrimary(primary *spec.Swagger) {
+ if primary.SecurityDefinitions == nil {
+ primary.SecurityDefinitions = make(map[string]*spec.SecurityScheme)
+ }
+
+ if primary.Security == nil {
+ primary.Security = make([]map[string][]string, 0, allocSmallMap)
+ }
+
+ if primary.Produces == nil {
+ primary.Produces = make([]string, 0, allocSmallMap)
+ }
+
+ if primary.Consumes == nil {
+ primary.Consumes = make([]string, 0, allocSmallMap)
+ }
+
+ if primary.Tags == nil {
+ primary.Tags = make([]spec.Tag, 0, allocSmallMap)
+ }
+
+ if primary.Schemes == nil {
+ primary.Schemes = make([]string, 0, allocSmallMap)
+ }
+
+ if primary.Paths == nil {
+ primary.Paths = &spec.Paths{Paths: make(map[string]spec.PathItem)}
+ }
+
+ if primary.Paths.Paths == nil {
+ primary.Paths.Paths = make(map[string]spec.PathItem)
+ }
+
+ if primary.Definitions == nil {
+ primary.Definitions = make(spec.Definitions)
+ }
+
+ if primary.Parameters == nil {
+ primary.Parameters = make(map[string]spec.Parameter)
+ }
+
+ if primary.Responses == nil {
+ primary.Responses = make(map[string]spec.Response)
+ }
+}
diff --git a/vendor/github.com/go-openapi/analysis/schema.go b/vendor/github.com/go-openapi/analysis/schema.go
new file mode 100644
index 000000000000..039dac15661b
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/schema.go
@@ -0,0 +1,257 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+// SchemaOpts configures the schema analyzer
+type SchemaOpts struct {
+ Schema *spec.Schema
+ Root any
+ BasePath string
+ _ struct{}
+}
+
+// Schema analysis, will classify the schema according to known
+// patterns.
+func Schema(opts SchemaOpts) (*AnalyzedSchema, error) {
+ if opts.Schema == nil {
+ return nil, ErrNoSchema
+ }
+
+ a := &AnalyzedSchema{
+ schema: opts.Schema,
+ root: opts.Root,
+ basePath: opts.BasePath,
+ }
+
+ a.initializeFlags()
+ a.inferKnownType()
+ a.inferEnum()
+ a.inferBaseType()
+
+ if err := a.inferMap(); err != nil {
+ return nil, err
+ }
+ if err := a.inferArray(); err != nil {
+ return nil, err
+ }
+
+ a.inferTuple()
+
+ if err := a.inferFromRef(); err != nil {
+ return nil, err
+ }
+
+ a.inferSimpleSchema()
+
+ return a, nil
+}
+
+// AnalyzedSchema indicates what the schema represents
+type AnalyzedSchema struct {
+ schema *spec.Schema
+ root any
+ basePath string
+
+ hasProps bool
+ hasAllOf bool
+ hasItems bool
+ hasAdditionalProps bool
+ hasAdditionalItems bool
+ hasRef bool
+
+ IsKnownType bool
+ IsSimpleSchema bool
+ IsArray bool
+ IsSimpleArray bool
+ IsMap bool
+ IsSimpleMap bool
+ IsExtendedObject bool
+ IsTuple bool
+ IsTupleWithExtra bool
+ IsBaseType bool
+ IsEnum bool
+}
+
+// Inherits copies value fields from other onto this schema
+func (a *AnalyzedSchema) inherits(other *AnalyzedSchema) {
+ if other == nil {
+ return
+ }
+ a.hasProps = other.hasProps
+ a.hasAllOf = other.hasAllOf
+ a.hasItems = other.hasItems
+ a.hasAdditionalItems = other.hasAdditionalItems
+ a.hasAdditionalProps = other.hasAdditionalProps
+ a.hasRef = other.hasRef
+
+ a.IsKnownType = other.IsKnownType
+ a.IsSimpleSchema = other.IsSimpleSchema
+ a.IsArray = other.IsArray
+ a.IsSimpleArray = other.IsSimpleArray
+ a.IsMap = other.IsMap
+ a.IsSimpleMap = other.IsSimpleMap
+ a.IsExtendedObject = other.IsExtendedObject
+ a.IsTuple = other.IsTuple
+ a.IsTupleWithExtra = other.IsTupleWithExtra
+ a.IsBaseType = other.IsBaseType
+ a.IsEnum = other.IsEnum
+}
+
+func (a *AnalyzedSchema) inferFromRef() error {
+ if a.hasRef {
+ sch := new(spec.Schema)
+ sch.Ref = a.schema.Ref
+ err := spec.ExpandSchema(sch, a.root, nil)
+ if err != nil {
+ return err
+ }
+ rsch, err := Schema(SchemaOpts{
+ Schema: sch,
+ Root: a.root,
+ BasePath: a.basePath,
+ })
+ if err != nil {
+ // NOTE(fredbi): currently the only cause for errors is
+ // unresolved ref. Since spec.ExpandSchema() expands the
+ // schema recursively, there is no chance to get there,
+ // until we add more causes for error in this schema analysis.
+ return err
+ }
+ a.inherits(rsch)
+ }
+
+ return nil
+}
+
+func (a *AnalyzedSchema) inferSimpleSchema() {
+ a.IsSimpleSchema = a.IsKnownType || a.IsSimpleArray || a.IsSimpleMap
+}
+
+func (a *AnalyzedSchema) inferKnownType() {
+ tpe := a.schema.Type
+ format := a.schema.Format
+ a.IsKnownType = tpe.Contains("boolean") ||
+ tpe.Contains("integer") ||
+ tpe.Contains("number") ||
+ tpe.Contains("string") ||
+ (format != "" && strfmt.Default.ContainsName(format)) ||
+ (a.isObjectType() && !a.hasProps && !a.hasAllOf && !a.hasAdditionalProps && !a.hasAdditionalItems)
+}
+
+func (a *AnalyzedSchema) inferMap() error {
+ if !a.isObjectType() {
+ return nil
+ }
+
+ hasExtra := a.hasProps || a.hasAllOf
+ a.IsMap = a.hasAdditionalProps && !hasExtra
+ a.IsExtendedObject = a.hasAdditionalProps && hasExtra
+
+ if !a.IsMap {
+ return nil
+ }
+
+ // maps
+ if a.schema.AdditionalProperties.Schema != nil {
+ msch, err := Schema(SchemaOpts{
+ Schema: a.schema.AdditionalProperties.Schema,
+ Root: a.root,
+ BasePath: a.basePath,
+ })
+ if err != nil {
+ return err
+ }
+ a.IsSimpleMap = msch.IsSimpleSchema
+ } else if a.schema.AdditionalProperties.Allows {
+ a.IsSimpleMap = true
+ }
+
+ return nil
+}
+
+func (a *AnalyzedSchema) inferArray() error {
+ // an array has Items defined as an object schema, otherwise we qualify this JSON array as a tuple
+ // (yes, even if the Items array contains only one element).
+ // arrays in JSON schema may be unrestricted (i.e no Items specified).
+ // Note that arrays in Swagger MUST have Items. Nonetheless, we analyze unrestricted arrays.
+ //
+ // NOTE: the spec package misses the distinction between:
+ // items: [] and items: {}, so we consider both arrays here.
+ a.IsArray = a.isArrayType() && (a.schema.Items == nil || a.schema.Items.Schemas == nil)
+ if a.IsArray && a.hasItems {
+ if a.schema.Items.Schema != nil {
+ itsch, err := Schema(SchemaOpts{
+ Schema: a.schema.Items.Schema,
+ Root: a.root,
+ BasePath: a.basePath,
+ })
+ if err != nil {
+ return err
+ }
+
+ a.IsSimpleArray = itsch.IsSimpleSchema
+ }
+ }
+
+ if a.IsArray && !a.hasItems {
+ a.IsSimpleArray = true
+ }
+
+ return nil
+}
+
+func (a *AnalyzedSchema) inferTuple() {
+ tuple := a.hasItems && a.schema.Items.Schemas != nil
+ a.IsTuple = tuple && !a.hasAdditionalItems
+ a.IsTupleWithExtra = tuple && a.hasAdditionalItems
+}
+
+func (a *AnalyzedSchema) inferBaseType() {
+ if a.isObjectType() {
+ a.IsBaseType = a.schema.Discriminator != ""
+ }
+}
+
+func (a *AnalyzedSchema) inferEnum() {
+ a.IsEnum = len(a.schema.Enum) > 0
+}
+
+func (a *AnalyzedSchema) initializeFlags() {
+ a.hasProps = len(a.schema.Properties) > 0
+ a.hasAllOf = len(a.schema.AllOf) > 0
+ a.hasRef = a.schema.Ref.String() != ""
+
+ a.hasItems = a.schema.Items != nil &&
+ (a.schema.Items.Schema != nil || len(a.schema.Items.Schemas) > 0)
+
+ a.hasAdditionalProps = a.schema.AdditionalProperties != nil &&
+ (a.schema.AdditionalProperties.Schema != nil || a.schema.AdditionalProperties.Allows)
+
+ a.hasAdditionalItems = a.schema.AdditionalItems != nil &&
+ (a.schema.AdditionalItems.Schema != nil || a.schema.AdditionalItems.Allows)
+}
+
+func (a *AnalyzedSchema) isObjectType() bool {
+ return !a.hasRef && (a.schema.Type == nil || a.schema.Type.Contains("") || a.schema.Type.Contains("object"))
+}
+
+func (a *AnalyzedSchema) isArrayType() bool {
+ return !a.hasRef && (a.schema.Type != nil && a.schema.Type.Contains("array"))
+}
+
+// isAnalyzedAsComplex determines if an analyzed schema is eligible to flattening (i.e. it is "complex").
+//
+// Complex means the schema is any of:
+// - a simple type (primitive)
+// - an array of something (items are possibly complex ; if this is the case, items will generate a definition)
+// - a map of something (additionalProperties are possibly complex ; if this is the case, additionalProperties will
+// generate a definition)
+func (a *AnalyzedSchema) isAnalyzedAsComplex() bool {
+ return !a.IsSimpleSchema && !a.IsArray && !a.IsMap
+}
diff --git a/vendor/github.com/go-openapi/errors/.gitattributes b/vendor/github.com/go-openapi/errors/.gitattributes
new file mode 100644
index 000000000000..a0717e4b3b90
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/.gitattributes
@@ -0,0 +1 @@
+*.go text eol=lf
\ No newline at end of file
diff --git a/vendor/github.com/go-openapi/errors/.gitignore b/vendor/github.com/go-openapi/errors/.gitignore
new file mode 100644
index 000000000000..dd91ed6a04e6
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/.gitignore
@@ -0,0 +1,2 @@
+secrets.yml
+coverage.out
diff --git a/vendor/github.com/go-openapi/errors/.golangci.yml b/vendor/github.com/go-openapi/errors/.golangci.yml
new file mode 100644
index 000000000000..5609b4fea9cb
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ #- intrange # disabled while < go1.22
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - noinlineerr
+ - nonamedreturns
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/errors/LICENSE b/vendor/github.com/go-openapi/errors/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/errors/README.md b/vendor/github.com/go-openapi/errors/README.md
new file mode 100644
index 000000000000..d7e3a18bcf54
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/README.md
@@ -0,0 +1,12 @@
+# OpenAPI errors [](https://github.com/go-openapi/errors/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/errors)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/errors)
+[](https://goreportcard.com/report/github.com/go-openapi/errors)
+
+Shared errors and error interface used throughout the various libraries found in the go-openapi toolkit.
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
diff --git a/vendor/github.com/go-openapi/errors/api.go b/vendor/github.com/go-openapi/errors/api.go
new file mode 100644
index 000000000000..d39233bafe42
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/api.go
@@ -0,0 +1,181 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package errors
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+)
+
+// DefaultHTTPCode is used when the error Code cannot be used as an HTTP code.
+var DefaultHTTPCode = http.StatusUnprocessableEntity
+
+// Error represents a error interface all swagger framework errors implement
+type Error interface {
+ error
+ Code() int32
+}
+
+type apiError struct {
+ code int32
+ message string
+}
+
+func (a *apiError) Error() string {
+ return a.message
+}
+
+func (a *apiError) Code() int32 {
+ return a.code
+}
+
+// MarshalJSON implements the JSON encoding interface
+func (a apiError) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]any{
+ "code": a.code,
+ "message": a.message,
+ })
+}
+
+// New creates a new API error with a code and a message
+func New(code int32, message string, args ...any) Error {
+ if len(args) > 0 {
+ return &apiError{
+ code: code,
+ message: fmt.Sprintf(message, args...),
+ }
+ }
+ return &apiError{
+ code: code,
+ message: message,
+ }
+}
+
+// NotFound creates a new not found error
+func NotFound(message string, args ...any) Error {
+ if message == "" {
+ message = "Not found"
+ }
+ return New(http.StatusNotFound, message, args...)
+}
+
+// NotImplemented creates a new not implemented error
+func NotImplemented(message string) Error {
+ return New(http.StatusNotImplemented, "%s", message)
+}
+
+// MethodNotAllowedError represents an error for when the path matches but the method doesn't
+type MethodNotAllowedError struct {
+ code int32
+ Allowed []string
+ message string
+}
+
+func (m *MethodNotAllowedError) Error() string {
+ return m.message
+}
+
+// Code the error code
+func (m *MethodNotAllowedError) Code() int32 {
+ return m.code
+}
+
+// MarshalJSON implements the JSON encoding interface
+func (m MethodNotAllowedError) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]any{
+ "code": m.code,
+ "message": m.message,
+ "allowed": m.Allowed,
+ })
+}
+
+func errorAsJSON(err Error) []byte {
+ //nolint:errchkjson
+ b, _ := json.Marshal(struct {
+ Code int32 `json:"code"`
+ Message string `json:"message"`
+ }{err.Code(), err.Error()})
+ return b
+}
+
+func flattenComposite(errs *CompositeError) *CompositeError {
+ var res []error
+ for _, er := range errs.Errors {
+ switch e := er.(type) {
+ case *CompositeError:
+ if e != nil && len(e.Errors) > 0 {
+ flat := flattenComposite(e)
+ if len(flat.Errors) > 0 {
+ res = append(res, flat.Errors...)
+ }
+ }
+ default:
+ if e != nil {
+ res = append(res, e)
+ }
+ }
+ }
+ return CompositeValidationError(res...)
+}
+
+// MethodNotAllowed creates a new method not allowed error
+func MethodNotAllowed(requested string, allow []string) Error {
+ msg := fmt.Sprintf("method %s is not allowed, but [%s] are", requested, strings.Join(allow, ","))
+ return &MethodNotAllowedError{
+ code: http.StatusMethodNotAllowed,
+ Allowed: allow,
+ message: msg,
+ }
+}
+
+// ServeError implements the http error handler interface
+func ServeError(rw http.ResponseWriter, r *http.Request, err error) {
+ rw.Header().Set("Content-Type", "application/json")
+ switch e := err.(type) {
+ case *CompositeError:
+ er := flattenComposite(e)
+ // strips composite errors to first element only
+ if len(er.Errors) > 0 {
+ ServeError(rw, r, er.Errors[0])
+ } else {
+ // guard against empty CompositeError (invalid construct)
+ ServeError(rw, r, nil)
+ }
+ case *MethodNotAllowedError:
+ rw.Header().Add("Allow", strings.Join(e.Allowed, ","))
+ rw.WriteHeader(asHTTPCode(int(e.Code())))
+ if r == nil || r.Method != http.MethodHead {
+ _, _ = rw.Write(errorAsJSON(e))
+ }
+ case Error:
+ value := reflect.ValueOf(e)
+ if value.Kind() == reflect.Ptr && value.IsNil() {
+ rw.WriteHeader(http.StatusInternalServerError)
+ _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
+ return
+ }
+ rw.WriteHeader(asHTTPCode(int(e.Code())))
+ if r == nil || r.Method != http.MethodHead {
+ _, _ = rw.Write(errorAsJSON(e))
+ }
+ case nil:
+ rw.WriteHeader(http.StatusInternalServerError)
+ _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
+ default:
+ rw.WriteHeader(http.StatusInternalServerError)
+ if r == nil || r.Method != http.MethodHead {
+ _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "%v", err)))
+ }
+ }
+}
+
+func asHTTPCode(input int) int {
+ if input >= maximumValidHTTPCode {
+ return DefaultHTTPCode
+ }
+ return input
+}
diff --git a/vendor/github.com/go-openapi/errors/auth.go b/vendor/github.com/go-openapi/errors/auth.go
new file mode 100644
index 000000000000..08de582e5db2
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/auth.go
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package errors
+
+import "net/http"
+
+// Unauthenticated returns an unauthenticated error
+func Unauthenticated(scheme string) Error {
+ return New(http.StatusUnauthorized, "unauthenticated for %s", scheme)
+}
diff --git a/vendor/github.com/go-openapi/errors/doc.go b/vendor/github.com/go-openapi/errors/doc.go
new file mode 100644
index 000000000000..b4627f30f4c9
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/doc.go
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+Package errors provides an Error interface and several concrete types
+implementing this interface to manage API errors and JSON-schema validation
+errors.
+
+A middleware handler ServeError() is provided to serve the errors types
+it defines.
+
+It is used throughout the various go-openapi toolkit libraries
+(https://github.com/go-openapi).
+*/
+package errors
diff --git a/vendor/github.com/go-openapi/errors/headers.go b/vendor/github.com/go-openapi/errors/headers.go
new file mode 100644
index 000000000000..2d837c34ac47
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/headers.go
@@ -0,0 +1,92 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package errors
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+// Validation represents a failure of a precondition
+type Validation struct { //nolint: errname
+ code int32
+ Name string
+ In string
+ Value any
+ message string
+ Values []any
+}
+
+func (e *Validation) Error() string {
+ return e.message
+}
+
+// Code the error code
+func (e *Validation) Code() int32 {
+ return e.code
+}
+
+// MarshalJSON implements the JSON encoding interface
+func (e Validation) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]any{
+ "code": e.code,
+ "message": e.message,
+ "in": e.In,
+ "name": e.Name,
+ "value": e.Value,
+ "values": e.Values,
+ })
+}
+
+// ValidateName sets the name for a validation or updates it for a nested property
+func (e *Validation) ValidateName(name string) *Validation {
+ if name != "" {
+ if e.Name == "" {
+ e.Name = name
+ e.message = name + e.message
+ } else {
+ e.Name = name + "." + e.Name
+ e.message = name + "." + e.message
+ }
+ }
+ return e
+}
+
+const (
+ contentTypeFail = `unsupported media type %q, only %v are allowed`
+ responseFormatFail = `unsupported media type requested, only %v are available`
+)
+
+// InvalidContentType error for an invalid content type
+func InvalidContentType(value string, allowed []string) *Validation {
+ values := make([]any, 0, len(allowed))
+ for _, v := range allowed {
+ values = append(values, v)
+ }
+ return &Validation{
+ code: http.StatusUnsupportedMediaType,
+ Name: "Content-Type",
+ In: "header",
+ Value: value,
+ Values: values,
+ message: fmt.Sprintf(contentTypeFail, value, allowed),
+ }
+}
+
+// InvalidResponseFormat error for an unacceptable response format request
+func InvalidResponseFormat(value string, allowed []string) *Validation {
+ values := make([]any, 0, len(allowed))
+ for _, v := range allowed {
+ values = append(values, v)
+ }
+ return &Validation{
+ code: http.StatusNotAcceptable,
+ Name: "Accept",
+ In: "header",
+ Value: value,
+ Values: values,
+ message: fmt.Sprintf(responseFormatFail, allowed),
+ }
+}
diff --git a/vendor/github.com/go-openapi/errors/middleware.go b/vendor/github.com/go-openapi/errors/middleware.go
new file mode 100644
index 000000000000..c434e59a6fa2
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/middleware.go
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package errors
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+)
+
+// APIVerificationFailed is an error that contains all the missing info for a mismatched section
+// between the api registrations and the api spec
+type APIVerificationFailed struct { //nolint: errname
+ Section string `json:"section,omitempty"`
+ MissingSpecification []string `json:"missingSpecification,omitempty"`
+ MissingRegistration []string `json:"missingRegistration,omitempty"`
+}
+
+func (v *APIVerificationFailed) Error() string {
+ buf := bytes.NewBuffer(nil)
+
+ hasRegMissing := len(v.MissingRegistration) > 0
+ hasSpecMissing := len(v.MissingSpecification) > 0
+
+ if hasRegMissing {
+ fmt.Fprintf(buf, "missing [%s] %s registrations", strings.Join(v.MissingRegistration, ", "), v.Section)
+ }
+
+ if hasRegMissing && hasSpecMissing {
+ buf.WriteString("\n")
+ }
+
+ if hasSpecMissing {
+ fmt.Fprintf(buf, "missing from spec file [%s] %s", strings.Join(v.MissingSpecification, ", "), v.Section)
+ }
+
+ return buf.String()
+}
diff --git a/vendor/github.com/go-openapi/errors/parsing.go b/vendor/github.com/go-openapi/errors/parsing.go
new file mode 100644
index 000000000000..ea2a7c603771
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/parsing.go
@@ -0,0 +1,68 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package errors
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+// ParseError represents a parsing error
+type ParseError struct {
+ code int32
+ Name string
+ In string
+ Value string
+ Reason error
+ message string
+}
+
+// NewParseError creates a new parse error
+func NewParseError(name, in, value string, reason error) *ParseError {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(parseErrorTemplContentNoIn, name, value, reason)
+ } else {
+ msg = fmt.Sprintf(parseErrorTemplContent, name, in, value, reason)
+ }
+ return &ParseError{
+ code: http.StatusBadRequest,
+ Name: name,
+ In: in,
+ Value: value,
+ Reason: reason,
+ message: msg,
+ }
+}
+
+func (e *ParseError) Error() string {
+ return e.message
+}
+
+// Code returns the http status code for this error
+func (e *ParseError) Code() int32 {
+ return e.code
+}
+
+// MarshalJSON implements the JSON encoding interface
+func (e ParseError) MarshalJSON() ([]byte, error) {
+ var reason string
+ if e.Reason != nil {
+ reason = e.Reason.Error()
+ }
+ return json.Marshal(map[string]any{
+ "code": e.code,
+ "message": e.message,
+ "in": e.In,
+ "name": e.Name,
+ "value": e.Value,
+ "reason": reason,
+ })
+}
+
+const (
+ parseErrorTemplContent = `parsing %s %s from %q failed, because %s`
+ parseErrorTemplContentNoIn = `parsing %s from %q failed, because %s`
+)
diff --git a/vendor/github.com/go-openapi/errors/schema.go b/vendor/github.com/go-openapi/errors/schema.go
new file mode 100644
index 000000000000..e59ca4f863f2
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/schema.go
@@ -0,0 +1,608 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package errors
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+)
+
+const (
+ invalidType = "%s is an invalid type name"
+ typeFail = "%s in %s must be of type %s"
+ typeFailWithData = "%s in %s must be of type %s: %q"
+ typeFailWithError = "%s in %s must be of type %s, because: %s"
+ requiredFail = "%s in %s is required"
+ readOnlyFail = "%s in %s is readOnly"
+ tooLongMessage = "%s in %s should be at most %d chars long"
+ tooShortMessage = "%s in %s should be at least %d chars long"
+ patternFail = "%s in %s should match '%s'"
+ enumFail = "%s in %s should be one of %v"
+ multipleOfFail = "%s in %s should be a multiple of %v"
+ maximumIncFail = "%s in %s should be less than or equal to %v"
+ maximumExcFail = "%s in %s should be less than %v"
+ minIncFail = "%s in %s should be greater than or equal to %v"
+ minExcFail = "%s in %s should be greater than %v"
+ uniqueFail = "%s in %s shouldn't contain duplicates"
+ maximumItemsFail = "%s in %s should have at most %d items"
+ minItemsFail = "%s in %s should have at least %d items"
+ typeFailNoIn = "%s must be of type %s"
+ typeFailWithDataNoIn = "%s must be of type %s: %q"
+ typeFailWithErrorNoIn = "%s must be of type %s, because: %s"
+ requiredFailNoIn = "%s is required"
+ readOnlyFailNoIn = "%s is readOnly"
+ tooLongMessageNoIn = "%s should be at most %d chars long"
+ tooShortMessageNoIn = "%s should be at least %d chars long"
+ patternFailNoIn = "%s should match '%s'"
+ enumFailNoIn = "%s should be one of %v"
+ multipleOfFailNoIn = "%s should be a multiple of %v"
+ maximumIncFailNoIn = "%s should be less than or equal to %v"
+ maximumExcFailNoIn = "%s should be less than %v"
+ minIncFailNoIn = "%s should be greater than or equal to %v"
+ minExcFailNoIn = "%s should be greater than %v"
+ uniqueFailNoIn = "%s shouldn't contain duplicates"
+ maximumItemsFailNoIn = "%s should have at most %d items"
+ minItemsFailNoIn = "%s should have at least %d items"
+ noAdditionalItems = "%s in %s can't have additional items"
+ noAdditionalItemsNoIn = "%s can't have additional items"
+ tooFewProperties = "%s in %s should have at least %d properties"
+ tooFewPropertiesNoIn = "%s should have at least %d properties"
+ tooManyProperties = "%s in %s should have at most %d properties"
+ tooManyPropertiesNoIn = "%s should have at most %d properties"
+ unallowedProperty = "%s.%s in %s is a forbidden property"
+ unallowedPropertyNoIn = "%s.%s is a forbidden property"
+ failedAllPatternProps = "%s.%s in %s failed all pattern properties"
+ failedAllPatternPropsNoIn = "%s.%s failed all pattern properties"
+ multipleOfMustBePositive = "factor MultipleOf declared for %s must be positive: %v"
+)
+
+const maximumValidHTTPCode = 600
+
+// All code responses can be used to differentiate errors for different handling
+// by the consuming program
+const (
+ // CompositeErrorCode remains 422 for backwards-compatibility
+ // and to separate it from validation errors with cause
+ CompositeErrorCode = http.StatusUnprocessableEntity
+
+ // InvalidTypeCode is used for any subclass of invalid types
+ InvalidTypeCode = maximumValidHTTPCode + iota
+ RequiredFailCode
+ TooLongFailCode
+ TooShortFailCode
+ PatternFailCode
+ EnumFailCode
+ MultipleOfFailCode
+ MaxFailCode
+ MinFailCode
+ UniqueFailCode
+ MaxItemsFailCode
+ MinItemsFailCode
+ NoAdditionalItemsCode
+ TooFewPropertiesCode
+ TooManyPropertiesCode
+ UnallowedPropertyCode
+ FailedAllPatternPropsCode
+ MultipleOfMustBePositiveCode
+ ReadOnlyFailCode
+)
+
+// CompositeError is an error that groups several errors together
+type CompositeError struct {
+ Errors []error
+ code int32
+ message string
+}
+
+// Code for this error
+func (c *CompositeError) Code() int32 {
+ return c.code
+}
+
+func (c *CompositeError) Error() string {
+ if len(c.Errors) > 0 {
+ msgs := []string{c.message + ":"}
+ for _, e := range c.Errors {
+ msgs = append(msgs, e.Error())
+ }
+ return strings.Join(msgs, "\n")
+ }
+ return c.message
+}
+
+func (c *CompositeError) Unwrap() []error {
+ return c.Errors
+}
+
+// MarshalJSON implements the JSON encoding interface
+func (c CompositeError) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]any{
+ "code": c.code,
+ "message": c.message,
+ "errors": c.Errors,
+ })
+}
+
+// CompositeValidationError an error to wrap a bunch of other errors
+func CompositeValidationError(errors ...error) *CompositeError {
+ return &CompositeError{
+ code: CompositeErrorCode,
+ Errors: append(make([]error, 0, len(errors)), errors...),
+ message: "validation failure list",
+ }
+}
+
+// ValidateName recursively sets the name for all validations or updates them for nested properties
+func (c *CompositeError) ValidateName(name string) *CompositeError {
+ for i, e := range c.Errors {
+ if ve, ok := e.(*Validation); ok {
+ c.Errors[i] = ve.ValidateName(name)
+ } else if ce, ok := e.(*CompositeError); ok {
+ c.Errors[i] = ce.ValidateName(name)
+ }
+ }
+
+ return c
+}
+
+// FailedAllPatternProperties an error for when the property doesn't match a pattern
+func FailedAllPatternProperties(name, in, key string) *Validation {
+ msg := fmt.Sprintf(failedAllPatternProps, name, key, in)
+ if in == "" {
+ msg = fmt.Sprintf(failedAllPatternPropsNoIn, name, key)
+ }
+ return &Validation{
+ code: FailedAllPatternPropsCode,
+ Name: name,
+ In: in,
+ Value: key,
+ message: msg,
+ }
+}
+
+// PropertyNotAllowed an error for when the property doesn't match a pattern
+func PropertyNotAllowed(name, in, key string) *Validation {
+ msg := fmt.Sprintf(unallowedProperty, name, key, in)
+ if in == "" {
+ msg = fmt.Sprintf(unallowedPropertyNoIn, name, key)
+ }
+ return &Validation{
+ code: UnallowedPropertyCode,
+ Name: name,
+ In: in,
+ Value: key,
+ message: msg,
+ }
+}
+
+// TooFewProperties an error for an object with too few properties
+func TooFewProperties(name, in string, n int64) *Validation {
+ msg := fmt.Sprintf(tooFewProperties, name, in, n)
+ if in == "" {
+ msg = fmt.Sprintf(tooFewPropertiesNoIn, name, n)
+ }
+ return &Validation{
+ code: TooFewPropertiesCode,
+ Name: name,
+ In: in,
+ Value: n,
+ message: msg,
+ }
+}
+
+// TooManyProperties an error for an object with too many properties
+func TooManyProperties(name, in string, n int64) *Validation {
+ msg := fmt.Sprintf(tooManyProperties, name, in, n)
+ if in == "" {
+ msg = fmt.Sprintf(tooManyPropertiesNoIn, name, n)
+ }
+ return &Validation{
+ code: TooManyPropertiesCode,
+ Name: name,
+ In: in,
+ Value: n,
+ message: msg,
+ }
+}
+
+// AdditionalItemsNotAllowed an error for invalid additional items
+func AdditionalItemsNotAllowed(name, in string) *Validation {
+ msg := fmt.Sprintf(noAdditionalItems, name, in)
+ if in == "" {
+ msg = fmt.Sprintf(noAdditionalItemsNoIn, name)
+ }
+ return &Validation{
+ code: NoAdditionalItemsCode,
+ Name: name,
+ In: in,
+ message: msg,
+ }
+}
+
+// InvalidCollectionFormat another flavor of invalid type error
+func InvalidCollectionFormat(name, in, format string) *Validation {
+ return &Validation{
+ code: InvalidTypeCode,
+ Name: name,
+ In: in,
+ Value: format,
+ message: fmt.Sprintf("the collection format %q is not supported for the %s param %q", format, in, name),
+ }
+}
+
+// InvalidTypeName an error for when the type is invalid
+func InvalidTypeName(typeName string) *Validation {
+ return &Validation{
+ code: InvalidTypeCode,
+ Value: typeName,
+ message: fmt.Sprintf(invalidType, typeName),
+ }
+}
+
+// InvalidType creates an error for when the type is invalid
+func InvalidType(name, in, typeName string, value any) *Validation {
+ var message string
+
+ if in != "" {
+ switch value.(type) {
+ case string:
+ message = fmt.Sprintf(typeFailWithData, name, in, typeName, value)
+ case error:
+ message = fmt.Sprintf(typeFailWithError, name, in, typeName, value)
+ default:
+ message = fmt.Sprintf(typeFail, name, in, typeName)
+ }
+ } else {
+ switch value.(type) {
+ case string:
+ message = fmt.Sprintf(typeFailWithDataNoIn, name, typeName, value)
+ case error:
+ message = fmt.Sprintf(typeFailWithErrorNoIn, name, typeName, value)
+ default:
+ message = fmt.Sprintf(typeFailNoIn, name, typeName)
+ }
+ }
+
+ return &Validation{
+ code: InvalidTypeCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+
+}
+
+// DuplicateItems error for when an array contains duplicates
+func DuplicateItems(name, in string) *Validation {
+ msg := fmt.Sprintf(uniqueFail, name, in)
+ if in == "" {
+ msg = fmt.Sprintf(uniqueFailNoIn, name)
+ }
+ return &Validation{
+ code: UniqueFailCode,
+ Name: name,
+ In: in,
+ message: msg,
+ }
+}
+
+// TooManyItems error for when an array contains too many items
+func TooManyItems(name, in string, maximum int64, value any) *Validation {
+ msg := fmt.Sprintf(maximumItemsFail, name, in, maximum)
+ if in == "" {
+ msg = fmt.Sprintf(maximumItemsFailNoIn, name, maximum)
+ }
+
+ return &Validation{
+ code: MaxItemsFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// TooFewItems error for when an array contains too few items
+func TooFewItems(name, in string, minimum int64, value any) *Validation {
+ msg := fmt.Sprintf(minItemsFail, name, in, minimum)
+ if in == "" {
+ msg = fmt.Sprintf(minItemsFailNoIn, name, minimum)
+ }
+ return &Validation{
+ code: MinItemsFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// ExceedsMaximumInt error for when maximumimum validation fails
+func ExceedsMaximumInt(name, in string, maximum int64, exclusive bool, value any) *Validation {
+ var message string
+ if in == "" {
+ m := maximumIncFailNoIn
+ if exclusive {
+ m = maximumExcFailNoIn
+ }
+ message = fmt.Sprintf(m, name, maximum)
+ } else {
+ m := maximumIncFail
+ if exclusive {
+ m = maximumExcFail
+ }
+ message = fmt.Sprintf(m, name, in, maximum)
+ }
+ return &Validation{
+ code: MaxFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+}
+
+// ExceedsMaximumUint error for when maximumimum validation fails
+func ExceedsMaximumUint(name, in string, maximum uint64, exclusive bool, value any) *Validation {
+ var message string
+ if in == "" {
+ m := maximumIncFailNoIn
+ if exclusive {
+ m = maximumExcFailNoIn
+ }
+ message = fmt.Sprintf(m, name, maximum)
+ } else {
+ m := maximumIncFail
+ if exclusive {
+ m = maximumExcFail
+ }
+ message = fmt.Sprintf(m, name, in, maximum)
+ }
+ return &Validation{
+ code: MaxFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+}
+
+// ExceedsMaximum error for when maximumimum validation fails
+func ExceedsMaximum(name, in string, maximum float64, exclusive bool, value any) *Validation {
+ var message string
+ if in == "" {
+ m := maximumIncFailNoIn
+ if exclusive {
+ m = maximumExcFailNoIn
+ }
+ message = fmt.Sprintf(m, name, maximum)
+ } else {
+ m := maximumIncFail
+ if exclusive {
+ m = maximumExcFail
+ }
+ message = fmt.Sprintf(m, name, in, maximum)
+ }
+ return &Validation{
+ code: MaxFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+}
+
+// ExceedsMinimumInt error for when minimum validation fails
+func ExceedsMinimumInt(name, in string, minimum int64, exclusive bool, value any) *Validation {
+ var message string
+ if in == "" {
+ m := minIncFailNoIn
+ if exclusive {
+ m = minExcFailNoIn
+ }
+ message = fmt.Sprintf(m, name, minimum)
+ } else {
+ m := minIncFail
+ if exclusive {
+ m = minExcFail
+ }
+ message = fmt.Sprintf(m, name, in, minimum)
+ }
+ return &Validation{
+ code: MinFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+}
+
+// ExceedsMinimumUint error for when minimum validation fails
+func ExceedsMinimumUint(name, in string, minimum uint64, exclusive bool, value any) *Validation {
+ var message string
+ if in == "" {
+ m := minIncFailNoIn
+ if exclusive {
+ m = minExcFailNoIn
+ }
+ message = fmt.Sprintf(m, name, minimum)
+ } else {
+ m := minIncFail
+ if exclusive {
+ m = minExcFail
+ }
+ message = fmt.Sprintf(m, name, in, minimum)
+ }
+ return &Validation{
+ code: MinFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+}
+
+// ExceedsMinimum error for when minimum validation fails
+func ExceedsMinimum(name, in string, minimum float64, exclusive bool, value any) *Validation {
+ var message string
+ if in == "" {
+ m := minIncFailNoIn
+ if exclusive {
+ m = minExcFailNoIn
+ }
+ message = fmt.Sprintf(m, name, minimum)
+ } else {
+ m := minIncFail
+ if exclusive {
+ m = minExcFail
+ }
+ message = fmt.Sprintf(m, name, in, minimum)
+ }
+ return &Validation{
+ code: MinFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: message,
+ }
+}
+
+// NotMultipleOf error for when multiple of validation fails
+func NotMultipleOf(name, in string, multiple, value any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple)
+ } else {
+ msg = fmt.Sprintf(multipleOfFail, name, in, multiple)
+ }
+ return &Validation{
+ code: MultipleOfFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// EnumFail error for when an enum validation fails
+func EnumFail(name, in string, value any, values []any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(enumFailNoIn, name, values)
+ } else {
+ msg = fmt.Sprintf(enumFail, name, in, values)
+ }
+
+ return &Validation{
+ code: EnumFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ Values: values,
+ message: msg,
+ }
+}
+
+// Required error for when a value is missing
+func Required(name, in string, value any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(requiredFailNoIn, name)
+ } else {
+ msg = fmt.Sprintf(requiredFail, name, in)
+ }
+ return &Validation{
+ code: RequiredFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// ReadOnly error for when a value is present in request
+func ReadOnly(name, in string, value any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(readOnlyFailNoIn, name)
+ } else {
+ msg = fmt.Sprintf(readOnlyFail, name, in)
+ }
+ return &Validation{
+ code: ReadOnlyFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// TooLong error for when a string is too long
+func TooLong(name, in string, maximum int64, value any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(tooLongMessageNoIn, name, maximum)
+ } else {
+ msg = fmt.Sprintf(tooLongMessage, name, in, maximum)
+ }
+ return &Validation{
+ code: TooLongFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// TooShort error for when a string is too short
+func TooShort(name, in string, minimum int64, value any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(tooShortMessageNoIn, name, minimum)
+ } else {
+ msg = fmt.Sprintf(tooShortMessage, name, in, minimum)
+ }
+
+ return &Validation{
+ code: TooShortFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// FailedPattern error for when a string fails a regex pattern match
+// the pattern that is returned is the ECMA syntax version of the pattern not the golang version.
+func FailedPattern(name, in, pattern string, value any) *Validation {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(patternFailNoIn, name, pattern)
+ } else {
+ msg = fmt.Sprintf(patternFail, name, in, pattern)
+ }
+
+ return &Validation{
+ code: PatternFailCode,
+ Name: name,
+ In: in,
+ Value: value,
+ message: msg,
+ }
+}
+
+// MultipleOfMustBePositive error for when a
+// multipleOf factor is negative
+func MultipleOfMustBePositive(name, in string, factor any) *Validation {
+ return &Validation{
+ code: MultipleOfMustBePositiveCode,
+ Name: name,
+ In: in,
+ Value: factor,
+ message: fmt.Sprintf(multipleOfMustBePositive, name, factor),
+ }
+}
diff --git a/vendor/github.com/go-openapi/jsonpointer/.editorconfig b/vendor/github.com/go-openapi/jsonpointer/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/jsonpointer/.gitignore b/vendor/github.com/go-openapi/jsonpointer/.gitignore
new file mode 100644
index 000000000000..769c244007b5
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/.gitignore
@@ -0,0 +1 @@
+secrets.yml
diff --git a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml
new file mode 100644
index 000000000000..7cea1af8b529
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ #- intrange # disabled while < go1.22
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/jsonpointer/LICENSE b/vendor/github.com/go-openapi/jsonpointer/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/jsonpointer/README.md b/vendor/github.com/go-openapi/jsonpointer/README.md
new file mode 100644
index 000000000000..45bd31b14fc0
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/README.md
@@ -0,0 +1,26 @@
+# gojsonpointer [](https://github.com/go-openapi/jsonpointer/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/jsonpointer)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/jsonpointer/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/jsonpointer)
+[](https://goreportcard.com/report/github.com/go-openapi/jsonpointer)
+
+An implementation of JSON Pointer - Go language
+
+## Status
+Completed YES
+
+Tested YES
+
+## References
+
+
+
+also known as [RFC6901](https://www.rfc-editor.org/rfc/rfc6901)
+
+### Note
+
+The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, the reference token MUST contain either...' is not implemented.
+
+That is because our implementation of the JSON pointer only supports explicit references to array elements: the provision in the spec
+to resolve non-existent members as "the last element in the array", using the special trailing character "-".
diff --git a/vendor/github.com/go-openapi/jsonpointer/errors.go b/vendor/github.com/go-openapi/jsonpointer/errors.go
new file mode 100644
index 000000000000..b84343d9d74e
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/errors.go
@@ -0,0 +1,18 @@
+package jsonpointer
+
+type pointerError string
+
+func (e pointerError) Error() string {
+ return string(e)
+}
+
+const (
+ // ErrPointer is an error raised by the jsonpointer package
+ ErrPointer pointerError = "JSON pointer error"
+
+ // ErrInvalidStart states that a JSON pointer must start with a separator ("/")
+ ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator
+
+ // ErrUnsupportedValueType indicates that a value of the wrong type is being set
+ ErrUnsupportedValueType pointerError = "only structs, pointers, maps and slices are supported for setting values"
+)
diff --git a/vendor/github.com/go-openapi/jsonpointer/pointer.go b/vendor/github.com/go-openapi/jsonpointer/pointer.go
new file mode 100644
index 000000000000..7513c4763ba6
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/pointer.go
@@ -0,0 +1,535 @@
+// Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+//
+// 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.
+
+// author sigu-399
+// author-github https://github.com/sigu-399
+// author-mail sigu.399@gmail.com
+//
+// repository-name jsonpointer
+// repository-desc An implementation of JSON Pointer - Go language
+//
+// description Main and unique file.
+//
+// created 25-02-2013
+
+package jsonpointer
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/go-openapi/swag/jsonname"
+)
+
+const (
+ emptyPointer = ``
+ pointerSeparator = `/`
+)
+
+var (
+ jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem()
+ jsonSetableType = reflect.TypeOf(new(JSONSetable)).Elem()
+)
+
+// JSONPointable is an interface for structs to implement when they need to customize the
+// json pointer process
+type JSONPointable interface {
+ JSONLookup(string) (any, error)
+}
+
+// JSONSetable is an interface for structs to implement when they need to customize the
+// json pointer process
+type JSONSetable interface {
+ JSONSet(string, any) error
+}
+
+// Pointer is a representation of a json pointer
+type Pointer struct {
+ referenceTokens []string
+}
+
+// New creates a new json pointer for the given string
+func New(jsonPointerString string) (Pointer, error) {
+ var p Pointer
+ err := p.parse(jsonPointerString)
+
+ return p, err
+}
+
+// Get uses the pointer to retrieve a value from a JSON document
+func (p *Pointer) Get(document any) (any, reflect.Kind, error) {
+ return p.get(document, jsonname.DefaultJSONNameProvider)
+}
+
+// Set uses the pointer to set a value from a JSON document
+func (p *Pointer) Set(document any, value any) (any, error) {
+ return document, p.set(document, value, jsonname.DefaultJSONNameProvider)
+}
+
+// DecodedTokens returns the decoded tokens of this JSON pointer
+func (p *Pointer) DecodedTokens() []string {
+ result := make([]string, 0, len(p.referenceTokens))
+ for _, t := range p.referenceTokens {
+ result = append(result, Unescape(t))
+ }
+ return result
+}
+
+// IsEmpty returns true if this is an empty json pointer
+// this indicates that it points to the root document
+func (p *Pointer) IsEmpty() bool {
+ return len(p.referenceTokens) == 0
+}
+
+// Pointer to string representation function
+func (p *Pointer) String() string {
+
+ if len(p.referenceTokens) == 0 {
+ return emptyPointer
+ }
+
+ return pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator)
+}
+
+func (p *Pointer) Offset(document string) (int64, error) {
+ dec := json.NewDecoder(strings.NewReader(document))
+ var offset int64
+ for _, ttk := range p.DecodedTokens() {
+ tk, err := dec.Token()
+ if err != nil {
+ return 0, err
+ }
+ switch tk := tk.(type) {
+ case json.Delim:
+ switch tk {
+ case '{':
+ offset, err = offsetSingleObject(dec, ttk)
+ if err != nil {
+ return 0, err
+ }
+ case '[':
+ offset, err = offsetSingleArray(dec, ttk)
+ if err != nil {
+ return 0, err
+ }
+ default:
+ return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
+ }
+ default:
+ return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
+ }
+ }
+ return offset, nil
+}
+
+// "Constructor", parses the given string JSON pointer
+func (p *Pointer) parse(jsonPointerString string) error {
+ var err error
+
+ if jsonPointerString != emptyPointer {
+ if !strings.HasPrefix(jsonPointerString, pointerSeparator) {
+ err = errors.Join(ErrInvalidStart, ErrPointer)
+ } else {
+ referenceTokens := strings.Split(jsonPointerString, pointerSeparator)
+ p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...)
+ }
+ }
+
+ return err
+}
+
+func (p *Pointer) get(node any, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) {
+ if nameProvider == nil {
+ nameProvider = jsonname.DefaultJSONNameProvider
+ }
+
+ kind := reflect.Invalid
+
+ // Full document when empty
+ if len(p.referenceTokens) == 0 {
+ return node, kind, nil
+ }
+
+ for _, token := range p.referenceTokens {
+ decodedToken := Unescape(token)
+
+ r, knd, err := getSingleImpl(node, decodedToken, nameProvider)
+ if err != nil {
+ return nil, knd, err
+ }
+ node = r
+ }
+
+ rValue := reflect.ValueOf(node)
+ kind = rValue.Kind()
+
+ return node, kind, nil
+}
+
+func (p *Pointer) set(node, data any, nameProvider *jsonname.NameProvider) error {
+ knd := reflect.ValueOf(node).Kind()
+
+ if knd != reflect.Pointer && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array {
+ return errors.Join(
+ ErrUnsupportedValueType,
+ ErrPointer,
+ )
+ }
+
+ if nameProvider == nil {
+ nameProvider = jsonname.DefaultJSONNameProvider
+ }
+
+ // Full document when empty
+ if len(p.referenceTokens) == 0 {
+ return nil
+ }
+
+ lastI := len(p.referenceTokens) - 1
+ for i, token := range p.referenceTokens {
+ isLastToken := i == lastI
+ decodedToken := Unescape(token)
+
+ if isLastToken {
+
+ return setSingleImpl(node, data, decodedToken, nameProvider)
+ }
+
+ // Check for nil during traversal
+ if isNil(node) {
+ return fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer)
+ }
+
+ rValue := reflect.Indirect(reflect.ValueOf(node))
+ kind := rValue.Kind()
+
+ if rValue.Type().Implements(jsonPointableType) {
+ r, err := node.(JSONPointable).JSONLookup(decodedToken)
+ if err != nil {
+ return err
+ }
+ fld := reflect.ValueOf(r)
+ if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer {
+ node = fld.Addr().Interface()
+ continue
+ }
+ node = r
+ continue
+ }
+
+ switch kind { //nolint:exhaustive
+ case reflect.Struct:
+ nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
+ if !ok {
+ return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
+ }
+ fld := rValue.FieldByName(nm)
+ if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer {
+ node = fld.Addr().Interface()
+ continue
+ }
+ node = fld.Interface()
+
+ case reflect.Map:
+ kv := reflect.ValueOf(decodedToken)
+ mv := rValue.MapIndex(kv)
+
+ if !mv.IsValid() {
+ return fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer)
+ }
+ if mv.CanAddr() && mv.Kind() != reflect.Interface && mv.Kind() != reflect.Map && mv.Kind() != reflect.Slice && mv.Kind() != reflect.Pointer {
+ node = mv.Addr().Interface()
+ continue
+ }
+ node = mv.Interface()
+
+ case reflect.Slice:
+ tokenIndex, err := strconv.Atoi(decodedToken)
+ if err != nil {
+ return err
+ }
+ sLength := rValue.Len()
+ if tokenIndex < 0 || tokenIndex >= sLength {
+ return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer)
+ }
+
+ elem := rValue.Index(tokenIndex)
+ if elem.CanAddr() && elem.Kind() != reflect.Interface && elem.Kind() != reflect.Map && elem.Kind() != reflect.Slice && elem.Kind() != reflect.Pointer {
+ node = elem.Addr().Interface()
+ continue
+ }
+ node = elem.Interface()
+
+ default:
+ return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
+ }
+ }
+
+ return nil
+}
+
+func isNil(input any) bool {
+ if input == nil {
+ return true
+ }
+
+ kind := reflect.TypeOf(input).Kind()
+ switch kind { //nolint:exhaustive
+ case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Chan:
+ return reflect.ValueOf(input).IsNil()
+ default:
+ return false
+ }
+}
+
+// GetForToken gets a value for a json pointer token 1 level deep
+func GetForToken(document any, decodedToken string) (any, reflect.Kind, error) {
+ return getSingleImpl(document, decodedToken, jsonname.DefaultJSONNameProvider)
+}
+
+// SetForToken gets a value for a json pointer token 1 level deep
+func SetForToken(document any, decodedToken string, value any) (any, error) {
+ return document, setSingleImpl(document, value, decodedToken, jsonname.DefaultJSONNameProvider)
+}
+
+func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) {
+ rValue := reflect.Indirect(reflect.ValueOf(node))
+ kind := rValue.Kind()
+ if isNil(node) {
+ return nil, kind, fmt.Errorf("nil value has no field %q: %w", decodedToken, ErrPointer)
+ }
+
+ switch typed := node.(type) {
+ case JSONPointable:
+ r, err := typed.JSONLookup(decodedToken)
+ if err != nil {
+ return nil, kind, err
+ }
+ return r, kind, nil
+ case *any: // case of a pointer to interface, that is not resolved by reflect.Indirect
+ return getSingleImpl(*typed, decodedToken, nameProvider)
+ }
+
+ switch kind { //nolint:exhaustive
+ case reflect.Struct:
+ nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
+ if !ok {
+ return nil, kind, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
+ }
+ fld := rValue.FieldByName(nm)
+ return fld.Interface(), kind, nil
+
+ case reflect.Map:
+ kv := reflect.ValueOf(decodedToken)
+ mv := rValue.MapIndex(kv)
+
+ if mv.IsValid() {
+ return mv.Interface(), kind, nil
+ }
+ return nil, kind, fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer)
+
+ case reflect.Slice:
+ tokenIndex, err := strconv.Atoi(decodedToken)
+ if err != nil {
+ return nil, kind, err
+ }
+ sLength := rValue.Len()
+ if tokenIndex < 0 || tokenIndex >= sLength {
+ return nil, kind, fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength-1, tokenIndex, ErrPointer)
+ }
+
+ elem := rValue.Index(tokenIndex)
+ return elem.Interface(), kind, nil
+
+ default:
+ return nil, kind, fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
+ }
+}
+
+func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.NameProvider) error {
+ rValue := reflect.Indirect(reflect.ValueOf(node))
+
+ // Check for nil to prevent panic when calling rValue.Type()
+ if isNil(node) {
+ return fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer)
+ }
+
+ if ns, ok := node.(JSONSetable); ok { // pointer impl
+ return ns.JSONSet(decodedToken, data)
+ }
+
+ if rValue.Type().Implements(jsonSetableType) {
+ return node.(JSONSetable).JSONSet(decodedToken, data)
+ }
+
+ switch rValue.Kind() { //nolint:exhaustive
+ case reflect.Struct:
+ nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
+ if !ok {
+ return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
+ }
+ fld := rValue.FieldByName(nm)
+ if fld.IsValid() {
+ fld.Set(reflect.ValueOf(data))
+ }
+ return nil
+
+ case reflect.Map:
+ kv := reflect.ValueOf(decodedToken)
+ rValue.SetMapIndex(kv, reflect.ValueOf(data))
+ return nil
+
+ case reflect.Slice:
+ tokenIndex, err := strconv.Atoi(decodedToken)
+ if err != nil {
+ return err
+ }
+ sLength := rValue.Len()
+ if tokenIndex < 0 || tokenIndex >= sLength {
+ return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer)
+ }
+
+ elem := rValue.Index(tokenIndex)
+ if !elem.CanSet() {
+ return fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer)
+ }
+ elem.Set(reflect.ValueOf(data))
+ return nil
+
+ default:
+ return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
+ }
+}
+
+func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) {
+ for dec.More() {
+ offset := dec.InputOffset()
+ tk, err := dec.Token()
+ if err != nil {
+ return 0, err
+ }
+ switch tk := tk.(type) {
+ case json.Delim:
+ switch tk {
+ case '{':
+ if err = drainSingle(dec); err != nil {
+ return 0, err
+ }
+ case '[':
+ if err = drainSingle(dec); err != nil {
+ return 0, err
+ }
+ }
+ case string:
+ if tk == decodedToken {
+ return offset, nil
+ }
+ default:
+ return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
+ }
+ }
+ return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer)
+}
+
+func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) {
+ idx, err := strconv.Atoi(decodedToken)
+ if err != nil {
+ return 0, fmt.Errorf("token reference %q is not a number: %v: %w", decodedToken, err, ErrPointer)
+ }
+ var i int
+ for i = 0; i < idx && dec.More(); i++ {
+ tk, err := dec.Token()
+ if err != nil {
+ return 0, err
+ }
+
+ if delim, isDelim := tk.(json.Delim); isDelim {
+ switch delim {
+ case '{':
+ if err = drainSingle(dec); err != nil {
+ return 0, err
+ }
+ case '[':
+ if err = drainSingle(dec); err != nil {
+ return 0, err
+ }
+ }
+ }
+ }
+
+ if !dec.More() {
+ return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer)
+ }
+ return dec.InputOffset(), nil
+}
+
+// drainSingle drains a single level of object or array.
+// The decoder has to guarantee the beginning delim (i.e. '{' or '[') has been consumed.
+func drainSingle(dec *json.Decoder) error {
+ for dec.More() {
+ tk, err := dec.Token()
+ if err != nil {
+ return err
+ }
+ if delim, isDelim := tk.(json.Delim); isDelim {
+ switch delim {
+ case '{':
+ if err = drainSingle(dec); err != nil {
+ return err
+ }
+ case '[':
+ if err = drainSingle(dec); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ // Consumes the ending delim
+ if _, err := dec.Token(); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Specific JSON pointer encoding here
+// ~0 => ~
+// ~1 => /
+// ... and vice versa
+
+const (
+ encRefTok0 = `~0`
+ encRefTok1 = `~1`
+ decRefTok0 = `~`
+ decRefTok1 = `/`
+)
+
+var (
+ encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0)
+ decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0)
+)
+
+// Unescape unescapes a json pointer reference token string to the original representation
+func Unescape(token string) string {
+ return encRefTokReplacer.Replace(token)
+}
+
+// Escape escapes a pointer reference token string
+func Escape(token string) string {
+ return decRefTokReplacer.Replace(token)
+}
diff --git a/vendor/github.com/go-openapi/jsonreference/.gitignore b/vendor/github.com/go-openapi/jsonreference/.gitignore
new file mode 100644
index 000000000000..769c244007b5
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/.gitignore
@@ -0,0 +1 @@
+secrets.yml
diff --git a/vendor/github.com/go-openapi/jsonreference/.golangci.yml b/vendor/github.com/go-openapi/jsonreference/.golangci.yml
new file mode 100644
index 000000000000..7cea1af8b529
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ #- intrange # disabled while < go1.22
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/jsonreference/LICENSE b/vendor/github.com/go-openapi/jsonreference/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/jsonreference/NOTICE b/vendor/github.com/go-openapi/jsonreference/NOTICE
new file mode 100644
index 000000000000..f9ad7e0f7a0a
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/NOTICE
@@ -0,0 +1,36 @@
+Copyright 2015-2025 go-swagger maintainers
+
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+This software library, github.com/go-openapi/jsonpointer, includes software developed
+by the go-swagger and go-openapi maintainers ("go-swagger maintainers").
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software except in compliance with the License.
+You may obtain a copy of the License at
+
+This software is copied from, derived from, and inspired by other original software products.
+It ships with copies of other software which license terms are recalled below.
+
+The original sofware was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com).
+
+github.com/sigh-399/jsonpointer
+===========================
+
+// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+// SPDX-License-Identifier: Apache-2.0
+
+Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+
+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/github.com/go-openapi/jsonreference/README.md b/vendor/github.com/go-openapi/jsonreference/README.md
new file mode 100644
index 000000000000..2274a4b78fc5
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/README.md
@@ -0,0 +1,26 @@
+# gojsonreference [](https://github.com/go-openapi/jsonreference/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/jsonreference)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/jsonreference)
+[](https://goreportcard.com/report/github.com/go-openapi/jsonreference)
+
+An implementation of JSON Reference - Go language
+
+## Status
+Feature complete. Stable API
+
+## Dependencies
+* https://github.com/go-openapi/jsonpointer
+
+## References
+
+* http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
+* http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software
+on top of which it has been built.
diff --git a/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go
new file mode 100644
index 000000000000..ca79391dcf3e
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package internal
+
+import (
+ "net/url"
+ "regexp"
+ "strings"
+)
+
+const (
+ defaultHTTPPort = ":80"
+ defaultHTTPSPort = ":443"
+)
+
+// Regular expressions used by the normalizations
+var rxPort = regexp.MustCompile(`(:\d+)/?$`)
+var rxDupSlashes = regexp.MustCompile(`/{2,}`)
+
+// NormalizeURL will normalize the specified URL
+// This was added to replace a previous call to the no longer maintained purell library:
+// The call that was used looked like the following:
+//
+// url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes))
+//
+// To explain all that was included in the call above, purell.FlagsSafe was really just the following:
+// - FlagLowercaseScheme
+// - FlagLowercaseHost
+// - FlagRemoveDefaultPort
+// - FlagRemoveDuplicateSlashes (and this was mixed in with the |)
+//
+// This also normalizes the URL into its urlencoded form by removing RawPath and RawFragment.
+func NormalizeURL(u *url.URL) {
+ lowercaseScheme(u)
+ lowercaseHost(u)
+ removeDefaultPort(u)
+ removeDuplicateSlashes(u)
+
+ u.RawPath = ""
+ u.RawFragment = ""
+}
+
+func lowercaseScheme(u *url.URL) {
+ if len(u.Scheme) > 0 {
+ u.Scheme = strings.ToLower(u.Scheme)
+ }
+}
+
+func lowercaseHost(u *url.URL) {
+ if len(u.Host) > 0 {
+ u.Host = strings.ToLower(u.Host)
+ }
+}
+
+func removeDefaultPort(u *url.URL) {
+ if len(u.Host) > 0 {
+ scheme := strings.ToLower(u.Scheme)
+ u.Host = rxPort.ReplaceAllStringFunc(u.Host, func(val string) string {
+ if (scheme == "http" && val == defaultHTTPPort) || (scheme == "https" && val == defaultHTTPSPort) {
+ return ""
+ }
+ return val
+ })
+ }
+}
+
+func removeDuplicateSlashes(u *url.URL) {
+ if len(u.Path) > 0 {
+ u.Path = rxDupSlashes.ReplaceAllString(u.Path, "/")
+ }
+}
diff --git a/vendor/github.com/go-openapi/jsonreference/reference.go b/vendor/github.com/go-openapi/jsonreference/reference.go
new file mode 100644
index 000000000000..33d4798cad36
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/reference.go
@@ -0,0 +1,135 @@
+// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package jsonreference
+
+import (
+ "errors"
+ "net/url"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/jsonreference/internal"
+)
+
+const (
+ fragmentRune = `#`
+)
+
+var ErrChildURL = errors.New("child url is nil")
+
+// Ref represents a json reference object
+type Ref struct {
+ referenceURL *url.URL
+ referencePointer jsonpointer.Pointer
+
+ HasFullURL bool
+ HasURLPathOnly bool
+ HasFragmentOnly bool
+ HasFileScheme bool
+ HasFullFilePath bool
+}
+
+// New creates a new reference for the given string
+func New(jsonReferenceString string) (Ref, error) {
+ var r Ref
+ err := r.parse(jsonReferenceString)
+ return r, err
+}
+
+// MustCreateRef parses the ref string and panics when it's invalid.
+// Use the New method for a version that returns an error
+func MustCreateRef(ref string) Ref {
+ r, err := New(ref)
+ if err != nil {
+ panic(err)
+ }
+
+ return r
+}
+
+// GetURL gets the URL for this reference
+func (r *Ref) GetURL() *url.URL {
+ return r.referenceURL
+}
+
+// GetPointer gets the json pointer for this reference
+func (r *Ref) GetPointer() *jsonpointer.Pointer {
+ return &r.referencePointer
+}
+
+// String returns the best version of the url for this reference
+func (r *Ref) String() string {
+ if r.referenceURL != nil {
+ return r.referenceURL.String()
+ }
+
+ if r.HasFragmentOnly {
+ return fragmentRune + r.referencePointer.String()
+ }
+
+ return r.referencePointer.String()
+}
+
+// IsRoot returns true if this reference is a root document
+func (r *Ref) IsRoot() bool {
+ return r.referenceURL != nil &&
+ !r.IsCanonical() &&
+ !r.HasURLPathOnly &&
+ r.referenceURL.Fragment == ""
+}
+
+// IsCanonical returns true when this pointer starts with http(s):// or file://
+func (r *Ref) IsCanonical() bool {
+ return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullURL)
+}
+
+// Inherits creates a new reference from a parent and a child
+// If the child cannot inherit from the parent, an error is returned
+func (r *Ref) Inherits(child Ref) (*Ref, error) {
+ childURL := child.GetURL()
+ parentURL := r.GetURL()
+ if childURL == nil {
+ return nil, ErrChildURL
+ }
+ if parentURL == nil {
+ return &child, nil
+ }
+
+ ref, err := New(parentURL.ResolveReference(childURL).String())
+ if err != nil {
+ return nil, err
+ }
+ return &ref, nil
+}
+
+// "Constructor", parses the given string JSON reference
+func (r *Ref) parse(jsonReferenceString string) error {
+ parsed, err := url.Parse(jsonReferenceString)
+ if err != nil {
+ return err
+ }
+
+ internal.NormalizeURL(parsed)
+
+ r.referenceURL = parsed
+ refURL := r.referenceURL
+
+ if refURL.Scheme != "" && refURL.Host != "" {
+ r.HasFullURL = true
+ } else {
+ if refURL.Path != "" {
+ r.HasURLPathOnly = true
+ } else if refURL.RawQuery == "" && refURL.Fragment != "" {
+ r.HasFragmentOnly = true
+ }
+ }
+
+ r.HasFileScheme = refURL.Scheme == "file"
+ r.HasFullFilePath = strings.HasPrefix(refURL.Path, "/")
+
+ // invalid json-pointer error means url has no json-pointer fragment. simply ignore error
+ r.referencePointer, _ = jsonpointer.New(refURL.Fragment)
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/loads/.editorconfig b/vendor/github.com/go-openapi/loads/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/loads/.gitignore b/vendor/github.com/go-openapi/loads/.gitignore
new file mode 100644
index 000000000000..e4f15f17bfc2
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/.gitignore
@@ -0,0 +1,4 @@
+secrets.yml
+coverage.out
+profile.cov
+profile.out
diff --git a/vendor/github.com/go-openapi/loads/.golangci.yml b/vendor/github.com/go-openapi/loads/.golangci.yml
new file mode 100644
index 000000000000..1ad5adf47e69
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ - intrange
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/loads/.travis.yml b/vendor/github.com/go-openapi/loads/.travis.yml
new file mode 100644
index 000000000000..cd4a7c331bc7
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/.travis.yml
@@ -0,0 +1,25 @@
+after_success:
+- bash <(curl -s https://codecov.io/bash)
+go:
+- 1.16.x
+- 1.x
+install:
+- go get gotest.tools/gotestsum
+language: go
+arch:
+- amd64
+- ppc64le
+jobs:
+ include:
+ # include linting job, but only for latest go version and amd64 arch
+ - go: 1.x
+ arch: amd64
+ install:
+ go get github.com/golangci/golangci-lint/cmd/golangci-lint
+ script:
+ - golangci-lint run --new-from-rev master
+notifications:
+ slack:
+ secure: OxkPwVp35qBTUilgWC8xykSj+sGMcj0h8IIOKD+Rflx2schZVlFfdYdyVBM+s9OqeOfvtuvnR9v1Ye2rPKAvcjWdC4LpRGUsgmItZaI6Um8Aj6+K9udCw5qrtZVfOVmRu8LieH//XznWWKdOultUuniW0MLqw5+II87Gd00RWbCGi0hk0PykHe7uK+PDA2BEbqyZ2WKKYCvfB3j+0nrFOHScXqnh0V05l2E83J4+Sgy1fsPy+1WdX58ZlNBG333ibaC1FS79XvKSmTgKRkx3+YBo97u6ZtUmJa5WZjf2OdLG3KIckGWAv6R5xgxeU31N0Ng8L332w/Edpp2O/M2bZwdnKJ8hJQikXIAQbICbr+lTDzsoNzMdEIYcHpJ5hjPbiUl3Bmd+Jnsjf5McgAZDiWIfpCKZ29tPCEkVwRsOCqkyPRMNMzHHmoja495P5jR+ODS7+J8RFg5xgcnOgpP9D4Wlhztlf5WyZMpkLxTUD+bZq2SRf50HfHFXTkfq22zPl3d1eq0yrLwh/Z/fWKkfb6SyysROL8y6s8u3dpFX1YHSg0BR6i913h4aoZw9B2BG27cafLLTwKYsp2dFo1PWl4O6u9giFJIeqwloZHLKKrwh0cBFhB7RH0I58asxkZpCH6uWjJierahmHe7iS+E6i+9oCHkOZ59hmCYNimIs3hM=
+script:
+- gotestsum -f short-verbose -- -race -timeout=20m -coverprofile=coverage.txt -covermode=atomic ./...
diff --git a/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/loads/LICENSE b/vendor/github.com/go-openapi/loads/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/loads/README.md b/vendor/github.com/go-openapi/loads/README.md
new file mode 100644
index 000000000000..1f0174f2d918
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/README.md
@@ -0,0 +1,32 @@
+# Loads OAI specs [](https://github.com/go-openapi/loads/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/loads)
+
+[](https://raw.githubusercontent.com/go-openapi/loads/master/LICENSE) [](http://godoc.org/github.com/go-openapi/loads)
+[](https://goreportcard.com/report/github.com/go-openapi/loads)
+
+Loading of OAI v2 API specification documents from local or remote locations. Supports JSON and YAML documents.
+
+Primary usage:
+
+```go
+ import (
+ "github.com/go-openapi/loads"
+ )
+
+ ...
+
+ // loads a YAML spec from a http file
+ doc, err := loads.Spec(ts.URL)
+
+ ...
+
+ // retrieves the object model for the API specification
+ spec := doc.Spec()
+
+ ...
+```
+
+See also the provided [examples](https://pkg.go.dev/github.com/go-openapi/loads#pkg-examples).
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
diff --git a/vendor/github.com/go-openapi/loads/doc.go b/vendor/github.com/go-openapi/loads/doc.go
new file mode 100644
index 000000000000..7981e70e9f19
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/doc.go
@@ -0,0 +1,7 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package loads provides document loading methods for swagger (OAI v2) API specifications.
+//
+// It is used by other go-openapi packages to load and run analysis on local or remote spec documents.
+package loads
diff --git a/vendor/github.com/go-openapi/loads/errors.go b/vendor/github.com/go-openapi/loads/errors.go
new file mode 100644
index 000000000000..8f2d602f5ccb
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/errors.go
@@ -0,0 +1,18 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loads
+
+type loaderError string
+
+func (e loaderError) Error() string {
+ return string(e)
+}
+
+const (
+ // ErrLoads is an error returned by the loads package
+ ErrLoads loaderError = "loaderrs error"
+
+ // ErrNoLoader indicates that no configured loader matched the input
+ ErrNoLoader loaderError = "no loader matched"
+)
diff --git a/vendor/github.com/go-openapi/loads/loaders.go b/vendor/github.com/go-openapi/loads/loaders.go
new file mode 100644
index 000000000000..25b157302e4e
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/loaders.go
@@ -0,0 +1,155 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loads
+
+import (
+ "encoding/json"
+ "errors"
+ "net/url"
+ "slices"
+
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/swag/loading"
+)
+
+var (
+ // Default chain of loaders, defined at the package level.
+ //
+ // By default this matches json and yaml documents.
+ //
+ // May be altered with AddLoader().
+ loaders *loader
+)
+
+func init() {
+ jsonLoader := &loader{
+ DocLoaderWithMatch: DocLoaderWithMatch{
+ Match: func(_ string) bool {
+ return true
+ },
+ Fn: JSONDoc,
+ },
+ }
+
+ loaders = jsonLoader.WithHead(&loader{
+ DocLoaderWithMatch: DocLoaderWithMatch{
+ Match: loading.YAMLMatcher,
+ Fn: loading.YAMLDoc,
+ },
+ })
+
+ // sets the global default loader for go-openapi/spec
+ spec.PathLoader = loaders.Load
+}
+
+// DocLoader represents a doc loader type
+type DocLoader func(string, ...loading.Option) (json.RawMessage, error)
+
+// DocMatcher represents a predicate to check if a loader matches
+type DocMatcher func(string) bool
+
+// DocLoaderWithMatch describes a loading function for a given extension match.
+type DocLoaderWithMatch struct {
+ Fn DocLoader
+ Match DocMatcher
+}
+
+// NewDocLoaderWithMatch builds a DocLoaderWithMatch to be used in load options
+func NewDocLoaderWithMatch(fn DocLoader, matcher DocMatcher) DocLoaderWithMatch {
+ return DocLoaderWithMatch{
+ Fn: fn,
+ Match: matcher,
+ }
+}
+
+type loader struct {
+ DocLoaderWithMatch
+
+ loadingOptions []loading.Option
+
+ Next *loader
+}
+
+// WithHead adds a loader at the head of the current stack
+func (l *loader) WithHead(head *loader) *loader {
+ if head == nil {
+ return l
+ }
+ head.Next = l
+ return head
+}
+
+// WithNext adds a loader at the trail of the current stack
+func (l *loader) WithNext(next *loader) *loader {
+ l.Next = next
+ return next
+}
+
+// Load the raw document from path
+func (l *loader) Load(path string) (json.RawMessage, error) {
+ _, erp := url.Parse(path)
+ if erp != nil {
+ return nil, errors.Join(erp, ErrLoads)
+ }
+
+ var lastErr error = ErrNoLoader // default error if no match was found
+ for ldr := l; ldr != nil; ldr = ldr.Next {
+ if ldr.Match != nil && !ldr.Match(path) {
+ continue
+ }
+
+ // try then move to next one if there is an error
+ b, err := ldr.Fn(path, l.loadingOptions...)
+ if err == nil {
+ return b, nil
+ }
+
+ lastErr = err
+ }
+
+ return nil, errors.Join(lastErr, ErrLoads)
+}
+
+func (l *loader) clone() *loader {
+ if l == nil {
+ return nil
+ }
+
+ return &loader{
+ DocLoaderWithMatch: l.DocLoaderWithMatch,
+ loadingOptions: slices.Clone(l.loadingOptions),
+ Next: l.Next.clone(),
+ }
+}
+
+// JSONDoc loads a json document from either a file or a remote url.
+//
+// See [loading.Option] for available options (e.g. configuring authentifaction,
+// headers or using embedded file system resources).
+func JSONDoc(path string, opts ...loading.Option) (json.RawMessage, error) {
+ data, err := loading.LoadFromFileOrHTTP(path, opts...)
+ if err != nil {
+ return nil, errors.Join(err, ErrLoads)
+ }
+ return json.RawMessage(data), nil
+}
+
+// AddLoader for a document, executed before other previously set loaders.
+//
+// This sets the configuration at the package level.
+//
+// NOTE:
+// - this updates the default loader used by github.com/go-openapi/spec
+// - since this sets package level globals, you shouln't call this concurrently
+func AddLoader(predicate DocMatcher, load DocLoader) {
+ loaders = loaders.WithHead(&loader{
+ DocLoaderWithMatch: DocLoaderWithMatch{
+ Match: predicate,
+ Fn: load,
+ },
+ })
+
+ // sets the global default loader for go-openapi/spec
+ spec.PathLoader = loaders.Load
+}
diff --git a/vendor/github.com/go-openapi/loads/options.go b/vendor/github.com/go-openapi/loads/options.go
new file mode 100644
index 000000000000..adb5e6d15b02
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/options.go
@@ -0,0 +1,77 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loads
+
+import "github.com/go-openapi/swag/loading"
+
+type options struct {
+ loader *loader
+ loadingOptions []loading.Option
+}
+
+func defaultOptions() *options {
+ return &options{
+ loader: loaders,
+ }
+}
+
+func loaderFromOptions(options []LoaderOption) *loader {
+ opts := defaultOptions()
+ for _, apply := range options {
+ apply(opts)
+ }
+
+ l := opts.loader.clone()
+ l.loadingOptions = opts.loadingOptions
+
+ return l
+}
+
+// LoaderOption allows to fine-tune the spec loader behavior
+type LoaderOption func(*options)
+
+// WithDocLoader sets a custom loader for loading specs
+func WithDocLoader(l DocLoader) LoaderOption {
+ return func(opt *options) {
+ if l == nil {
+ return
+ }
+ opt.loader = &loader{
+ DocLoaderWithMatch: DocLoaderWithMatch{
+ Fn: l,
+ },
+ }
+ }
+}
+
+// WithDocLoaderMatches sets a chain of custom loaders for loading specs
+// for different extension matches.
+//
+// Loaders are executed in the order of provided DocLoaderWithMatch'es.
+func WithDocLoaderMatches(l ...DocLoaderWithMatch) LoaderOption {
+ return func(opt *options) {
+ var final, prev *loader
+ for _, ldr := range l {
+ if ldr.Fn == nil {
+ continue
+ }
+
+ if prev == nil {
+ final = &loader{DocLoaderWithMatch: ldr}
+ prev = final
+ continue
+ }
+
+ prev = prev.WithNext(&loader{DocLoaderWithMatch: ldr})
+ }
+ opt.loader = final
+ }
+}
+
+// WithLoadingOptions adds some [loading.Option] to be added when calling a registered loader.
+func WithLoadingOptions(loadingOptions ...loading.Option) LoaderOption {
+ return func(opt *options) {
+ opt.loadingOptions = loadingOptions
+ }
+}
diff --git a/vendor/github.com/go-openapi/loads/spec.go b/vendor/github.com/go-openapi/loads/spec.go
new file mode 100644
index 000000000000..213c40c657ab
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/spec.go
@@ -0,0 +1,276 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loads
+
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "maps"
+
+ "github.com/go-openapi/analysis"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/swag/yamlutils"
+)
+
+func init() {
+ gob.Register(map[string]any{})
+ gob.Register([]any{})
+}
+
+// Document represents a swagger spec document
+type Document struct {
+ // specAnalyzer
+ Analyzer *analysis.Spec
+ spec *spec.Swagger
+ specFilePath string
+ origSpec *spec.Swagger
+ schema *spec.Schema
+ pathLoader *loader
+ raw json.RawMessage
+}
+
+// JSONSpec loads a spec from a json document, using the [JSONDoc] loader.
+//
+// A set of [loading.Option] may be passed to this loader using [WithLoadingOptions].
+func JSONSpec(path string, opts ...LoaderOption) (*Document, error) {
+ var o options
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ data, err := JSONDoc(path, o.loadingOptions...)
+ if err != nil {
+ return nil, err
+ }
+ // convert to json
+ doc, err := Analyzed(data, "", opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ doc.specFilePath = path
+
+ return doc, nil
+}
+
+// Embedded returns a Document based on embedded specs (i.e. as a raw [json.RawMessage]). No analysis is required
+func Embedded(orig, flat json.RawMessage, opts ...LoaderOption) (*Document, error) {
+ var origSpec, flatSpec spec.Swagger
+ if err := json.Unmarshal(orig, &origSpec); err != nil {
+ return nil, err
+ }
+ if err := json.Unmarshal(flat, &flatSpec); err != nil {
+ return nil, err
+ }
+ return &Document{
+ raw: orig,
+ origSpec: &origSpec,
+ spec: &flatSpec,
+ pathLoader: loaderFromOptions(opts),
+ }, nil
+}
+
+// Spec loads a new spec document from a local or remote path.
+//
+// By default it uses a JSON or YAML loader, with auto-detection based on the resource extension.
+func Spec(path string, opts ...LoaderOption) (*Document, error) {
+ ldr := loaderFromOptions(opts)
+
+ b, err := ldr.Load(path)
+ if err != nil {
+ return nil, err
+ }
+
+ document, err := Analyzed(b, "", opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ document.specFilePath = path
+ document.pathLoader = ldr
+
+ return document, nil
+}
+
+// Analyzed creates a new analyzed spec document for a root json.RawMessage.
+func Analyzed(data json.RawMessage, version string, options ...LoaderOption) (*Document, error) {
+ if version == "" {
+ version = "2.0"
+ }
+ if version != "2.0" {
+ return nil, fmt.Errorf("spec version %q is not supported: %w", version, ErrLoads)
+ }
+
+ raw, err := trimData(data) // trim blanks, then convert yaml docs into json
+ if err != nil {
+ return nil, err
+ }
+
+ swspec := new(spec.Swagger)
+ if err = json.Unmarshal(raw, swspec); err != nil {
+ return nil, errors.Join(err, ErrLoads)
+ }
+
+ origsqspec, err := cloneSpec(swspec)
+ if err != nil {
+ return nil, errors.Join(err, ErrLoads)
+ }
+
+ d := &Document{
+ Analyzer: analysis.New(swspec), // NOTE: at this moment, analysis does not follow $refs to documents outside the root doc
+ schema: spec.MustLoadSwagger20Schema(),
+ spec: swspec,
+ raw: raw,
+ origSpec: origsqspec,
+ pathLoader: loaderFromOptions(options),
+ }
+
+ return d, nil
+}
+
+func trimData(in json.RawMessage) (json.RawMessage, error) {
+ trimmed := bytes.TrimSpace(in)
+ if len(trimmed) == 0 {
+ return in, nil
+ }
+
+ if trimmed[0] == '{' || trimmed[0] == '[' {
+ return trimmed, nil
+ }
+
+ // assume yaml doc: convert it to json
+ yml, err := yamlutils.BytesToYAMLDoc(trimmed)
+ if err != nil {
+ return nil, fmt.Errorf("analyzed: %v: %w", err, ErrLoads)
+ }
+
+ d, err := yamlutils.YAMLToJSON(yml)
+ if err != nil {
+ return nil, fmt.Errorf("analyzed: %v: %w", err, ErrLoads)
+ }
+
+ return d, nil
+}
+
+// Expanded expands the $ref fields in the spec [Document] and returns a new expanded [Document]
+func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
+ swspec := new(spec.Swagger)
+ if err := json.Unmarshal(d.raw, swspec); err != nil {
+ return nil, err
+ }
+
+ var expandOptions *spec.ExpandOptions
+ if len(options) > 0 {
+ expandOptions = options[0]
+ if expandOptions.RelativeBase == "" {
+ expandOptions.RelativeBase = d.specFilePath
+ }
+ } else {
+ expandOptions = &spec.ExpandOptions{
+ RelativeBase: d.specFilePath,
+ }
+ }
+
+ if expandOptions.PathLoader == nil {
+ if d.pathLoader != nil {
+ // use loader from Document options
+ expandOptions.PathLoader = d.pathLoader.Load
+ } else {
+ // use package level loader
+ expandOptions.PathLoader = loaders.Load
+ }
+ }
+
+ if err := spec.ExpandSpec(swspec, expandOptions); err != nil {
+ return nil, err
+ }
+
+ dd := &Document{
+ Analyzer: analysis.New(swspec),
+ spec: swspec,
+ specFilePath: d.specFilePath,
+ schema: spec.MustLoadSwagger20Schema(),
+ raw: d.raw,
+ origSpec: d.origSpec,
+ }
+ return dd, nil
+}
+
+// BasePath the base path for the API specified by this spec
+func (d *Document) BasePath() string {
+ if d.spec == nil {
+ return ""
+ }
+ return d.spec.BasePath
+}
+
+// Version returns the OpenAPI version of this spec (e.g. 2.0)
+func (d *Document) Version() string {
+ return d.spec.Swagger
+}
+
+// Schema returns the swagger 2.0 meta-schema
+func (d *Document) Schema() *spec.Schema {
+ return d.schema
+}
+
+// Spec returns the swagger object model for this API specification
+func (d *Document) Spec() *spec.Swagger {
+ return d.spec
+}
+
+// Host returns the host for the API
+func (d *Document) Host() string {
+ return d.spec.Host
+}
+
+// Raw returns the raw swagger spec as json bytes
+func (d *Document) Raw() json.RawMessage {
+ return d.raw
+}
+
+// OrigSpec yields the original spec
+func (d *Document) OrigSpec() *spec.Swagger {
+ return d.origSpec
+}
+
+// ResetDefinitions yields a shallow copy with the models reset to the original spec
+func (d *Document) ResetDefinitions() *Document {
+ d.spec.Definitions = make(map[string]spec.Schema, len(d.origSpec.Definitions))
+ maps.Copy(d.spec.Definitions, d.origSpec.Definitions)
+
+ return d
+}
+
+// Pristine creates a new pristine document instance based on the input data
+func (d *Document) Pristine() *Document {
+ raw, _ := json.Marshal(d.Spec())
+ dd, _ := Analyzed(raw, d.Version())
+ dd.pathLoader = d.pathLoader
+ dd.specFilePath = d.specFilePath
+
+ return dd
+}
+
+// SpecFilePath returns the file path of the spec if one is defined
+func (d *Document) SpecFilePath() string {
+ return d.specFilePath
+}
+
+func cloneSpec(src *spec.Swagger) (*spec.Swagger, error) {
+ var b bytes.Buffer
+ if err := gob.NewEncoder(&b).Encode(src); err != nil {
+ return nil, err
+ }
+
+ var dst spec.Swagger
+ if err := gob.NewDecoder(&b).Decode(&dst); err != nil {
+ return nil, err
+ }
+
+ return &dst, nil
+}
diff --git a/vendor/github.com/go-openapi/runtime/.editorconfig b/vendor/github.com/go-openapi/runtime/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/runtime/.gitattributes b/vendor/github.com/go-openapi/runtime/.gitattributes
new file mode 100644
index 000000000000..d207b1802b20
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/.gitattributes
@@ -0,0 +1 @@
+*.go text eol=lf
diff --git a/vendor/github.com/go-openapi/runtime/.gitignore b/vendor/github.com/go-openapi/runtime/.gitignore
new file mode 100644
index 000000000000..fea8b84eca99
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/.gitignore
@@ -0,0 +1,5 @@
+secrets.yml
+coverage.out
+*.cov
+*.out
+playground
diff --git a/vendor/github.com/go-openapi/runtime/.golangci.yml b/vendor/github.com/go-openapi/runtime/.golangci.yml
new file mode 100644
index 000000000000..0087ed311303
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/.golangci.yml
@@ -0,0 +1,77 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - err113 # disabled temporarily: there are just too many issues to address
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gomoddirectives # moved to mono-repo, multi-modules, so replace directives are needed
+ - gosmopolitan
+ - inamedparam
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nilerr # nilerr crashes on this repo
+ - nlreturn
+ - noinlineerr
+ - nonamedreturns
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/runtime/LICENSE b/vendor/github.com/go-openapi/runtime/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/runtime/README.md b/vendor/github.com/go-openapi/runtime/README.md
new file mode 100644
index 000000000000..9e15b1adb5be
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/README.md
@@ -0,0 +1,43 @@
+# runtime [](https://github.com/go-openapi/runtime/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/runtime)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/runtime/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/runtime)
+[](https://goreportcard.com/report/github.com/go-openapi/runtime)
+
+# go OpenAPI toolkit runtime
+
+The runtime component for use in code generation or as untyped usage.
+
+## Release notes
+
+### v0.29.0
+
+**New with this release**:
+
+* upgraded to `go1.24` and modernized the code base accordingly
+* updated all dependencies, and removed an noticable indirect dependency (e.g. `mailru/easyjson`)
+* **breaking change** no longer imports `opentracing-go` (#365).
+ * the `WithOpentracing()` method now returns an opentelemetry transport
+ * for users who can't transition to opentelemetry, the previous behavior
+ of `WithOpentracing` delivering an opentracing transport is provided by a separate
+ module `github.com/go-openapi/runtime/client-middleware/opentracing`.
+* removed direct dependency to `gopkg.in/yaml.v3`, in favor of `go.yaml.in/yaml/v3` (an indirect
+ test dependency to the older package is still around)
+* technically, the repo has evolved to a mono-repo, multiple modules structures (2 go modules
+ published), with CI adapted accordingly
+
+**What coming next?**
+
+Moving forward, we want to :
+
+* [ ] continue narrowing down the scope of dependencies:
+ * yaml support in an independent module
+ * introduce more up-to-date support for opentelemetry as a separate module that evolves
+ independently from the main package (to avoid breaking changes, the existing API
+ will remain maintained, but evolve at a slower pace than opentelemetry).
+* [ ] fix a few known issues with some file upload requests (e.g. #286)
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
diff --git a/vendor/github.com/go-openapi/runtime/bytestream.go b/vendor/github.com/go-openapi/runtime/bytestream.go
new file mode 100644
index 000000000000..eb649742e8e1
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/bytestream.go
@@ -0,0 +1,211 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+func defaultCloser() error { return nil }
+
+type byteStreamOpt func(opts *byteStreamOpts)
+
+// ClosesStream when the bytestream consumer or producer is finished
+func ClosesStream(opts *byteStreamOpts) {
+ opts.Close = true
+}
+
+type byteStreamOpts struct {
+ Close bool
+}
+
+// ByteStreamConsumer creates a consumer for byte streams.
+//
+// The consumer consumes from a provided reader into the data passed by reference.
+//
+// Supported output underlying types and interfaces, prioritized in this order:
+// - io.ReaderFrom (for maximum control)
+// - io.Writer (performs io.Copy)
+// - encoding.BinaryUnmarshaler
+// - *string
+// - *[]byte
+func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
+ var vals byteStreamOpts
+ for _, opt := range opts {
+ opt(&vals)
+ }
+
+ return ConsumerFunc(func(reader io.Reader, data any) error {
+ if reader == nil {
+ return errors.New("ByteStreamConsumer requires a reader") // early exit
+ }
+ if data == nil {
+ return errors.New("nil destination for ByteStreamConsumer")
+ }
+
+ closer := defaultCloser
+ if vals.Close {
+ if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
+ closer = cl.Close
+ }
+ }
+ defer func() {
+ _ = closer()
+ }()
+
+ if readerFrom, isReaderFrom := data.(io.ReaderFrom); isReaderFrom {
+ _, err := readerFrom.ReadFrom(reader)
+ return err
+ }
+
+ if writer, isDataWriter := data.(io.Writer); isDataWriter {
+ _, err := io.Copy(writer, reader)
+ return err
+ }
+
+ // buffers input before writing to data
+ var buf bytes.Buffer
+ _, err := buf.ReadFrom(reader)
+ if err != nil {
+ return err
+ }
+ b := buf.Bytes()
+
+ switch destinationPointer := data.(type) {
+ case encoding.BinaryUnmarshaler:
+ return destinationPointer.UnmarshalBinary(b)
+ case *any:
+ switch (*destinationPointer).(type) {
+ case string:
+ *destinationPointer = string(b)
+
+ return nil
+
+ case []byte:
+ *destinationPointer = b
+
+ return nil
+ }
+ default:
+ // check for the underlying type to be pointer to []byte or string,
+ if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
+ return errors.New("destination must be a pointer")
+ }
+
+ v := reflect.Indirect(reflect.ValueOf(data))
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
+ v.SetBytes(b)
+ return nil
+
+ case t.Kind() == reflect.String:
+ v.SetString(string(b))
+ return nil
+ }
+ }
+
+ return fmt.Errorf("%v (%T) is not supported by the ByteStreamConsumer, %s",
+ data, data, "can be resolved by supporting Writer/BinaryUnmarshaler interface")
+ })
+}
+
+// ByteStreamProducer creates a producer for byte streams.
+//
+// The producer takes input data then writes to an output writer (essentially as a pipe).
+//
+// Supported input underlying types and interfaces, prioritized in this order:
+// - io.WriterTo (for maximum control)
+// - io.Reader (performs io.Copy). A ReadCloser is closed before exiting.
+// - encoding.BinaryMarshaler
+// - error (writes as a string)
+// - []byte
+// - string
+// - struct, other slices: writes as JSON
+func ByteStreamProducer(opts ...byteStreamOpt) Producer {
+ var vals byteStreamOpts
+ for _, opt := range opts {
+ opt(&vals)
+ }
+
+ return ProducerFunc(func(writer io.Writer, data any) error {
+ if writer == nil {
+ return errors.New("ByteStreamProducer requires a writer") // early exit
+ }
+ if data == nil {
+ return errors.New("nil data for ByteStreamProducer")
+ }
+
+ closer := defaultCloser
+ if vals.Close {
+ if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
+ closer = cl.Close
+ }
+ }
+ defer func() {
+ _ = closer()
+ }()
+
+ if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
+ defer rc.Close()
+ }
+
+ switch origin := data.(type) {
+ case io.WriterTo:
+ _, err := origin.WriteTo(writer)
+ return err
+
+ case io.Reader:
+ _, err := io.Copy(writer, origin)
+ return err
+
+ case encoding.BinaryMarshaler:
+ bytes, err := origin.MarshalBinary()
+ if err != nil {
+ return err
+ }
+
+ _, err = writer.Write(bytes)
+ return err
+
+ case error:
+ _, err := writer.Write([]byte(origin.Error()))
+ return err
+
+ default:
+ v := reflect.Indirect(reflect.ValueOf(data))
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
+ _, err := writer.Write(v.Bytes())
+ return err
+
+ case t.Kind() == reflect.String:
+ _, err := writer.Write([]byte(v.String()))
+ return err
+
+ case t.Kind() == reflect.Struct || t.Kind() == reflect.Slice:
+ b, err := jsonutils.WriteJSON(data)
+ if err != nil {
+ return err
+ }
+
+ _, err = writer.Write(b)
+ return err
+ }
+ }
+
+ return fmt.Errorf("%v (%T) is not supported by the ByteStreamProducer, %s",
+ data, data, "can be resolved by supporting Reader/BinaryMarshaler interface")
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/auth_info.go b/vendor/github.com/go-openapi/runtime/client/auth_info.go
new file mode 100644
index 000000000000..a98690c4d602
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/auth_info.go
@@ -0,0 +1,66 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "encoding/base64"
+
+ "github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/runtime"
+)
+
+// PassThroughAuth never manipulates the request
+var PassThroughAuth runtime.ClientAuthInfoWriter
+
+func init() {
+ PassThroughAuth = runtime.ClientAuthInfoWriterFunc(func(_ runtime.ClientRequest, _ strfmt.Registry) error { return nil })
+}
+
+// BasicAuth provides a basic auth info writer
+func BasicAuth(username, password string) runtime.ClientAuthInfoWriter {
+ return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
+ encoded := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
+ return r.SetHeaderParam(runtime.HeaderAuthorization, "Basic "+encoded)
+ })
+}
+
+// APIKeyAuth provides an API key auth info writer
+func APIKeyAuth(name, in, value string) runtime.ClientAuthInfoWriter {
+ if in == "query" {
+ return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
+ return r.SetQueryParam(name, value)
+ })
+ }
+
+ if in == "header" {
+ return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
+ return r.SetHeaderParam(name, value)
+ })
+ }
+ return nil
+}
+
+// BearerToken provides a header based oauth2 bearer access token auth info writer
+func BearerToken(token string) runtime.ClientAuthInfoWriter {
+ return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
+ return r.SetHeaderParam(runtime.HeaderAuthorization, "Bearer "+token)
+ })
+}
+
+// Compose combines multiple ClientAuthInfoWriters into a single one.
+// Useful when multiple auth headers are needed.
+func Compose(auths ...runtime.ClientAuthInfoWriter) runtime.ClientAuthInfoWriter {
+ return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
+ for _, auth := range auths {
+ if auth == nil {
+ continue
+ }
+ if err := auth.AuthenticateRequest(r, nil); err != nil {
+ return err
+ }
+ }
+ return nil
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/keepalive.go b/vendor/github.com/go-openapi/runtime/client/keepalive.go
new file mode 100644
index 000000000000..831d23b511d5
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/keepalive.go
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "io"
+ "net/http"
+ "sync/atomic"
+)
+
+// KeepAliveTransport drains the remaining body from a response
+// so that go will reuse the TCP connections.
+// This is not enabled by default because there are servers where
+// the response never gets closed and that would make the code hang forever.
+// So instead it's provided as a http client middleware that can be used to override
+// any request.
+func KeepAliveTransport(rt http.RoundTripper) http.RoundTripper {
+ return &keepAliveTransport{wrapped: rt}
+}
+
+type keepAliveTransport struct {
+ wrapped http.RoundTripper
+}
+
+func (k *keepAliveTransport) RoundTrip(r *http.Request) (*http.Response, error) {
+ resp, err := k.wrapped.RoundTrip(r)
+ if err != nil {
+ return resp, err
+ }
+ resp.Body = &drainingReadCloser{rdr: resp.Body}
+ return resp, nil
+}
+
+type drainingReadCloser struct {
+ rdr io.ReadCloser
+ seenEOF uint32
+}
+
+func (d *drainingReadCloser) Read(p []byte) (n int, err error) {
+ n, err = d.rdr.Read(p)
+ if err == io.EOF || n == 0 {
+ atomic.StoreUint32(&d.seenEOF, 1)
+ }
+ return
+}
+
+func (d *drainingReadCloser) Close() error {
+ // drain buffer
+ if atomic.LoadUint32(&d.seenEOF) != 1 {
+ // If the reader side (a HTTP server) is misbehaving, it still may send
+ // some bytes, but the closer ignores them to keep the underling
+ // connection open.
+ _, _ = io.Copy(io.Discard, d.rdr)
+ }
+ return d.rdr.Close()
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/opentelemetry.go b/vendor/github.com/go-openapi/runtime/client/opentelemetry.go
new file mode 100644
index 000000000000..e77941293f9c
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/opentelemetry.go
@@ -0,0 +1,216 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/strfmt"
+ "go.opentelemetry.io/otel"
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/codes"
+ "go.opentelemetry.io/otel/propagation"
+ semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
+ "go.opentelemetry.io/otel/trace"
+)
+
+const (
+ instrumentationVersion = "1.0.0"
+ tracerName = "go-openapi"
+)
+
+type config struct {
+ Tracer trace.Tracer
+ Propagator propagation.TextMapPropagator
+ SpanStartOptions []trace.SpanStartOption
+ SpanNameFormatter func(*runtime.ClientOperation) string
+ TracerProvider trace.TracerProvider
+}
+
+type OpenTelemetryOpt interface {
+ apply(*config)
+}
+
+type optionFunc func(*config)
+
+func (o optionFunc) apply(c *config) {
+ o(c)
+}
+
+// WithTracerProvider specifies a tracer provider to use for creating a tracer.
+// If none is specified, the global provider is used.
+func WithTracerProvider(provider trace.TracerProvider) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ if provider != nil {
+ c.TracerProvider = provider
+ }
+ })
+}
+
+// WithPropagators configures specific propagators. If this
+// option isn't specified, then the global TextMapPropagator is used.
+func WithPropagators(ps propagation.TextMapPropagator) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ if ps != nil {
+ c.Propagator = ps
+ }
+ })
+}
+
+// WithSpanOptions configures an additional set of
+// trace.SpanOptions, which are applied to each new span.
+func WithSpanOptions(opts ...trace.SpanStartOption) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ c.SpanStartOptions = append(c.SpanStartOptions, opts...)
+ })
+}
+
+// WithSpanNameFormatter takes a function that will be called on every
+// request and the returned string will become the Span Name.
+func WithSpanNameFormatter(f func(op *runtime.ClientOperation) string) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ c.SpanNameFormatter = f
+ })
+}
+
+func defaultTransportFormatter(op *runtime.ClientOperation) string {
+ if op.ID != "" {
+ return op.ID
+ }
+
+ return fmt.Sprintf("%s_%s", strings.ToLower(op.Method), op.PathPattern)
+}
+
+type openTelemetryTransport struct {
+ transport runtime.ClientTransport
+ host string
+ tracer trace.Tracer
+ config *config
+}
+
+func newOpenTelemetryTransport(transport runtime.ClientTransport, host string, opts []OpenTelemetryOpt) *openTelemetryTransport {
+ tr := &openTelemetryTransport{
+ transport: transport,
+ host: host,
+ }
+
+ defaultOpts := []OpenTelemetryOpt{
+ WithSpanOptions(trace.WithSpanKind(trace.SpanKindClient)),
+ WithSpanNameFormatter(defaultTransportFormatter),
+ WithPropagators(otel.GetTextMapPropagator()),
+ WithTracerProvider(otel.GetTracerProvider()),
+ }
+
+ c := newConfig(append(defaultOpts, opts...)...)
+ tr.config = c
+
+ return tr
+}
+
+func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (any, error) {
+ if op.Context == nil {
+ return t.transport.Submit(op)
+ }
+
+ params := op.Params
+ reader := op.Reader
+
+ var span trace.Span
+ defer func() {
+ if span != nil {
+ span.End()
+ }
+ }()
+
+ op.Params = runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
+ span = t.newOpenTelemetrySpan(op, req.GetHeaderParams())
+ return params.WriteToRequest(req, reg)
+ })
+
+ op.Reader = runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (any, error) {
+ if span != nil {
+ statusCode := response.Code()
+ // NOTE: this is replaced by semconv.HTTPResponseStatusCode in semconv v1.21
+ span.SetAttributes(semconv.HTTPResponseStatusCode(statusCode))
+ // NOTE: the conversion from HTTP status code to trace code is no longer available with
+ // semconv v1.21
+ const minHTTPStatusIsError = 400
+ if statusCode >= minHTTPStatusIsError {
+ span.SetStatus(codes.Error, http.StatusText(statusCode))
+ }
+ }
+
+ return reader.ReadResponse(response, consumer)
+ })
+
+ submit, err := t.transport.Submit(op)
+ if err != nil && span != nil {
+ span.RecordError(err)
+ span.SetStatus(codes.Error, err.Error())
+ }
+
+ return submit, err
+}
+
+func (t *openTelemetryTransport) newOpenTelemetrySpan(op *runtime.ClientOperation, header http.Header) trace.Span {
+ ctx := op.Context
+
+ tracer := t.tracer
+ if tracer == nil {
+ if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() {
+ tracer = newTracer(span.TracerProvider())
+ } else {
+ tracer = newTracer(otel.GetTracerProvider())
+ }
+ }
+
+ ctx, span := tracer.Start(ctx, t.config.SpanNameFormatter(op), t.config.SpanStartOptions...)
+
+ var scheme string
+ if len(op.Schemes) > 0 {
+ scheme = op.Schemes[0]
+ }
+
+ span.SetAttributes(
+ attribute.String("net.peer.name", t.host),
+ attribute.String(string(semconv.HTTPRouteKey), op.PathPattern),
+ attribute.String(string(semconv.HTTPRequestMethodKey), op.Method),
+ attribute.String("span.kind", trace.SpanKindClient.String()),
+ attribute.String("http.scheme", scheme),
+ )
+
+ carrier := propagation.HeaderCarrier(header)
+ t.config.Propagator.Inject(ctx, carrier)
+
+ return span
+}
+
+func newTracer(tp trace.TracerProvider) trace.Tracer {
+ return tp.Tracer(tracerName, trace.WithInstrumentationVersion(version()))
+}
+
+func newConfig(opts ...OpenTelemetryOpt) *config {
+ c := &config{
+ Propagator: otel.GetTextMapPropagator(),
+ }
+
+ for _, opt := range opts {
+ opt.apply(c)
+ }
+
+ // Tracer is only initialized if manually specified. Otherwise, can be passed with the tracing context.
+ if c.TracerProvider != nil {
+ c.Tracer = newTracer(c.TracerProvider)
+ }
+
+ return c
+}
+
+// Version is the current release version of the go-runtime instrumentation.
+func version() string {
+ return instrumentationVersion
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/request.go b/vendor/github.com/go-openapi/runtime/client/request.go
new file mode 100644
index 000000000000..6d9b25912ec2
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/request.go
@@ -0,0 +1,469 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "log"
+ "mime/multipart"
+ "net/http"
+ "net/textproto"
+ "net/url"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/strfmt"
+)
+
+var _ runtime.ClientRequest = new(request) // ensure compliance to the interface
+
+// Request represents a swagger client request.
+//
+// This Request struct converts to a HTTP request.
+// There might be others that convert to other transports.
+// There is no error checking here, it is assumed to be used after a spec has been validated.
+// so impossible combinations should not arise (hopefully).
+//
+// The main purpose of this struct is to hide the machinery of adding params to a transport request.
+// The generated code only implements what is necessary to turn a param into a valid value for these methods.
+type request struct {
+ pathPattern string
+ method string
+ writer runtime.ClientRequestWriter
+
+ pathParams map[string]string
+ header http.Header
+ query url.Values
+ formFields url.Values
+ fileFields map[string][]runtime.NamedReadCloser
+ payload any
+ timeout time.Duration
+ buf *bytes.Buffer
+
+ getBody func(r *request) []byte
+}
+
+// NewRequest creates a new swagger http client request
+func newRequest(method, pathPattern string, writer runtime.ClientRequestWriter) *request {
+ return &request{
+ pathPattern: pathPattern,
+ method: method,
+ writer: writer,
+ header: make(http.Header),
+ query: make(url.Values),
+ timeout: DefaultTimeout,
+ getBody: getRequestBuffer,
+ }
+}
+
+// BuildHTTP creates a new http request based on the data from the params
+func (r *request) BuildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry) (*http.Request, error) {
+ return r.buildHTTP(mediaType, basePath, producers, registry, nil)
+}
+
+func (r *request) GetMethod() string {
+ return r.method
+}
+
+func (r *request) GetPath() string {
+ path := r.pathPattern
+ for k, v := range r.pathParams {
+ path = strings.ReplaceAll(path, "{"+k+"}", v)
+ }
+ return path
+}
+
+func (r *request) GetBody() []byte {
+ return r.getBody(r)
+}
+
+// SetHeaderParam adds a header param to the request
+// when there is only 1 value provided for the varargs, it will set it.
+// when there are several values provided for the varargs it will add it (no overriding)
+func (r *request) SetHeaderParam(name string, values ...string) error {
+ if r.header == nil {
+ r.header = make(http.Header)
+ }
+ r.header[http.CanonicalHeaderKey(name)] = values
+ return nil
+}
+
+// GetHeaderParams returns the all headers currently set for the request
+func (r *request) GetHeaderParams() http.Header {
+ return r.header
+}
+
+// SetQueryParam adds a query param to the request
+// when there is only 1 value provided for the varargs, it will set it.
+// when there are several values provided for the varargs it will add it (no overriding)
+func (r *request) SetQueryParam(name string, values ...string) error {
+ if r.query == nil {
+ r.query = make(url.Values)
+ }
+ r.query[name] = values
+ return nil
+}
+
+// GetQueryParams returns a copy of all query params currently set for the request
+func (r *request) GetQueryParams() url.Values {
+ var result = make(url.Values)
+ for key, value := range r.query {
+ result[key] = append([]string{}, value...)
+ }
+ return result
+}
+
+// SetFormParam adds a forn param to the request
+// when there is only 1 value provided for the varargs, it will set it.
+// when there are several values provided for the varargs it will add it (no overriding)
+func (r *request) SetFormParam(name string, values ...string) error {
+ if r.formFields == nil {
+ r.formFields = make(url.Values)
+ }
+ r.formFields[name] = values
+ return nil
+}
+
+// SetPathParam adds a path param to the request
+func (r *request) SetPathParam(name string, value string) error {
+ if r.pathParams == nil {
+ r.pathParams = make(map[string]string)
+ }
+
+ r.pathParams[name] = value
+ return nil
+}
+
+// SetFileParam adds a file param to the request
+func (r *request) SetFileParam(name string, files ...runtime.NamedReadCloser) error {
+ for _, file := range files {
+ if actualFile, ok := file.(*os.File); ok {
+ fi, err := os.Stat(actualFile.Name())
+ if err != nil {
+ return err
+ }
+ if fi.IsDir() {
+ return fmt.Errorf("%q is a directory, only files are supported", file.Name())
+ }
+ }
+ }
+
+ if r.fileFields == nil {
+ r.fileFields = make(map[string][]runtime.NamedReadCloser)
+ }
+ if r.formFields == nil {
+ r.formFields = make(url.Values)
+ }
+
+ r.fileFields[name] = files
+ return nil
+}
+
+func (r *request) GetFileParam() map[string][]runtime.NamedReadCloser {
+ return r.fileFields
+}
+
+// SetBodyParam sets a body parameter on the request.
+// This does not yet serialze the object, this happens as late as possible.
+func (r *request) SetBodyParam(payload any) error {
+ r.payload = payload
+ return nil
+}
+
+func (r *request) GetBodyParam() any {
+ return r.payload
+}
+
+// SetTimeout sets the timeout for a request
+func (r *request) SetTimeout(timeout time.Duration) error {
+ r.timeout = timeout
+ return nil
+}
+
+func (r *request) isMultipart(mediaType string) bool {
+ if len(r.fileFields) > 0 {
+ return true
+ }
+
+ return runtime.MultipartFormMime == mediaType
+}
+
+func (r *request) buildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter) (*http.Request, error) { //nolint:gocyclo,maintidx
+ // build the data
+ if err := r.writer.WriteToRequest(r, registry); err != nil {
+ return nil, err
+ }
+
+ // Our body must be an io.Reader.
+ // When we create the http.Request, if we pass it a
+ // bytes.Buffer then it will wrap it in an io.ReadCloser
+ // and set the content length automatically.
+ var body io.Reader
+ var pr *io.PipeReader
+ var pw *io.PipeWriter
+
+ r.buf = bytes.NewBuffer(nil)
+ if r.payload != nil || len(r.formFields) > 0 || len(r.fileFields) > 0 {
+ body = r.buf
+ if r.isMultipart(mediaType) {
+ pr, pw = io.Pipe()
+ body = pr
+ }
+ }
+
+ // check if this is a form type request
+ if len(r.formFields) > 0 || len(r.fileFields) > 0 {
+ if !r.isMultipart(mediaType) {
+ r.header.Set(runtime.HeaderContentType, mediaType)
+ formString := r.formFields.Encode()
+ r.buf.WriteString(formString)
+ goto DoneChoosingBodySource
+ }
+
+ mp := multipart.NewWriter(pw)
+ r.header.Set(runtime.HeaderContentType, mangleContentType(mediaType, mp.Boundary()))
+
+ go func() {
+ defer func() {
+ mp.Close()
+ pw.Close()
+ }()
+
+ for fn, v := range r.formFields {
+ for _, vi := range v {
+ if err := mp.WriteField(fn, vi); err != nil {
+ logClose(err, pw)
+ return
+ }
+ }
+ }
+
+ defer func() {
+ for _, ff := range r.fileFields {
+ for _, ffi := range ff {
+ ffi.Close()
+ }
+ }
+ }()
+ for fn, f := range r.fileFields {
+ for _, fi := range f {
+ var fileContentType string
+ if p, ok := fi.(interface {
+ ContentType() string
+ }); ok {
+ fileContentType = p.ContentType()
+ } else {
+ // Need to read the data so that we can detect the content type
+ const contentTypeBufferSize = 512
+ buf := make([]byte, contentTypeBufferSize)
+ size, err := fi.Read(buf)
+ if err != nil && err != io.EOF {
+ logClose(err, pw)
+ return
+ }
+ fileContentType = http.DetectContentType(buf)
+ fi = runtime.NamedReader(fi.Name(), io.MultiReader(bytes.NewReader(buf[:size]), fi))
+ }
+
+ // Create the MIME headers for the new part
+ h := make(textproto.MIMEHeader)
+ h.Set("Content-Disposition",
+ fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
+ escapeQuotes(fn), escapeQuotes(filepath.Base(fi.Name()))))
+ h.Set("Content-Type", fileContentType)
+
+ wrtr, err := mp.CreatePart(h)
+ if err != nil {
+ logClose(err, pw)
+ return
+ }
+ if _, err := io.Copy(wrtr, fi); err != nil {
+ logClose(err, pw)
+ }
+ }
+ }
+ }()
+
+ goto DoneChoosingBodySource
+ }
+
+ // if there is payload, use the producer to write the payload, and then
+ // set the header to the content-type appropriate for the payload produced
+ if r.payload != nil {
+ // TODO: infer most appropriate content type based on the producer used,
+ // and the `consumers` section of the spec/operation
+ r.header.Set(runtime.HeaderContentType, mediaType)
+ if rdr, ok := r.payload.(io.ReadCloser); ok {
+ body = rdr
+ goto DoneChoosingBodySource
+ }
+
+ if rdr, ok := r.payload.(io.Reader); ok {
+ body = rdr
+ goto DoneChoosingBodySource
+ }
+
+ producer := producers[mediaType]
+ if err := producer.Produce(r.buf, r.payload); err != nil {
+ return nil, err
+ }
+ }
+
+DoneChoosingBodySource:
+
+ if runtime.CanHaveBody(r.method) && body != nil && r.header.Get(runtime.HeaderContentType) == "" {
+ r.header.Set(runtime.HeaderContentType, mediaType)
+ }
+
+ if auth != nil {
+ // If we're not using r.buf as our http.Request's body,
+ // either the payload is an io.Reader or io.ReadCloser,
+ // or we're doing a multipart form/file.
+ //
+ // In those cases, if the AuthenticateRequest call asks for the body,
+ // we must read it into a buffer and provide that, then use that buffer
+ // as the body of our http.Request.
+ //
+ // This is done in-line with the GetBody() request rather than ahead
+ // of time, because there's no way to know if the AuthenticateRequest
+ // will even ask for the body of the request.
+ //
+ // If for some reason the copy fails, there's no way to return that
+ // error to the GetBody() call, so return it afterwards.
+ //
+ // An error from the copy action is prioritized over any error
+ // from the AuthenticateRequest call, because the mis-read
+ // body may have interfered with the auth.
+ //
+ var copyErr error
+ if buf, ok := body.(*bytes.Buffer); body != nil && (!ok || buf != r.buf) {
+ var copied bool
+ r.getBody = func(r *request) []byte {
+ if copied {
+ return getRequestBuffer(r)
+ }
+
+ defer func() {
+ copied = true
+ }()
+
+ if _, copyErr = io.Copy(r.buf, body); copyErr != nil {
+ return nil
+ }
+
+ if closer, ok := body.(io.ReadCloser); ok {
+ if copyErr = closer.Close(); copyErr != nil {
+ return nil
+ }
+ }
+
+ body = r.buf
+ return getRequestBuffer(r)
+ }
+ }
+
+ authErr := auth.AuthenticateRequest(r, registry)
+
+ if copyErr != nil {
+ return nil, fmt.Errorf("error retrieving the response body: %v", copyErr)
+ }
+
+ if authErr != nil {
+ return nil, authErr
+ }
+ }
+
+ // In case the basePath or the request pathPattern include static query parameters,
+ // parse those out before constructing the final path. The parameters themselves
+ // will be merged with the ones set by the client, with the priority given first to
+ // the ones set by the client, then the path pattern, and lastly the base path.
+ basePathURL, err := url.Parse(basePath)
+ if err != nil {
+ return nil, err
+ }
+ staticQueryParams := basePathURL.Query()
+
+ pathPatternURL, err := url.Parse(r.pathPattern)
+ if err != nil {
+ return nil, err
+ }
+ for name, values := range pathPatternURL.Query() {
+ if _, present := staticQueryParams[name]; present {
+ staticQueryParams.Del(name)
+ }
+ for _, value := range values {
+ staticQueryParams.Add(name, value)
+ }
+ }
+
+ // create http request
+ var reinstateSlash bool
+ if pathPatternURL.Path != "" && pathPatternURL.Path != "/" && pathPatternURL.Path[len(pathPatternURL.Path)-1] == '/' {
+ reinstateSlash = true
+ }
+
+ urlPath := path.Join(basePathURL.Path, pathPatternURL.Path)
+ for k, v := range r.pathParams {
+ urlPath = strings.ReplaceAll(urlPath, "{"+k+"}", url.PathEscape(v))
+ }
+ if reinstateSlash {
+ urlPath += "/"
+ }
+
+ req, err := http.NewRequestWithContext(context.Background(), r.method, urlPath, body)
+ if err != nil {
+ return nil, err
+ }
+
+ originalParams := r.GetQueryParams()
+
+ // Merge the query parameters extracted from the basePath with the ones set by
+ // the client in this struct. In case of conflict, the client wins.
+ for k, v := range staticQueryParams {
+ _, present := originalParams[k]
+ if !present {
+ if err = r.SetQueryParam(k, v...); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ req.URL.RawQuery = r.query.Encode()
+ req.Header = r.header
+
+ return req, nil
+}
+
+func escapeQuotes(s string) string {
+ return strings.NewReplacer("\\", "\\\\", `"`, "\\\"").Replace(s)
+}
+
+func getRequestBuffer(r *request) []byte {
+ if r.buf == nil {
+ return nil
+ }
+ return r.buf.Bytes()
+}
+
+func logClose(err error, pw *io.PipeWriter) {
+ log.Println(err)
+ closeErr := pw.CloseWithError(err)
+ if closeErr != nil {
+ log.Println(closeErr)
+ }
+}
+
+func mangleContentType(mediaType, boundary string) string {
+ if strings.ToLower(mediaType) == runtime.URLencodedFormMime {
+ return fmt.Sprintf("%s; boundary=%s", mediaType, boundary)
+ }
+ return "multipart/form-data; boundary=" + boundary
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/response.go b/vendor/github.com/go-openapi/runtime/client/response.go
new file mode 100644
index 000000000000..59abc3b549a3
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/response.go
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "io"
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+)
+
+var _ runtime.ClientResponse = response{}
+
+func newResponse(resp *http.Response) runtime.ClientResponse { return response{resp: resp} }
+
+type response struct {
+ resp *http.Response
+}
+
+func (r response) Code() int {
+ return r.resp.StatusCode
+}
+
+func (r response) Message() string {
+ return r.resp.Status
+}
+
+func (r response) GetHeader(name string) string {
+ return r.resp.Header.Get(name)
+}
+
+func (r response) GetHeaders(name string) []string {
+ return r.resp.Header.Values(name)
+}
+
+func (r response) Body() io.ReadCloser {
+ return r.resp.Body
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/runtime.go b/vendor/github.com/go-openapi/runtime/client/runtime.go
new file mode 100644
index 000000000000..203c74e49db9
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/runtime.go
@@ -0,0 +1,564 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "mime"
+ "net/http"
+ "net/http/httputil"
+ "os"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/logger"
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/runtime/yamlpc"
+ "github.com/go-openapi/strfmt"
+)
+
+const (
+ schemeHTTP = "http"
+ schemeHTTPS = "https"
+)
+
+// DefaultTimeout the default request timeout
+var DefaultTimeout = 30 * time.Second
+
+// TLSClientOptions to configure client authentication with mutual TLS
+type TLSClientOptions struct {
+ // Certificate is the path to a PEM-encoded certificate to be used for
+ // client authentication. If set then Key must also be set.
+ Certificate string
+
+ // LoadedCertificate is the certificate to be used for client authentication.
+ // This field is ignored if Certificate is set. If this field is set, LoadedKey
+ // is also required.
+ LoadedCertificate *x509.Certificate
+
+ // Key is the path to an unencrypted PEM-encoded private key for client
+ // authentication. This field is required if Certificate is set.
+ Key string
+
+ // LoadedKey is the key for client authentication. This field is required if
+ // LoadedCertificate is set.
+ LoadedKey crypto.PrivateKey
+
+ // CA is a path to a PEM-encoded certificate that specifies the root certificate
+ // to use when validating the TLS certificate presented by the server. If this field
+ // (and LoadedCA) is not set, the system certificate pool is used. This field is ignored if LoadedCA
+ // is set.
+ CA string
+
+ // LoadedCA specifies the root certificate to use when validating the server's TLS certificate.
+ // If this field (and CA) is not set, the system certificate pool is used.
+ LoadedCA *x509.Certificate
+
+ // LoadedCAPool specifies a pool of RootCAs to use when validating the server's TLS certificate.
+ // If set, it will be combined with the other loaded certificates (see LoadedCA and CA).
+ // If neither LoadedCA or CA is set, the provided pool with override the system
+ // certificate pool.
+ // The caller must not use the supplied pool after calling TLSClientAuth.
+ LoadedCAPool *x509.CertPool
+
+ // ServerName specifies the hostname to use when verifying the server certificate.
+ // If this field is set then InsecureSkipVerify will be ignored and treated as
+ // false.
+ ServerName string
+
+ // InsecureSkipVerify controls whether the certificate chain and hostname presented
+ // by the server are validated. If true, any certificate is accepted.
+ InsecureSkipVerify bool
+
+ // VerifyPeerCertificate, if not nil, is called after normal
+ // certificate verification. It receives the raw ASN.1 certificates
+ // provided by the peer and also any verified chains that normal processing found.
+ // If it returns a non-nil error, the handshake is aborted and that error results.
+ //
+ // If normal verification fails then the handshake will abort before
+ // considering this callback. If normal verification is disabled by
+ // setting InsecureSkipVerify then this callback will be considered but
+ // the verifiedChains argument will always be nil.
+ VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
+
+ // SessionTicketsDisabled may be set to true to disable session ticket and
+ // PSK (resumption) support. Note that on clients, session ticket support is
+ // also disabled if ClientSessionCache is nil.
+ SessionTicketsDisabled bool
+
+ // ClientSessionCache is a cache of ClientSessionState entries for TLS
+ // session resumption. It is only used by clients.
+ ClientSessionCache tls.ClientSessionCache
+
+ // Prevents callers using unkeyed fields.
+ _ struct{}
+}
+
+// TLSClientAuth creates a tls.Config for mutual auth
+func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
+ // create client tls config
+ cfg := &tls.Config{
+ MinVersion: tls.VersionTLS12,
+ }
+
+ // load client cert if specified
+ if opts.Certificate != "" {
+ cert, err := tls.LoadX509KeyPair(opts.Certificate, opts.Key)
+ if err != nil {
+ return nil, fmt.Errorf("tls client cert: %v", err)
+ }
+ cfg.Certificates = []tls.Certificate{cert}
+ } else if opts.LoadedCertificate != nil {
+ block := pem.Block{Type: "CERTIFICATE", Bytes: opts.LoadedCertificate.Raw}
+ certPem := pem.EncodeToMemory(&block)
+
+ var keyBytes []byte
+ switch k := opts.LoadedKey.(type) {
+ case *rsa.PrivateKey:
+ keyBytes = x509.MarshalPKCS1PrivateKey(k)
+ case *ecdsa.PrivateKey:
+ var err error
+ keyBytes, err = x509.MarshalECPrivateKey(k)
+ if err != nil {
+ return nil, fmt.Errorf("tls client priv key: %v", err)
+ }
+ default:
+ return nil, errors.New("tls client priv key: unsupported key type")
+ }
+
+ block = pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes}
+ keyPem := pem.EncodeToMemory(&block)
+
+ cert, err := tls.X509KeyPair(certPem, keyPem)
+ if err != nil {
+ return nil, fmt.Errorf("tls client cert: %v", err)
+ }
+ cfg.Certificates = []tls.Certificate{cert}
+ }
+
+ cfg.InsecureSkipVerify = opts.InsecureSkipVerify
+
+ cfg.VerifyPeerCertificate = opts.VerifyPeerCertificate
+ cfg.SessionTicketsDisabled = opts.SessionTicketsDisabled
+ cfg.ClientSessionCache = opts.ClientSessionCache
+
+ // When no CA certificate is provided, default to the system cert pool
+ // that way when a request is made to a server known by the system trust store,
+ // the name is still verified
+ switch {
+ case opts.LoadedCA != nil:
+ caCertPool := basePool(opts.LoadedCAPool)
+ caCertPool.AddCert(opts.LoadedCA)
+ cfg.RootCAs = caCertPool
+ case opts.CA != "":
+ // load ca cert
+ caCert, err := os.ReadFile(opts.CA)
+ if err != nil {
+ return nil, fmt.Errorf("tls client ca: %v", err)
+ }
+ caCertPool := basePool(opts.LoadedCAPool)
+ caCertPool.AppendCertsFromPEM(caCert)
+ cfg.RootCAs = caCertPool
+ case opts.LoadedCAPool != nil:
+ cfg.RootCAs = opts.LoadedCAPool
+ }
+
+ // apply servername overrride
+ if opts.ServerName != "" {
+ cfg.InsecureSkipVerify = false
+ cfg.ServerName = opts.ServerName
+ }
+
+ return cfg, nil
+}
+
+// TLSTransport creates a http client transport suitable for mutual tls auth
+func TLSTransport(opts TLSClientOptions) (http.RoundTripper, error) {
+ cfg, err := TLSClientAuth(opts)
+ if err != nil {
+ return nil, err
+ }
+
+ return &http.Transport{TLSClientConfig: cfg}, nil
+}
+
+// TLSClient creates a http.Client for mutual auth
+func TLSClient(opts TLSClientOptions) (*http.Client, error) {
+ transport, err := TLSTransport(opts)
+ if err != nil {
+ return nil, err
+ }
+ return &http.Client{Transport: transport}, nil
+}
+
+// Runtime represents an API client that uses the transport
+// to make http requests based on a swagger specification.
+type Runtime struct {
+ DefaultMediaType string
+ DefaultAuthentication runtime.ClientAuthInfoWriter
+ Consumers map[string]runtime.Consumer
+ Producers map[string]runtime.Producer
+
+ Transport http.RoundTripper
+ Jar http.CookieJar
+ // Spec *spec.Document
+ Host string
+ BasePath string
+ Formats strfmt.Registry
+ Context context.Context //nolint:containedctx // we precisely want this type to contain the request context
+
+ Debug bool
+ logger logger.Logger
+
+ clientOnce *sync.Once
+ client *http.Client
+ schemes []string
+ response ClientResponseFunc
+}
+
+// New creates a new default runtime for a swagger api runtime.Client
+func New(host, basePath string, schemes []string) *Runtime {
+ var rt Runtime
+ rt.DefaultMediaType = runtime.JSONMime
+
+ // TODO: actually infer this stuff from the spec
+ rt.Consumers = map[string]runtime.Consumer{
+ runtime.YAMLMime: yamlpc.YAMLConsumer(),
+ runtime.JSONMime: runtime.JSONConsumer(),
+ runtime.XMLMime: runtime.XMLConsumer(),
+ runtime.TextMime: runtime.TextConsumer(),
+ runtime.HTMLMime: runtime.TextConsumer(),
+ runtime.CSVMime: runtime.CSVConsumer(),
+ runtime.DefaultMime: runtime.ByteStreamConsumer(),
+ }
+ rt.Producers = map[string]runtime.Producer{
+ runtime.YAMLMime: yamlpc.YAMLProducer(),
+ runtime.JSONMime: runtime.JSONProducer(),
+ runtime.XMLMime: runtime.XMLProducer(),
+ runtime.TextMime: runtime.TextProducer(),
+ runtime.HTMLMime: runtime.TextProducer(),
+ runtime.CSVMime: runtime.CSVProducer(),
+ runtime.DefaultMime: runtime.ByteStreamProducer(),
+ }
+ rt.Transport = http.DefaultTransport
+ rt.Jar = nil
+ rt.Host = host
+ rt.BasePath = basePath
+ rt.Context = context.Background()
+ rt.clientOnce = new(sync.Once)
+ if !strings.HasPrefix(rt.BasePath, "/") {
+ rt.BasePath = "/" + rt.BasePath
+ }
+
+ rt.Debug = logger.DebugEnabled()
+ rt.logger = logger.StandardLogger{}
+ rt.response = newResponse
+
+ if len(schemes) > 0 {
+ rt.schemes = schemes
+ }
+ return &rt
+}
+
+// NewWithClient allows you to create a new transport with a configured http.Client
+func NewWithClient(host, basePath string, schemes []string, client *http.Client) *Runtime {
+ rt := New(host, basePath, schemes)
+ if client != nil {
+ rt.clientOnce.Do(func() {
+ rt.client = client
+ })
+ }
+ return rt
+}
+
+// WithOpenTracing adds opentracing support to the provided runtime.
+// A new client span is created for each request.
+// If the context of the client operation does not contain an active span, no span is created.
+// The provided opts are applied to each spans - for example to add global tags.
+//
+// Deprecated: use [WithOpenTelemetry] instead, as opentracing is now archived and superseded by opentelemetry.
+//
+// # Deprecation notice
+//
+// The [Runtime.WithOpenTracing] method has been deprecated in favor of [Runtime.WithOpenTelemetry].
+//
+// The method is still around so programs calling it will still build. However, it will return
+// an opentelemetry transport.
+//
+// If you have a strict requirement on using opentracing, you may still do so by importing
+// module [github.com/go-openapi/runtime/client-middleware/opentracing] and using
+// [github.com/go-openapi/runtime/client-middleware/opentracing.WithOpenTracing] with your
+// usual opentracing options and opentracing-enabled transport.
+//
+// Passed options are ignored unless they are of type [OpenTelemetryOpt].
+func (r *Runtime) WithOpenTracing(opts ...any) runtime.ClientTransport {
+ otelOpts := make([]OpenTelemetryOpt, 0, len(opts))
+ for _, o := range opts {
+ otelOpt, ok := o.(OpenTelemetryOpt)
+ if !ok {
+ continue
+ }
+ otelOpts = append(otelOpts, otelOpt)
+ }
+
+ return r.WithOpenTelemetry(otelOpts...)
+}
+
+// WithOpenTelemetry adds opentelemetry support to the provided runtime.
+// A new client span is created for each request.
+// If the context of the client operation does not contain an active span, no span is created.
+// The provided opts are applied to each spans - for example to add global tags.
+func (r *Runtime) WithOpenTelemetry(opts ...OpenTelemetryOpt) runtime.ClientTransport {
+ return newOpenTelemetryTransport(r, r.Host, opts)
+}
+
+// EnableConnectionReuse drains the remaining body from a response
+// so that go will reuse the TCP connections.
+//
+// This is not enabled by default because there are servers where
+// the response never gets closed and that would make the code hang forever.
+// So instead it's provided as a http client middleware that can be used to override
+// any request.
+func (r *Runtime) EnableConnectionReuse() {
+ if r.client == nil {
+ r.Transport = KeepAliveTransport(
+ transportOrDefault(r.Transport, http.DefaultTransport),
+ )
+ return
+ }
+
+ r.client.Transport = KeepAliveTransport(
+ transportOrDefault(r.client.Transport,
+ transportOrDefault(r.Transport, http.DefaultTransport),
+ ),
+ )
+}
+
+func (r *Runtime) CreateHttpRequest(operation *runtime.ClientOperation) (req *http.Request, err error) { //nolint:revive
+ _, req, err = r.createHttpRequest(operation)
+ return
+}
+
+// Submit a request and when there is a body on success it will turn that into the result
+// all other things are turned into an api error for swagger which retains the status code
+func (r *Runtime) Submit(operation *runtime.ClientOperation) (any, error) {
+ _, readResponse, _ := operation.Params, operation.Reader, operation.AuthInfo
+
+ request, req, err := r.createHttpRequest(operation)
+ if err != nil {
+ return nil, err
+ }
+
+ r.clientOnce.Do(func() {
+ r.client = &http.Client{
+ Transport: r.Transport,
+ Jar: r.Jar,
+ }
+ })
+
+ if r.Debug {
+ b, err2 := httputil.DumpRequestOut(req, true)
+ if err2 != nil {
+ return nil, err2
+ }
+ r.logger.Debugf("%s\n", string(b))
+ }
+
+ var parentCtx context.Context
+ switch {
+ case operation.Context != nil:
+ parentCtx = operation.Context
+ case r.Context != nil:
+ parentCtx = r.Context
+ default:
+ parentCtx = context.Background()
+ }
+
+ var (
+ ctx context.Context
+ cancel context.CancelFunc
+ )
+ if request.timeout == 0 {
+ // There may be a deadline in the context passed to the operation.
+ // Otherwise, there is no timeout set.
+ ctx, cancel = context.WithCancel(parentCtx)
+ } else {
+ // Sets the timeout passed from request params (by default runtime.DefaultTimeout).
+ // If there is already a deadline in the parent context, the shortest will
+ // apply.
+ ctx, cancel = context.WithTimeout(parentCtx, request.timeout)
+ }
+ defer cancel()
+
+ var client *http.Client
+ if operation.Client != nil {
+ client = operation.Client
+ } else {
+ client = r.client
+ }
+ req = req.WithContext(ctx)
+ res, err := client.Do(req) // make requests, by default follows 10 redirects before failing
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+
+ ct := res.Header.Get(runtime.HeaderContentType)
+ if ct == "" { // this should really never occur
+ ct = r.DefaultMediaType
+ }
+
+ if r.Debug {
+ printBody := true
+ if ct == runtime.DefaultMime {
+ printBody = false // Spare the terminal from a binary blob.
+ }
+ b, err2 := httputil.DumpResponse(res, printBody)
+ if err2 != nil {
+ return nil, err2
+ }
+ r.logger.Debugf("%s\n", string(b))
+ }
+
+ mt, _, err := mime.ParseMediaType(ct)
+ if err != nil {
+ return nil, fmt.Errorf("parse content type: %s", err)
+ }
+
+ cons, ok := r.Consumers[mt]
+ if !ok {
+ if cons, ok = r.Consumers["*/*"]; !ok {
+ // scream about not knowing what to do
+ return nil, fmt.Errorf("no consumer: %q", ct)
+ }
+ }
+ return readResponse.ReadResponse(r.response(res), cons)
+}
+
+// SetDebug changes the debug flag.
+// It ensures that client and middlewares have the set debug level.
+func (r *Runtime) SetDebug(debug bool) {
+ r.Debug = debug
+ middleware.Debug = debug
+}
+
+// SetLogger changes the logger stream.
+// It ensures that client and middlewares use the same logger.
+func (r *Runtime) SetLogger(logger logger.Logger) {
+ r.logger = logger
+ middleware.Logger = logger
+}
+
+type ClientResponseFunc = func(*http.Response) runtime.ClientResponse //nolint:revive
+
+// SetResponseReader changes the response reader implementation.
+func (r *Runtime) SetResponseReader(f ClientResponseFunc) {
+ if f == nil {
+ return
+ }
+ r.response = f
+}
+
+func (r *Runtime) pickScheme(schemes []string) string {
+ if v := r.selectScheme(r.schemes); v != "" {
+ return v
+ }
+ if v := r.selectScheme(schemes); v != "" {
+ return v
+ }
+ return schemeHTTP
+}
+
+func (r *Runtime) selectScheme(schemes []string) string {
+ schLen := len(schemes)
+ if schLen == 0 {
+ return ""
+ }
+
+ scheme := schemes[0]
+ // prefer https, but skip when not possible
+ if scheme != schemeHTTPS && schLen > 1 {
+ for _, sch := range schemes {
+ if sch == schemeHTTPS {
+ scheme = sch
+ break
+ }
+ }
+ }
+ return scheme
+}
+
+func transportOrDefault(left, right http.RoundTripper) http.RoundTripper {
+ if left == nil {
+ return right
+ }
+ return left
+}
+
+// takes a client operation and creates equivalent http.Request
+func (r *Runtime) createHttpRequest(operation *runtime.ClientOperation) (*request, *http.Request, error) { //nolint:revive
+ params, _, auth := operation.Params, operation.Reader, operation.AuthInfo
+
+ request := newRequest(operation.Method, operation.PathPattern, params)
+
+ var accept []string
+ accept = append(accept, operation.ProducesMediaTypes...)
+ if err := request.SetHeaderParam(runtime.HeaderAccept, accept...); err != nil {
+ return nil, nil, err
+ }
+
+ if auth == nil && r.DefaultAuthentication != nil {
+ auth = runtime.ClientAuthInfoWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
+ if req.GetHeaderParams().Get(runtime.HeaderAuthorization) != "" {
+ return nil
+ }
+ return r.DefaultAuthentication.AuthenticateRequest(req, reg)
+ })
+ }
+ // if auth != nil {
+ // if err := auth.AuthenticateRequest(request, r.Formats); err != nil {
+ // return nil, err
+ // }
+ //}
+
+ // TODO: pick appropriate media type
+ cmt := r.DefaultMediaType
+ for _, mediaType := range operation.ConsumesMediaTypes {
+ // Pick first non-empty media type
+ if mediaType != "" {
+ cmt = mediaType
+ break
+ }
+ }
+
+ if _, ok := r.Producers[cmt]; !ok && cmt != runtime.MultipartFormMime && cmt != runtime.URLencodedFormMime {
+ return nil, nil, fmt.Errorf("none of producers: %v registered. try %s", r.Producers, cmt)
+ }
+
+ req, err := request.buildHTTP(cmt, r.BasePath, r.Producers, r.Formats, auth)
+ if err != nil {
+ return nil, nil, err
+ }
+ req.URL.Scheme = r.pickScheme(operation.Schemes)
+ req.URL.Host = r.Host
+ req.Host = r.Host
+ return request, req, nil
+}
+
+func basePool(pool *x509.CertPool) *x509.CertPool {
+ if pool == nil {
+ return x509.NewCertPool()
+ }
+ return pool
+}
diff --git a/vendor/github.com/go-openapi/runtime/client_auth_info.go b/vendor/github.com/go-openapi/runtime/client_auth_info.go
new file mode 100644
index 000000000000..581e64451a21
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client_auth_info.go
@@ -0,0 +1,19 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import "github.com/go-openapi/strfmt"
+
+// A ClientAuthInfoWriterFunc converts a function to a request writer interface
+type ClientAuthInfoWriterFunc func(ClientRequest, strfmt.Registry) error
+
+// AuthenticateRequest adds authentication data to the request
+func (fn ClientAuthInfoWriterFunc) AuthenticateRequest(req ClientRequest, reg strfmt.Registry) error {
+ return fn(req, reg)
+}
+
+// A ClientAuthInfoWriter implementor knows how to write authentication info to a request
+type ClientAuthInfoWriter interface {
+ AuthenticateRequest(ClientRequest, strfmt.Registry) error
+}
diff --git a/vendor/github.com/go-openapi/runtime/client_operation.go b/vendor/github.com/go-openapi/runtime/client_operation.go
new file mode 100644
index 000000000000..b0bb0977db5c
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client_operation.go
@@ -0,0 +1,30 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "context"
+ "net/http"
+)
+
+// ClientOperation represents the context for a swagger operation to be submitted to the transport
+type ClientOperation struct {
+ ID string
+ Method string
+ PathPattern string
+ ProducesMediaTypes []string
+ ConsumesMediaTypes []string
+ Schemes []string
+ AuthInfo ClientAuthInfoWriter
+ Params ClientRequestWriter
+ Reader ClientResponseReader
+ Context context.Context //nolint:containedctx // we precisely want this type to contain the request context
+ Client *http.Client
+}
+
+// A ClientTransport implementor knows how to submit Request objects to some destination
+type ClientTransport interface {
+ // Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error)
+ Submit(*ClientOperation) (any, error)
+}
diff --git a/vendor/github.com/go-openapi/runtime/client_request.go b/vendor/github.com/go-openapi/runtime/client_request.go
new file mode 100644
index 000000000000..6e335b36f325
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client_request.go
@@ -0,0 +1,141 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/go-openapi/strfmt"
+)
+
+// ClientRequestWriterFunc converts a function to a request writer interface
+type ClientRequestWriterFunc func(ClientRequest, strfmt.Registry) error
+
+// WriteToRequest adds data to the request
+func (fn ClientRequestWriterFunc) WriteToRequest(req ClientRequest, reg strfmt.Registry) error {
+ return fn(req, reg)
+}
+
+// ClientRequestWriter is an interface for things that know how to write to a request
+type ClientRequestWriter interface {
+ WriteToRequest(ClientRequest, strfmt.Registry) error
+}
+
+// ClientRequest is an interface for things that know how to
+// add information to a swagger client request.
+type ClientRequest interface { //nolint:interfacebloat // a swagger-capable request is quite rich, hence the many getter/setters
+ SetHeaderParam(string, ...string) error
+
+ GetHeaderParams() http.Header
+
+ SetQueryParam(string, ...string) error
+
+ SetFormParam(string, ...string) error
+
+ SetPathParam(string, string) error
+
+ GetQueryParams() url.Values
+
+ SetFileParam(string, ...NamedReadCloser) error
+
+ SetBodyParam(any) error
+
+ SetTimeout(time.Duration) error
+
+ GetMethod() string
+
+ GetPath() string
+
+ GetBody() []byte
+
+ GetBodyParam() any
+
+ GetFileParam() map[string][]NamedReadCloser
+}
+
+// NamedReadCloser represents a named ReadCloser interface
+type NamedReadCloser interface {
+ io.ReadCloser
+ Name() string
+}
+
+// NamedReader creates a NamedReadCloser for use as file upload
+func NamedReader(name string, rdr io.Reader) NamedReadCloser {
+ rc, ok := rdr.(io.ReadCloser)
+ if !ok {
+ rc = io.NopCloser(rdr)
+ }
+ return &namedReadCloser{
+ name: name,
+ cr: rc,
+ }
+}
+
+type namedReadCloser struct {
+ name string
+ cr io.ReadCloser
+}
+
+func (n *namedReadCloser) Close() error {
+ return n.cr.Close()
+}
+func (n *namedReadCloser) Read(p []byte) (int, error) {
+ return n.cr.Read(p)
+}
+func (n *namedReadCloser) Name() string {
+ return n.name
+}
+
+type TestClientRequest struct {
+ Headers http.Header
+ Body any
+}
+
+func (t *TestClientRequest) SetHeaderParam(name string, values ...string) error {
+ if t.Headers == nil {
+ t.Headers = make(http.Header)
+ }
+ t.Headers.Set(name, values[0])
+ return nil
+}
+
+func (t *TestClientRequest) SetQueryParam(_ string, _ ...string) error { return nil }
+
+func (t *TestClientRequest) SetFormParam(_ string, _ ...string) error { return nil }
+
+func (t *TestClientRequest) SetPathParam(_ string, _ string) error { return nil }
+
+func (t *TestClientRequest) SetFileParam(_ string, _ ...NamedReadCloser) error { return nil }
+
+func (t *TestClientRequest) SetBodyParam(body any) error {
+ t.Body = body
+ return nil
+}
+
+func (t *TestClientRequest) SetTimeout(time.Duration) error {
+ return nil
+}
+
+func (t *TestClientRequest) GetQueryParams() url.Values { return nil }
+
+func (t *TestClientRequest) GetMethod() string { return "" }
+
+func (t *TestClientRequest) GetPath() string { return "" }
+
+func (t *TestClientRequest) GetBody() []byte { return nil }
+
+func (t *TestClientRequest) GetBodyParam() any {
+ return t.Body
+}
+
+func (t *TestClientRequest) GetFileParam() map[string][]NamedReadCloser {
+ return nil
+}
+
+func (t *TestClientRequest) GetHeaderParams() http.Header {
+ return t.Headers
+}
diff --git a/vendor/github.com/go-openapi/runtime/client_response.go b/vendor/github.com/go-openapi/runtime/client_response.go
new file mode 100644
index 000000000000..f2cf942ab360
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client_response.go
@@ -0,0 +1,109 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// A ClientResponse represents a client response.
+//
+// This bridges between responses obtained from different transports
+type ClientResponse interface {
+ Code() int
+ Message() string
+ GetHeader(string) string
+ GetHeaders(string) []string
+ Body() io.ReadCloser
+}
+
+// A ClientResponseReaderFunc turns a function into a ClientResponseReader interface implementation
+type ClientResponseReaderFunc func(ClientResponse, Consumer) (any, error)
+
+// ReadResponse reads the response
+func (read ClientResponseReaderFunc) ReadResponse(resp ClientResponse, consumer Consumer) (any, error) {
+ return read(resp, consumer)
+}
+
+// A ClientResponseReader is an interface for things want to read a response.
+// An application of this is to create structs from response values
+type ClientResponseReader interface {
+ ReadResponse(ClientResponse, Consumer) (any, error)
+}
+
+// APIError wraps an error model and captures the status code
+type APIError struct {
+ OperationName string
+ Response any
+ Code int
+}
+
+// NewAPIError creates a new API error
+func NewAPIError(opName string, payload any, code int) *APIError {
+ return &APIError{
+ OperationName: opName,
+ Response: payload,
+ Code: code,
+ }
+}
+
+// sanitizer ensures that single quotes are escaped
+var sanitizer = strings.NewReplacer(`\`, `\\`, `'`, `\'`)
+
+func (o *APIError) Error() string {
+ var resp []byte
+ if err, ok := o.Response.(error); ok {
+ resp = []byte("'" + sanitizer.Replace(err.Error()) + "'")
+ } else {
+ resp, _ = json.Marshal(o.Response)
+ }
+
+ return fmt.Sprintf("%s (status %d): %s", o.OperationName, o.Code, resp)
+}
+
+func (o *APIError) String() string {
+ return o.Error()
+}
+
+// IsSuccess returns true when this API response returns a 2xx status code
+func (o *APIError) IsSuccess() bool {
+ const statusOK = 2
+ return o.Code/100 == statusOK
+}
+
+// IsRedirect returns true when this API response returns a 3xx status code
+func (o *APIError) IsRedirect() bool {
+ const statusRedirect = 3
+ return o.Code/100 == statusRedirect
+}
+
+// IsClientError returns true when this API response returns a 4xx status code
+func (o *APIError) IsClientError() bool {
+ const statusClientError = 4
+ return o.Code/100 == statusClientError
+}
+
+// IsServerError returns true when this API response returns a 5xx status code
+func (o *APIError) IsServerError() bool {
+ const statusServerError = 5
+ return o.Code/100 == statusServerError
+}
+
+// IsCode returns true when this API response returns a given status code
+func (o *APIError) IsCode(code int) bool {
+ return o.Code == code
+}
+
+// A ClientResponseStatus is a common interface implemented by all responses on the generated code
+// You can use this to treat any client response based on status code
+type ClientResponseStatus interface {
+ IsSuccess() bool
+ IsRedirect() bool
+ IsClientError() bool
+ IsServerError() bool
+ IsCode(int) bool
+}
diff --git a/vendor/github.com/go-openapi/runtime/constants.go b/vendor/github.com/go-openapi/runtime/constants.go
new file mode 100644
index 000000000000..62ae9eec0cff
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/constants.go
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+const (
+ // HeaderContentType represents a http content-type header, it's value is supposed to be a mime type
+ HeaderContentType = "Content-Type"
+
+ // HeaderTransferEncoding represents a http transfer-encoding header.
+ HeaderTransferEncoding = "Transfer-Encoding"
+
+ // HeaderAccept the Accept header
+ HeaderAccept = "Accept"
+ // HeaderAuthorization the Authorization header
+ HeaderAuthorization = "Authorization"
+
+ charsetKey = "charset"
+
+ // DefaultMime the default fallback mime type
+ DefaultMime = "application/octet-stream"
+ // JSONMime the json mime type
+ JSONMime = "application/json"
+ // YAMLMime the yaml mime type
+ YAMLMime = "application/x-yaml"
+ // XMLMime the xml mime type
+ XMLMime = "application/xml"
+ // TextMime the text mime type
+ TextMime = "text/plain"
+ // HTMLMime the html mime type
+ HTMLMime = "text/html"
+ // CSVMime the csv mime type
+ CSVMime = "text/csv"
+ // MultipartFormMime the multipart form mime type
+ MultipartFormMime = "multipart/form-data"
+ // URLencodedFormMime the url encoded form mime type
+ URLencodedFormMime = "application/x-www-form-urlencoded"
+)
diff --git a/vendor/github.com/go-openapi/runtime/csv.go b/vendor/github.com/go-openapi/runtime/csv.go
new file mode 100644
index 000000000000..567e3d9db246
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/csv.go
@@ -0,0 +1,339 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "bytes"
+ "context"
+ "encoding"
+ "encoding/csv"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+
+ "golang.org/x/sync/errgroup"
+)
+
+// CSVConsumer creates a new CSV consumer.
+//
+// The consumer consumes CSV records from a provided reader into the data passed by reference.
+//
+// CSVOpts options may be specified to alter the default CSV behavior on the reader and the writer side (e.g. separator, skip header, ...).
+// The defaults are those of the standard library's csv.Reader and csv.Writer.
+//
+// Supported output underlying types and interfaces, prioritized in this order:
+// - *csv.Writer
+// - CSVWriter (writer options are ignored)
+// - io.Writer (as raw bytes)
+// - io.ReaderFrom (as raw bytes)
+// - encoding.BinaryUnmarshaler (as raw bytes)
+// - *[][]string (as a collection of records)
+// - *[]byte (as raw bytes)
+// - *string (a raw bytes)
+//
+// The consumer prioritizes situations where buffering the input is not required.
+func CSVConsumer(opts ...CSVOpt) Consumer {
+ o := csvOptsWithDefaults(opts)
+
+ return ConsumerFunc(func(reader io.Reader, data any) error {
+ if reader == nil {
+ return errors.New("CSVConsumer requires a reader")
+ }
+ if data == nil {
+ return errors.New("nil destination for CSVConsumer")
+ }
+
+ csvReader := csv.NewReader(reader)
+ o.applyToReader(csvReader)
+ closer := defaultCloser
+ if o.closeStream {
+ if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
+ closer = cl.Close
+ }
+ }
+ defer func() {
+ _ = closer()
+ }()
+
+ switch destination := data.(type) {
+ case *csv.Writer:
+ csvWriter := destination
+ o.applyToWriter(csvWriter)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case CSVWriter:
+ csvWriter := destination
+ // no writer options available
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.Writer:
+ csvWriter := csv.NewWriter(destination)
+ o.applyToWriter(csvWriter)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.ReaderFrom:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+ _, err := destination.ReadFrom(&buf)
+
+ return err
+
+ case encoding.BinaryUnmarshaler:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+
+ return destination.UnmarshalBinary(buf.Bytes())
+
+ default:
+ // support *[][]string, *[]byte, *string
+ if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
+ return errors.New("destination must be a pointer")
+ }
+
+ v := reflect.Indirect(reflect.ValueOf(data))
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Slice && t.Elem().Elem().Kind() == reflect.String:
+ csvWriter := &csvRecordsWriter{}
+ // writer options are ignored
+ if err := pipeCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+
+ v.Grow(len(csvWriter.records))
+ v.SetCap(len(csvWriter.records)) // in case Grow was unnessary, trim down the capacity
+ v.SetLen(len(csvWriter.records))
+ reflect.Copy(v, reflect.ValueOf(csvWriter.records))
+
+ return nil
+
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+ v.SetBytes(buf.Bytes())
+
+ return nil
+
+ case t.Kind() == reflect.String:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+ v.SetString(buf.String())
+
+ return nil
+
+ default:
+ return fmt.Errorf("%v (%T) is not supported by the CSVConsumer, %s",
+ data, data, "can be resolved by supporting CSVWriter/Writer/BinaryUnmarshaler interface",
+ )
+ }
+ }
+ })
+}
+
+// CSVProducer creates a new CSV producer.
+//
+// The producer takes input data then writes as CSV to an output writer (essentially as a pipe).
+//
+// Supported input underlying types and interfaces, prioritized in this order:
+// - *csv.Reader
+// - CSVReader (reader options are ignored)
+// - io.Reader
+// - io.WriterTo
+// - encoding.BinaryMarshaler
+// - [][]string
+// - []byte
+// - string
+//
+// The producer prioritizes situations where buffering the input is not required.
+func CSVProducer(opts ...CSVOpt) Producer {
+ o := csvOptsWithDefaults(opts)
+
+ return ProducerFunc(func(writer io.Writer, data any) error {
+ if writer == nil {
+ return errors.New("CSVProducer requires a writer")
+ }
+ if data == nil {
+ return errors.New("nil data for CSVProducer")
+ }
+
+ csvWriter := csv.NewWriter(writer)
+ o.applyToWriter(csvWriter)
+ closer := defaultCloser
+ if o.closeStream {
+ if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
+ closer = cl.Close
+ }
+ }
+ defer func() {
+ _ = closer()
+ }()
+
+ if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
+ defer rc.Close()
+ }
+
+ switch origin := data.(type) {
+ case *csv.Reader:
+ csvReader := origin
+ o.applyToReader(csvReader)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case CSVReader:
+ csvReader := origin
+ // no reader options available
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.Reader:
+ csvReader := csv.NewReader(origin)
+ o.applyToReader(csvReader)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.WriterTo:
+ // async piping of the writes performed by WriteTo
+ r, w := io.Pipe()
+ csvReader := csv.NewReader(r)
+ o.applyToReader(csvReader)
+
+ pipe, _ := errgroup.WithContext(context.Background())
+ pipe.Go(func() error {
+ _, err := origin.WriteTo(w)
+ _ = w.Close()
+ return err
+ })
+
+ pipe.Go(func() error {
+ defer func() {
+ _ = r.Close()
+ }()
+
+ return pipeCSV(csvWriter, csvReader, o)
+ })
+
+ return pipe.Wait()
+
+ case encoding.BinaryMarshaler:
+ buf, err := origin.MarshalBinary()
+ if err != nil {
+ return err
+ }
+ rdr := bytes.NewBuffer(buf)
+ csvReader := csv.NewReader(rdr)
+
+ return bufferedCSV(csvWriter, csvReader, o)
+
+ default:
+ // support [][]string, []byte, string (or pointers to those)
+ v := reflect.Indirect(reflect.ValueOf(data))
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Slice && t.Elem().Elem().Kind() == reflect.String:
+ csvReader := &csvRecordsWriter{
+ records: make([][]string, v.Len()),
+ }
+ reflect.Copy(reflect.ValueOf(csvReader.records), v)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
+ buf := bytes.NewBuffer(v.Bytes())
+ csvReader := csv.NewReader(buf)
+ o.applyToReader(csvReader)
+
+ return bufferedCSV(csvWriter, csvReader, o)
+
+ case t.Kind() == reflect.String:
+ buf := bytes.NewBufferString(v.String())
+ csvReader := csv.NewReader(buf)
+ o.applyToReader(csvReader)
+
+ return bufferedCSV(csvWriter, csvReader, o)
+
+ default:
+ return fmt.Errorf("%v (%T) is not supported by the CSVProducer, %s",
+ data, data, "can be resolved by supporting CSVReader/Reader/BinaryMarshaler interface",
+ )
+ }
+ }
+ })
+}
+
+// pipeCSV copies CSV records from a CSV reader to a CSV writer
+func pipeCSV(csvWriter CSVWriter, csvReader CSVReader, opts csvOpts) error {
+ for ; opts.skippedLines > 0; opts.skippedLines-- {
+ _, err := csvReader.Read()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+
+ return err
+ }
+ }
+
+ for {
+ record, err := csvReader.Read()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+
+ return err
+ }
+
+ if err := csvWriter.Write(record); err != nil {
+ return err
+ }
+ }
+
+ csvWriter.Flush()
+
+ return csvWriter.Error()
+}
+
+// bufferedCSV copies CSV records from a CSV reader to a CSV writer,
+// by first reading all records then writing them at once.
+func bufferedCSV(csvWriter *csv.Writer, csvReader *csv.Reader, opts csvOpts) error {
+ for ; opts.skippedLines > 0; opts.skippedLines-- {
+ _, err := csvReader.Read()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+
+ return err
+ }
+ }
+
+ records, err := csvReader.ReadAll()
+ if err != nil {
+ return err
+ }
+
+ return csvWriter.WriteAll(records)
+}
diff --git a/vendor/github.com/go-openapi/runtime/csv_options.go b/vendor/github.com/go-openapi/runtime/csv_options.go
new file mode 100644
index 000000000000..4cc043900100
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/csv_options.go
@@ -0,0 +1,124 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "encoding/csv"
+ "io"
+)
+
+// CSVOpt alter the behavior of the CSV consumer or producer.
+type CSVOpt func(*csvOpts)
+
+type csvOpts struct {
+ csvReader csv.Reader
+ csvWriter csv.Writer
+ skippedLines int
+ closeStream bool
+}
+
+// WithCSVReaderOpts specifies the options to csv.Reader
+// when reading CSV.
+func WithCSVReaderOpts(reader csv.Reader) CSVOpt {
+ return func(o *csvOpts) {
+ o.csvReader = reader
+ }
+}
+
+// WithCSVWriterOpts specifies the options to csv.Writer
+// when writing CSV.
+func WithCSVWriterOpts(writer csv.Writer) CSVOpt {
+ return func(o *csvOpts) {
+ o.csvWriter = writer
+ }
+}
+
+// WithCSVSkipLines will skip header lines.
+func WithCSVSkipLines(skipped int) CSVOpt {
+ return func(o *csvOpts) {
+ o.skippedLines = skipped
+ }
+}
+
+func WithCSVClosesStream() CSVOpt {
+ return func(o *csvOpts) {
+ o.closeStream = true
+ }
+}
+
+func (o csvOpts) applyToReader(in *csv.Reader) {
+ if o.csvReader.Comma != 0 {
+ in.Comma = o.csvReader.Comma
+ }
+ if o.csvReader.Comment != 0 {
+ in.Comment = o.csvReader.Comment
+ }
+ if o.csvReader.FieldsPerRecord != 0 {
+ in.FieldsPerRecord = o.csvReader.FieldsPerRecord
+ }
+
+ in.LazyQuotes = o.csvReader.LazyQuotes
+ in.TrimLeadingSpace = o.csvReader.TrimLeadingSpace
+ in.ReuseRecord = o.csvReader.ReuseRecord
+}
+
+func (o csvOpts) applyToWriter(in *csv.Writer) {
+ if o.csvWriter.Comma != 0 {
+ in.Comma = o.csvWriter.Comma
+ }
+ in.UseCRLF = o.csvWriter.UseCRLF
+}
+
+func csvOptsWithDefaults(opts []CSVOpt) csvOpts {
+ var o csvOpts
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ return o
+}
+
+type CSVWriter interface {
+ Write([]string) error
+ Flush()
+ Error() error
+}
+
+type CSVReader interface {
+ Read() ([]string, error)
+}
+
+var (
+ _ CSVWriter = &csvRecordsWriter{}
+ _ CSVReader = &csvRecordsWriter{}
+)
+
+// csvRecordsWriter is an internal container to move CSV records back and forth
+type csvRecordsWriter struct {
+ i int
+ records [][]string
+}
+
+func (w *csvRecordsWriter) Write(record []string) error {
+ w.records = append(w.records, record)
+
+ return nil
+}
+
+func (w *csvRecordsWriter) Read() ([]string, error) {
+ if w.i >= len(w.records) {
+ return nil, io.EOF
+ }
+ defer func() {
+ w.i++
+ }()
+
+ return w.records[w.i], nil
+}
+
+func (w *csvRecordsWriter) Flush() {}
+
+func (w *csvRecordsWriter) Error() error {
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/runtime/discard.go b/vendor/github.com/go-openapi/runtime/discard.go
new file mode 100644
index 000000000000..b05678becd9a
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/discard.go
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import "io"
+
+// DiscardConsumer does absolutely nothing, it's a black hole.
+var DiscardConsumer = ConsumerFunc(func(_ io.Reader, _ any) error { return nil })
+
+// DiscardProducer does absolutely nothing, it's a black hole.
+var DiscardProducer = ProducerFunc(func(_ io.Writer, _ any) error { return nil })
diff --git a/vendor/github.com/go-openapi/runtime/file.go b/vendor/github.com/go-openapi/runtime/file.go
new file mode 100644
index 000000000000..2a85379a748f
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/file.go
@@ -0,0 +1,8 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import "github.com/go-openapi/swag/fileutils"
+
+type File = fileutils.File
diff --git a/vendor/github.com/go-openapi/runtime/go.work b/vendor/github.com/go-openapi/runtime/go.work
new file mode 100644
index 000000000000..b4cd9e01e86c
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/go.work
@@ -0,0 +1,6 @@
+use (
+ .
+ ./client-middleware/opentracing
+)
+
+go 1.24.0
diff --git a/vendor/github.com/go-openapi/runtime/go.work.sum b/vendor/github.com/go-openapi/runtime/go.work.sum
new file mode 100644
index 000000000000..b0c2c9a63dee
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/go.work.sum
@@ -0,0 +1,93 @@
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/go-openapi/errors v0.22.2/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
+github.com/go-openapi/jsonpointer v0.22.0/go.mod h1:xt3jV88UtExdIkkL7NloURjRQjbeUgcxFblMjq2iaiU=
+github.com/go-openapi/jsonreference v0.21.1/go.mod h1:PWs8rO4xxTUqKGu+lEvvCxD5k2X7QYkKAepJyCmSTT8=
+github.com/go-openapi/swag v0.24.1/go.mod h1:sm8I3lCPlspsBBwUm1t5oZeWZS0s7m/A+Psg0ooRU0A=
+github.com/go-openapi/swag/cmdutils v0.24.0/go.mod h1:uxib2FAeQMByyHomTlsP8h1TtPd54Msu2ZDU/H5Vuf8=
+github.com/go-openapi/swag/conv v0.24.0/go.mod h1:jbn140mZd7EW2g8a8Y5bwm8/Wy1slLySQQ0ND6DPc2c=
+github.com/go-openapi/swag/fileutils v0.24.0/go.mod h1:3SCrCSBHyP1/N+3oErQ1gP+OX1GV2QYFSnrTbzwli90=
+github.com/go-openapi/swag/jsonname v0.24.0/go.mod h1:GXqrPzGJe611P7LG4QB9JKPtUZ7flE4DOVechNaDd7Q=
+github.com/go-openapi/swag/jsonutils v0.24.0/go.mod h1:vBowZtF5Z4DDApIoxcIVfR8v0l9oq5PpYRUuteVu6f0=
+github.com/go-openapi/swag/loading v0.24.0/go.mod h1:gShCN4woKZYIxPxbfbyHgjXAhO61m88tmjy0lp/LkJk=
+github.com/go-openapi/swag/mangling v0.24.0/go.mod h1:Jm5Go9LHkycsz0wfoaBDkdc4CkpuSnIEf62brzyCbhc=
+github.com/go-openapi/swag/netutils v0.24.0/go.mod h1:WRgiHcYTnx+IqfMCtu0hy9oOaPR0HnPbmArSRN1SkZM=
+github.com/go-openapi/swag/stringutils v0.24.0/go.mod h1:5nUXB4xA0kw2df5PRipZDslPJgJut+NjL7D25zPZ/4w=
+github.com/go-openapi/swag/typeutils v0.24.0/go.mod h1:q8C3Kmk/vh2VhpCLaoR2MVWOGP8y7Jc8l82qCTd1DYI=
+github.com/go-openapi/swag/yamlutils v0.24.0/go.mod h1:DpKv5aYuaGm/sULePoeiG8uwMpZSfReo1HR3Ik0yaG8=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
+golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
+golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
+golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
+golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
+golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
+golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
+golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
+golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/vendor/github.com/go-openapi/runtime/headers.go b/vendor/github.com/go-openapi/runtime/headers.go
new file mode 100644
index 000000000000..510e396ca733
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/headers.go
@@ -0,0 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "mime"
+ "net/http"
+
+ "github.com/go-openapi/errors"
+)
+
+// ContentType parses a content type header
+func ContentType(headers http.Header) (string, string, error) {
+ ct := headers.Get(HeaderContentType)
+ orig := ct
+ if ct == "" {
+ ct = DefaultMime
+ }
+ if ct == "" {
+ return "", "", nil
+ }
+
+ mt, opts, err := mime.ParseMediaType(ct)
+ if err != nil {
+ return "", "", errors.NewParseError(HeaderContentType, "header", orig, err)
+ }
+
+ if cs, ok := opts[charsetKey]; ok {
+ return mt, cs, nil
+ }
+
+ return mt, "", nil
+}
diff --git a/vendor/github.com/go-openapi/runtime/interfaces.go b/vendor/github.com/go-openapi/runtime/interfaces.go
new file mode 100644
index 000000000000..90046bf367e9
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/interfaces.go
@@ -0,0 +1,101 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "context"
+ "io"
+ "net/http"
+
+ "github.com/go-openapi/strfmt"
+)
+
+// OperationHandlerFunc an adapter for a function to the OperationHandler interface
+type OperationHandlerFunc func(any) (any, error)
+
+// Handle implements the operation handler interface
+func (s OperationHandlerFunc) Handle(data any) (any, error) {
+ return s(data)
+}
+
+// OperationHandler a handler for a swagger operation
+type OperationHandler interface {
+ Handle(any) (any, error)
+}
+
+// ConsumerFunc represents a function that can be used as a consumer
+type ConsumerFunc func(io.Reader, any) error
+
+// Consume consumes the reader into the data parameter
+func (fn ConsumerFunc) Consume(reader io.Reader, data any) error {
+ return fn(reader, data)
+}
+
+// Consumer implementations know how to bind the values on the provided interface to
+// data provided by the request body
+type Consumer interface {
+ // Consume performs the binding of request values
+ Consume(io.Reader, any) error
+}
+
+// ProducerFunc represents a function that can be used as a producer
+type ProducerFunc func(io.Writer, any) error
+
+// Produce produces the response for the provided data
+func (f ProducerFunc) Produce(writer io.Writer, data any) error {
+ return f(writer, data)
+}
+
+// Producer implementations know how to turn the provided interface into a valid
+// HTTP response
+type Producer interface {
+ // Produce writes to the http response
+ Produce(io.Writer, any) error
+}
+
+// AuthenticatorFunc turns a function into an authenticator
+type AuthenticatorFunc func(any) (bool, any, error)
+
+// Authenticate authenticates the request with the provided data
+func (f AuthenticatorFunc) Authenticate(params any) (bool, any, error) {
+ return f(params)
+}
+
+// Authenticator represents an authentication strategy
+// implementations of Authenticator know how to authenticate the
+// request data and translate that into a valid principal object or an error
+type Authenticator interface {
+ Authenticate(any) (bool, any, error)
+}
+
+// AuthorizerFunc turns a function into an authorizer
+type AuthorizerFunc func(*http.Request, any) error
+
+// Authorize authorizes the processing of the request for the principal
+func (f AuthorizerFunc) Authorize(r *http.Request, principal any) error {
+ return f(r, principal)
+}
+
+// Authorizer represents an authorization strategy
+// implementations of Authorizer know how to authorize the principal object
+// using the request data and returns error if unauthorized
+type Authorizer interface {
+ Authorize(*http.Request, any) error
+}
+
+// Validatable types implementing this interface allow customizing their validation
+// this will be used instead of the reflective validation based on the spec document.
+// the implementations are assumed to have been generated by the swagger tool so they should
+// contain all the validations obtained from the spec
+type Validatable interface {
+ Validate(strfmt.Registry) error
+}
+
+// ContextValidatable types implementing this interface allow customizing their validation
+// this will be used instead of the reflective validation based on the spec document.
+// the implementations are assumed to have been generated by the swagger tool so they should
+// contain all the context validations obtained from the spec
+type ContextValidatable interface {
+ ContextValidate(context.Context, strfmt.Registry) error
+}
diff --git a/vendor/github.com/go-openapi/runtime/json.go b/vendor/github.com/go-openapi/runtime/json.go
new file mode 100644
index 000000000000..8f93eebfaa2a
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/json.go
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "encoding/json"
+ "io"
+)
+
+// JSONConsumer creates a new JSON consumer
+func JSONConsumer() Consumer {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
+ dec := json.NewDecoder(reader)
+ dec.UseNumber() // preserve number formats
+ return dec.Decode(data)
+ })
+}
+
+// JSONProducer creates a new JSON producer
+func JSONProducer() Producer {
+ return ProducerFunc(func(writer io.Writer, data any) error {
+ enc := json.NewEncoder(writer)
+ enc.SetEscapeHTML(false)
+ return enc.Encode(data)
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/logger/logger.go b/vendor/github.com/go-openapi/runtime/logger/logger.go
new file mode 100644
index 000000000000..45484deb5938
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/logger/logger.go
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package logger
+
+import "os"
+
+type Logger interface {
+ Printf(format string, args ...any)
+ Debugf(format string, args ...any)
+}
+
+func DebugEnabled() bool {
+ d := os.Getenv("SWAGGER_DEBUG")
+ if d != "" && d != "false" && d != "0" {
+ return true
+ }
+ d = os.Getenv("DEBUG")
+ if d != "" && d != "false" && d != "0" {
+ return true
+ }
+ return false
+}
diff --git a/vendor/github.com/go-openapi/runtime/logger/standard.go b/vendor/github.com/go-openapi/runtime/logger/standard.go
new file mode 100644
index 000000000000..48ba27f4a3d4
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/logger/standard.go
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package logger
+
+import (
+ "fmt"
+ "os"
+)
+
+var _ Logger = StandardLogger{}
+
+type StandardLogger struct{}
+
+func (StandardLogger) Printf(format string, args ...any) {
+ if len(format) == 0 || format[len(format)-1] != '\n' {
+ format += "\n"
+ }
+ fmt.Fprintf(os.Stderr, format, args...)
+}
+
+func (StandardLogger) Debugf(format string, args ...any) {
+ if len(format) == 0 || format[len(format)-1] != '\n' {
+ format += "\n"
+ }
+ fmt.Fprintf(os.Stderr, format, args...)
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/context.go b/vendor/github.com/go-openapi/runtime/middleware/context.go
new file mode 100644
index 000000000000..bb00b93b89be
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/context.go
@@ -0,0 +1,714 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ stdContext "context"
+ "fmt"
+ "net/http"
+ "net/url"
+ "path"
+ "strings"
+ "sync"
+
+ "github.com/go-openapi/analysis"
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/loads"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/logger"
+ "github.com/go-openapi/runtime/middleware/untyped"
+ "github.com/go-openapi/runtime/security"
+)
+
+// Debug when true turns on verbose logging
+var Debug = logger.DebugEnabled()
+
+// Logger is the standard libray logger used for printing debug messages
+var Logger logger.Logger = logger.StandardLogger{}
+
+func debugLogfFunc(lg logger.Logger) func(string, ...any) {
+ if logger.DebugEnabled() {
+ if lg == nil {
+ return Logger.Debugf
+ }
+
+ return lg.Debugf
+ }
+
+ // muted logger
+ return func(_ string, _ ...any) {}
+}
+
+// A Builder can create middlewares
+type Builder func(http.Handler) http.Handler
+
+// PassthroughBuilder returns the handler, aka the builder identity function
+func PassthroughBuilder(handler http.Handler) http.Handler { return handler }
+
+// RequestBinder is an interface for types to implement
+// when they want to be able to bind from a request
+type RequestBinder interface {
+ BindRequest(*http.Request, *MatchedRoute) error
+}
+
+// Responder is an interface for types to implement
+// when they want to be considered for writing HTTP responses
+type Responder interface {
+ WriteResponse(http.ResponseWriter, runtime.Producer)
+}
+
+// ResponderFunc wraps a func as a Responder interface
+type ResponderFunc func(http.ResponseWriter, runtime.Producer)
+
+// WriteResponse writes to the response
+func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Producer) {
+ fn(rw, pr)
+}
+
+// Context is a type safe wrapper around an untyped request context
+// used throughout to store request context with the standard context attached
+// to the http.Request
+type Context struct {
+ spec *loads.Document
+ analyzer *analysis.Spec
+ api RoutableAPI
+ router Router
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
+}
+
+type routableUntypedAPI struct {
+ api *untyped.API
+ hlock *sync.Mutex
+ handlers map[string]map[string]http.Handler
+ defaultConsumes string
+ defaultProduces string
+}
+
+func newRoutableUntypedAPI(spec *loads.Document, api *untyped.API, context *Context) *routableUntypedAPI {
+ var handlers map[string]map[string]http.Handler
+ if spec == nil || api == nil {
+ return nil
+ }
+ analyzer := analysis.New(spec.Spec())
+ for method, hls := range analyzer.Operations() {
+ um := strings.ToUpper(method)
+ for path, op := range hls {
+ schemes := analyzer.SecurityRequirementsFor(op)
+
+ if oh, ok := api.OperationHandlerFor(method, path); ok {
+ if handlers == nil {
+ handlers = make(map[string]map[string]http.Handler)
+ }
+ if b, ok := handlers[um]; !ok || b == nil {
+ handlers[um] = make(map[string]http.Handler)
+ }
+
+ var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ // lookup route info in the context
+ route, rCtx, _ := context.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+
+ // bind and validate the request using reflection
+ var bound any
+ var validation error
+ bound, r, validation = context.BindAndValidate(r, route)
+ if validation != nil {
+ context.Respond(w, r, route.Produces, route, validation)
+ return
+ }
+
+ // actually handle the request
+ result, err := oh.Handle(bound)
+ if err != nil {
+ // respond with failure
+ context.Respond(w, r, route.Produces, route, err)
+ return
+ }
+
+ // respond with success
+ context.Respond(w, r, route.Produces, route, result)
+ })
+
+ if len(schemes) > 0 {
+ handler = newSecureAPI(context, handler)
+ }
+ handlers[um][path] = handler
+ }
+ }
+ }
+
+ return &routableUntypedAPI{
+ api: api,
+ hlock: new(sync.Mutex),
+ handlers: handlers,
+ defaultProduces: api.DefaultProduces,
+ defaultConsumes: api.DefaultConsumes,
+ }
+}
+
+func (r *routableUntypedAPI) HandlerFor(method, path string) (http.Handler, bool) {
+ r.hlock.Lock()
+ paths, ok := r.handlers[strings.ToUpper(method)]
+ if !ok {
+ r.hlock.Unlock()
+ return nil, false
+ }
+ handler, ok := paths[path]
+ r.hlock.Unlock()
+ return handler, ok
+}
+func (r *routableUntypedAPI) ServeErrorFor(_ string) func(http.ResponseWriter, *http.Request, error) {
+ return r.api.ServeError
+}
+func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
+ return r.api.ConsumersFor(mediaTypes)
+}
+func (r *routableUntypedAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
+ return r.api.ProducersFor(mediaTypes)
+}
+func (r *routableUntypedAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
+ return r.api.AuthenticatorsFor(schemes)
+}
+func (r *routableUntypedAPI) Authorizer() runtime.Authorizer {
+ return r.api.Authorizer()
+}
+func (r *routableUntypedAPI) Formats() strfmt.Registry {
+ return r.api.Formats()
+}
+
+func (r *routableUntypedAPI) DefaultProduces() string {
+ return r.defaultProduces
+}
+
+func (r *routableUntypedAPI) DefaultConsumes() string {
+ return r.defaultConsumes
+}
+
+// NewRoutableContext creates a new context for a routable API.
+//
+// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
+func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context {
+ var an *analysis.Spec
+ if spec != nil {
+ an = analysis.New(spec.Spec())
+ }
+
+ return NewRoutableContextWithAnalyzedSpec(spec, an, routableAPI, routes)
+}
+
+// NewRoutableContextWithAnalyzedSpec is like NewRoutableContext but takes as input an already analysed spec.
+//
+// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
+func NewRoutableContextWithAnalyzedSpec(spec *loads.Document, an *analysis.Spec, routableAPI RoutableAPI, routes Router) *Context {
+ // Either there are no spec doc and analysis, or both of them.
+ if (spec != nil || an != nil) && (spec == nil || an == nil) {
+ panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, "routable context requires either both spec doc and analysis, or none of them"))
+ }
+
+ return &Context{
+ spec: spec,
+ api: routableAPI,
+ analyzer: an,
+ router: routes,
+ debugLogf: debugLogfFunc(nil),
+ }
+}
+
+// NewContext creates a new context wrapper.
+//
+// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
+func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context {
+ var an *analysis.Spec
+ if spec != nil {
+ an = analysis.New(spec.Spec())
+ }
+ ctx := &Context{
+ spec: spec,
+ analyzer: an,
+ router: routes,
+ debugLogf: debugLogfFunc(nil),
+ }
+ ctx.api = newRoutableUntypedAPI(spec, api, ctx)
+
+ return ctx
+}
+
+// Serve serves the specified spec with the specified api registrations as a http.Handler
+func Serve(spec *loads.Document, api *untyped.API) http.Handler {
+ return ServeWithBuilder(spec, api, PassthroughBuilder)
+}
+
+// ServeWithBuilder serves the specified spec with the specified api registrations as a http.Handler that is decorated
+// by the Builder
+func ServeWithBuilder(spec *loads.Document, api *untyped.API, builder Builder) http.Handler {
+ context := NewContext(spec, api, nil)
+ return context.APIHandler(builder)
+}
+
+type contextKey int8
+
+const (
+ _ contextKey = iota
+ ctxContentType
+ ctxResponseFormat
+ ctxMatchedRoute
+ ctxBoundParams
+ ctxSecurityPrincipal
+ ctxSecurityScopes
+)
+
+// MatchedRouteFrom request context value.
+func MatchedRouteFrom(req *http.Request) *MatchedRoute {
+ mr := req.Context().Value(ctxMatchedRoute)
+ if mr == nil {
+ return nil
+ }
+ if res, ok := mr.(*MatchedRoute); ok {
+ return res
+ }
+ return nil
+}
+
+// SecurityPrincipalFrom request context value.
+func SecurityPrincipalFrom(req *http.Request) any {
+ return req.Context().Value(ctxSecurityPrincipal)
+}
+
+// SecurityScopesFrom request context value.
+func SecurityScopesFrom(req *http.Request) []string {
+ rs := req.Context().Value(ctxSecurityScopes)
+ if res, ok := rs.([]string); ok {
+ return res
+ }
+ return nil
+}
+
+type contentTypeValue struct {
+ MediaType string
+ Charset string
+}
+
+// BasePath returns the base path for this API
+func (c *Context) BasePath() string {
+ if c.spec == nil {
+ return ""
+ }
+ return c.spec.BasePath()
+}
+
+// SetLogger allows for injecting a logger to catch debug entries.
+//
+// The logger is enabled in DEBUG mode only.
+func (c *Context) SetLogger(lg logger.Logger) {
+ c.debugLogf = debugLogfFunc(lg)
+}
+
+// RequiredProduces returns the accepted content types for responses
+func (c *Context) RequiredProduces() []string {
+ return c.analyzer.RequiredProduces()
+}
+
+// BindValidRequest binds a params object to a request but only when the request is valid
+// if the request is not valid an error will be returned
+func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, binder RequestBinder) error {
+ var res []error
+ var requestContentType string
+
+ // check and validate content type, select consumer
+ if runtime.HasBody(request) {
+ ct, _, err := runtime.ContentType(request.Header)
+ if err != nil {
+ res = append(res, err)
+ } else {
+ c.debugLogf("validating content type for %q against [%s]", ct, strings.Join(route.Consumes, ", "))
+ if err := validateContentType(route.Consumes, ct); err != nil {
+ res = append(res, err)
+ }
+ if len(res) == 0 {
+ cons, ok := route.Consumers[ct]
+ if !ok {
+ res = append(res, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct))
+ } else {
+ route.Consumer = cons
+ requestContentType = ct
+ }
+ }
+ }
+ }
+
+ // check and validate the response format
+ if len(res) == 0 {
+ // if the route does not provide Produces and a default contentType could not be identified
+ // based on a body, typical for GET and DELETE requests, then default contentType to.
+ if len(route.Produces) == 0 && requestContentType == "" {
+ requestContentType = "*/*"
+ }
+
+ if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" {
+ res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces))
+ }
+ }
+
+ // now bind the request with the provided binder
+ // it's assumed the binder will also validate the request and return an error if the
+ // request is invalid
+ if binder != nil && len(res) == 0 {
+ if err := binder.BindRequest(request, route); err != nil {
+ return err
+ }
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+// ContentType gets the parsed value of a content type
+// Returns the media type, its charset and a shallow copy of the request
+// when its context doesn't contain the content type value, otherwise it returns
+// the same request
+// Returns the error that runtime.ContentType may retunrs.
+func (c *Context) ContentType(request *http.Request) (string, string, *http.Request, error) {
+ var rCtx = request.Context()
+
+ if v, ok := rCtx.Value(ctxContentType).(*contentTypeValue); ok {
+ return v.MediaType, v.Charset, request, nil
+ }
+
+ mt, cs, err := runtime.ContentType(request.Header)
+ if err != nil {
+ return "", "", nil, err
+ }
+ rCtx = stdContext.WithValue(rCtx, ctxContentType, &contentTypeValue{mt, cs})
+ return mt, cs, request.WithContext(rCtx), nil
+}
+
+// LookupRoute looks a route up and returns true when it is found
+func (c *Context) LookupRoute(request *http.Request) (*MatchedRoute, bool) {
+ if route, ok := c.router.Lookup(request.Method, request.URL.EscapedPath()); ok {
+ return route, ok
+ }
+ return nil, false
+}
+
+// RouteInfo tries to match a route for this request
+// Returns the matched route, a shallow copy of the request if its context
+// contains the matched router, otherwise the same request, and a bool to
+// indicate if it the request matches one of the routes, if it doesn't
+// then it returns false and nil for the other two return values
+func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, *http.Request, bool) {
+ var rCtx = request.Context()
+
+ if v, ok := rCtx.Value(ctxMatchedRoute).(*MatchedRoute); ok {
+ return v, request, ok
+ }
+
+ if route, ok := c.LookupRoute(request); ok {
+ rCtx = stdContext.WithValue(rCtx, ctxMatchedRoute, route)
+ return route, request.WithContext(rCtx), ok
+ }
+
+ return nil, nil, false
+}
+
+// ResponseFormat negotiates the response content type
+// Returns the response format and a shallow copy of the request if its context
+// doesn't contain the response format, otherwise the same request
+func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *http.Request) {
+ var rCtx = r.Context()
+
+ if v, ok := rCtx.Value(ctxResponseFormat).(string); ok {
+ c.debugLogf("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
+ return v, r
+ }
+
+ format := NegotiateContentType(r, offers, "")
+ if format != "" {
+ c.debugLogf("[%s %s] set response format %q in context", r.Method, r.URL.Path, format)
+ r = r.WithContext(stdContext.WithValue(rCtx, ctxResponseFormat, format))
+ }
+ c.debugLogf("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
+ return format, r
+}
+
+// AllowedMethods gets the allowed methods for the path of this request
+func (c *Context) AllowedMethods(request *http.Request) []string {
+ return c.router.OtherMethods(request.Method, request.URL.EscapedPath())
+}
+
+// ResetAuth removes the current principal from the request context
+func (c *Context) ResetAuth(request *http.Request) *http.Request {
+ rctx := request.Context()
+ rctx = stdContext.WithValue(rctx, ctxSecurityPrincipal, nil)
+ rctx = stdContext.WithValue(rctx, ctxSecurityScopes, nil)
+ return request.WithContext(rctx)
+}
+
+// Authorize authorizes the request
+// Returns the principal object and a shallow copy of the request when its
+// context doesn't contain the principal, otherwise the same request or an error
+// (the last) if one of the authenticators returns one or an Unauthenticated error
+func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (any, *http.Request, error) {
+ if route == nil || !route.HasAuth() {
+ return nil, nil, nil
+ }
+
+ var rCtx = request.Context()
+ if v := rCtx.Value(ctxSecurityPrincipal); v != nil {
+ return v, request, nil
+ }
+
+ applies, usr, err := route.Authenticators.Authenticate(request, route)
+ if !applies || err != nil || !route.Authenticators.AllowsAnonymous() && usr == nil {
+ if err != nil {
+ return nil, nil, err
+ }
+ return nil, nil, errors.Unauthenticated("invalid credentials")
+ }
+ if route.Authorizer != nil {
+ if err := route.Authorizer.Authorize(request, usr); err != nil {
+ if _, ok := err.(errors.Error); ok {
+ return nil, nil, err
+ }
+
+ return nil, nil, errors.New(http.StatusForbidden, "%v", err)
+ }
+ }
+
+ rCtx = request.Context()
+
+ rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr)
+ rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Authenticator.AllScopes())
+ return usr, request.WithContext(rCtx), nil
+}
+
+// BindAndValidate binds and validates the request
+// Returns the validation map and a shallow copy of the request when its context
+// doesn't contain the validation, otherwise it returns the same request or an
+// CompositeValidationError error
+func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute) (any, *http.Request, error) {
+ var rCtx = request.Context()
+
+ if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok {
+ c.debugLogf("got cached validation (valid: %t)", len(v.result) == 0)
+ if len(v.result) > 0 {
+ return v.bound, request, errors.CompositeValidationError(v.result...)
+ }
+ return v.bound, request, nil
+ }
+ result := validateRequest(c, request, matched)
+ rCtx = stdContext.WithValue(rCtx, ctxBoundParams, result)
+ request = request.WithContext(rCtx)
+ if len(result.result) > 0 {
+ return result.bound, request, errors.CompositeValidationError(result.result...)
+ }
+ c.debugLogf("no validation errors found")
+ return result.bound, request, nil
+}
+
+// NotFound the default not found responder for when no route has been matched yet
+func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) {
+ c.Respond(rw, r, []string{c.api.DefaultProduces()}, nil, errors.NotFound("not found"))
+}
+
+// Respond renders the response after doing some content negotiation
+func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data any) {
+ c.debugLogf("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces)
+ offers := []string{}
+ for _, mt := range produces {
+ if mt != c.api.DefaultProduces() {
+ offers = append(offers, mt)
+ }
+ }
+ // the default producer is last so more specific producers take precedence
+ offers = append(offers, c.api.DefaultProduces())
+ c.debugLogf("offers: %v", offers)
+
+ var format string
+ format, r = c.ResponseFormat(r, offers)
+ rw.Header().Set(runtime.HeaderContentType, format)
+
+ if resp, ok := data.(Responder); ok {
+ producers := route.Producers
+ // producers contains keys with normalized format, if a format has MIME type parameter such as `text/plain; charset=utf-8`
+ // then you must provide `text/plain` to get the correct producer. HOWEVER, format here is not normalized.
+ prod, ok := producers[normalizeOffer(format)]
+ if !ok {
+ prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
+ pr, ok := prods[c.api.DefaultProduces()]
+ if !ok {
+ panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format)))
+ }
+ prod = pr
+ }
+ resp.WriteResponse(rw, prod)
+ return
+ }
+
+ if err, ok := data.(error); ok {
+ if format == "" {
+ rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime)
+ }
+
+ if realm := security.FailedBasicAuth(r); realm != "" {
+ rw.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=%q", realm))
+ }
+
+ if route == nil || route.Operation == nil {
+ c.api.ServeErrorFor("")(rw, r, err)
+ return
+ }
+ c.api.ServeErrorFor(route.Operation.ID)(rw, r, err)
+ return
+ }
+
+ if route == nil || route.Operation == nil {
+ rw.WriteHeader(http.StatusOK)
+ if r.Method == http.MethodHead {
+ return
+ }
+ producers := c.api.ProducersFor(normalizeOffers(offers))
+ prod, ok := producers[format]
+ if !ok {
+ panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format)))
+ }
+ if err := prod.Produce(rw, data); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ return
+ }
+
+ if _, code, ok := route.Operation.SuccessResponse(); ok {
+ rw.WriteHeader(code)
+ if code == http.StatusNoContent || r.Method == http.MethodHead {
+ return
+ }
+
+ producers := route.Producers
+ prod, ok := producers[format]
+ if !ok {
+ if !ok {
+ prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
+ pr, ok := prods[c.api.DefaultProduces()]
+ if !ok {
+ panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format)))
+ }
+ prod = pr
+ }
+ }
+ if err := prod.Produce(rw, data); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ return
+ }
+
+ c.api.ServeErrorFor(route.Operation.ID)(rw, r, fmt.Errorf("%d: %s", http.StatusInternalServerError, "can't produce response"))
+}
+
+// APIHandlerSwaggerUI returns a handler to serve the API.
+//
+// This handler includes a swagger spec, router and the contract defined in the swagger spec.
+//
+// A spec UI (SwaggerUI) is served at {API base path}/docs and the spec document at /swagger.json
+// (these can be modified with uiOptions).
+func (c *Context) APIHandlerSwaggerUI(builder Builder, opts ...UIOption) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
+ }
+
+ specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
+ var swaggerUIOpts SwaggerUIOpts
+ fromCommonToAnyOptions(uiOpts, &swaggerUIOpts)
+
+ return Spec(specPath, c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)), specOpts...)
+}
+
+// APIHandlerRapiDoc returns a handler to serve the API.
+//
+// This handler includes a swagger spec, router and the contract defined in the swagger spec.
+//
+// A spec UI (RapiDoc) is served at {API base path}/docs and the spec document at /swagger.json
+// (these can be modified with uiOptions).
+func (c *Context) APIHandlerRapiDoc(builder Builder, opts ...UIOption) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
+ }
+
+ specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
+ var rapidocUIOpts RapiDocOpts
+ fromCommonToAnyOptions(uiOpts, &rapidocUIOpts)
+
+ return Spec(specPath, c.spec.Raw(), RapiDoc(rapidocUIOpts, c.RoutesHandler(b)), specOpts...)
+}
+
+// APIHandler returns a handler to serve the API.
+//
+// This handler includes a swagger spec, router and the contract defined in the swagger spec.
+//
+// A spec UI (Redoc) is served at {API base path}/docs and the spec document at /swagger.json
+// (these can be modified with uiOptions).
+func (c *Context) APIHandler(builder Builder, opts ...UIOption) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
+ }
+
+ specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
+ var redocOpts RedocOpts
+ fromCommonToAnyOptions(uiOpts, &redocOpts)
+
+ return Spec(specPath, c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)), specOpts...)
+}
+
+// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
+func (c *Context) RoutesHandler(builder Builder) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
+ }
+ return NewRouter(c, b(NewOperationExecutor(c)))
+}
+
+func (c Context) uiOptionsForHandler(opts []UIOption) (string, uiOptions, []SpecOption) {
+ var title string
+ sp := c.spec.Spec()
+ if sp != nil && sp.Info != nil && sp.Info.Title != "" {
+ title = sp.Info.Title
+ }
+
+ // default options (may be overridden)
+ optsForContext := []UIOption{
+ WithUIBasePath(c.BasePath()),
+ WithUITitle(title),
+ }
+ optsForContext = append(optsForContext, opts...)
+ uiOpts := uiOptionsWithDefaults(optsForContext)
+
+ // If spec URL is provided, there is a non-default path to serve the spec.
+ // This makes sure that the UI middleware is aligned with the Spec middleware.
+ u, _ := url.Parse(uiOpts.SpecURL)
+ var specPath string
+ if u != nil {
+ specPath = u.Path
+ }
+
+ pth, doc := path.Split(specPath)
+ if pth == "." {
+ pth = ""
+ }
+
+ return pth, uiOpts, []SpecOption{WithSpecDocument(doc)}
+}
+
+func cantFindProducer(format string) string {
+ return "can't find a producer for " + format
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE b/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE
new file mode 100644
index 000000000000..e65039ad84ca
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Naoya Inada
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/README.md b/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
new file mode 100644
index 000000000000..30109e17d5ed
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
@@ -0,0 +1,180 @@
+# Denco [](https://travis-ci.org/naoina/denco)
+
+The fast and flexible HTTP request router for [Go](http://golang.org).
+
+Denco is based on Double-Array implementation of [Kocha-urlrouter](https://github.com/naoina/kocha-urlrouter).
+However, Denco is optimized and some features added.
+
+## Features
+
+* Fast (See [go-http-routing-benchmark](https://github.com/naoina/go-http-routing-benchmark))
+* [URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`)
+* Small (but enough) URL router API
+* HTTP request multiplexer like `http.ServeMux`
+
+## Installation
+
+ go get -u github.com/go-openapi/runtime/middleware/denco
+
+## Using as HTTP request multiplexer
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware/denco"
+)
+
+func Index(w http.ResponseWriter, r *http.Request, params denco.Params) {
+ fmt.Fprintf(w, "Welcome to Denco!\n")
+}
+
+func User(w http.ResponseWriter, r *http.Request, params denco.Params) {
+ fmt.Fprintf(w, "Hello %s!\n", params.Get("name"))
+}
+
+func main() {
+ mux := denco.NewMux()
+ handler, err := mux.Build([]denco.Handler{
+ mux.GET("/", Index),
+ mux.GET("/user/:name", User),
+ mux.POST("/user/:name", User),
+ })
+ if err != nil {
+ panic(err)
+ }
+ log.Fatal(http.ListenAndServe(":8080", handler))
+}
+```
+
+## Using as URL router
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/go-openapi/runtime/middleware/denco"
+)
+
+type route struct {
+ name string
+}
+
+func main() {
+ router := denco.New()
+ router.Build([]denco.Record{
+ {"/", &route{"root"}},
+ {"/user/:id", &route{"user"}},
+ {"/user/:name/:id", &route{"username"}},
+ {"/static/*filepath", &route{"static"}},
+ })
+
+ data, params, found := router.Lookup("/")
+ // print `&main.route{name:"root"}, denco.Params(nil), true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+
+ data, params, found = router.Lookup("/user/hoge")
+ // print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+
+ data, params, found = router.Lookup("/user/hoge/7")
+ // print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+
+ data, params, found = router.Lookup("/static/path/to/file")
+ // print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+}
+```
+
+See [Godoc](http://godoc.org/github.com/go-openapi/runtime/middleware/denco) for more details.
+
+## Getting the value of path parameter
+
+You can get the value of path parameter by 2 ways.
+
+1. Using [`denco.Params.Get`](http://godoc.org/github.com/go-openapi/runtime/middleware/denco#Params.Get) method
+2. Find by loop
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/go-openapi/runtime/middleware/denco"
+)
+
+func main() {
+ router := denco.New()
+ if err := router.Build([]denco.Record{
+ {"/user/:name/:id", "route1"},
+ }); err != nil {
+ panic(err)
+ }
+
+ // 1. Using denco.Params.Get method.
+ _, params, _ := router.Lookup("/user/alice/1")
+ name := params.Get("name")
+ if name != "" {
+ fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
+ }
+
+ // 2. Find by loop.
+ for _, param := range params {
+ if param.Name == "name" {
+ fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
+ }
+ }
+}
+```
+
+## URL patterns
+
+Denco's route matching strategy is "most nearly matching".
+
+When routes `/:name` and `/alice` have been built, URI `/alice` matches the route `/alice`, not `/:name`.
+Because URI `/alice` is more match with the route `/alice` than `/:name`.
+
+For more example, when routes below have been built:
+
+```
+/user/alice
+/user/:name
+/user/:name/:id
+/user/alice/:id
+/user/:id/bob
+```
+
+Routes matching are:
+
+```
+/user/alice => "/user/alice" (no match with "/user/:name")
+/user/bob => "/user/:name"
+/user/naoina/1 => "/user/:name/1"
+/user/alice/1 => "/user/alice/:id" (no match with "/user/:name/:id")
+/user/1/bob => "/user/:id/bob" (no match with "/user/:name/:id")
+/user/alice/bob => "/user/alice/:id" (no match with "/user/:name/:id" and "/user/:id/bob")
+```
+
+## Limitation
+
+Denco has some limitations below.
+
+* Number of param records (such as `/:name`) must be less than 2^22
+* Number of elements of internal slice must be less than 2^22
+
+## Benchmarks
+
+ cd $GOPATH/github.com/go-openapi/runtime/middleware/denco
+ go test -bench . -benchmem
+
+## License
+
+Denco is licensed under the MIT License.
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
new file mode 100644
index 000000000000..b371a2cf84ea
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
@@ -0,0 +1,479 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package denco provides fast URL router.
+package denco
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+const (
+ // ParamCharacter is a special character for path parameter.
+ ParamCharacter = ':'
+
+ // WildcardCharacter is a special character for wildcard path parameter.
+ WildcardCharacter = '*'
+
+ // TerminationCharacter is a special character for end of path.
+ TerminationCharacter = '#'
+
+ // SeparatorCharacter separates path segments.
+ SeparatorCharacter = '/'
+
+ // PathParamCharacter indicates a RESTCONF path param
+ PathParamCharacter = '='
+
+ // MaxSize is max size of records and internal slice.
+ MaxSize = (1 << 22) - 1 //nolint:mnd
+)
+
+// Router represents a URL router.
+type Router struct {
+ param *doubleArray
+ // SizeHint expects the maximum number of path parameters in records to Build.
+ // SizeHint will be used to determine the capacity of the memory to allocate.
+ // By default, SizeHint will be determined from given records to Build.
+ SizeHint int
+
+ static map[string]any
+}
+
+// New returns a new Router.
+func New() *Router {
+ return &Router{
+ SizeHint: -1,
+ static: make(map[string]any),
+ param: newDoubleArray(),
+ }
+}
+
+// Lookup returns data and path parameters that associated with path.
+// params is a slice of the Param that arranged in the order in which parameters appeared.
+// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
+func (rt *Router) Lookup(path string) (data any, params Params, found bool) {
+ if data, found = rt.static[path]; found {
+ return data, nil, true
+ }
+ if len(rt.param.node) == 1 {
+ return nil, nil, false
+ }
+ nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1)
+ if !found {
+ return nil, nil, false
+ }
+ for i := range params {
+ params[i].Name = nd.paramNames[i]
+ }
+ return nd.data, params, true
+}
+
+// Build builds URL router from records.
+func (rt *Router) Build(records []Record) error {
+ statics, params := makeRecords(records)
+ if len(params) > MaxSize {
+ return errors.New("denco: too many records")
+ }
+ if rt.SizeHint < 0 {
+ rt.SizeHint = 0
+ for _, p := range params {
+ size := 0
+ for _, k := range p.Key {
+ if k == ParamCharacter || k == WildcardCharacter {
+ size++
+ }
+ }
+ if size > rt.SizeHint {
+ rt.SizeHint = size
+ }
+ }
+ }
+ for _, r := range statics {
+ rt.static[r.Key] = r.Value
+ }
+ if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Param represents name and value of path parameter.
+type Param struct {
+ Name string
+ Value string
+}
+
+// Params represents the name and value of path parameters.
+type Params []Param
+
+// Get gets the first value associated with the given name.
+// If there are no values associated with the key, Get returns "".
+func (ps Params) Get(name string) string {
+ for _, p := range ps {
+ if p.Name == name {
+ return p.Value
+ }
+ }
+ return ""
+}
+
+type doubleArray struct {
+ bc []baseCheck
+ node []*node
+}
+
+func newDoubleArray() *doubleArray {
+ return &doubleArray{
+ bc: []baseCheck{0},
+ node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node.
+ }
+}
+
+// baseCheck contains BASE, CHECK and Extra flags.
+// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
+//
+// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
+//
+// |----------------------|--|--------|
+// 32 10 8 0
+type baseCheck uint32
+
+const (
+ flagsBits = 10
+ checkBits = 8
+)
+
+func (bc baseCheck) Base() int {
+ return int(bc >> flagsBits)
+}
+
+func (bc *baseCheck) SetBase(base int) {
+ *bc |= baseCheck(base) << flagsBits //nolint:gosec // integer conversion is ok
+}
+
+func (bc baseCheck) Check() byte {
+ return byte(bc)
+}
+
+func (bc *baseCheck) SetCheck(check byte) {
+ *bc |= baseCheck(check)
+}
+
+func (bc baseCheck) IsEmpty() bool {
+ return bc&0xfffffcff == 0
+}
+
+func (bc baseCheck) IsSingleParam() bool {
+ return bc¶mTypeSingle == paramTypeSingle
+}
+
+func (bc baseCheck) IsWildcardParam() bool {
+ return bc¶mTypeWildcard == paramTypeWildcard
+}
+
+func (bc baseCheck) IsAnyParam() bool {
+ return bc¶mTypeAny != 0
+}
+
+func (bc *baseCheck) SetSingleParam() {
+ *bc |= (1 << checkBits)
+}
+
+func (bc *baseCheck) SetWildcardParam() {
+ *bc |= (1 << (checkBits + 1))
+}
+
+const (
+ paramTypeSingle = 0x0100
+ paramTypeWildcard = 0x0200
+ paramTypeAny = 0x0300
+
+ indexOffset = 32
+ indexMask = uint64(0xffffffff)
+)
+
+func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) {
+ indices := make([]uint64, 0, 1)
+ for i := range len(path) {
+ if da.bc[idx].IsAnyParam() {
+ indices = append(indices, (uint64(i)<= len(da.bc) || da.bc[idx].Check() != c {
+ goto BACKTRACKING
+ }
+ }
+ if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
+ return da.node[da.bc[next].Base()], params, true
+ }
+
+BACKTRACKING:
+ for j := len(indices) - 1; j >= 0; j-- {
+ i, idx := int(indices[j]>>indexOffset), int(indices[j]&indexMask) //nolint:gosec // integer conversion is okay
+ if da.bc[idx].IsSingleParam() {
+ nextIdx := nextIndex(da.bc[idx].Base(), ParamCharacter)
+ if nextIdx >= len(da.bc) {
+ break
+ }
+
+ next := NextSeparator(path, i)
+ nextParams := params
+ nextParams = append(nextParams, Param{Value: path[i:next]})
+ if nd, nextNextParams, found := da.lookup(path[next:], nextParams, nextIdx); found {
+ return nd, nextNextParams, true
+ }
+ }
+
+ if da.bc[idx].IsWildcardParam() {
+ nextIdx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
+ nextParams := params
+ nextParams = append(nextParams, Param{Value: path[i:]})
+ return da.node[da.bc[nextIdx].Base()], nextParams, true
+ }
+ }
+ return nil, nil, false
+}
+
+// build builds double-array from records.
+func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error {
+ sort.Stable(recordSlice(srcs))
+ base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase)
+ if err != nil {
+ return err
+ }
+ if leaf != nil {
+ nd, err := makeNode(leaf)
+ if err != nil {
+ return err
+ }
+ da.bc[idx].SetBase(len(da.node))
+ da.node = append(da.node, nd)
+ }
+ for _, sib := range siblings {
+ da.setCheck(nextIndex(base, sib.c), sib.c)
+ }
+ for _, sib := range siblings {
+ records := srcs[sib.start:sib.end]
+ switch sib.c {
+ case ParamCharacter:
+ for _, r := range records {
+ next := NextSeparator(r.Key, depth+1)
+ name := r.Key[depth+1 : next]
+ r.paramNames = append(r.paramNames, name)
+ r.Key = r.Key[next:]
+ }
+ da.bc[idx].SetSingleParam()
+ if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
+ return err
+ }
+ case WildcardCharacter:
+ r := records[0]
+ name := r.Key[depth+1 : len(r.Key)-1]
+ r.paramNames = append(r.paramNames, name)
+ r.Key = ""
+ da.bc[idx].SetWildcardParam()
+ if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
+ return err
+ }
+ default:
+ if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// setBase sets BASE.
+func (da *doubleArray) setBase(i, base int) {
+ da.bc[i].SetBase(base)
+}
+
+// setCheck sets CHECK.
+func (da *doubleArray) setCheck(i int, check byte) {
+ da.bc[i].SetCheck(check)
+}
+
+// findEmptyIndex returns an index of unused BASE/CHECK node.
+func (da *doubleArray) findEmptyIndex(start int) int {
+ i := start
+ for ; i < len(da.bc); i++ {
+ if da.bc[i].IsEmpty() {
+ break
+ }
+ }
+ return i
+}
+
+// findBase returns good BASE.
+func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) {
+ for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) {
+ base = nextIndex(idx, firstChar)
+ if _, used := usedBase[base]; used {
+ continue
+ }
+ i := 0
+ for ; i < len(siblings); i++ {
+ next := nextIndex(base, siblings[i].c)
+ if len(da.bc) <= next {
+ da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...)
+ }
+ if !da.bc[next].IsEmpty() {
+ break
+ }
+ }
+ if i == len(siblings) {
+ break
+ }
+ }
+ usedBase[base] = struct{}{}
+ return base
+}
+
+func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) {
+ siblings, leaf, err = makeSiblings(records, depth)
+ if err != nil {
+ return -1, nil, nil, err
+ }
+ if len(siblings) < 1 {
+ return -1, nil, leaf, nil
+ }
+ base = da.findBase(siblings, idx, usedBase)
+ if base > MaxSize {
+ return -1, nil, nil, errors.New("denco: too many elements of internal slice")
+ }
+ da.setBase(idx, base)
+ return base, siblings, leaf, err
+}
+
+// node represents a node of Double-Array.
+type node struct {
+ data any
+
+ // Names of path parameters.
+ paramNames []string
+}
+
+// makeNode returns a new node from record.
+func makeNode(r *record) (*node, error) {
+ dups := make(map[string]bool)
+ for _, name := range r.paramNames {
+ if dups[name] {
+ return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key)
+ }
+ dups[name] = true
+ }
+ return &node{data: r.Value, paramNames: r.paramNames}, nil
+}
+
+// sibling represents an intermediate data of build for Double-Array.
+type sibling struct {
+ // An index of start of duplicated characters.
+ start int
+
+ // An index of end of duplicated characters.
+ end int
+
+ // A character of sibling.
+ c byte
+}
+
+// nextIndex returns a next index of array of BASE/CHECK.
+func nextIndex(base int, c byte) int {
+ return base ^ int(c)
+}
+
+// makeSiblings returns slice of sibling.
+func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) {
+ var (
+ pc byte
+ n int
+ )
+ for i, r := range records {
+ if len(r.Key) <= depth {
+ leaf = r
+ continue
+ }
+ c := r.Key[depth]
+ switch {
+ case pc < c:
+ sib = append(sib, sibling{start: i, c: c})
+ case pc == c:
+ continue
+ default:
+ return nil, nil, errors.New("denco: BUG: routing table hasn't been sorted")
+ }
+ if n > 0 {
+ sib[n-1].end = i
+ }
+ pc = c
+ n++
+ }
+ if n == 0 {
+ return nil, leaf, nil
+ }
+ sib[n-1].end = len(records)
+ return sib, leaf, nil
+}
+
+// Record represents a record data for router construction.
+type Record struct {
+ // Key for router construction.
+ Key string
+
+ // Result value for Key.
+ Value any
+}
+
+// NewRecord returns a new Record.
+func NewRecord(key string, value any) Record {
+ return Record{
+ Key: key,
+ Value: value,
+ }
+}
+
+// record represents a record that use to build the Double-Array.
+type record struct {
+ Record
+
+ paramNames []string
+}
+
+// makeRecords returns the records that use to build Double-Arrays.
+func makeRecords(srcs []Record) (statics, params []*record) {
+ termChar := string(TerminationCharacter)
+ paramPrefix := string(SeparatorCharacter) + string(ParamCharacter)
+ wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter)
+ restconfPrefix := string(PathParamCharacter) + string(ParamCharacter)
+ for _, r := range srcs {
+ if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) || strings.Contains(r.Key, restconfPrefix) {
+ r.Key += termChar
+ params = append(params, &record{Record: r})
+ } else {
+ statics = append(statics, &record{Record: r})
+ }
+ }
+ return statics, params
+}
+
+// recordSlice represents a slice of Record for sort and implements the sort.Interface.
+type recordSlice []*record
+
+// Len implements the sort.Interface.Len.
+func (rs recordSlice) Len() int {
+ return len(rs)
+}
+
+// Less implements the sort.Interface.Less.
+func (rs recordSlice) Less(i, j int) bool {
+ return rs[i].Key < rs[j].Key
+}
+
+// Swap implements the sort.Interface.Swap.
+func (rs recordSlice) Swap(i, j int) {
+ rs[i], rs[j] = rs[j], rs[i]
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/server.go b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go
new file mode 100644
index 000000000000..8f04d93dba98
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go
@@ -0,0 +1,109 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package denco
+
+import (
+ "net/http"
+)
+
+// Mux represents a multiplexer for HTTP request.
+type Mux struct{}
+
+// NewMux returns a new Mux.
+func NewMux() *Mux {
+ return &Mux{}
+}
+
+// GET is shorthand of Mux.Handler("GET", path, handler).
+func (m *Mux) GET(path string, handler HandlerFunc) Handler {
+ return m.Handler("GET", path, handler)
+}
+
+// POST is shorthand of Mux.Handler("POST", path, handler).
+func (m *Mux) POST(path string, handler HandlerFunc) Handler {
+ return m.Handler("POST", path, handler)
+}
+
+// PUT is shorthand of Mux.Handler("PUT", path, handler).
+func (m *Mux) PUT(path string, handler HandlerFunc) Handler {
+ return m.Handler("PUT", path, handler)
+}
+
+// HEAD is shorthand of Mux.Handler("HEAD", path, handler).
+func (m *Mux) HEAD(path string, handler HandlerFunc) Handler {
+ return m.Handler("HEAD", path, handler)
+}
+
+// Handler returns a handler for HTTP method.
+func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler {
+ return Handler{
+ Method: method,
+ Path: path,
+ Func: handler,
+ }
+}
+
+// Build builds a http.Handler.
+func (m *Mux) Build(handlers []Handler) (http.Handler, error) {
+ recordMap := make(map[string][]Record)
+ for _, h := range handlers {
+ recordMap[h.Method] = append(recordMap[h.Method], NewRecord(h.Path, h.Func))
+ }
+ mux := newServeMux()
+ for m, records := range recordMap {
+ router := New()
+ if err := router.Build(records); err != nil {
+ return nil, err
+ }
+ mux.routers[m] = router
+ }
+ return mux, nil
+}
+
+// Handler represents a handler of HTTP request.
+type Handler struct {
+ // Method is an HTTP method.
+ Method string
+
+ // Path is a routing path for handler.
+ Path string
+
+ // Func is a function of handler of HTTP request.
+ Func HandlerFunc
+}
+
+// The HandlerFunc type is aliased to type of handler function.
+type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params)
+
+type serveMux struct {
+ routers map[string]*Router
+}
+
+func newServeMux() *serveMux {
+ return &serveMux{
+ routers: make(map[string]*Router),
+ }
+}
+
+// ServeHTTP implements http.Handler interface.
+func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ handler, params := mux.handler(r.Method, r.URL.Path)
+ handler(w, r, params)
+}
+
+func (mux *serveMux) handler(method, path string) (HandlerFunc, []Param) {
+ if router, found := mux.routers[method]; found {
+ if handler, params, found := router.Lookup(path); found {
+ return handler.(HandlerFunc), params
+ }
+ }
+ return NotFound, nil
+}
+
+// NotFound replies to the request with an HTTP 404 not found error.
+// NotFound is called when unknown HTTP method or a handler not found.
+// If you want to use the your own NotFound handler, please overwrite this variable.
+var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) {
+ http.NotFound(w, r)
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/util.go b/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
new file mode 100644
index 000000000000..f002bc4693f8
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package denco
+
+// NextSeparator returns an index of next separator in path.
+func NextSeparator(path string, start int) int {
+ for start < len(path) {
+ if c := path[start]; c == '/' || c == TerminationCharacter {
+ break
+ }
+ start++
+ }
+ return start
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/doc.go b/vendor/github.com/go-openapi/runtime/middleware/doc.go
new file mode 100644
index 000000000000..04b83223638b
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/doc.go
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+Package middleware provides the library with helper functions for serving swagger APIs.
+
+Pseudo middleware handler
+
+ import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ )
+
+ func newCompleteMiddleware(ctx *Context) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ // use context to lookup routes
+ if matched, ok := ctx.RouteInfo(r); ok {
+
+ if matched.NeedsAuth() {
+ if _, err := ctx.Authorize(r, matched); err != nil {
+ ctx.Respond(rw, r, matched.Produces, matched, err)
+ return
+ }
+ }
+
+ bound, validation := ctx.BindAndValidate(r, matched)
+ if validation != nil {
+ ctx.Respond(rw, r, matched.Produces, matched, validation)
+ return
+ }
+
+ result, err := matched.Handler.Handle(bound)
+ if err != nil {
+ ctx.Respond(rw, r, matched.Produces, matched, err)
+ return
+ }
+
+ ctx.Respond(rw, r, matched.Produces, matched, result)
+ return
+ }
+
+ // Not found, check if it exists in the other methods first
+ if others := ctx.AllowedMethods(r); len(others) > 0 {
+ ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
+ return
+ }
+ ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
+ })
+ }
+*/
+package middleware
diff --git a/vendor/github.com/go-openapi/runtime/middleware/header/header.go b/vendor/github.com/go-openapi/runtime/middleware/header/header.go
new file mode 100644
index 000000000000..6ce870d89364
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/header/header.go
@@ -0,0 +1,339 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Copyright 2013 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// this file was taken from the github.com/golang/gddo repository
+
+// Package header provides functions for parsing HTTP headers.
+package header
+
+import (
+ "maps"
+ "net/http"
+ "strings"
+ "time"
+)
+
+// Octet types from RFC 2616.
+var octetTypes [256]octetType
+
+type octetType byte
+
+const (
+ isToken octetType = 1 << iota
+ isSpace
+)
+
+const (
+ asciiMaxControlChar = 31
+ asciiMaxChar = 127
+)
+
+func init() {
+ // OCTET =
+ // CHAR =
+ // CTL =
+ // CR =
+ // LF =
+ // SP =
+ // HT =
+ // <"> =
+ // CRLF = CR LF
+ // LWS = [CRLF] 1*( SP | HT )
+ // TEXT =
+ // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
+ // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
+ // token = 1*
+ // qdtext = >
+
+ for c := range 256 {
+ var t octetType
+ isCtl := c <= asciiMaxControlChar || c == asciiMaxChar
+ isChar := 0 <= c && c <= asciiMaxChar
+ isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
+ if strings.ContainsRune(" \t\r\n", rune(c)) {
+ t |= isSpace
+ }
+ if isChar && !isCtl && !isSeparator {
+ t |= isToken
+ }
+ octetTypes[c] = t
+ }
+}
+
+// Copy returns a shallow copy of the header.
+func Copy(header http.Header) http.Header {
+ h := make(http.Header)
+ maps.Copy(h, header)
+ return h
+}
+
+var timeLayouts = []string{"Mon, 02 Jan 2006 15:04:05 GMT", time.RFC850, time.ANSIC}
+
+// ParseTime parses the header as time. The zero value is returned if the
+// header is not present or there is an error parsing the
+// header.
+func ParseTime(header http.Header, key string) time.Time {
+ if s := header.Get(key); s != "" {
+ for _, layout := range timeLayouts {
+ if t, err := time.Parse(layout, s); err == nil {
+ return t.UTC()
+ }
+ }
+ }
+ return time.Time{}
+}
+
+// ParseList parses a comma separated list of values. Commas are ignored in
+// quoted strings. Quoted values are not unescaped or unquoted. Whitespace is
+// trimmed.
+func ParseList(header http.Header, key string) []string {
+ var result []string
+ for _, s := range header[http.CanonicalHeaderKey(key)] {
+ begin := 0
+ end := 0
+ escape := false
+ quote := false
+ for i := range len(s) {
+ b := s[i]
+ switch {
+ case escape:
+ escape = false
+ end = i + 1
+ case quote:
+ switch b {
+ case '\\':
+ escape = true
+ case '"':
+ quote = false
+ }
+ end = i + 1
+ case b == '"':
+ quote = true
+ end = i + 1
+ case octetTypes[b]&isSpace != 0:
+ if begin == end {
+ begin = i + 1
+ end = begin
+ }
+ case b == ',':
+ if begin < end {
+ result = append(result, s[begin:end])
+ }
+ begin = i + 1
+ end = begin
+ default:
+ end = i + 1
+ }
+ }
+ if begin < end {
+ result = append(result, s[begin:end])
+ }
+ }
+ return result
+}
+
+// ParseValueAndParams parses a comma separated list of values with optional
+// semicolon separated name-value pairs. Content-Type and Content-Disposition
+// headers are in this format.
+func ParseValueAndParams(header http.Header, key string) (string, map[string]string) {
+ return parseValueAndParams(header.Get(key))
+}
+
+func parseValueAndParams(s string) (value string, params map[string]string) {
+ params = make(map[string]string)
+ value, s = expectTokenSlash(s)
+ if value == "" {
+ return
+ }
+ value = strings.ToLower(value)
+ s = skipSpace(s)
+ for strings.HasPrefix(s, ";") {
+ var pkey string
+ pkey, s = expectToken(skipSpace(s[1:]))
+ if pkey == "" {
+ return
+ }
+ if !strings.HasPrefix(s, "=") {
+ return
+ }
+ var pvalue string
+ pvalue, s = expectTokenOrQuoted(s[1:])
+ if pvalue == "" {
+ return
+ }
+ pkey = strings.ToLower(pkey)
+ params[pkey] = pvalue
+ s = skipSpace(s)
+ }
+ return
+}
+
+// AcceptSpec ...
+type AcceptSpec struct {
+ Value string
+ Q float64
+}
+
+// ParseAccept2 ...
+func ParseAccept2(header http.Header, key string) (specs []AcceptSpec) {
+ for _, en := range ParseList(header, key) {
+ v, p := parseValueAndParams(en)
+ var spec AcceptSpec
+ spec.Value = v
+ spec.Q = 1.0
+ if p != nil {
+ if q, ok := p["q"]; ok {
+ spec.Q, _ = expectQuality(q)
+ }
+ }
+ if spec.Q < 0.0 {
+ continue
+ }
+ specs = append(specs, spec)
+ }
+
+ return
+}
+
+// ParseAccept parses Accept* headers.
+func ParseAccept(header http.Header, key string) []AcceptSpec {
+ var specs []AcceptSpec
+loop:
+ for _, s := range header[key] {
+ for {
+ var spec AcceptSpec
+ spec.Value, s = expectTokenSlash(s)
+ if spec.Value == "" {
+ continue loop
+ }
+ spec.Q = 1.0
+ s = skipSpace(s)
+ if strings.HasPrefix(s, ";") {
+ s = skipSpace(s[1:])
+ for !strings.HasPrefix(s, "q=") && s != "" && !strings.HasPrefix(s, ",") {
+ s = skipSpace(s[1:])
+ }
+ if strings.HasPrefix(s, "q=") {
+ spec.Q, s = expectQuality(s[2:])
+ if spec.Q < 0.0 {
+ continue loop
+ }
+ }
+ }
+
+ specs = append(specs, spec)
+ s = skipSpace(s)
+ if !strings.HasPrefix(s, ",") {
+ continue loop
+ }
+ s = skipSpace(s[1:])
+ }
+ }
+
+ return specs
+}
+
+func skipSpace(s string) (rest string) {
+ i := 0
+ for ; i < len(s); i++ {
+ if octetTypes[s[i]]&isSpace == 0 {
+ break
+ }
+ }
+ return s[i:]
+}
+
+func expectToken(s string) (token, rest string) {
+ i := 0
+ for ; i < len(s); i++ {
+ if octetTypes[s[i]]&isToken == 0 {
+ break
+ }
+ }
+ return s[:i], s[i:]
+}
+
+func expectTokenSlash(s string) (token, rest string) {
+ i := 0
+ for ; i < len(s); i++ {
+ b := s[i]
+ if (octetTypes[b]&isToken == 0) && b != '/' {
+ break
+ }
+ }
+ return s[:i], s[i:]
+}
+
+func expectQuality(s string) (q float64, rest string) {
+ switch {
+ case len(s) == 0:
+ return -1, ""
+ case s[0] == '0':
+ // q is already 0
+ s = s[1:]
+ case s[0] == '1':
+ s = s[1:]
+ q = 1
+ case s[0] == '.':
+ // q is already 0
+ default:
+ return -1, ""
+ }
+ if !strings.HasPrefix(s, ".") {
+ return q, s
+ }
+ s = s[1:]
+ i := 0
+ n := 0
+ d := 1
+ for ; i < len(s); i++ {
+ b := s[i]
+ if b < '0' || b > '9' {
+ break
+ }
+ n = n*10 + int(b) - '0'
+ d *= 10
+ }
+ return q + float64(n)/float64(d), s[i:]
+}
+
+func expectTokenOrQuoted(s string) (value string, rest string) {
+ if !strings.HasPrefix(s, "\"") {
+ return expectToken(s)
+ }
+ s = s[1:]
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '"':
+ return s[:i], s[i+1:]
+ case '\\':
+ p := make([]byte, len(s)-1)
+ j := copy(p, s[:i])
+ escape := true
+ for i++; i < len(s); i++ {
+ b := s[i]
+ switch {
+ case escape:
+ escape = false
+ p[j] = b
+ j++
+ case b == '\\':
+ escape = true
+ case b == '"':
+ return string(p[:j]), s[i+1:]
+ default:
+ p[j] = b
+ j++
+ }
+ }
+ return "", ""
+ }
+ }
+ return "", ""
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/negotiate.go b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
new file mode 100644
index 000000000000..cb0a85283c13
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
@@ -0,0 +1,102 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Copyright 2013 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// this file was taken from the github.com/golang/gddo repository
+
+package middleware
+
+import (
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/runtime/middleware/header"
+)
+
+// NegotiateContentEncoding returns the best offered content encoding for the
+// request's Accept-Encoding header. If two offers match with equal weight and
+// then the offer earlier in the list is preferred. If no offers are
+// acceptable, then "" is returned.
+func NegotiateContentEncoding(r *http.Request, offers []string) string {
+ bestOffer := "identity"
+ bestQ := -1.0
+ specs := header.ParseAccept(r.Header, "Accept-Encoding")
+ for _, offer := range offers {
+ for _, spec := range specs {
+ if spec.Q > bestQ &&
+ (spec.Value == "*" || spec.Value == offer) {
+ bestQ = spec.Q
+ bestOffer = offer
+ }
+ }
+ }
+ if bestQ == 0 {
+ bestOffer = ""
+ }
+ return bestOffer
+}
+
+// NegotiateContentType returns the best offered content type for the request's
+// Accept header. If two offers match with equal weight, then the more specific
+// offer is preferred. For example, text/* trumps */*. If two offers match
+// with equal weight and specificity, then the offer earlier in the list is
+// preferred. If no offers match, then defaultOffer is returned.
+func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string {
+ bestOffer := defaultOffer
+ bestQ := -1.0
+ bestWild := 3
+ specs := header.ParseAccept(r.Header, "Accept")
+ for _, rawOffer := range offers {
+ offer := normalizeOffer(rawOffer)
+ // No Accept header: just return the first offer.
+ if len(specs) == 0 {
+ return rawOffer
+ }
+ for _, spec := range specs {
+ switch {
+ case spec.Q == 0.0:
+ // ignore
+ case spec.Q < bestQ:
+ // better match found
+ case spec.Value == "*/*":
+ if spec.Q > bestQ || bestWild > 2 {
+ bestQ = spec.Q
+ bestWild = 2
+ bestOffer = rawOffer
+ }
+ case strings.HasSuffix(spec.Value, "/*"):
+ if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) &&
+ (spec.Q > bestQ || bestWild > 1) {
+ bestQ = spec.Q
+ bestWild = 1
+ bestOffer = rawOffer
+ }
+ default:
+ if spec.Value == offer &&
+ (spec.Q > bestQ || bestWild > 0) {
+ bestQ = spec.Q
+ bestWild = 0
+ bestOffer = rawOffer
+ }
+ }
+ }
+ }
+ return bestOffer
+}
+
+func normalizeOffers(orig []string) (norm []string) {
+ for _, o := range orig {
+ norm = append(norm, normalizeOffer(o))
+ }
+ return
+}
+
+func normalizeOffer(orig string) string {
+ const maxParts = 2
+ return strings.SplitN(orig, ";", maxParts)[0]
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
new file mode 100644
index 000000000000..2e63780c70bf
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+)
+
+type errorResp struct {
+ code int
+ response any
+ headers http.Header
+}
+
+func (e *errorResp) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+ for k, v := range e.headers {
+ for _, val := range v {
+ rw.Header().Add(k, val)
+ }
+ }
+ if e.code > 0 {
+ rw.WriteHeader(e.code)
+ } else {
+ rw.WriteHeader(http.StatusInternalServerError)
+ }
+ if err := producer.Produce(rw, e.response); err != nil {
+ Logger.Printf("failed to write error response: %v", err)
+ }
+}
+
+// NotImplemented the error response when the response is not implemented
+func NotImplemented(message string) Responder {
+ return Error(http.StatusNotImplemented, message)
+}
+
+// Error creates a generic responder for returning errors, the data will be serialized
+// with the matching producer for the request
+func Error(code int, data any, headers ...http.Header) Responder {
+ var hdr http.Header
+ for _, h := range headers {
+ for k, v := range h {
+ if hdr == nil {
+ hdr = make(http.Header)
+ }
+ hdr[k] = v
+ }
+ }
+ return &errorResp{
+ code: code,
+ response: data,
+ headers: hdr,
+ }
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/operation.go b/vendor/github.com/go-openapi/runtime/middleware/operation.go
new file mode 100644
index 000000000000..2a7ab1fadaf8
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/operation.go
@@ -0,0 +1,19 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import "net/http"
+
+// NewOperationExecutor creates a context aware middleware that handles the operations after routing
+func NewOperationExecutor(ctx *Context) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ // use context to lookup routes
+ route, rCtx, _ := ctx.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+
+ route.Handler.ServeHTTP(rw, r)
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/parameter.go b/vendor/github.com/go-openapi/runtime/middleware/parameter.go
new file mode 100644
index 000000000000..7d630d6cce62
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/parameter.go
@@ -0,0 +1,480 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "net/http"
+ "reflect"
+ "strconv"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/conv"
+ "github.com/go-openapi/swag/stringutils"
+ "github.com/go-openapi/validate"
+)
+
+const defaultMaxMemory = 32 << 20
+
+const (
+ typeString = "string"
+ typeArray = "array"
+)
+
+var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
+
+func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
+ binder := new(untypedParamBinder)
+ binder.Name = param.Name
+ binder.parameter = ¶m
+ binder.formats = formats
+ if param.In != "body" {
+ binder.validator = validate.NewParamValidator(¶m, formats)
+ } else {
+ binder.validator = validate.NewSchemaValidator(param.Schema, spec, param.Name, formats)
+ }
+
+ return binder
+}
+
+type untypedParamBinder struct {
+ parameter *spec.Parameter
+ formats strfmt.Registry
+ Name string
+ validator validate.EntityValidator
+}
+
+func (p *untypedParamBinder) Type() reflect.Type {
+ return p.typeForSchema(p.parameter.Type, p.parameter.Format, p.parameter.Items)
+}
+
+func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, target reflect.Value) error {
+ // fmt.Println("binding", p.name, "as", p.Type())
+ switch p.parameter.In {
+ case "query":
+ data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+
+ return p.bindValue(data, hasKey, target)
+
+ case "header":
+ data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+
+ case "path":
+ data, custom, hasKey, err := p.readValue(routeParams, target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+
+ case "formData":
+ var err error
+ var mt string
+
+ mt, _, e := runtime.ContentType(request.Header)
+ if e != nil {
+ // because of the interface conversion go thinks the error is not nil
+ // so we first check for nil and then set the err var if it's not nil
+ err = e
+ }
+
+ if err != nil {
+ return errors.InvalidContentType("", []string{"multipart/form-data", "application/x-www-form-urlencoded"})
+ }
+
+ if mt != "multipart/form-data" && mt != "application/x-www-form-urlencoded" {
+ return errors.InvalidContentType(mt, []string{"multipart/form-data", "application/x-www-form-urlencoded"})
+ }
+
+ if mt == "multipart/form-data" {
+ if err = request.ParseMultipartForm(defaultMaxMemory); err != nil {
+ return errors.NewParseError(p.Name, p.parameter.In, "", err)
+ }
+ }
+
+ if err = request.ParseForm(); err != nil {
+ return errors.NewParseError(p.Name, p.parameter.In, "", err)
+ }
+
+ if p.parameter.Type == "file" {
+ file, header, ffErr := request.FormFile(p.parameter.Name)
+ if ffErr != nil {
+ if p.parameter.Required {
+ return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
+ }
+
+ return nil
+ }
+
+ target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
+ return nil
+ }
+
+ if request.MultipartForm != nil {
+ data, custom, hasKey, rvErr := p.readValue(runtime.Values(request.MultipartForm.Value), target)
+ if rvErr != nil {
+ return rvErr
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+ }
+ data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+
+ case "body":
+ newValue := reflect.New(target.Type())
+ if !runtime.HasBody(request) {
+ if p.parameter.Default != nil {
+ target.Set(reflect.ValueOf(p.parameter.Default))
+ }
+
+ return nil
+ }
+ if err := consumer.Consume(request.Body, newValue.Interface()); err != nil {
+ if err == io.EOF && p.parameter.Default != nil {
+ target.Set(reflect.ValueOf(p.parameter.Default))
+ return nil
+ }
+ tpe := p.parameter.Type
+ if p.parameter.Format != "" {
+ tpe = p.parameter.Format
+ }
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, nil)
+ }
+ target.Set(reflect.Indirect(newValue))
+ return nil
+ default:
+ return fmt.Errorf("%d: invalid parameter location %q", http.StatusInternalServerError, p.parameter.In)
+ }
+}
+
+func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type {
+ switch tpe {
+ case "boolean":
+ return reflect.TypeFor[bool]()
+
+ case typeString:
+ if tt, ok := p.formats.GetType(format); ok {
+ return tt
+ }
+ return reflect.TypeFor[string]()
+
+ case "integer":
+ switch format {
+ case "int8":
+ return reflect.TypeFor[int8]()
+ case "int16":
+ return reflect.TypeFor[int16]()
+ case "int32":
+ return reflect.TypeFor[int32]()
+ case "int64":
+ return reflect.TypeFor[int64]()
+ default:
+ return reflect.TypeFor[int64]()
+ }
+
+ case "number":
+ switch format {
+ case "float":
+ return reflect.TypeFor[float32]()
+ case "double":
+ return reflect.TypeFor[float64]()
+ }
+
+ case typeArray:
+ if items == nil {
+ return nil
+ }
+ itemsType := p.typeForSchema(items.Type, items.Format, items.Items)
+ if itemsType == nil {
+ return nil
+ }
+ return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type()
+
+ case "file":
+ return reflect.TypeFor[runtime.File]()
+
+ case "object":
+ return reflect.TypeFor[map[string]any]()
+ }
+ return nil
+}
+
+func (p *untypedParamBinder) allowsMulti() bool {
+ return p.parameter.In == "query" || p.parameter.In == "formData"
+}
+
+func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
+ name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
+ if tpe == typeArray {
+ if cf == "multi" {
+ if !p.allowsMulti() {
+ return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
+ }
+ vv, hasKey, _ := values.GetOK(name)
+ return vv, false, hasKey, nil
+ }
+
+ v, hk, hv := values.GetOK(name)
+ if !hv {
+ return nil, false, hk, nil
+ }
+ d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target)
+ return d, c, hk, e
+ }
+
+ vv, hk, _ := values.GetOK(name)
+ return vv, false, hk, nil
+}
+
+func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
+ if p.parameter.Type == typeArray {
+ return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
+ }
+ var d string
+ if len(data) > 0 {
+ d = data[len(data)-1]
+ }
+ return p.setFieldValue(target, p.parameter.Default, d, hasKey)
+}
+
+func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue any, data string, hasKey bool) error { //nolint:gocyclo
+ tpe := p.parameter.Type
+ if p.parameter.Format != "" {
+ tpe = p.parameter.Format
+ }
+
+ if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil {
+ return errors.Required(p.Name, p.parameter.In, data)
+ }
+
+ ok, err := p.tryUnmarshaler(target, defaultValue, data)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if ok {
+ return nil
+ }
+
+ defVal := reflect.Zero(target.Type())
+ if defaultValue != nil {
+ defVal = reflect.ValueOf(defaultValue)
+ }
+
+ if tpe == "byte" {
+ if data == "" {
+ if target.CanSet() {
+ target.SetBytes(defVal.Bytes())
+ }
+ return nil
+ }
+
+ b, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ b, err = base64.URLEncoding.DecodeString(data)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ }
+ if target.CanSet() {
+ target.SetBytes(b)
+ }
+ return nil
+ }
+
+ switch target.Kind() { //nolint:exhaustive // we want to check only types that map from a swagger parameter
+ case reflect.Bool:
+ if data == "" {
+ if target.CanSet() {
+ target.SetBool(defVal.Bool())
+ }
+ return nil
+ }
+ b, err := conv.ConvertBool(data)
+ if err != nil {
+ return err
+ }
+ if target.CanSet() {
+ target.SetBool(b)
+ }
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if data == "" {
+ if target.CanSet() {
+ rd := defVal.Convert(reflect.TypeFor[int64]())
+ target.SetInt(rd.Int())
+ }
+ return nil
+ }
+ i, err := strconv.ParseInt(data, 10, 64)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.OverflowInt(i) {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.CanSet() {
+ target.SetInt(i)
+ }
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ if data == "" {
+ if target.CanSet() {
+ rd := defVal.Convert(reflect.TypeFor[uint64]())
+ target.SetUint(rd.Uint())
+ }
+ return nil
+ }
+ u, err := strconv.ParseUint(data, 10, 64)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.OverflowUint(u) {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.CanSet() {
+ target.SetUint(u)
+ }
+
+ case reflect.Float32, reflect.Float64:
+ if data == "" {
+ if target.CanSet() {
+ rd := defVal.Convert(reflect.TypeFor[float64]())
+ target.SetFloat(rd.Float())
+ }
+ return nil
+ }
+ f, err := strconv.ParseFloat(data, 64)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.OverflowFloat(f) {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.CanSet() {
+ target.SetFloat(f)
+ }
+
+ case reflect.String:
+ value := data
+ if value == "" {
+ value = defVal.String()
+ }
+ // validate string
+ if target.CanSet() {
+ target.SetString(value)
+ }
+
+ case reflect.Ptr:
+ if data == "" && defVal.Kind() == reflect.Ptr {
+ if target.CanSet() {
+ target.Set(defVal)
+ }
+ return nil
+ }
+ newVal := reflect.New(target.Type().Elem())
+ if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data, hasKey); err != nil {
+ return err
+ }
+ if target.CanSet() {
+ target.Set(newVal)
+ }
+
+ default:
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ return nil
+}
+
+func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue any, data string) (bool, error) {
+ if !target.CanSet() {
+ return false, nil
+ }
+ // When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more
+ if reflect.PointerTo(target.Type()).Implements(textUnmarshalType) {
+ if defaultValue != nil && len(data) == 0 {
+ target.Set(reflect.ValueOf(defaultValue))
+ return true, nil
+ }
+ value := reflect.New(target.Type())
+ if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil {
+ return true, err
+ }
+ target.Set(reflect.Indirect(value))
+ return true, nil
+ }
+ return false, nil
+}
+
+func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target reflect.Value) ([]string, bool, error) {
+ ok, err := p.tryUnmarshaler(target, p.parameter.Default, data)
+ if err != nil {
+ return nil, true, err
+ }
+ if ok {
+ return nil, true, nil
+ }
+
+ return stringutils.SplitByFormat(data, p.parameter.CollectionFormat), false, nil
+}
+
+func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue any, data []string, hasKey bool) error {
+ sz := len(data)
+ if (!hasKey || (!p.parameter.AllowEmptyValue && (sz == 0 || (sz == 1 && data[0] == "")))) && p.parameter.Required && defaultValue == nil {
+ return errors.Required(p.Name, p.parameter.In, data)
+ }
+
+ defVal := reflect.Zero(target.Type())
+ if defaultValue != nil {
+ defVal = reflect.ValueOf(defaultValue)
+ }
+
+ if !target.CanSet() {
+ return nil
+ }
+ if sz == 0 {
+ target.Set(defVal)
+ return nil
+ }
+
+ value := reflect.MakeSlice(reflect.SliceOf(target.Type().Elem()), sz, sz)
+
+ for i := range sz {
+ if err := p.setFieldValue(value.Index(i), nil, data[i], hasKey); err != nil {
+ return err
+ }
+ }
+
+ target.Set(value)
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go b/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
new file mode 100644
index 000000000000..6039a26f33ef
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
@@ -0,0 +1,83 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "net/http"
+ "path"
+)
+
+// RapiDocOpts configures the RapiDoc middlewares
+type RapiDocOpts struct {
+ // BasePath for the UI, defaults to: /
+ BasePath string
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
+ Path string
+
+ // SpecURL is the URL of the spec document.
+ //
+ // Defaults to: /swagger.json
+ SpecURL string
+
+ // Title for the documentation site, default to: API documentation
+ Title string
+
+ // Template specifies a custom template to serve the UI
+ Template string
+
+ // RapiDocURL points to the js asset that generates the rapidoc site.
+ //
+ // Defaults to https://unpkg.com/rapidoc/dist/rapidoc-min.js
+ RapiDocURL string
+}
+
+func (r *RapiDocOpts) EnsureDefaults() {
+ common := toCommonUIOptions(r)
+ common.EnsureDefaults()
+ fromCommonToAnyOptions(common, r)
+
+ // rapidoc-specifics
+ if r.RapiDocURL == "" {
+ r.RapiDocURL = rapidocLatest
+ }
+ if r.Template == "" {
+ r.Template = rapidocTemplate
+ }
+}
+
+// RapiDoc creates a middleware to serve a documentation site for a swagger spec.
+//
+// This allows for altering the spec before starting the http listener.
+func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler {
+ opts.EnsureDefaults()
+
+ pth := path.Join(opts.BasePath, opts.Path)
+ tmpl := template.Must(template.New("rapidoc").Parse(opts.Template))
+ assets := bytes.NewBuffer(nil)
+ if err := tmpl.Execute(assets, opts); err != nil {
+ panic(fmt.Errorf("cannot execute template: %w", err))
+ }
+
+ return serveUI(pth, assets.Bytes(), next)
+}
+
+const (
+ rapidocLatest = "https://unpkg.com/rapidoc/dist/rapidoc-min.js"
+ rapidocTemplate = `
+
+
+ {{ .Title }}
+
+
+
+
+
+
+
+`
+)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/redoc.go b/vendor/github.com/go-openapi/runtime/middleware/redoc.go
new file mode 100644
index 000000000000..cbaec73c438d
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/redoc.go
@@ -0,0 +1,97 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "net/http"
+ "path"
+)
+
+// RedocOpts configures the Redoc middlewares
+type RedocOpts struct {
+ // BasePath for the UI, defaults to: /
+ BasePath string
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
+ Path string
+
+ // SpecURL is the URL of the spec document.
+ //
+ // Defaults to: /swagger.json
+ SpecURL string
+
+ // Title for the documentation site, default to: API documentation
+ Title string
+
+ // Template specifies a custom template to serve the UI
+ Template string
+
+ // RedocURL points to the js that generates the redoc site.
+ //
+ // Defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
+ RedocURL string
+}
+
+// EnsureDefaults in case some options are missing
+func (r *RedocOpts) EnsureDefaults() {
+ common := toCommonUIOptions(r)
+ common.EnsureDefaults()
+ fromCommonToAnyOptions(common, r)
+
+ // redoc-specifics
+ if r.RedocURL == "" {
+ r.RedocURL = redocLatest
+ }
+ if r.Template == "" {
+ r.Template = redocTemplate
+ }
+}
+
+// Redoc creates a middleware to serve a documentation site for a swagger spec.
+//
+// This allows for altering the spec before starting the http listener.
+func Redoc(opts RedocOpts, next http.Handler) http.Handler {
+ opts.EnsureDefaults()
+
+ pth := path.Join(opts.BasePath, opts.Path)
+ tmpl := template.Must(template.New("redoc").Parse(opts.Template))
+ assets := bytes.NewBuffer(nil)
+ if err := tmpl.Execute(assets, opts); err != nil {
+ panic(fmt.Errorf("cannot execute template: %w", err))
+ }
+
+ return serveUI(pth, assets.Bytes(), next)
+}
+
+const (
+ redocLatest = "https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"
+ redocTemplate = `
+
+
+ {{ .Title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+`
+)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/request.go b/vendor/github.com/go-openapi/runtime/middleware/request.go
new file mode 100644
index 000000000000..52facfefcd22
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/request.go
@@ -0,0 +1,106 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "net/http"
+ "reflect"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/logger"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+// UntypedRequestBinder binds and validates the data from a http request
+type UntypedRequestBinder struct {
+ Spec *spec.Swagger
+ Parameters map[string]spec.Parameter
+ Formats strfmt.Registry
+ paramBinders map[string]*untypedParamBinder
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
+}
+
+// NewUntypedRequestBinder creates a new binder for reading a request.
+func NewUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *UntypedRequestBinder {
+ binders := make(map[string]*untypedParamBinder)
+ for fieldName, param := range parameters {
+ binders[fieldName] = newUntypedParamBinder(param, spec, formats)
+ }
+ return &UntypedRequestBinder{
+ Parameters: parameters,
+ paramBinders: binders,
+ Spec: spec,
+ Formats: formats,
+ debugLogf: debugLogfFunc(nil),
+ }
+}
+
+// Bind perform the databinding and validation
+func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data any) error {
+ val := reflect.Indirect(reflect.ValueOf(data))
+ isMap := val.Kind() == reflect.Map
+ var result []error
+ o.debugLogf("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
+ for fieldName, param := range o.Parameters {
+ binder := o.paramBinders[fieldName]
+ o.debugLogf("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
+ var target reflect.Value
+ if !isMap {
+ binder.Name = fieldName
+ target = val.FieldByName(fieldName)
+ }
+
+ if isMap {
+ tpe := binder.Type()
+ if tpe == nil {
+ if param.Schema.Type.Contains(typeArray) {
+ tpe = reflect.TypeFor[[]any]()
+ } else {
+ tpe = reflect.TypeFor[map[string]any]()
+ }
+ }
+ target = reflect.Indirect(reflect.New(tpe))
+ }
+
+ if !target.IsValid() {
+ result = append(result, errors.New(http.StatusInternalServerError, "parameter name %q is an unknown field", binder.Name))
+ continue
+ }
+
+ if err := binder.Bind(request, routeParams, consumer, target); err != nil {
+ result = append(result, err)
+ continue
+ }
+
+ if binder.validator != nil {
+ rr := binder.validator.Validate(target.Interface())
+ if rr != nil && rr.HasErrors() {
+ result = append(result, rr.AsError())
+ }
+ }
+
+ if isMap {
+ val.SetMapIndex(reflect.ValueOf(param.Name), target)
+ }
+ }
+
+ if len(result) > 0 {
+ return errors.CompositeValidationError(result...)
+ }
+
+ return nil
+}
+
+// SetLogger allows for injecting a logger to catch debug entries.
+//
+// The logger is enabled in DEBUG mode only.
+func (o *UntypedRequestBinder) SetLogger(lg logger.Logger) {
+ o.debugLogf = debugLogfFunc(lg)
+}
+
+func (o *UntypedRequestBinder) setDebugLogf(fn func(string, ...any)) {
+ o.debugLogf = fn
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/router.go b/vendor/github.com/go-openapi/runtime/middleware/router.go
new file mode 100644
index 000000000000..16816580da8b
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/router.go
@@ -0,0 +1,520 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ fpath "path"
+ "regexp"
+ "strings"
+
+ "github.com/go-openapi/analysis"
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/loads"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/logger"
+ "github.com/go-openapi/runtime/middleware/denco"
+ "github.com/go-openapi/runtime/security"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/stringutils"
+)
+
+// RouteParam is a object to capture route params in a framework agnostic way.
+// implementations of the muxer should use these route params to communicate with the
+// swagger framework
+type RouteParam struct {
+ Name string
+ Value string
+}
+
+// RouteParams the collection of route params
+type RouteParams []RouteParam
+
+// Get gets the value for the route param for the specified key
+func (r RouteParams) Get(name string) string {
+ vv, _, _ := r.GetOK(name)
+ if len(vv) > 0 {
+ return vv[len(vv)-1]
+ }
+ return ""
+}
+
+// GetOK gets the value but also returns booleans to indicate if a key or value
+// is present. This aids in validation and satisfies an interface in use there
+//
+// The returned values are: data, has key, has value
+func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
+ for _, p := range r {
+ if p.Name == name {
+ return []string{p.Value}, true, p.Value != ""
+ }
+ }
+ return nil, false, false
+}
+
+// NewRouter creates a new context-aware router middleware
+func NewRouter(ctx *Context, next http.Handler) http.Handler {
+ if ctx.router == nil {
+ ctx.router = DefaultRouter(ctx.spec, ctx.api, WithDefaultRouterLoggerFunc(ctx.debugLogf))
+ }
+
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ if _, rCtx, ok := ctx.RouteInfo(r); ok {
+ next.ServeHTTP(rw, rCtx)
+ return
+ }
+
+ // Not found, check if it exists in the other methods first
+ if others := ctx.AllowedMethods(r); len(others) > 0 {
+ ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
+ return
+ }
+
+ ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.EscapedPath()))
+ })
+}
+
+// RoutableAPI represents an interface for things that can serve
+// as a provider of implementations for the swagger router
+type RoutableAPI interface {
+ HandlerFor(string, string) (http.Handler, bool)
+ ServeErrorFor(string) func(http.ResponseWriter, *http.Request, error)
+ ConsumersFor([]string) map[string]runtime.Consumer
+ ProducersFor([]string) map[string]runtime.Producer
+ AuthenticatorsFor(map[string]spec.SecurityScheme) map[string]runtime.Authenticator
+ Authorizer() runtime.Authorizer
+ Formats() strfmt.Registry
+ DefaultProduces() string
+ DefaultConsumes() string
+}
+
+// Router represents a swagger-aware router
+type Router interface {
+ Lookup(method, path string) (*MatchedRoute, bool)
+ OtherMethods(method, path string) []string
+}
+
+type defaultRouteBuilder struct {
+ spec *loads.Document
+ analyzer *analysis.Spec
+ api RoutableAPI
+ records map[string][]denco.Record
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
+}
+
+type defaultRouter struct {
+ spec *loads.Document
+ routers map[string]*denco.Router
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
+}
+
+func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) *defaultRouteBuilder {
+ var o defaultRouterOpts
+ for _, apply := range opts {
+ apply(&o)
+ }
+ if o.debugLogf == nil {
+ o.debugLogf = debugLogfFunc(nil) // defaults to standard logger
+ }
+
+ return &defaultRouteBuilder{
+ spec: spec,
+ analyzer: analysis.New(spec.Spec()),
+ api: api,
+ records: make(map[string][]denco.Record),
+ debugLogf: o.debugLogf,
+ }
+}
+
+// DefaultRouterOpt allows to inject optional behavior to the default router.
+type DefaultRouterOpt func(*defaultRouterOpts)
+
+type defaultRouterOpts struct {
+ debugLogf func(string, ...any)
+}
+
+// WithDefaultRouterLogger sets the debug logger for the default router.
+//
+// This is enabled only in DEBUG mode.
+func WithDefaultRouterLogger(lg logger.Logger) DefaultRouterOpt {
+ return func(o *defaultRouterOpts) {
+ o.debugLogf = debugLogfFunc(lg)
+ }
+}
+
+// WithDefaultRouterLoggerFunc sets a logging debug method for the default router.
+func WithDefaultRouterLoggerFunc(fn func(string, ...any)) DefaultRouterOpt {
+ return func(o *defaultRouterOpts) {
+ o.debugLogf = fn
+ }
+}
+
+// DefaultRouter creates a default implementation of the router
+func DefaultRouter(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) Router {
+ builder := newDefaultRouteBuilder(spec, api, opts...)
+ if spec != nil {
+ for method, paths := range builder.analyzer.Operations() {
+ for path, operation := range paths {
+ fp := fpath.Join(spec.BasePath(), path)
+ builder.debugLogf("adding route %s %s %q", method, fp, operation.ID)
+ builder.AddRoute(method, fp, operation)
+ }
+ }
+ }
+ return builder.Build()
+}
+
+// RouteAuthenticator is an authenticator that can compose several authenticators together.
+// It also knows when it contains an authenticator that allows for anonymous pass through.
+// Contains a group of 1 or more authenticators that have a logical AND relationship
+type RouteAuthenticator struct {
+ Authenticator map[string]runtime.Authenticator
+ Schemes []string
+ Scopes map[string][]string
+ allScopes []string
+ commonScopes []string
+ allowAnonymous bool
+}
+
+func (ra *RouteAuthenticator) AllowsAnonymous() bool {
+ return ra.allowAnonymous
+}
+
+// AllScopes returns a list of unique scopes that is the combination
+// of all the scopes in the requirements
+func (ra *RouteAuthenticator) AllScopes() []string {
+ return ra.allScopes
+}
+
+// CommonScopes returns a list of unique scopes that are common in all the
+// scopes in the requirements
+func (ra *RouteAuthenticator) CommonScopes() []string {
+ return ra.commonScopes
+}
+
+// Authenticate Authenticator interface implementation
+func (ra *RouteAuthenticator) Authenticate(req *http.Request, route *MatchedRoute) (bool, any, error) {
+ if ra.allowAnonymous {
+ route.Authenticator = ra
+ return true, nil, nil
+ }
+ // iterate in proper order
+ var lastResult any
+ for _, scheme := range ra.Schemes {
+ if authenticator, ok := ra.Authenticator[scheme]; ok {
+ applies, princ, err := authenticator.Authenticate(&security.ScopedAuthRequest{
+ Request: req,
+ RequiredScopes: ra.Scopes[scheme],
+ })
+ if !applies {
+ return false, nil, nil
+ }
+ if err != nil {
+ route.Authenticator = ra
+ return true, nil, err
+ }
+ lastResult = princ
+ }
+ }
+ route.Authenticator = ra
+ return true, lastResult, nil
+}
+
+func stringSliceUnion(slices ...[]string) []string {
+ unique := make(map[string]struct{})
+ var result []string
+ for _, slice := range slices {
+ for _, entry := range slice {
+ if _, ok := unique[entry]; ok {
+ continue
+ }
+ unique[entry] = struct{}{}
+ result = append(result, entry)
+ }
+ }
+ return result
+}
+
+func stringSliceIntersection(slices ...[]string) []string {
+ unique := make(map[string]int)
+ var intersection []string
+
+ total := len(slices)
+ var emptyCnt int
+ for _, slice := range slices {
+ if len(slice) == 0 {
+ emptyCnt++
+ continue
+ }
+
+ for _, entry := range slice {
+ unique[entry]++
+ if unique[entry] == total-emptyCnt { // this entry appeared in all the non-empty slices
+ intersection = append(intersection, entry)
+ }
+ }
+ }
+
+ return intersection
+}
+
+// RouteAuthenticators represents a group of authenticators that represent a logical OR
+type RouteAuthenticators []RouteAuthenticator
+
+// AllowsAnonymous returns true when there is an authenticator that means optional auth
+func (ras RouteAuthenticators) AllowsAnonymous() bool {
+ for _, ra := range ras {
+ if ra.AllowsAnonymous() {
+ return true
+ }
+ }
+ return false
+}
+
+// Authenticate method implemention so this collection can be used as authenticator
+func (ras RouteAuthenticators) Authenticate(req *http.Request, route *MatchedRoute) (bool, any, error) {
+ var lastError error
+ var allowsAnon bool
+ var anonAuth RouteAuthenticator
+
+ for _, ra := range ras {
+ if ra.AllowsAnonymous() {
+ anonAuth = ra
+ allowsAnon = true
+ continue
+ }
+ applies, usr, err := ra.Authenticate(req, route)
+ if !applies || err != nil || usr == nil {
+ if err != nil {
+ lastError = err
+ }
+ continue
+ }
+ return applies, usr, nil
+ }
+
+ if allowsAnon && lastError == nil {
+ route.Authenticator = &anonAuth
+ return true, nil, lastError
+ }
+ return lastError != nil, nil, lastError
+}
+
+type routeEntry struct {
+ PathPattern string
+ BasePath string
+ Operation *spec.Operation
+ Consumes []string
+ Consumers map[string]runtime.Consumer
+ Produces []string
+ Producers map[string]runtime.Producer
+ Parameters map[string]spec.Parameter
+ Handler http.Handler
+ Formats strfmt.Registry
+ Binder *UntypedRequestBinder
+ Authenticators RouteAuthenticators
+ Authorizer runtime.Authorizer
+}
+
+// MatchedRoute represents the route that was matched in this request
+type MatchedRoute struct {
+ routeEntry
+
+ Params RouteParams
+ Consumer runtime.Consumer
+ Producer runtime.Producer
+ Authenticator *RouteAuthenticator
+}
+
+// HasAuth returns true when the route has a security requirement defined
+func (m *MatchedRoute) HasAuth() bool {
+ return len(m.Authenticators) > 0
+}
+
+// NeedsAuth returns true when the request still
+// needs to perform authentication
+func (m *MatchedRoute) NeedsAuth() bool {
+ return m.HasAuth() && m.Authenticator == nil
+}
+
+func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
+ mth := strings.ToUpper(method)
+ d.debugLogf("looking up route for %s %s", method, path)
+ if Debug {
+ if len(d.routers) == 0 {
+ d.debugLogf("there are no known routers")
+ }
+ for meth := range d.routers {
+ d.debugLogf("got a router for %s", meth)
+ }
+ }
+ if router, ok := d.routers[mth]; ok {
+ if m, rp, ok := router.Lookup(fpath.Clean(path)); ok && m != nil {
+ if entry, ok := m.(*routeEntry); ok {
+ d.debugLogf("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
+ var params RouteParams
+ for _, p := range rp {
+ v, err := url.PathUnescape(p.Value)
+ if err != nil {
+ d.debugLogf("failed to escape %q: %v", p.Value, err)
+ v = p.Value
+ }
+ // a workaround to handle fragment/composing parameters until they are supported in denco router
+ // check if this parameter is a fragment within a path segment
+ const enclosureSize = 2
+ if xpos := strings.Index(entry.PathPattern, fmt.Sprintf("{%s}", p.Name)) + len(p.Name) + enclosureSize; xpos < len(entry.PathPattern) && entry.PathPattern[xpos] != '/' {
+ // extract fragment parameters
+ ep := strings.Split(entry.PathPattern[xpos:], "/")[0]
+ pnames, pvalues := decodeCompositParams(p.Name, v, ep, nil, nil)
+ for i, pname := range pnames {
+ params = append(params, RouteParam{Name: pname, Value: pvalues[i]})
+ }
+ } else {
+ // use the parameter directly
+ params = append(params, RouteParam{Name: p.Name, Value: v})
+ }
+ }
+ return &MatchedRoute{routeEntry: *entry, Params: params}, true
+ }
+ } else {
+ d.debugLogf("couldn't find a route by path for %s %s", method, path)
+ }
+ } else {
+ d.debugLogf("couldn't find a route by method for %s %s", method, path)
+ }
+ return nil, false
+}
+
+func (d *defaultRouter) OtherMethods(method, path string) []string {
+ mn := strings.ToUpper(method)
+ var methods []string
+ for k, v := range d.routers {
+ if k != mn {
+ if _, _, ok := v.Lookup(fpath.Clean(path)); ok {
+ methods = append(methods, k)
+ continue
+ }
+ }
+ }
+ return methods
+}
+
+func (d *defaultRouter) SetLogger(lg logger.Logger) {
+ d.debugLogf = debugLogfFunc(lg)
+}
+
+// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco
+var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`)
+
+func decodeCompositParams(name string, value string, pattern string, names []string, values []string) ([]string, []string) {
+ pleft := strings.Index(pattern, "{")
+ names = append(names, name)
+ if pleft < 0 {
+ if strings.HasSuffix(value, pattern) {
+ values = append(values, value[:len(value)-len(pattern)])
+ } else {
+ values = append(values, "")
+ }
+ } else {
+ toskip := pattern[:pleft]
+ pright := strings.Index(pattern, "}")
+ vright := strings.Index(value, toskip)
+ if vright >= 0 {
+ values = append(values, value[:vright])
+ } else {
+ values = append(values, "")
+ value = ""
+ }
+ return decodeCompositParams(pattern[pleft+1:pright], value[vright+len(toskip):], pattern[pright+1:], names, values)
+ }
+ return names, values
+}
+
+func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Operation) {
+ mn := strings.ToUpper(method)
+
+ bp := fpath.Clean(d.spec.BasePath())
+ if len(bp) > 0 && bp[len(bp)-1] == '/' {
+ bp = bp[:len(bp)-1]
+ }
+
+ d.debugLogf("operation: %#v", *operation)
+ if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok {
+ consumes := d.analyzer.ConsumesFor(operation)
+ produces := d.analyzer.ProducesFor(operation)
+ parameters := d.analyzer.ParamsFor(method, strings.TrimPrefix(path, bp))
+
+ // add API defaults if not part of the spec
+ if defConsumes := d.api.DefaultConsumes(); defConsumes != "" && !stringutils.ContainsStringsCI(consumes, defConsumes) {
+ consumes = append(consumes, defConsumes)
+ }
+
+ if defProduces := d.api.DefaultProduces(); defProduces != "" && !stringutils.ContainsStringsCI(produces, defProduces) {
+ produces = append(produces, defProduces)
+ }
+
+ requestBinder := NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats())
+ requestBinder.setDebugLogf(d.debugLogf)
+ record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
+ BasePath: bp,
+ PathPattern: path,
+ Operation: operation,
+ Handler: handler,
+ Consumes: consumes,
+ Produces: produces,
+ Consumers: d.api.ConsumersFor(normalizeOffers(consumes)),
+ Producers: d.api.ProducersFor(normalizeOffers(produces)),
+ Parameters: parameters,
+ Formats: d.api.Formats(),
+ Binder: requestBinder,
+ Authenticators: d.buildAuthenticators(operation),
+ Authorizer: d.api.Authorizer(),
+ })
+ d.records[mn] = append(d.records[mn], record)
+ }
+}
+
+func (d *defaultRouteBuilder) Build() *defaultRouter {
+ routers := make(map[string]*denco.Router)
+ for method, records := range d.records {
+ router := denco.New()
+ _ = router.Build(records)
+ routers[method] = router
+ }
+ return &defaultRouter{
+ spec: d.spec,
+ routers: routers,
+ debugLogf: d.debugLogf,
+ }
+}
+
+func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) RouteAuthenticators {
+ requirements := d.analyzer.SecurityRequirementsFor(operation)
+ auths := make([]RouteAuthenticator, 0, len(requirements))
+ for _, reqs := range requirements {
+ schemes := make([]string, 0, len(reqs))
+ scopes := make(map[string][]string, len(reqs))
+ scopeSlices := make([][]string, 0, len(reqs))
+ for _, req := range reqs {
+ schemes = append(schemes, req.Name)
+ scopes[req.Name] = req.Scopes
+ scopeSlices = append(scopeSlices, req.Scopes)
+ }
+
+ definitions := d.analyzer.SecurityDefinitionsForRequirements(reqs)
+ authenticators := d.api.AuthenticatorsFor(definitions)
+ auths = append(auths, RouteAuthenticator{
+ Authenticator: authenticators,
+ Schemes: schemes,
+ Scopes: scopes,
+ allScopes: stringSliceUnion(scopeSlices...),
+ commonScopes: stringSliceIntersection(scopeSlices...),
+ allowAnonymous: len(reqs) == 1 && reqs[0].Name == "",
+ })
+ }
+ return auths
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/security.go b/vendor/github.com/go-openapi/runtime/middleware/security.go
new file mode 100644
index 000000000000..37ecfa6fd4e7
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/security.go
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import "net/http"
+
+func newSecureAPI(ctx *Context, next http.Handler) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := ctx.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+ if route != nil && !route.NeedsAuth() {
+ next.ServeHTTP(rw, r)
+ return
+ }
+
+ _, rCtx, err := ctx.Authorize(r, route)
+ if err != nil {
+ ctx.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ r = rCtx
+
+ next.ServeHTTP(rw, r)
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/spec.go b/vendor/github.com/go-openapi/runtime/middleware/spec.go
new file mode 100644
index 000000000000..9cc9940aaa59
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/spec.go
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "net/http"
+ "path"
+)
+
+const (
+ contentTypeHeader = "Content-Type"
+ applicationJSON = "application/json"
+)
+
+// SpecOption can be applied to the Spec serving middleware
+type SpecOption func(*specOptions)
+
+var defaultSpecOptions = specOptions{
+ Path: "",
+ Document: "swagger.json",
+}
+
+type specOptions struct {
+ Path string
+ Document string
+}
+
+func specOptionsWithDefaults(opts []SpecOption) specOptions {
+ o := defaultSpecOptions
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ return o
+}
+
+// Spec creates a middleware to serve a swagger spec as a JSON document.
+//
+// This allows for altering the spec before starting the http listener.
+//
+// The basePath argument indicates the path of the spec document (defaults to "/").
+// Additional SpecOption can be used to change the name of the document (defaults to "swagger.json").
+func Spec(basePath string, b []byte, next http.Handler, opts ...SpecOption) http.Handler {
+ if basePath == "" {
+ basePath = "/"
+ }
+ o := specOptionsWithDefaults(opts)
+ pth := path.Join(basePath, o.Path, o.Document)
+
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ if path.Clean(r.URL.Path) == pth {
+ rw.Header().Set(contentTypeHeader, applicationJSON)
+ rw.WriteHeader(http.StatusOK)
+ _, _ = rw.Write(b)
+
+ return
+ }
+
+ if next != nil {
+ next.ServeHTTP(rw, r)
+
+ return
+ }
+
+ rw.Header().Set(contentTypeHeader, applicationJSON)
+ rw.WriteHeader(http.StatusNotFound)
+ })
+}
+
+// WithSpecPath sets the path to be joined to the base path of the Spec middleware.
+//
+// This is empty by default.
+func WithSpecPath(pth string) SpecOption {
+ return func(o *specOptions) {
+ o.Path = pth
+ }
+}
+
+// WithSpecDocument sets the name of the JSON document served as a spec.
+//
+// By default, this is "swagger.json"
+func WithSpecDocument(doc string) SpecOption {
+ return func(o *specOptions) {
+ if doc == "" {
+ return
+ }
+
+ o.Document = doc
+ }
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go b/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
new file mode 100644
index 000000000000..b25a3a2cff7d
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
@@ -0,0 +1,178 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "net/http"
+ "path"
+)
+
+// SwaggerUIOpts configures the SwaggerUI middleware
+type SwaggerUIOpts struct {
+ // BasePath for the API, defaults to: /
+ BasePath string
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
+ Path string
+
+ // SpecURL is the URL of the spec document.
+ //
+ // Defaults to: /swagger.json
+ SpecURL string
+
+ // Title for the documentation site, default to: API documentation
+ Title string
+
+ // Template specifies a custom template to serve the UI
+ Template string
+
+ // OAuthCallbackURL the url called after OAuth2 login
+ OAuthCallbackURL string
+
+ // The three components needed to embed swagger-ui
+
+ // SwaggerURL points to the js that generates the SwaggerUI site.
+ //
+ // Defaults to: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js
+ SwaggerURL string
+
+ SwaggerPresetURL string
+ SwaggerStylesURL string
+
+ Favicon32 string
+ Favicon16 string
+}
+
+// EnsureDefaults in case some options are missing
+func (r *SwaggerUIOpts) EnsureDefaults() {
+ r.ensureDefaults()
+
+ if r.Template == "" {
+ r.Template = swaggeruiTemplate
+ }
+}
+
+func (r *SwaggerUIOpts) EnsureDefaultsOauth2() {
+ r.ensureDefaults()
+
+ if r.Template == "" {
+ r.Template = swaggerOAuthTemplate
+ }
+}
+
+func (r *SwaggerUIOpts) ensureDefaults() {
+ common := toCommonUIOptions(r)
+ common.EnsureDefaults()
+ fromCommonToAnyOptions(common, r)
+
+ // swaggerui-specifics
+ if r.OAuthCallbackURL == "" {
+ r.OAuthCallbackURL = path.Join(r.BasePath, r.Path, "oauth2-callback")
+ }
+ if r.SwaggerURL == "" {
+ r.SwaggerURL = swaggerLatest
+ }
+ if r.SwaggerPresetURL == "" {
+ r.SwaggerPresetURL = swaggerPresetLatest
+ }
+ if r.SwaggerStylesURL == "" {
+ r.SwaggerStylesURL = swaggerStylesLatest
+ }
+ if r.Favicon16 == "" {
+ r.Favicon16 = swaggerFavicon16Latest
+ }
+ if r.Favicon32 == "" {
+ r.Favicon32 = swaggerFavicon32Latest
+ }
+}
+
+// SwaggerUI creates a middleware to serve a documentation site for a swagger spec.
+//
+// This allows for altering the spec before starting the http listener.
+func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler {
+ opts.EnsureDefaults()
+
+ pth := path.Join(opts.BasePath, opts.Path)
+ tmpl := template.Must(template.New("swaggerui").Parse(opts.Template))
+ assets := bytes.NewBuffer(nil)
+ if err := tmpl.Execute(assets, opts); err != nil {
+ panic(fmt.Errorf("cannot execute template: %w", err))
+ }
+
+ return serveUI(pth, assets.Bytes(), next)
+}
+
+const (
+ swaggerLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"
+ swaggerPresetLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js"
+ swaggerStylesLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui.css"
+ swaggerFavicon32Latest = "https://unpkg.com/swagger-ui-dist/favicon-32x32.png"
+ swaggerFavicon16Latest = "https://unpkg.com/swagger-ui-dist/favicon-16x16.png"
+ swaggeruiTemplate = `
+
+
+
+
+ {{ .Title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`
+)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go b/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go
new file mode 100644
index 000000000000..879bdbaadea7
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go
@@ -0,0 +1,108 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "text/template"
+)
+
+func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler {
+ opts.EnsureDefaultsOauth2()
+
+ pth := opts.OAuthCallbackURL
+ tmpl := template.Must(template.New("swaggeroauth").Parse(opts.Template))
+ assets := bytes.NewBuffer(nil)
+ if err := tmpl.Execute(assets, opts); err != nil {
+ panic(fmt.Errorf("cannot execute template: %w", err))
+ }
+
+ return serveUI(pth, assets.Bytes(), next)
+}
+
+const (
+ swaggerOAuthTemplate = `
+
+
+
+ {{ .Title }}
+
+
+
+
+
+`
+)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/ui_options.go b/vendor/github.com/go-openapi/runtime/middleware/ui_options.go
new file mode 100644
index 000000000000..cf2f673d3cb9
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/ui_options.go
@@ -0,0 +1,176 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ "net/http"
+ "path"
+ "strings"
+)
+
+const (
+ // constants that are common to all UI-serving middlewares
+ defaultDocsPath = "docs"
+ defaultDocsURL = "/swagger.json"
+ defaultDocsTitle = "API Documentation"
+)
+
+// uiOptions defines common options for UI serving middlewares.
+type uiOptions struct {
+ // BasePath for the UI, defaults to: /
+ BasePath string
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
+ Path string
+
+ // SpecURL is the URL of the spec document.
+ //
+ // Defaults to: /swagger.json
+ SpecURL string
+
+ // Title for the documentation site, default to: API documentation
+ Title string
+
+ // Template specifies a custom template to serve the UI
+ Template string
+}
+
+// toCommonUIOptions converts any UI option type to retain the common options.
+//
+// This uses gob encoding/decoding to convert common fields from one struct to another.
+func toCommonUIOptions(opts any) uiOptions {
+ var buf bytes.Buffer
+ enc := gob.NewEncoder(&buf)
+ dec := gob.NewDecoder(&buf)
+ var o uiOptions
+ err := enc.Encode(opts)
+ if err != nil {
+ panic(err)
+ }
+
+ err = dec.Decode(&o)
+ if err != nil {
+ panic(err)
+ }
+
+ return o
+}
+
+func fromCommonToAnyOptions[T any](source uiOptions, target *T) {
+ var buf bytes.Buffer
+ enc := gob.NewEncoder(&buf)
+ dec := gob.NewDecoder(&buf)
+ err := enc.Encode(source)
+ if err != nil {
+ panic(err)
+ }
+
+ err = dec.Decode(target)
+ if err != nil {
+ panic(err)
+ }
+}
+
+// UIOption can be applied to UI serving middleware, such as Context.APIHandler or
+// Context.APIHandlerSwaggerUI to alter the defaut behavior.
+type UIOption func(*uiOptions)
+
+func uiOptionsWithDefaults(opts []UIOption) uiOptions {
+ var o uiOptions
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ return o
+}
+
+// WithUIBasePath sets the base path from where to serve the UI assets.
+//
+// By default, Context middleware sets this value to the API base path.
+func WithUIBasePath(base string) UIOption {
+ return func(o *uiOptions) {
+ if !strings.HasPrefix(base, "/") {
+ base = "/" + base
+ }
+ o.BasePath = base
+ }
+}
+
+// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}.
+func WithUIPath(pth string) UIOption {
+ return func(o *uiOptions) {
+ o.Path = pth
+ }
+}
+
+// WithUISpecURL sets the path from where to serve swagger spec document.
+//
+// This may be specified as a full URL or a path.
+//
+// By default, this is "/swagger.json"
+func WithUISpecURL(specURL string) UIOption {
+ return func(o *uiOptions) {
+ o.SpecURL = specURL
+ }
+}
+
+// WithUITitle sets the title of the UI.
+//
+// By default, Context middleware sets this value to the title found in the API spec.
+func WithUITitle(title string) UIOption {
+ return func(o *uiOptions) {
+ o.Title = title
+ }
+}
+
+// WithTemplate allows to set a custom template for the UI.
+//
+// UI middleware will panic if the template does not parse or execute properly.
+func WithTemplate(tpl string) UIOption {
+ return func(o *uiOptions) {
+ o.Template = tpl
+ }
+}
+
+// EnsureDefaults in case some options are missing
+func (r *uiOptions) EnsureDefaults() {
+ if r.BasePath == "" {
+ r.BasePath = "/"
+ }
+ if r.Path == "" {
+ r.Path = defaultDocsPath
+ }
+ if r.SpecURL == "" {
+ r.SpecURL = defaultDocsURL
+ }
+ if r.Title == "" {
+ r.Title = defaultDocsTitle
+ }
+}
+
+// serveUI creates a middleware that serves a templated asset as text/html.
+func serveUI(pth string, assets []byte, next http.Handler) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ if path.Clean(r.URL.Path) == pth {
+ rw.Header().Set(contentTypeHeader, "text/html; charset=utf-8")
+ rw.WriteHeader(http.StatusOK)
+ _, _ = rw.Write(assets)
+
+ return
+ }
+
+ if next != nil {
+ next.ServeHTTP(rw, r)
+
+ return
+ }
+
+ rw.Header().Set(contentTypeHeader, "text/plain")
+ rw.WriteHeader(http.StatusNotFound)
+ _, _ = fmt.Fprintf(rw, "%q not found", pth)
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
new file mode 100644
index 000000000000..774da0ba0c86
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
@@ -0,0 +1,282 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package untyped
+
+import (
+ "fmt"
+ "net/http"
+ "sort"
+ "strings"
+
+ "github.com/go-openapi/analysis"
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/loads"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/runtime"
+)
+
+const (
+ smallPreallocatedSlots = 10
+ mediumPreallocatedSlots = 30
+)
+
+// API represents an untyped mux for a swagger spec
+type API struct {
+ spec *loads.Document
+ analyzer *analysis.Spec
+ DefaultProduces string
+ DefaultConsumes string
+ consumers map[string]runtime.Consumer
+ producers map[string]runtime.Producer
+ authenticators map[string]runtime.Authenticator
+ authorizer runtime.Authorizer
+ operations map[string]map[string]runtime.OperationHandler
+ ServeError func(http.ResponseWriter, *http.Request, error)
+ Models map[string]func() any
+ formats strfmt.Registry
+}
+
+// NewAPI creates the default untyped API
+func NewAPI(spec *loads.Document) *API {
+ var an *analysis.Spec
+ if spec != nil && spec.Spec() != nil {
+ an = analysis.New(spec.Spec())
+ }
+ api := &API{
+ spec: spec,
+ analyzer: an,
+ consumers: make(map[string]runtime.Consumer, smallPreallocatedSlots),
+ producers: make(map[string]runtime.Producer, smallPreallocatedSlots),
+ authenticators: make(map[string]runtime.Authenticator),
+ operations: make(map[string]map[string]runtime.OperationHandler),
+ ServeError: errors.ServeError,
+ Models: make(map[string]func() any),
+ formats: strfmt.NewFormats(),
+ }
+
+ return api.WithJSONDefaults()
+}
+
+// WithJSONDefaults loads the json defaults for this api
+func (d *API) WithJSONDefaults() *API {
+ d.DefaultConsumes = runtime.JSONMime
+ d.DefaultProduces = runtime.JSONMime
+ d.consumers[runtime.JSONMime] = runtime.JSONConsumer()
+ d.producers[runtime.JSONMime] = runtime.JSONProducer()
+ return d
+}
+
+// WithoutJSONDefaults clears the json defaults for this api
+func (d *API) WithoutJSONDefaults() *API {
+ d.DefaultConsumes = ""
+ d.DefaultProduces = ""
+ delete(d.consumers, runtime.JSONMime)
+ delete(d.producers, runtime.JSONMime)
+ return d
+}
+
+// Formats returns the registered string formats
+func (d *API) Formats() strfmt.Registry {
+ if d.formats == nil {
+ d.formats = strfmt.NewFormats()
+ }
+ return d.formats
+}
+
+// RegisterFormat registers a custom format validator
+func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) {
+ if d.formats == nil {
+ d.formats = strfmt.NewFormats()
+ }
+ d.formats.Add(name, format, validator)
+}
+
+// RegisterAuth registers an auth handler in this api
+func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) {
+ if d.authenticators == nil {
+ d.authenticators = make(map[string]runtime.Authenticator)
+ }
+ d.authenticators[scheme] = handler
+}
+
+// RegisterAuthorizer registers an authorizer handler in this api
+func (d *API) RegisterAuthorizer(handler runtime.Authorizer) {
+ d.authorizer = handler
+}
+
+// RegisterConsumer registers a consumer for a media type.
+func (d *API) RegisterConsumer(mediaType string, handler runtime.Consumer) {
+ if d.consumers == nil {
+ d.consumers = make(map[string]runtime.Consumer, smallPreallocatedSlots)
+ }
+ d.consumers[strings.ToLower(mediaType)] = handler
+}
+
+// RegisterProducer registers a producer for a media type
+func (d *API) RegisterProducer(mediaType string, handler runtime.Producer) {
+ if d.producers == nil {
+ d.producers = make(map[string]runtime.Producer, smallPreallocatedSlots)
+ }
+ d.producers[strings.ToLower(mediaType)] = handler
+}
+
+// RegisterOperation registers an operation handler for an operation name
+func (d *API) RegisterOperation(method, path string, handler runtime.OperationHandler) {
+ if d.operations == nil {
+ d.operations = make(map[string]map[string]runtime.OperationHandler, mediumPreallocatedSlots)
+ }
+ um := strings.ToUpper(method)
+ if b, ok := d.operations[um]; !ok || b == nil {
+ d.operations[um] = make(map[string]runtime.OperationHandler)
+ }
+ d.operations[um][path] = handler
+}
+
+// OperationHandlerFor returns the operation handler for the specified id if it can be found
+func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler, bool) {
+ if d.operations == nil {
+ return nil, false
+ }
+ if pi, ok := d.operations[strings.ToUpper(method)]; ok {
+ h, ok := pi[path]
+ return h, ok
+ }
+ return nil, false
+}
+
+// ConsumersFor gets the consumers for the specified media types
+func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
+ result := make(map[string]runtime.Consumer)
+ for _, mt := range mediaTypes {
+ if consumer, ok := d.consumers[mt]; ok {
+ result[mt] = consumer
+ }
+ }
+ return result
+}
+
+// ProducersFor gets the producers for the specified media types
+func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
+ result := make(map[string]runtime.Producer)
+ for _, mt := range mediaTypes {
+ if producer, ok := d.producers[mt]; ok {
+ result[mt] = producer
+ }
+ }
+ return result
+}
+
+// AuthenticatorsFor gets the authenticators for the specified security schemes
+func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
+ result := make(map[string]runtime.Authenticator)
+ for k := range schemes {
+ if a, ok := d.authenticators[k]; ok {
+ result[k] = a
+ }
+ }
+ return result
+}
+
+// Authorizer returns the registered authorizer
+func (d *API) Authorizer() runtime.Authorizer {
+ return d.authorizer
+}
+
+// Validate validates this API for any missing items
+func (d *API) Validate() error {
+ return d.validate()
+}
+
+// validateWith validates the registrations in this API against the provided spec analyzer
+func (d *API) validate() error {
+ consumes := make([]string, 0, len(d.consumers))
+ for k := range d.consumers {
+ consumes = append(consumes, k)
+ }
+
+ produces := make([]string, 0, len(d.producers))
+ for k := range d.producers {
+ produces = append(produces, k)
+ }
+
+ authenticators := make([]string, 0, len(d.authenticators))
+ for k := range d.authenticators {
+ authenticators = append(authenticators, k)
+ }
+
+ operations := make([]string, 0, len(d.operations))
+ for m, v := range d.operations {
+ for p := range v {
+ operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
+ }
+ }
+
+ secDefinitions := d.spec.Spec().SecurityDefinitions
+ definedAuths := make([]string, 0, len(secDefinitions))
+ for k := range secDefinitions {
+ definedAuths = append(definedAuths, k)
+ }
+
+ if err := d.verify("consumes", consumes, d.analyzer.RequiredConsumes()); err != nil {
+ return err
+ }
+ if err := d.verify("produces", produces, d.analyzer.RequiredProduces()); err != nil {
+ return err
+ }
+ if err := d.verify("operation", operations, d.analyzer.OperationMethodPaths()); err != nil {
+ return err
+ }
+
+ requiredAuths := d.analyzer.RequiredSecuritySchemes()
+ if err := d.verify("auth scheme", authenticators, requiredAuths); err != nil {
+ return err
+ }
+ if err := d.verify("security definitions", definedAuths, requiredAuths); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (d *API) verify(name string, registrations []string, expectations []string) error {
+ sort.Strings(registrations)
+ sort.Strings(expectations)
+
+ expected := map[string]struct{}{}
+ seen := map[string]struct{}{}
+
+ for _, v := range expectations {
+ expected[v] = struct{}{}
+ }
+
+ var unspecified []string
+ for _, v := range registrations {
+ seen[v] = struct{}{}
+ if _, ok := expected[v]; !ok {
+ unspecified = append(unspecified, v)
+ }
+ }
+
+ for k := range seen {
+ delete(expected, k)
+ }
+
+ unregistered := make([]string, 0, len(expected))
+ for k := range expected {
+ unregistered = append(unregistered, k)
+ }
+ sort.Strings(unspecified)
+ sort.Strings(unregistered)
+
+ if len(unregistered) > 0 || len(unspecified) > 0 {
+ return &errors.APIVerificationFailed{
+ Section: name,
+ MissingSpecification: unspecified,
+ MissingRegistration: unregistered,
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/validation.go b/vendor/github.com/go-openapi/runtime/middleware/validation.go
new file mode 100644
index 000000000000..ed026d626ba4
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/validation.go
@@ -0,0 +1,118 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "mime"
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/swag/stringutils"
+)
+
+type validation struct {
+ context *Context
+ result []error
+ request *http.Request
+ route *MatchedRoute
+ bound map[string]any
+}
+
+// ContentType validates the content type of a request
+func validateContentType(allowed []string, actual string) error {
+ if len(allowed) == 0 {
+ return nil
+ }
+ mt, _, err := mime.ParseMediaType(actual)
+ if err != nil {
+ return errors.InvalidContentType(actual, allowed)
+ }
+ if stringutils.ContainsStringsCI(allowed, mt) {
+ return nil
+ }
+ if stringutils.ContainsStringsCI(allowed, "*/*") {
+ return nil
+ }
+ parts := strings.Split(actual, "/")
+ if len(parts) == 2 && stringutils.ContainsStringsCI(allowed, parts[0]+"/*") {
+ return nil
+ }
+ return errors.InvalidContentType(actual, allowed)
+}
+
+func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation {
+ validate := &validation{
+ context: ctx,
+ request: request,
+ route: route,
+ bound: make(map[string]any),
+ }
+ validate.debugLogf("validating request %s %s", request.Method, request.URL.EscapedPath())
+
+ validate.contentType()
+ if len(validate.result) == 0 {
+ validate.responseFormat()
+ }
+ if len(validate.result) == 0 {
+ validate.parameters()
+ }
+
+ return validate
+}
+
+func (v *validation) debugLogf(format string, args ...any) {
+ v.context.debugLogf(format, args...)
+}
+
+func (v *validation) parameters() {
+ v.debugLogf("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
+ if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil {
+ if result.Error() == "validation failure list" {
+ for _, e := range result.(*errors.Validation).Value.([]any) {
+ v.result = append(v.result, e.(error))
+ }
+ return
+ }
+ v.result = append(v.result, result)
+ }
+}
+
+func (v *validation) contentType() {
+ if len(v.result) == 0 && runtime.HasBody(v.request) {
+ v.debugLogf("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
+ ct, _, req, err := v.context.ContentType(v.request)
+ if err != nil {
+ v.result = append(v.result, err)
+ } else {
+ v.request = req
+ }
+
+ if len(v.result) == 0 {
+ v.debugLogf("validating content type for %q against [%s]", ct, strings.Join(v.route.Consumes, ", "))
+ if err := validateContentType(v.route.Consumes, ct); err != nil {
+ v.result = append(v.result, err)
+ }
+ }
+ if ct != "" && v.route.Consumer == nil {
+ cons, ok := v.route.Consumers[ct]
+ if !ok {
+ v.result = append(v.result, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct))
+ } else {
+ v.route.Consumer = cons
+ }
+ }
+ }
+}
+
+func (v *validation) responseFormat() {
+ // if the route provides values for Produces and no format could be identify then return an error.
+ // if the route does not specify values for Produces then treat request as valid since the API designer
+ // choose not to specify the format for responses.
+ if str, rCtx := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && len(v.route.Produces) > 0 {
+ v.request = rCtx
+ v.result = append(v.result, errors.InvalidResponseFormat(v.request.Header.Get(runtime.HeaderAccept), v.route.Produces))
+ }
+}
diff --git a/vendor/github.com/go-openapi/runtime/request.go b/vendor/github.com/go-openapi/runtime/request.go
new file mode 100644
index 000000000000..aab7b8c055a3
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/request.go
@@ -0,0 +1,138 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "bufio"
+ "context"
+ "errors"
+ "io"
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/swag/stringutils"
+)
+
+// CanHaveBody returns true if this method can have a body
+func CanHaveBody(method string) bool {
+ mn := strings.ToUpper(method)
+ return mn == "POST" || mn == "PUT" || mn == "PATCH" || mn == "DELETE"
+}
+
+// IsSafe returns true if this is a request with a safe method
+func IsSafe(r *http.Request) bool {
+ mn := strings.ToUpper(r.Method)
+ return mn == "GET" || mn == "HEAD"
+}
+
+// AllowsBody returns true if the request allows for a body
+func AllowsBody(r *http.Request) bool {
+ mn := strings.ToUpper(r.Method)
+ return mn != "HEAD"
+}
+
+// HasBody returns true if this method needs a content-type
+func HasBody(r *http.Request) bool {
+ // happy case: we have a content length set
+ if r.ContentLength > 0 {
+ return true
+ }
+
+ if r.Header.Get("Content-Length") != "" {
+ // in this case, no Transfer-Encoding should be present
+ // we have a header set but it was explicitly set to 0, so we assume no body
+ return false
+ }
+
+ rdr := newPeekingReader(r.Body)
+ r.Body = rdr
+ return rdr.HasContent()
+}
+
+func newPeekingReader(r io.ReadCloser) *peekingReader {
+ if r == nil {
+ return nil
+ }
+ return &peekingReader{
+ underlying: bufio.NewReader(r),
+ orig: r,
+ }
+}
+
+type peekingReader struct {
+ underlying interface {
+ Buffered() int
+ Peek(int) ([]byte, error)
+ Read([]byte) (int, error)
+ }
+ orig io.ReadCloser
+}
+
+func (p *peekingReader) HasContent() bool {
+ if p == nil {
+ return false
+ }
+ if p.underlying.Buffered() > 0 {
+ return true
+ }
+ b, err := p.underlying.Peek(1)
+ if err != nil {
+ return false
+ }
+ return len(b) > 0
+}
+
+func (p *peekingReader) Read(d []byte) (int, error) {
+ if p == nil {
+ return 0, io.EOF
+ }
+ if p.underlying == nil {
+ return 0, io.ErrUnexpectedEOF
+ }
+ return p.underlying.Read(d)
+}
+
+func (p *peekingReader) Close() error {
+ if p.underlying == nil {
+ return errors.New("reader already closed")
+ }
+ p.underlying = nil
+ if p.orig != nil {
+ return p.orig.Close()
+ }
+ return nil
+}
+
+// JSONRequest creates a new http request with json headers set.
+//
+// It uses context.Background.
+func JSONRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
+ req, err := http.NewRequestWithContext(context.Background(), method, urlStr, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Add(HeaderContentType, JSONMime)
+ req.Header.Add(HeaderAccept, JSONMime)
+ return req, nil
+}
+
+// Gettable for things with a method GetOK(string) (data string, hasKey bool, hasValue bool)
+type Gettable interface {
+ GetOK(string) ([]string, bool, bool)
+}
+
+// ReadSingleValue reads a single value from the source
+func ReadSingleValue(values Gettable, name string) string {
+ vv, _, hv := values.GetOK(name)
+ if hv {
+ return vv[len(vv)-1]
+ }
+ return ""
+}
+
+// ReadCollectionValue reads a collection value from a string data source
+func ReadCollectionValue(values Gettable, name, collectionFormat string) []string {
+ v := ReadSingleValue(values, name)
+ return stringutils.SplitByFormat(v, collectionFormat)
+}
diff --git a/vendor/github.com/go-openapi/runtime/security/authenticator.go b/vendor/github.com/go-openapi/runtime/security/authenticator.go
new file mode 100644
index 000000000000..b5b7904dc1e6
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/security/authenticator.go
@@ -0,0 +1,266 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package security
+
+import (
+ "context"
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/errors"
+
+ "github.com/go-openapi/runtime"
+)
+
+const (
+ query = "query"
+ header = "header"
+ accessTokenParam = "access_token"
+)
+
+// HttpAuthenticator is a function that authenticates a HTTP request
+func HttpAuthenticator(handler func(*http.Request) (bool, any, error)) runtime.Authenticator { //nolint:revive
+ return runtime.AuthenticatorFunc(func(params any) (bool, any, error) {
+ if request, ok := params.(*http.Request); ok {
+ return handler(request)
+ }
+ if scoped, ok := params.(*ScopedAuthRequest); ok {
+ return handler(scoped.Request)
+ }
+ return false, nil, nil
+ })
+}
+
+// ScopedAuthenticator is a function that authenticates a HTTP request against a list of valid scopes
+func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, any, error)) runtime.Authenticator {
+ return runtime.AuthenticatorFunc(func(params any) (bool, any, error) {
+ if request, ok := params.(*ScopedAuthRequest); ok {
+ return handler(request)
+ }
+ return false, nil, nil
+ })
+}
+
+// UserPassAuthentication authentication function
+type UserPassAuthentication func(string, string) (any, error)
+
+// UserPassAuthenticationCtx authentication function with context.Context
+type UserPassAuthenticationCtx func(context.Context, string, string) (context.Context, any, error)
+
+// TokenAuthentication authentication function
+type TokenAuthentication func(string) (any, error)
+
+// TokenAuthenticationCtx authentication function with context.Context
+type TokenAuthenticationCtx func(context.Context, string) (context.Context, any, error)
+
+// ScopedTokenAuthentication authentication function
+type ScopedTokenAuthentication func(string, []string) (any, error)
+
+// ScopedTokenAuthenticationCtx authentication function with context.Context
+type ScopedTokenAuthenticationCtx func(context.Context, string, []string) (context.Context, any, error)
+
+var DefaultRealmName = "API"
+
+type secCtxKey uint8
+
+const (
+ failedBasicAuth secCtxKey = iota
+ oauth2SchemeName
+)
+
+func FailedBasicAuth(r *http.Request) string {
+ return FailedBasicAuthCtx(r.Context())
+}
+
+func FailedBasicAuthCtx(ctx context.Context) string {
+ v, ok := ctx.Value(failedBasicAuth).(string)
+ if !ok {
+ return ""
+ }
+ return v
+}
+
+func OAuth2SchemeName(r *http.Request) string {
+ return OAuth2SchemeNameCtx(r.Context())
+}
+
+func OAuth2SchemeNameCtx(ctx context.Context) string {
+ v, ok := ctx.Value(oauth2SchemeName).(string)
+ if !ok {
+ return ""
+ }
+ return v
+}
+
+// BasicAuth creates a basic auth authenticator with the provided authentication function
+func BasicAuth(authenticate UserPassAuthentication) runtime.Authenticator {
+ return BasicAuthRealm(DefaultRealmName, authenticate)
+}
+
+// BasicAuthRealm creates a basic auth authenticator with the provided authentication function and realm name
+func BasicAuthRealm(realm string, authenticate UserPassAuthentication) runtime.Authenticator {
+ if realm == "" {
+ realm = DefaultRealmName
+ }
+
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
+ if usr, pass, ok := r.BasicAuth(); ok {
+ p, err := authenticate(usr, pass)
+ if err != nil {
+ *r = *r.WithContext(context.WithValue(r.Context(), failedBasicAuth, realm))
+ }
+ return true, p, err
+ }
+ *r = *r.WithContext(context.WithValue(r.Context(), failedBasicAuth, realm))
+ return false, nil, nil
+ })
+}
+
+// BasicAuthCtx creates a basic auth authenticator with the provided authentication function with support for context.Context
+func BasicAuthCtx(authenticate UserPassAuthenticationCtx) runtime.Authenticator {
+ return BasicAuthRealmCtx(DefaultRealmName, authenticate)
+}
+
+// BasicAuthRealmCtx creates a basic auth authenticator with the provided authentication function and realm name with support for context.Context
+func BasicAuthRealmCtx(realm string, authenticate UserPassAuthenticationCtx) runtime.Authenticator {
+ if realm == "" {
+ realm = DefaultRealmName
+ }
+
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
+ if usr, pass, ok := r.BasicAuth(); ok {
+ ctx, p, err := authenticate(r.Context(), usr, pass)
+ if err != nil {
+ ctx = context.WithValue(ctx, failedBasicAuth, realm)
+ }
+ *r = *r.WithContext(ctx)
+ return true, p, err
+ }
+ *r = *r.WithContext(context.WithValue(r.Context(), failedBasicAuth, realm))
+ return false, nil, nil
+ })
+}
+
+// APIKeyAuth creates an authenticator that uses a token for authorization.
+// This token can be obtained from either a header or a query string
+func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authenticator {
+ inl := strings.ToLower(in)
+ if inl != query && inl != header {
+ // panic because this is most likely a typo
+ panic(errors.New(http.StatusInternalServerError, "api key auth: in value needs to be either \"query\" or \"header\""))
+ }
+
+ var getToken func(*http.Request) string
+ switch inl {
+ case header:
+ getToken = func(r *http.Request) string { return r.Header.Get(name) }
+ case query:
+ getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
+ }
+
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
+ token := getToken(r)
+ if token == "" {
+ return false, nil, nil
+ }
+
+ p, err := authenticate(token)
+ return true, p, err
+ })
+}
+
+// APIKeyAuthCtx creates an authenticator that uses a token for authorization with support for context.Context.
+// This token can be obtained from either a header or a query string
+func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime.Authenticator {
+ inl := strings.ToLower(in)
+ if inl != query && inl != header {
+ // panic because this is most likely a typo
+ panic(errors.New(http.StatusInternalServerError, "api key auth: in value needs to be either \"query\" or \"header\""))
+ }
+
+ var getToken func(*http.Request) string
+ switch inl {
+ case header:
+ getToken = func(r *http.Request) string { return r.Header.Get(name) }
+ case query:
+ getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
+ }
+
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
+ token := getToken(r)
+ if token == "" {
+ return false, nil, nil
+ }
+
+ ctx, p, err := authenticate(r.Context(), token)
+ *r = *r.WithContext(ctx)
+ return true, p, err
+ })
+}
+
+// ScopedAuthRequest contains both a http request and the required scopes for a particular operation
+type ScopedAuthRequest struct {
+ Request *http.Request
+ RequiredScopes []string
+}
+
+// BearerAuth for use with oauth2 flows
+func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Authenticator {
+ const prefix = "Bearer "
+ return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, any, error) {
+ var token string
+ hdr := r.Request.Header.Get(runtime.HeaderAuthorization)
+ if after, ok := strings.CutPrefix(hdr, prefix); ok {
+ token = after
+ }
+ if token == "" {
+ qs := r.Request.URL.Query()
+ token = qs.Get(accessTokenParam)
+ }
+ //#nosec
+ ct, _, _ := runtime.ContentType(r.Request.Header)
+ if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
+ token = r.Request.FormValue(accessTokenParam)
+ }
+
+ if token == "" {
+ return false, nil, nil
+ }
+
+ rctx := context.WithValue(r.Request.Context(), oauth2SchemeName, name)
+ *r.Request = *r.Request.WithContext(rctx)
+ p, err := authenticate(token, r.RequiredScopes)
+ return true, p, err
+ })
+}
+
+// BearerAuthCtx for use with oauth2 flows with support for context.Context.
+func BearerAuthCtx(name string, authenticate ScopedTokenAuthenticationCtx) runtime.Authenticator {
+ const prefix = "Bearer "
+ return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, any, error) {
+ var token string
+ hdr := r.Request.Header.Get(runtime.HeaderAuthorization)
+ if after, ok := strings.CutPrefix(hdr, prefix); ok {
+ token = after
+ }
+ if token == "" {
+ qs := r.Request.URL.Query()
+ token = qs.Get(accessTokenParam)
+ }
+ //#nosec
+ ct, _, _ := runtime.ContentType(r.Request.Header)
+ if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
+ token = r.Request.FormValue(accessTokenParam)
+ }
+
+ if token == "" {
+ return false, nil, nil
+ }
+
+ rctx := context.WithValue(r.Request.Context(), oauth2SchemeName, name)
+ ctx, p, err := authenticate(rctx, token, r.RequiredScopes)
+ *r.Request = *r.Request.WithContext(ctx)
+ return true, p, err
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/security/authorizer.go b/vendor/github.com/go-openapi/runtime/security/authorizer.go
new file mode 100644
index 000000000000..69bd497a3c28
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/security/authorizer.go
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package security
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+)
+
+// Authorized provides a default implementation of the Authorizer interface where all
+// requests are authorized (successful)
+func Authorized() runtime.Authorizer {
+ return runtime.AuthorizerFunc(func(_ *http.Request, _ any) error { return nil })
+}
diff --git a/vendor/github.com/go-openapi/runtime/statuses.go b/vendor/github.com/go-openapi/runtime/statuses.go
new file mode 100644
index 000000000000..7e10a5a56c29
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/statuses.go
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+// Statuses lists the most common HTTP status codes to default message
+// taken from https://httpstatuses.com/
+var Statuses = map[int]string{
+ 100: "Continue",
+ 101: "Switching Protocols",
+ 102: "Processing",
+ 103: "Checkpoint",
+ 122: "URI too long",
+ 200: "OK",
+ 201: "Created",
+ 202: "Accepted",
+ 203: "Request Processed",
+ 204: "No Content",
+ 205: "Reset Content",
+ 206: "Partial Content",
+ 207: "Multi-Status",
+ 208: "Already Reported",
+ 226: "IM Used",
+ 300: "Multiple Choices",
+ 301: "Moved Permanently",
+ 302: "Found",
+ 303: "See Other",
+ 304: "Not Modified",
+ 305: "Use Proxy",
+ 306: "Switch Proxy",
+ 307: "Temporary Redirect",
+ 308: "Permanent Redirect",
+ 400: "Bad Request",
+ 401: "Unauthorized",
+ 402: "Payment Required",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 405: "Method Not Allowed",
+ 406: "Not Acceptable",
+ 407: "Proxy Authentication Required",
+ 408: "Request Timeout",
+ 409: "Conflict",
+ 410: "Gone",
+ 411: "Length Required",
+ 412: "Precondition Failed",
+ 413: "Request Entity Too Large",
+ 414: "Request-URI Too Long",
+ 415: "Unsupported Media Type",
+ 416: "Request Range Not Satisfiable",
+ 417: "Expectation Failed",
+ 418: "I'm a teapot",
+ 420: "Enhance Your Calm",
+ 422: "Unprocessable Entity",
+ 423: "Locked",
+ 424: "Failed Dependency",
+ 426: "Upgrade Required",
+ 428: "Precondition Required",
+ 429: "Too Many Requests",
+ 431: "Request Header Fields Too Large",
+ 444: "No Response",
+ 449: "Retry With",
+ 450: "Blocked by Windows Parental Controls",
+ 451: "Wrong Exchange Server",
+ 499: "Client Closed Request",
+ 500: "Internal Server Error",
+ 501: "Not Implemented",
+ 502: "Bad Gateway",
+ 503: "Service Unavailable",
+ 504: "Gateway Timeout",
+ 505: "HTTP Version Not Supported",
+ 506: "Variant Also Negotiates",
+ 507: "Insufficient Storage",
+ 508: "Loop Detected",
+ 509: "Bandwidth Limit Exceeded",
+ 510: "Not Extended",
+ 511: "Network Authentication Required",
+ 598: "Network read timeout error",
+ 599: "Network connect timeout error",
+}
diff --git a/vendor/github.com/go-openapi/runtime/text.go b/vendor/github.com/go-openapi/runtime/text.go
new file mode 100644
index 000000000000..2b8e4ac09d0f
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/text.go
@@ -0,0 +1,105 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// TextConsumer creates a new text consumer
+func TextConsumer() Consumer {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
+ if reader == nil {
+ return errors.New("TextConsumer requires a reader") // early exit
+ }
+
+ buf := new(bytes.Buffer)
+ _, err := buf.ReadFrom(reader)
+ if err != nil {
+ return err
+ }
+ b := buf.Bytes()
+
+ // If the buffer is empty, no need to unmarshal it, which causes a panic.
+ if len(b) == 0 {
+ return nil
+ }
+
+ if tu, ok := data.(encoding.TextUnmarshaler); ok {
+ err := tu.UnmarshalText(b)
+ if err != nil {
+ return fmt.Errorf("text consumer: %v", err)
+ }
+
+ return nil
+ }
+
+ t := reflect.TypeOf(data)
+ if data != nil && t.Kind() == reflect.Ptr {
+ v := reflect.Indirect(reflect.ValueOf(data))
+ if t.Elem().Kind() == reflect.String {
+ v.SetString(string(b))
+ return nil
+ }
+ }
+
+ return fmt.Errorf("%v (%T) is not supported by the TextConsumer, %s",
+ data, data, "can be resolved by supporting TextUnmarshaler interface")
+ })
+}
+
+// TextProducer creates a new text producer
+func TextProducer() Producer {
+ return ProducerFunc(func(writer io.Writer, data any) error {
+ if writer == nil {
+ return errors.New("TextProducer requires a writer") // early exit
+ }
+
+ if data == nil {
+ return errors.New("no data given to produce text from")
+ }
+
+ if tm, ok := data.(encoding.TextMarshaler); ok {
+ txt, err := tm.MarshalText()
+ if err != nil {
+ return fmt.Errorf("text producer: %v", err)
+ }
+ _, err = writer.Write(txt)
+ return err
+ }
+
+ if str, ok := data.(error); ok {
+ _, err := writer.Write([]byte(str.Error()))
+ return err
+ }
+
+ if str, ok := data.(fmt.Stringer); ok {
+ _, err := writer.Write([]byte(str.String()))
+ return err
+ }
+
+ v := reflect.Indirect(reflect.ValueOf(data))
+ if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice {
+ b, err := jsonutils.WriteJSON(data)
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write(b)
+ return err
+ }
+ if v.Kind() != reflect.String {
+ return fmt.Errorf("%T is not a supported type by the TextProducer", data)
+ }
+
+ _, err := writer.Write([]byte(v.String()))
+ return err
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/values.go b/vendor/github.com/go-openapi/runtime/values.go
new file mode 100644
index 000000000000..19894e78451c
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/values.go
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+// Values typically represent parameters on a http request.
+type Values map[string][]string
+
+// GetOK returns the values collection for the given key.
+// When the key is present in the map it will return true for hasKey.
+// When the value is not empty it will return true for hasValue.
+func (v Values) GetOK(key string) (value []string, hasKey bool, hasValue bool) {
+ value, hasKey = v[key]
+ if !hasKey {
+ return
+ }
+ if len(value) == 0 {
+ return
+ }
+ hasValue = true
+ return
+}
diff --git a/vendor/github.com/go-openapi/runtime/xml.go b/vendor/github.com/go-openapi/runtime/xml.go
new file mode 100644
index 000000000000..5060b5c8e915
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/xml.go
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "encoding/xml"
+ "io"
+)
+
+// XMLConsumer creates a new XML consumer
+func XMLConsumer() Consumer {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
+ dec := xml.NewDecoder(reader)
+ return dec.Decode(data)
+ })
+}
+
+// XMLProducer creates a new XML producer
+func XMLProducer() Producer {
+ return ProducerFunc(func(writer io.Writer, data any) error {
+ enc := xml.NewEncoder(writer)
+ return enc.Encode(data)
+ })
+}
diff --git a/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go
new file mode 100644
index 000000000000..ca63430e0b7b
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package yamlpc
+
+import (
+ "io"
+
+ "github.com/go-openapi/runtime"
+ yaml "go.yaml.in/yaml/v3"
+)
+
+// YAMLConsumer creates a consumer for yaml data
+func YAMLConsumer() runtime.Consumer {
+ return runtime.ConsumerFunc(func(r io.Reader, v any) error {
+ dec := yaml.NewDecoder(r)
+ return dec.Decode(v)
+ })
+}
+
+// YAMLProducer creates a producer for yaml data
+func YAMLProducer() runtime.Producer {
+ return runtime.ProducerFunc(func(w io.Writer, v any) error {
+ enc := yaml.NewEncoder(w)
+ defer enc.Close()
+ return enc.Encode(v)
+ })
+}
diff --git a/vendor/github.com/go-openapi/spec/.editorconfig b/vendor/github.com/go-openapi/spec/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/spec/.gitignore b/vendor/github.com/go-openapi/spec/.gitignore
new file mode 100644
index 000000000000..f47cb2045f13
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/.gitignore
@@ -0,0 +1 @@
+*.out
diff --git a/vendor/github.com/go-openapi/spec/.golangci.yml b/vendor/github.com/go-openapi/spec/.golangci.yml
new file mode 100644
index 000000000000..1ad5adf47e69
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ - intrange
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/spec/LICENSE b/vendor/github.com/go-openapi/spec/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/spec/README.md b/vendor/github.com/go-openapi/spec/README.md
new file mode 100644
index 000000000000..3203bd2556d6
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/README.md
@@ -0,0 +1,58 @@
+# OpenAPI v2 object model [](https://github.com/go-openapi/spec/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/spec)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/spec)
+[](https://goreportcard.com/report/github.com/go-openapi/spec)
+
+The object model for OpenAPI specification documents.
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+### FAQ
+
+* What does this do?
+
+> 1. This package knows how to marshal and unmarshal Swagger API specifications into a golang object model
+> 2. It knows how to resolve $ref and expand them to make a single root document
+
+* How does it play with the rest of the go-openapi packages ?
+
+> 1. This package is at the core of the go-openapi suite of packages and [code generator](https://github.com/go-swagger/go-swagger)
+> 2. There is a [spec loading package](https://github.com/go-openapi/loads) to fetch specs as JSON or YAML from local or remote locations
+> 3. There is a [spec validation package](https://github.com/go-openapi/validate) built on top of it
+> 4. There is a [spec analysis package](https://github.com/go-openapi/analysis) built on top of it, to analyze, flatten, fix and merge spec documents
+
+* Does this library support OpenAPI 3?
+
+> No.
+> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
+> There is no plan to make it evolve toward supporting OpenAPI 3.x.
+> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
+>
+> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3
+
+* Does the unmarshaling support YAML?
+
+> Not directly. The exposed types know only how to unmarshal from JSON.
+>
+> In order to load a YAML document as a Swagger spec, you need to use the loaders provided by
+> github.com/go-openapi/loads
+>
+> Take a look at the example there: https://pkg.go.dev/github.com/go-openapi/loads#example-Spec
+>
+> See also https://github.com/go-openapi/spec/issues/164
+
+* How can I validate a spec?
+
+> Validation is provided by [the validate package](http://github.com/go-openapi/validate)
+
+* Why do we have an `ID` field for `Schema` which is not part of the swagger spec?
+
+> We found jsonschema compatibility more important: since `id` in jsonschema influences
+> how `$ref` are resolved.
+> This `id` does not conflict with any property named `id`.
+>
+> See also https://github.com/go-openapi/spec/issues/23
diff --git a/vendor/github.com/go-openapi/spec/cache.go b/vendor/github.com/go-openapi/spec/cache.go
new file mode 100644
index 000000000000..10fba77a839c
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/cache.go
@@ -0,0 +1,86 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "maps"
+ "sync"
+)
+
+// ResolutionCache a cache for resolving urls
+type ResolutionCache interface {
+ Get(string) (any, bool)
+ Set(string, any)
+}
+
+type simpleCache struct {
+ lock sync.RWMutex
+ store map[string]any
+}
+
+func (s *simpleCache) ShallowClone() ResolutionCache {
+ store := make(map[string]any, len(s.store))
+ s.lock.RLock()
+ maps.Copy(store, s.store)
+ s.lock.RUnlock()
+
+ return &simpleCache{
+ store: store,
+ }
+}
+
+// Get retrieves a cached URI
+func (s *simpleCache) Get(uri string) (any, bool) {
+ s.lock.RLock()
+ v, ok := s.store[uri]
+
+ s.lock.RUnlock()
+ return v, ok
+}
+
+// Set caches a URI
+func (s *simpleCache) Set(uri string, data any) {
+ s.lock.Lock()
+ s.store[uri] = data
+ s.lock.Unlock()
+}
+
+var (
+ // resCache is a package level cache for $ref resolution and expansion.
+ // It is initialized lazily by methods that have the need for it: no
+ // memory is allocated unless some expander methods are called.
+ //
+ // It is initialized with JSON schema and swagger schema,
+ // which do not mutate during normal operations.
+ //
+ // All subsequent utilizations of this cache are produced from a shallow
+ // clone of this initial version.
+ resCache *simpleCache
+ onceCache sync.Once
+
+ _ ResolutionCache = &simpleCache{}
+)
+
+// initResolutionCache initializes the URI resolution cache. To be wrapped in a sync.Once.Do call.
+func initResolutionCache() {
+ resCache = defaultResolutionCache()
+}
+
+func defaultResolutionCache() *simpleCache {
+ return &simpleCache{store: map[string]any{
+ "http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(),
+ "http://json-schema.org/draft-04/schema": MustLoadJSONSchemaDraft04(),
+ }}
+}
+
+func cacheOrDefault(cache ResolutionCache) ResolutionCache {
+ onceCache.Do(initResolutionCache)
+
+ if cache != nil {
+ return cache
+ }
+
+ // get a shallow clone of the base cache with swagger and json schema
+ return resCache.ShallowClone()
+}
diff --git a/vendor/github.com/go-openapi/spec/contact_info.go b/vendor/github.com/go-openapi/spec/contact_info.go
new file mode 100644
index 000000000000..fafe639b45d6
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/contact_info.go
@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// ContactInfo contact information for the exposed API.
+//
+// For more information: http://goo.gl/8us55a#contactObject
+type ContactInfo struct {
+ ContactInfoProps
+ VendorExtensible
+}
+
+// ContactInfoProps hold the properties of a ContactInfo object
+type ContactInfoProps struct {
+ Name string `json:"name,omitempty"`
+ URL string `json:"url,omitempty"`
+ Email string `json:"email,omitempty"`
+}
+
+// UnmarshalJSON hydrates ContactInfo from json
+func (c *ContactInfo) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &c.ContactInfoProps); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &c.VendorExtensible)
+}
+
+// MarshalJSON produces ContactInfo as json
+func (c ContactInfo) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(c.ContactInfoProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(c.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2), nil
+}
diff --git a/vendor/github.com/go-openapi/spec/debug.go b/vendor/github.com/go-openapi/spec/debug.go
new file mode 100644
index 000000000000..f4316c26333d
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/debug.go
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path"
+ "runtime"
+)
+
+// Debug is true when the SWAGGER_DEBUG env var is not empty.
+//
+// It enables a more verbose logging of this package.
+var Debug = os.Getenv("SWAGGER_DEBUG") != ""
+
+var (
+ // specLogger is a debug logger for this package
+ specLogger *log.Logger
+)
+
+func init() {
+ debugOptions()
+}
+
+func debugOptions() {
+ specLogger = log.New(os.Stdout, "spec:", log.LstdFlags)
+}
+
+func debugLog(msg string, args ...any) {
+ // A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog()
+ if Debug {
+ _, file1, pos1, _ := runtime.Caller(1)
+ specLogger.Printf("%s:%d: %s", path.Base(file1), pos1, fmt.Sprintf(msg, args...))
+ }
+}
diff --git a/vendor/github.com/go-openapi/spec/embed.go b/vendor/github.com/go-openapi/spec/embed.go
new file mode 100644
index 000000000000..0d0b69996cce
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/embed.go
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "embed"
+ "path"
+)
+
+//go:embed schemas/*.json schemas/*/*.json
+var assets embed.FS
+
+func jsonschemaDraft04JSONBytes() ([]byte, error) {
+ return assets.ReadFile(path.Join("schemas", "jsonschema-draft-04.json"))
+}
+
+func v2SchemaJSONBytes() ([]byte, error) {
+ return assets.ReadFile(path.Join("schemas", "v2", "schema.json"))
+}
diff --git a/vendor/github.com/go-openapi/spec/errors.go b/vendor/github.com/go-openapi/spec/errors.go
new file mode 100644
index 000000000000..e39ab8bf71e9
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/errors.go
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import "errors"
+
+// Error codes
+var (
+ // ErrUnknownTypeForReference indicates that a resolved reference was found in an unsupported container type
+ ErrUnknownTypeForReference = errors.New("unknown type for the resolved reference")
+
+ // ErrResolveRefNeedsAPointer indicates that a $ref target must be a valid JSON pointer
+ ErrResolveRefNeedsAPointer = errors.New("resolve ref: target needs to be a pointer")
+
+ // ErrDerefUnsupportedType indicates that a resolved reference was found in an unsupported container type.
+ // At the moment, $ref are supported only inside: schemas, parameters, responses, path items
+ ErrDerefUnsupportedType = errors.New("deref: unsupported type")
+
+ // ErrExpandUnsupportedType indicates that $ref expansion is attempted on some invalid type
+ ErrExpandUnsupportedType = errors.New("expand: unsupported type. Input should be of type *Parameter or *Response")
+
+ // ErrSpec is an error raised by the spec package
+ ErrSpec = errors.New("spec error")
+)
diff --git a/vendor/github.com/go-openapi/spec/expander.go b/vendor/github.com/go-openapi/spec/expander.go
new file mode 100644
index 000000000000..cc4bd1cba1ba
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/expander.go
@@ -0,0 +1,598 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+const smallPrealloc = 10
+
+// ExpandOptions provides options for the spec expander.
+//
+// RelativeBase is the path to the root document. This can be a remote URL or a path to a local file.
+//
+// If left empty, the root document is assumed to be located in the current working directory:
+// all relative $ref's will be resolved from there.
+//
+// PathLoader injects a document loading method. By default, this resolves to the function provided by the SpecLoader package variable.
+type ExpandOptions struct {
+ RelativeBase string // the path to the root document to expand. This is a file, not a directory
+ SkipSchemas bool // do not expand schemas, just paths, parameters and responses
+ ContinueOnError bool // continue expanding even after and error is found
+ PathLoader func(string) (json.RawMessage, error) `json:"-"` // the document loading method that takes a path as input and yields a json document
+ AbsoluteCircularRef bool // circular $ref remaining after expansion remain absolute URLs
+}
+
+func optionsOrDefault(opts *ExpandOptions) *ExpandOptions {
+ if opts != nil {
+ clone := *opts // shallow clone to avoid internal changes to be propagated to the caller
+ if clone.RelativeBase != "" {
+ clone.RelativeBase = normalizeBase(clone.RelativeBase)
+ }
+ // if the relative base is empty, let the schema loader choose a pseudo root document
+ return &clone
+ }
+ return &ExpandOptions{}
+}
+
+// ExpandSpec expands the references in a swagger spec
+func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
+ options = optionsOrDefault(options)
+ resolver := defaultSchemaLoader(spec, options, nil, nil)
+
+ specBasePath := options.RelativeBase
+
+ if !options.SkipSchemas {
+ for key, definition := range spec.Definitions {
+ parentRefs := make([]string, 0, smallPrealloc)
+ parentRefs = append(parentRefs, "#/definitions/"+key)
+
+ def, err := expandSchema(definition, parentRefs, resolver, specBasePath)
+ if resolver.shouldStopOnError(err) {
+ return err
+ }
+ if def != nil {
+ spec.Definitions[key] = *def
+ }
+ }
+ }
+
+ for key := range spec.Parameters {
+ parameter := spec.Parameters[key]
+ if err := expandParameterOrResponse(¶meter, resolver, specBasePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ spec.Parameters[key] = parameter
+ }
+
+ for key := range spec.Responses {
+ response := spec.Responses[key]
+ if err := expandParameterOrResponse(&response, resolver, specBasePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ spec.Responses[key] = response
+ }
+
+ if spec.Paths != nil {
+ for key := range spec.Paths.Paths {
+ pth := spec.Paths.Paths[key]
+ if err := expandPathItem(&pth, resolver, specBasePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ spec.Paths.Paths[key] = pth
+ }
+ }
+
+ return nil
+}
+
+const rootBase = ".root"
+
+// baseForRoot loads in the cache the root document and produces a fake ".root" base path entry
+// for further $ref resolution
+func baseForRoot(root any, cache ResolutionCache) string {
+ // cache the root document to resolve $ref's
+ normalizedBase := normalizeBase(rootBase)
+
+ if root == nil {
+ // ensure that we never leave a nil root: always cache the root base pseudo-document
+ cachedRoot, found := cache.Get(normalizedBase)
+ if found && cachedRoot != nil {
+ // the cache is already preloaded with a root
+ return normalizedBase
+ }
+
+ root = map[string]any{}
+ }
+
+ cache.Set(normalizedBase, root)
+
+ return normalizedBase
+}
+
+// ExpandSchema expands the refs in the schema object with reference to the root object.
+//
+// go-openapi/validate uses this function.
+//
+// Notice that it is impossible to reference a json schema in a different document other than root
+// (use ExpandSchemaWithBasePath to resolve external references).
+//
+// Setting the cache is optional and this parameter may safely be left to nil.
+func ExpandSchema(schema *Schema, root any, cache ResolutionCache) error {
+ cache = cacheOrDefault(cache)
+ if root == nil {
+ root = schema
+ }
+
+ opts := &ExpandOptions{
+ // when a root is specified, cache the root as an in-memory document for $ref retrieval
+ RelativeBase: baseForRoot(root, cache),
+ SkipSchemas: false,
+ ContinueOnError: false,
+ }
+
+ return ExpandSchemaWithBasePath(schema, cache, opts)
+}
+
+// ExpandSchemaWithBasePath expands the refs in the schema object, base path configured through expand options.
+//
+// Setting the cache is optional and this parameter may safely be left to nil.
+func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *ExpandOptions) error {
+ if schema == nil {
+ return nil
+ }
+
+ cache = cacheOrDefault(cache)
+
+ opts = optionsOrDefault(opts)
+
+ resolver := defaultSchemaLoader(nil, opts, cache, nil)
+
+ parentRefs := make([]string, 0, smallPrealloc)
+ s, err := expandSchema(*schema, parentRefs, resolver, opts.RelativeBase)
+ if err != nil {
+ return err
+ }
+ if s != nil {
+ // guard for when continuing on error
+ *schema = *s
+ }
+
+ return nil
+}
+
+func expandItems(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) {
+ if target.Items == nil {
+ return &target, nil
+ }
+
+ // array
+ if target.Items.Schema != nil {
+ t, err := expandSchema(*target.Items.Schema, parentRefs, resolver, basePath)
+ if err != nil {
+ return nil, err
+ }
+ *target.Items.Schema = *t
+ }
+
+ // tuple
+ for i := range target.Items.Schemas {
+ t, err := expandSchema(target.Items.Schemas[i], parentRefs, resolver, basePath)
+ if err != nil {
+ return nil, err
+ }
+ target.Items.Schemas[i] = *t
+ }
+
+ return &target, nil
+}
+
+func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) {
+ if target.Ref.String() == "" && target.Ref.IsRoot() {
+ newRef := normalizeRef(&target.Ref, basePath)
+ target.Ref = *newRef
+ return &target, nil
+ }
+
+ // change the base path of resolution when an ID is encountered
+ // otherwise the basePath should inherit the parent's
+ if target.ID != "" {
+ basePath, _ = resolver.setSchemaID(target, target.ID, basePath)
+ }
+
+ if target.Ref.String() != "" {
+ if !resolver.options.SkipSchemas {
+ return expandSchemaRef(target, parentRefs, resolver, basePath)
+ }
+
+ // when "expand" with SkipSchema, we just rebase the existing $ref without replacing
+ // the full schema.
+ rebasedRef, err := NewRef(normalizeURI(target.Ref.String(), basePath))
+ if err != nil {
+ return nil, err
+ }
+ target.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID)
+
+ return &target, nil
+ }
+
+ for k := range target.Definitions {
+ tt, err := expandSchema(target.Definitions[k], parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if tt != nil {
+ target.Definitions[k] = *tt
+ }
+ }
+
+ t, err := expandItems(target, parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ target = *t
+ }
+
+ for i := range target.AllOf {
+ t, err := expandSchema(target.AllOf[i], parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ target.AllOf[i] = *t
+ }
+ }
+
+ for i := range target.AnyOf {
+ t, err := expandSchema(target.AnyOf[i], parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ target.AnyOf[i] = *t
+ }
+ }
+
+ for i := range target.OneOf {
+ t, err := expandSchema(target.OneOf[i], parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ target.OneOf[i] = *t
+ }
+ }
+
+ if target.Not != nil {
+ t, err := expandSchema(*target.Not, parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ *target.Not = *t
+ }
+ }
+
+ for k := range target.Properties {
+ t, err := expandSchema(target.Properties[k], parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ target.Properties[k] = *t
+ }
+ }
+
+ if target.AdditionalProperties != nil && target.AdditionalProperties.Schema != nil {
+ t, err := expandSchema(*target.AdditionalProperties.Schema, parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ *target.AdditionalProperties.Schema = *t
+ }
+ }
+
+ for k := range target.PatternProperties {
+ t, err := expandSchema(target.PatternProperties[k], parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ target.PatternProperties[k] = *t
+ }
+ }
+
+ for k := range target.Dependencies {
+ if target.Dependencies[k].Schema != nil {
+ t, err := expandSchema(*target.Dependencies[k].Schema, parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ *target.Dependencies[k].Schema = *t
+ }
+ }
+ }
+
+ if target.AdditionalItems != nil && target.AdditionalItems.Schema != nil {
+ t, err := expandSchema(*target.AdditionalItems.Schema, parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return &target, err
+ }
+ if t != nil {
+ *target.AdditionalItems.Schema = *t
+ }
+ }
+ return &target, nil
+}
+
+func expandSchemaRef(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) {
+ // if a Ref is found, all sibling fields are skipped
+ // Ref also changes the resolution scope of children expandSchema
+
+ // here the resolution scope is changed because a $ref was encountered
+ normalizedRef := normalizeRef(&target.Ref, basePath)
+ normalizedBasePath := normalizedRef.RemoteURI()
+
+ if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
+ // this means there is a cycle in the recursion tree: return the Ref
+ // - circular refs cannot be expanded. We leave them as ref.
+ // - denormalization means that a new local file ref is set relative to the original basePath
+ debugLog("short circuit circular ref: basePath: %s, normalizedPath: %s, normalized ref: %s",
+ basePath, normalizedBasePath, normalizedRef.String())
+ if !resolver.options.AbsoluteCircularRef {
+ target.Ref = denormalizeRef(normalizedRef, resolver.context.basePath, resolver.context.rootID)
+ } else {
+ target.Ref = *normalizedRef
+ }
+ return &target, nil
+ }
+
+ var t *Schema
+ err := resolver.Resolve(&target.Ref, &t, basePath)
+ if resolver.shouldStopOnError(err) {
+ return nil, err
+ }
+
+ if t == nil {
+ // guard for when continuing on error
+ return &target, nil
+ }
+
+ parentRefs = append(parentRefs, normalizedRef.String())
+ transitiveResolver := resolver.transitiveResolver(basePath, target.Ref)
+
+ basePath = resolver.updateBasePath(transitiveResolver, normalizedBasePath)
+
+ return expandSchema(*t, parentRefs, transitiveResolver, basePath)
+}
+
+func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string) error {
+ if pathItem == nil {
+ return nil
+ }
+
+ parentRefs := make([]string, 0, smallPrealloc)
+ if err := resolver.deref(pathItem, parentRefs, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+
+ if pathItem.Ref.String() != "" {
+ transitiveResolver := resolver.transitiveResolver(basePath, pathItem.Ref)
+ basePath = transitiveResolver.updateBasePath(resolver, basePath)
+ resolver = transitiveResolver
+ }
+
+ pathItem.Ref = Ref{}
+ for i := range pathItem.Parameters {
+ if err := expandParameterOrResponse(&(pathItem.Parameters[i]), resolver, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ }
+
+ ops := []*Operation{
+ pathItem.Get,
+ pathItem.Head,
+ pathItem.Options,
+ pathItem.Put,
+ pathItem.Post,
+ pathItem.Patch,
+ pathItem.Delete,
+ }
+ for _, op := range ops {
+ if err := expandOperation(op, resolver, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func expandOperation(op *Operation, resolver *schemaLoader, basePath string) error {
+ if op == nil {
+ return nil
+ }
+
+ for i := range op.Parameters {
+ param := op.Parameters[i]
+ if err := expandParameterOrResponse(¶m, resolver, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ op.Parameters[i] = param
+ }
+
+ if op.Responses == nil {
+ return nil
+ }
+
+ responses := op.Responses
+ if err := expandParameterOrResponse(responses.Default, resolver, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+
+ for code := range responses.StatusCodeResponses {
+ response := responses.StatusCodeResponses[code]
+ if err := expandParameterOrResponse(&response, resolver, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+ responses.StatusCodeResponses[code] = response
+ }
+
+ return nil
+}
+
+// ExpandResponseWithRoot expands a response based on a root document, not a fetchable document
+//
+// Notice that it is impossible to reference a json schema in a different document other than root
+// (use ExpandResponse to resolve external references).
+//
+// Setting the cache is optional and this parameter may safely be left to nil.
+func ExpandResponseWithRoot(response *Response, root any, cache ResolutionCache) error {
+ cache = cacheOrDefault(cache)
+ opts := &ExpandOptions{
+ RelativeBase: baseForRoot(root, cache),
+ }
+ resolver := defaultSchemaLoader(root, opts, cache, nil)
+
+ return expandParameterOrResponse(response, resolver, opts.RelativeBase)
+}
+
+// ExpandResponse expands a response based on a basepath
+//
+// All refs inside response will be resolved relative to basePath
+func ExpandResponse(response *Response, basePath string) error {
+ opts := optionsOrDefault(&ExpandOptions{
+ RelativeBase: basePath,
+ })
+ resolver := defaultSchemaLoader(nil, opts, nil, nil)
+
+ return expandParameterOrResponse(response, resolver, opts.RelativeBase)
+}
+
+// ExpandParameterWithRoot expands a parameter based on a root document, not a fetchable document.
+//
+// Notice that it is impossible to reference a json schema in a different document other than root
+// (use ExpandParameter to resolve external references).
+func ExpandParameterWithRoot(parameter *Parameter, root any, cache ResolutionCache) error {
+ cache = cacheOrDefault(cache)
+
+ opts := &ExpandOptions{
+ RelativeBase: baseForRoot(root, cache),
+ }
+ resolver := defaultSchemaLoader(root, opts, cache, nil)
+
+ return expandParameterOrResponse(parameter, resolver, opts.RelativeBase)
+}
+
+// ExpandParameter expands a parameter based on a basepath.
+// This is the exported version of expandParameter
+// all refs inside parameter will be resolved relative to basePath
+func ExpandParameter(parameter *Parameter, basePath string) error {
+ opts := optionsOrDefault(&ExpandOptions{
+ RelativeBase: basePath,
+ })
+ resolver := defaultSchemaLoader(nil, opts, nil, nil)
+
+ return expandParameterOrResponse(parameter, resolver, opts.RelativeBase)
+}
+
+func getRefAndSchema(input any) (*Ref, *Schema, error) {
+ var (
+ ref *Ref
+ sch *Schema
+ )
+
+ switch refable := input.(type) {
+ case *Parameter:
+ if refable == nil {
+ return nil, nil, nil
+ }
+ ref = &refable.Ref
+ sch = refable.Schema
+ case *Response:
+ if refable == nil {
+ return nil, nil, nil
+ }
+ ref = &refable.Ref
+ sch = refable.Schema
+ default:
+ return nil, nil, fmt.Errorf("unsupported type: %T: %w", input, ErrExpandUnsupportedType)
+ }
+
+ return ref, sch, nil
+}
+
+func expandParameterOrResponse(input any, resolver *schemaLoader, basePath string) error {
+ ref, sch, err := getRefAndSchema(input)
+ if err != nil {
+ return err
+ }
+
+ if ref == nil && sch == nil { // nothing to do
+ return nil
+ }
+
+ parentRefs := make([]string, 0, smallPrealloc)
+ if ref != nil {
+ // dereference this $ref
+ if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) {
+ return err
+ }
+
+ ref, sch, _ = getRefAndSchema(input)
+ }
+
+ if ref.String() != "" {
+ transitiveResolver := resolver.transitiveResolver(basePath, *ref)
+ basePath = resolver.updateBasePath(transitiveResolver, basePath)
+ resolver = transitiveResolver
+ }
+
+ if sch == nil {
+ // nothing to be expanded
+ if ref != nil {
+ *ref = Ref{}
+ }
+
+ return nil
+ }
+
+ if sch.Ref.String() != "" {
+ rebasedRef, ern := NewRef(normalizeURI(sch.Ref.String(), basePath))
+ if ern != nil {
+ return ern
+ }
+
+ if resolver.isCircular(&rebasedRef, basePath, parentRefs...) {
+ // this is a circular $ref: stop expansion
+ if !resolver.options.AbsoluteCircularRef {
+ sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID)
+ } else {
+ sch.Ref = rebasedRef
+ }
+ }
+ }
+
+ // $ref expansion or rebasing is performed by expandSchema below
+ if ref != nil {
+ *ref = Ref{}
+ }
+
+ // expand schema
+ // yes, we do it even if options.SkipSchema is true: we have to go down that rabbit hole and rebase nested $ref)
+ s, err := expandSchema(*sch, parentRefs, resolver, basePath)
+ if resolver.shouldStopOnError(err) {
+ return err
+ }
+
+ if s != nil { // guard for when continuing on error
+ *sch = *s
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/spec/external_docs.go b/vendor/github.com/go-openapi/spec/external_docs.go
new file mode 100644
index 000000000000..17b8efbf1008
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/external_docs.go
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+// ExternalDocumentation allows referencing an external resource for
+// extended documentation.
+//
+// For more information: http://goo.gl/8us55a#externalDocumentationObject
+type ExternalDocumentation struct {
+ Description string `json:"description,omitempty"`
+ URL string `json:"url,omitempty"`
+}
diff --git a/vendor/github.com/go-openapi/spec/header.go b/vendor/github.com/go-openapi/spec/header.go
new file mode 100644
index 000000000000..ab251ef76595
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/header.go
@@ -0,0 +1,192 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+const (
+ jsonArray = "array"
+)
+
+// HeaderProps describes a response header
+type HeaderProps struct {
+ Description string `json:"description,omitempty"`
+}
+
+// Header describes a header for a response of the API
+//
+// For more information: http://goo.gl/8us55a#headerObject
+type Header struct {
+ CommonValidations
+ SimpleSchema
+ VendorExtensible
+ HeaderProps
+}
+
+// ResponseHeader creates a new header instance for use in a response
+func ResponseHeader() *Header {
+ return new(Header)
+}
+
+// WithDescription sets the description on this response, allows for chaining
+func (h *Header) WithDescription(description string) *Header {
+ h.Description = description
+ return h
+}
+
+// Typed a fluent builder method for the type of parameter
+func (h *Header) Typed(tpe, format string) *Header {
+ h.Type = tpe
+ h.Format = format
+ return h
+}
+
+// CollectionOf a fluent builder method for an array item
+func (h *Header) CollectionOf(items *Items, format string) *Header {
+ h.Type = jsonArray
+ h.Items = items
+ h.CollectionFormat = format
+ return h
+}
+
+// WithDefault sets the default value on this item
+func (h *Header) WithDefault(defaultValue any) *Header {
+ h.Default = defaultValue
+ return h
+}
+
+// WithMaxLength sets a max length value
+func (h *Header) WithMaxLength(maximum int64) *Header {
+ h.MaxLength = &maximum
+ return h
+}
+
+// WithMinLength sets a min length value
+func (h *Header) WithMinLength(minimum int64) *Header {
+ h.MinLength = &minimum
+ return h
+}
+
+// WithPattern sets a pattern value
+func (h *Header) WithPattern(pattern string) *Header {
+ h.Pattern = pattern
+ return h
+}
+
+// WithMultipleOf sets a multiple of value
+func (h *Header) WithMultipleOf(number float64) *Header {
+ h.MultipleOf = &number
+ return h
+}
+
+// WithMaximum sets a maximum number value
+func (h *Header) WithMaximum(maximum float64, exclusive bool) *Header {
+ h.Maximum = &maximum
+ h.ExclusiveMaximum = exclusive
+ return h
+}
+
+// WithMinimum sets a minimum number value
+func (h *Header) WithMinimum(minimum float64, exclusive bool) *Header {
+ h.Minimum = &minimum
+ h.ExclusiveMinimum = exclusive
+ return h
+}
+
+// WithEnum sets a the enum values (replace)
+func (h *Header) WithEnum(values ...any) *Header {
+ h.Enum = append([]any{}, values...)
+ return h
+}
+
+// WithMaxItems sets the max items
+func (h *Header) WithMaxItems(size int64) *Header {
+ h.MaxItems = &size
+ return h
+}
+
+// WithMinItems sets the min items
+func (h *Header) WithMinItems(size int64) *Header {
+ h.MinItems = &size
+ return h
+}
+
+// UniqueValues dictates that this array can only have unique items
+func (h *Header) UniqueValues() *Header {
+ h.UniqueItems = true
+ return h
+}
+
+// AllowDuplicates this array can have duplicates
+func (h *Header) AllowDuplicates() *Header {
+ h.UniqueItems = false
+ return h
+}
+
+// WithValidations is a fluent method to set header validations
+func (h *Header) WithValidations(val CommonValidations) *Header {
+ h.SetValidations(SchemaValidations{CommonValidations: val})
+ return h
+}
+
+// MarshalJSON marshal this to JSON
+func (h Header) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(h.CommonValidations)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(h.SimpleSchema)
+ if err != nil {
+ return nil, err
+ }
+ b3, err := json.Marshal(h.HeaderProps)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2, b3), nil
+}
+
+// UnmarshalJSON unmarshals this header from JSON
+func (h *Header) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &h.CommonValidations); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &h.SimpleSchema); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &h.VendorExtensible); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &h.HeaderProps)
+}
+
+// JSONLookup look up a value by the json property name
+func (h Header) JSONLookup(token string) (any, error) {
+ if ex, ok := h.Extensions[token]; ok {
+ return &ex, nil
+ }
+
+ r, _, err := jsonpointer.GetForToken(h.CommonValidations, token)
+ if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
+ return nil, err
+ }
+ if r != nil {
+ return r, nil
+ }
+ r, _, err = jsonpointer.GetForToken(h.SimpleSchema, token)
+ if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
+ return nil, err
+ }
+ if r != nil {
+ return r, nil
+ }
+ r, _, err = jsonpointer.GetForToken(h.HeaderProps, token)
+ return r, err
+}
diff --git a/vendor/github.com/go-openapi/spec/info.go b/vendor/github.com/go-openapi/spec/info.go
new file mode 100644
index 000000000000..9401065bbdeb
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/info.go
@@ -0,0 +1,173 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "strconv"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// Extensions vendor specific extensions
+type Extensions map[string]any
+
+// Add adds a value to these extensions
+func (e Extensions) Add(key string, value any) {
+ realKey := strings.ToLower(key)
+ e[realKey] = value
+}
+
+// GetString gets a string value from the extensions
+func (e Extensions) GetString(key string) (string, bool) {
+ if v, ok := e[strings.ToLower(key)]; ok {
+ str, ok := v.(string)
+ return str, ok
+ }
+ return "", false
+}
+
+// GetInt gets a int value from the extensions
+func (e Extensions) GetInt(key string) (int, bool) {
+ realKey := strings.ToLower(key)
+
+ if v, ok := e.GetString(realKey); ok {
+ if r, err := strconv.Atoi(v); err == nil {
+ return r, true
+ }
+ }
+
+ if v, ok := e[realKey]; ok {
+ if r, rOk := v.(float64); rOk {
+ return int(r), true
+ }
+ }
+ return -1, false
+}
+
+// GetBool gets a string value from the extensions
+func (e Extensions) GetBool(key string) (bool, bool) {
+ if v, ok := e[strings.ToLower(key)]; ok {
+ str, ok := v.(bool)
+ return str, ok
+ }
+ return false, false
+}
+
+// GetStringSlice gets a string value from the extensions
+func (e Extensions) GetStringSlice(key string) ([]string, bool) {
+ if v, ok := e[strings.ToLower(key)]; ok {
+ arr, isSlice := v.([]any)
+ if !isSlice {
+ return nil, false
+ }
+ var strs []string
+ for _, iface := range arr {
+ str, isString := iface.(string)
+ if !isString {
+ return nil, false
+ }
+ strs = append(strs, str)
+ }
+ return strs, ok
+ }
+ return nil, false
+}
+
+// VendorExtensible composition block.
+type VendorExtensible struct {
+ Extensions Extensions
+}
+
+// AddExtension adds an extension to this extensible object
+func (v *VendorExtensible) AddExtension(key string, value any) {
+ if value == nil {
+ return
+ }
+ if v.Extensions == nil {
+ v.Extensions = make(map[string]any)
+ }
+ v.Extensions.Add(key, value)
+}
+
+// MarshalJSON marshals the extensions to json
+func (v VendorExtensible) MarshalJSON() ([]byte, error) {
+ toser := make(map[string]any)
+ for k, v := range v.Extensions {
+ lk := strings.ToLower(k)
+ if strings.HasPrefix(lk, "x-") {
+ toser[k] = v
+ }
+ }
+ return json.Marshal(toser)
+}
+
+// UnmarshalJSON for this extensible object
+func (v *VendorExtensible) UnmarshalJSON(data []byte) error {
+ var d map[string]any
+ if err := json.Unmarshal(data, &d); err != nil {
+ return err
+ }
+ for k, vv := range d {
+ lk := strings.ToLower(k)
+ if strings.HasPrefix(lk, "x-") {
+ if v.Extensions == nil {
+ v.Extensions = map[string]any{}
+ }
+ v.Extensions[k] = vv
+ }
+ }
+ return nil
+}
+
+// InfoProps the properties for an info definition
+type InfoProps struct {
+ Description string `json:"description,omitempty"`
+ Title string `json:"title,omitempty"`
+ TermsOfService string `json:"termsOfService,omitempty"`
+ Contact *ContactInfo `json:"contact,omitempty"`
+ License *License `json:"license,omitempty"`
+ Version string `json:"version,omitempty"`
+}
+
+// Info object provides metadata about the API.
+// The metadata can be used by the clients if needed, and can be presented in the Swagger-UI for convenience.
+//
+// For more information: http://goo.gl/8us55a#infoObject
+type Info struct {
+ VendorExtensible
+ InfoProps
+}
+
+// JSONLookup look up a value by the json property name
+func (i Info) JSONLookup(token string) (any, error) {
+ if ex, ok := i.Extensions[token]; ok {
+ return &ex, nil
+ }
+ r, _, err := jsonpointer.GetForToken(i.InfoProps, token)
+ return r, err
+}
+
+// MarshalJSON marshal this to JSON
+func (i Info) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(i.InfoProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(i.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2), nil
+}
+
+// UnmarshalJSON marshal this from JSON
+func (i *Info) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &i.InfoProps); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &i.VendorExtensible)
+}
diff --git a/vendor/github.com/go-openapi/spec/items.go b/vendor/github.com/go-openapi/spec/items.go
new file mode 100644
index 000000000000..d30ca3569b11
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/items.go
@@ -0,0 +1,223 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+const (
+ jsonRef = "$ref"
+)
+
+// SimpleSchema describe swagger simple schemas for parameters and headers
+type SimpleSchema struct {
+ Type string `json:"type,omitempty"`
+ Nullable bool `json:"nullable,omitempty"`
+ Format string `json:"format,omitempty"`
+ Items *Items `json:"items,omitempty"`
+ CollectionFormat string `json:"collectionFormat,omitempty"`
+ Default any `json:"default,omitempty"`
+ Example any `json:"example,omitempty"`
+}
+
+// TypeName return the type (or format) of a simple schema
+func (s *SimpleSchema) TypeName() string {
+ if s.Format != "" {
+ return s.Format
+ }
+ return s.Type
+}
+
+// ItemsTypeName yields the type of items in a simple schema array
+func (s *SimpleSchema) ItemsTypeName() string {
+ if s.Items == nil {
+ return ""
+ }
+ return s.Items.TypeName()
+}
+
+// Items a limited subset of JSON-Schema's items object.
+// It is used by parameter definitions that are not located in "body".
+//
+// For more information: http://goo.gl/8us55a#items-object
+type Items struct {
+ Refable
+ CommonValidations
+ SimpleSchema
+ VendorExtensible
+}
+
+// NewItems creates a new instance of items
+func NewItems() *Items {
+ return &Items{}
+}
+
+// Typed a fluent builder method for the type of item
+func (i *Items) Typed(tpe, format string) *Items {
+ i.Type = tpe
+ i.Format = format
+ return i
+}
+
+// AsNullable flags this schema as nullable.
+func (i *Items) AsNullable() *Items {
+ i.Nullable = true
+ return i
+}
+
+// CollectionOf a fluent builder method for an array item
+func (i *Items) CollectionOf(items *Items, format string) *Items {
+ i.Type = jsonArray
+ i.Items = items
+ i.CollectionFormat = format
+ return i
+}
+
+// WithDefault sets the default value on this item
+func (i *Items) WithDefault(defaultValue any) *Items {
+ i.Default = defaultValue
+ return i
+}
+
+// WithMaxLength sets a max length value
+func (i *Items) WithMaxLength(maximum int64) *Items {
+ i.MaxLength = &maximum
+ return i
+}
+
+// WithMinLength sets a min length value
+func (i *Items) WithMinLength(minimum int64) *Items {
+ i.MinLength = &minimum
+ return i
+}
+
+// WithPattern sets a pattern value
+func (i *Items) WithPattern(pattern string) *Items {
+ i.Pattern = pattern
+ return i
+}
+
+// WithMultipleOf sets a multiple of value
+func (i *Items) WithMultipleOf(number float64) *Items {
+ i.MultipleOf = &number
+ return i
+}
+
+// WithMaximum sets a maximum number value
+func (i *Items) WithMaximum(maximum float64, exclusive bool) *Items {
+ i.Maximum = &maximum
+ i.ExclusiveMaximum = exclusive
+ return i
+}
+
+// WithMinimum sets a minimum number value
+func (i *Items) WithMinimum(minimum float64, exclusive bool) *Items {
+ i.Minimum = &minimum
+ i.ExclusiveMinimum = exclusive
+ return i
+}
+
+// WithEnum sets a the enum values (replace)
+func (i *Items) WithEnum(values ...any) *Items {
+ i.Enum = append([]any{}, values...)
+ return i
+}
+
+// WithMaxItems sets the max items
+func (i *Items) WithMaxItems(size int64) *Items {
+ i.MaxItems = &size
+ return i
+}
+
+// WithMinItems sets the min items
+func (i *Items) WithMinItems(size int64) *Items {
+ i.MinItems = &size
+ return i
+}
+
+// UniqueValues dictates that this array can only have unique items
+func (i *Items) UniqueValues() *Items {
+ i.UniqueItems = true
+ return i
+}
+
+// AllowDuplicates this array can have duplicates
+func (i *Items) AllowDuplicates() *Items {
+ i.UniqueItems = false
+ return i
+}
+
+// WithValidations is a fluent method to set Items validations
+func (i *Items) WithValidations(val CommonValidations) *Items {
+ i.SetValidations(SchemaValidations{CommonValidations: val})
+ return i
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (i *Items) UnmarshalJSON(data []byte) error {
+ var validations CommonValidations
+ if err := json.Unmarshal(data, &validations); err != nil {
+ return err
+ }
+ var ref Refable
+ if err := json.Unmarshal(data, &ref); err != nil {
+ return err
+ }
+ var simpleSchema SimpleSchema
+ if err := json.Unmarshal(data, &simpleSchema); err != nil {
+ return err
+ }
+ var vendorExtensible VendorExtensible
+ if err := json.Unmarshal(data, &vendorExtensible); err != nil {
+ return err
+ }
+ i.Refable = ref
+ i.CommonValidations = validations
+ i.SimpleSchema = simpleSchema
+ i.VendorExtensible = vendorExtensible
+ return nil
+}
+
+// MarshalJSON converts this items object to JSON
+func (i Items) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(i.CommonValidations)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(i.SimpleSchema)
+ if err != nil {
+ return nil, err
+ }
+ b3, err := json.Marshal(i.Refable)
+ if err != nil {
+ return nil, err
+ }
+ b4, err := json.Marshal(i.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b4, b3, b1, b2), nil
+}
+
+// JSONLookup look up a value by the json property name
+func (i Items) JSONLookup(token string) (any, error) {
+ if token == jsonRef {
+ return &i.Ref, nil
+ }
+
+ r, _, err := jsonpointer.GetForToken(i.CommonValidations, token)
+ if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
+ return nil, err
+ }
+ if r != nil {
+ return r, nil
+ }
+ r, _, err = jsonpointer.GetForToken(i.SimpleSchema, token)
+ return r, err
+}
diff --git a/vendor/github.com/go-openapi/spec/license.go b/vendor/github.com/go-openapi/spec/license.go
new file mode 100644
index 000000000000..286b237e2bf7
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/license.go
@@ -0,0 +1,45 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// License information for the exposed API.
+//
+// For more information: http://goo.gl/8us55a#licenseObject
+type License struct {
+ LicenseProps
+ VendorExtensible
+}
+
+// LicenseProps holds the properties of a License object
+type LicenseProps struct {
+ Name string `json:"name,omitempty"`
+ URL string `json:"url,omitempty"`
+}
+
+// UnmarshalJSON hydrates License from json
+func (l *License) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &l.LicenseProps); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &l.VendorExtensible)
+}
+
+// MarshalJSON produces License as json
+func (l License) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(l.LicenseProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(l.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2), nil
+}
diff --git a/vendor/github.com/go-openapi/spec/normalizer.go b/vendor/github.com/go-openapi/spec/normalizer.go
new file mode 100644
index 000000000000..c3ea810aaf34
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/normalizer.go
@@ -0,0 +1,191 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "net/url"
+ "path"
+ "strings"
+)
+
+const fileScheme = "file"
+
+// normalizeURI ensures that all $ref paths used internally by the expander are canonicalized.
+//
+// NOTE(windows): there is a tolerance over the strict URI format on windows.
+//
+// The normalizer accepts relative file URLs like 'Path\File.JSON' as well as absolute file URLs like
+// 'C:\Path\file.Yaml'.
+//
+// Both are canonicalized with a "file://" scheme, slashes and a lower-cased path:
+// 'file:///c:/path/file.yaml'
+//
+// URLs can be specified with a file scheme, like in 'file:///folder/file.json' or
+// 'file:///c:\folder\File.json'.
+//
+// URLs like file://C:\folder are considered invalid (i.e. there is no host 'c:\folder') and a "repair"
+// is attempted.
+//
+// The base path argument is assumed to be canonicalized (e.g. using normalizeBase()).
+func normalizeURI(refPath, base string) string {
+ refURL, err := parseURL(refPath)
+ if err != nil {
+ specLogger.Printf("warning: invalid URI in $ref %q: %v", refPath, err)
+ refURL, refPath = repairURI(refPath)
+ }
+
+ fixWindowsURI(refURL, refPath) // noop on non-windows OS
+
+ refURL.Path = path.Clean(refURL.Path)
+ if refURL.Path == "." {
+ refURL.Path = ""
+ }
+
+ r := MustCreateRef(refURL.String())
+ if r.IsCanonical() {
+ return refURL.String()
+ }
+
+ baseURL, _ := parseURL(base)
+ if path.IsAbs(refURL.Path) {
+ baseURL.Path = refURL.Path
+ } else if refURL.Path != "" {
+ baseURL.Path = path.Join(path.Dir(baseURL.Path), refURL.Path)
+ }
+ // copying fragment from ref to base
+ baseURL.Fragment = refURL.Fragment
+
+ return baseURL.String()
+}
+
+// denormalizeRef returns the simplest notation for a normalized $ref, given the path of the original root document.
+//
+// When calling this, we assume that:
+// * $ref is a canonical URI
+// * originalRelativeBase is a canonical URI
+//
+// denormalizeRef is currently used when we rewrite a $ref after a circular $ref has been detected.
+// In this case, expansion stops and normally renders the internal canonical $ref.
+//
+// This internal $ref is eventually rebased to the original RelativeBase used for the expansion.
+//
+// There is a special case for schemas that are anchored with an "id":
+// in that case, the rebasing is performed // against the id only if this is an anchor for the initial root document.
+// All other intermediate "id"'s found along the way are ignored for the purpose of rebasing.
+func denormalizeRef(ref *Ref, originalRelativeBase, id string) Ref {
+ debugLog("denormalizeRef called:\n$ref: %q\noriginal: %s\nroot ID:%s", ref.String(), originalRelativeBase, id)
+
+ if ref.String() == "" || ref.IsRoot() || ref.HasFragmentOnly {
+ // short circuit: $ref to current doc
+ return *ref
+ }
+
+ if id != "" {
+ idBaseURL, err := parseURL(id)
+ if err == nil { // if the schema id is not usable as a URI, ignore it
+ if ref, ok := rebase(ref, idBaseURL, true); ok { // rebase, but keep references to root unchaged (do not want $ref: "")
+ // $ref relative to the ID of the schema in the root document
+ return ref
+ }
+ }
+ }
+
+ originalRelativeBaseURL, _ := parseURL(originalRelativeBase)
+
+ r, _ := rebase(ref, originalRelativeBaseURL, false)
+
+ return r
+}
+
+func rebase(ref *Ref, v *url.URL, notEqual bool) (Ref, bool) {
+ var newBase url.URL
+
+ u := ref.GetURL()
+
+ if u.Scheme != v.Scheme || u.Host != v.Host {
+ return *ref, false
+ }
+
+ docPath := v.Path
+ v.Path = path.Dir(v.Path)
+
+ if v.Path == "." {
+ v.Path = ""
+ } else if !strings.HasSuffix(v.Path, "/") {
+ v.Path += "/"
+ }
+
+ newBase.Fragment = u.Fragment
+
+ if after, ok := strings.CutPrefix(u.Path, docPath); ok {
+ newBase.Path = after
+ } else {
+ newBase.Path = strings.TrimPrefix(u.Path, v.Path)
+ }
+
+ if notEqual && newBase.Path == "" && newBase.Fragment == "" {
+ // do not want rebasing to end up in an empty $ref
+ return *ref, false
+ }
+
+ if path.IsAbs(newBase.Path) {
+ // whenever we end up with an absolute path, specify the scheme and host
+ newBase.Scheme = v.Scheme
+ newBase.Host = v.Host
+ }
+
+ return MustCreateRef(newBase.String()), true
+}
+
+// normalizeRef canonicalize a Ref, using a canonical relativeBase as its absolute anchor
+func normalizeRef(ref *Ref, relativeBase string) *Ref {
+ r := MustCreateRef(normalizeURI(ref.String(), relativeBase))
+ return &r
+}
+
+// normalizeBase performs a normalization of the input base path.
+//
+// This always yields a canonical URI (absolute), usable for the document cache.
+//
+// It ensures that all further internal work on basePath may safely assume
+// a non-empty, cross-platform, canonical URI (i.e. absolute).
+//
+// This normalization tolerates windows paths (e.g. C:\x\y\File.dat) and transform this
+// in a file:// URL with lower cased drive letter and path.
+//
+// See also: https://en.wikipedia.org/wiki/File_URI_scheme
+func normalizeBase(in string) string {
+ u, err := parseURL(in)
+ if err != nil {
+ specLogger.Printf("warning: invalid URI in RelativeBase %q: %v", in, err)
+ u, in = repairURI(in)
+ }
+
+ u.Fragment = "" // any fragment in the base is irrelevant
+
+ fixWindowsURI(u, in) // noop on non-windows OS
+
+ u.Path = path.Clean(u.Path)
+ if u.Path == "." { // empty after Clean()
+ u.Path = ""
+ }
+
+ if u.Scheme != "" {
+ if path.IsAbs(u.Path) || u.Scheme != fileScheme {
+ // this is absolute or explicitly not a local file: we're good
+ return u.String()
+ }
+ }
+
+ // no scheme or file scheme with relative path: assume file and make it absolute
+ // enforce scheme file://... with absolute path.
+ //
+ // If the input path is relative, we anchor the path to the current working directory.
+ // NOTE: we may end up with a host component. Leave it unchanged: e.g. file://host/folder/file.json
+
+ u.Scheme = fileScheme
+ u.Path = absPath(u.Path) // platform-dependent
+ u.RawQuery = "" // any query component is irrelevant for a base
+ return u.String()
+}
diff --git a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go
new file mode 100644
index 000000000000..0d55632349f8
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go
@@ -0,0 +1,32 @@
+//go:build !windows
+
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "net/url"
+ "path/filepath"
+)
+
+// absPath makes a file path absolute and compatible with a URI path component.
+//
+// The parameter must be a path, not an URI.
+func absPath(in string) string {
+ anchored, err := filepath.Abs(in)
+ if err != nil {
+ specLogger.Printf("warning: could not resolve current working directory: %v", err)
+ return in
+ }
+ return anchored
+}
+
+func repairURI(in string) (*url.URL, string) {
+ u, _ := parseURL("")
+ debugLog("repaired URI: original: %q, repaired: %q", in, "")
+ return u, ""
+}
+
+func fixWindowsURI(_ *url.URL, _ string) {
+}
diff --git a/vendor/github.com/go-openapi/spec/normalizer_windows.go b/vendor/github.com/go-openapi/spec/normalizer_windows.go
new file mode 100644
index 000000000000..61515c9a163f
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/normalizer_windows.go
@@ -0,0 +1,143 @@
+// -build windows
+
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "net/url"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+// absPath makes a file path absolute and compatible with a URI path component
+//
+// The parameter must be a path, not an URI.
+func absPath(in string) string {
+ // NOTE(windows): filepath.Abs exhibits a special behavior on windows for empty paths.
+ // See https://github.com/golang/go/issues/24441
+ if in == "" {
+ in = "."
+ }
+
+ anchored, err := filepath.Abs(in)
+ if err != nil {
+ specLogger.Printf("warning: could not resolve current working directory: %v", err)
+ return in
+ }
+
+ pth := strings.ReplaceAll(strings.ToLower(anchored), `\`, `/`)
+ if !strings.HasPrefix(pth, "/") {
+ pth = "/" + pth
+ }
+
+ return path.Clean(pth)
+}
+
+// repairURI tolerates invalid file URIs with common typos
+// such as 'file://E:\folder\file', that break the regular URL parser.
+//
+// Adopting the same defaults as for unixes (e.g. return an empty path) would
+// result into a counter-intuitive result for that case (e.g. E:\folder\file is
+// eventually resolved as the current directory). The repair will detect the missing "/".
+//
+// Note that this only works for the file scheme.
+func repairURI(in string) (*url.URL, string) {
+ const prefix = fileScheme + "://"
+ if !strings.HasPrefix(in, prefix) {
+ // giving up: resolve to empty path
+ u, _ := parseURL("")
+
+ return u, ""
+ }
+
+ // attempt the repair, stripping the scheme should be sufficient
+ u, _ := parseURL(strings.TrimPrefix(in, prefix))
+ debugLog("repaired URI: original: %q, repaired: %q", in, u.String())
+
+ return u, u.String()
+}
+
+// fixWindowsURI tolerates an absolute file path on windows such as C:\Base\File.yaml or \\host\share\Base\File.yaml
+// and makes it a canonical URI: file:///c:/base/file.yaml
+//
+// Catch 22 notes for Windows:
+//
+// * There may be a drive letter on windows (it is lower-cased)
+// * There may be a share UNC, e.g. \\server\folder\data.xml
+// * Paths are case insensitive
+// * Paths may already contain slashes
+// * Paths must be slashed
+//
+// NOTE: there is no escaping. "/" may be valid separators just like "\".
+// We don't use ToSlash() (which escapes everything) because windows now also
+// tolerates the use of "/". Hence, both C:\File.yaml and C:/File.yaml will work.
+func fixWindowsURI(u *url.URL, in string) {
+ drive := filepath.VolumeName(in)
+
+ if len(drive) > 0 {
+ if len(u.Scheme) == 1 && strings.EqualFold(u.Scheme, drive[:1]) { // a path with a drive letter
+ u.Scheme = fileScheme
+ u.Host = ""
+ u.Path = strings.Join([]string{drive, u.Opaque, u.Path}, `/`) // reconstruct the full path component (no fragment, no query)
+ } else if u.Host == "" && strings.HasPrefix(u.Path, drive) { // a path with a \\host volume
+ // NOTE: the special host@port syntax for UNC is not supported (yet)
+ u.Scheme = fileScheme
+
+ // this is a modified version of filepath.Dir() to apply on the VolumeName itself
+ i := len(drive) - 1
+ for i >= 0 && !os.IsPathSeparator(drive[i]) {
+ i--
+ }
+ host := drive[:i] // \\host\share => host
+
+ u.Path = strings.TrimPrefix(u.Path, host)
+ u.Host = strings.TrimPrefix(host, `\\`)
+ }
+
+ u.Opaque = ""
+ u.Path = strings.ReplaceAll(strings.ToLower(u.Path), `\`, `/`)
+
+ // ensure we form an absolute path
+ if !strings.HasPrefix(u.Path, "/") {
+ u.Path = "/" + u.Path
+ }
+
+ u.Path = path.Clean(u.Path)
+
+ return
+ }
+
+ if u.Scheme == fileScheme {
+ // Handle dodgy cases for file://{...} URIs on windows.
+ // A canonical URI should always be followed by an absolute path.
+ //
+ // Examples:
+ // * file:///folder/file => valid, unchanged
+ // * file:///c:\folder\file => slashed
+ // * file:///./folder/file => valid, cleaned to remove the dot
+ // * file:///.\folder\file => remapped to cwd
+ // * file:///. => dodgy, remapped to / (consistent with the behavior on unix)
+ // * file:///.. => dodgy, remapped to / (consistent with the behavior on unix)
+ if (!path.IsAbs(u.Path) && !filepath.IsAbs(u.Path)) || (strings.HasPrefix(u.Path, `/.`) && strings.Contains(u.Path, `\`)) {
+ // ensure we form an absolute path
+ u.Path, _ = filepath.Abs(strings.TrimLeft(u.Path, `/`))
+ if !strings.HasPrefix(u.Path, "/") {
+ u.Path = "/" + u.Path
+ }
+ }
+ u.Path = strings.ToLower(u.Path)
+ }
+
+ // NOTE: lower case normalization does not propagate to inner resources,
+ // generated when rebasing: when joining a relative URI with a file to an absolute base,
+ // only the base is currently lower-cased.
+ //
+ // For now, we assume this is good enough for most use cases
+ // and try not to generate too many differences
+ // between the output produced on different platforms.
+ u.Path = path.Clean(strings.ReplaceAll(u.Path, `\`, `/`))
+}
diff --git a/vendor/github.com/go-openapi/spec/operation.go b/vendor/github.com/go-openapi/spec/operation.go
new file mode 100644
index 000000000000..bbf8c7573723
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/operation.go
@@ -0,0 +1,392 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/json"
+ "sort"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+func init() {
+ gob.Register(map[string]any{})
+ gob.Register([]any{})
+}
+
+// OperationProps describes an operation
+//
+// NOTES:
+// - schemes, when present must be from [http, https, ws, wss]: see validate
+// - Security is handled as a special case: see MarshalJSON function
+type OperationProps struct {
+ Description string `json:"description,omitempty"`
+ Consumes []string `json:"consumes,omitempty"`
+ Produces []string `json:"produces,omitempty"`
+ Schemes []string `json:"schemes,omitempty"`
+ Tags []string `json:"tags,omitempty"`
+ Summary string `json:"summary,omitempty"`
+ ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
+ ID string `json:"operationId,omitempty"`
+ Deprecated bool `json:"deprecated,omitempty"`
+ Security []map[string][]string `json:"security,omitempty"`
+ Parameters []Parameter `json:"parameters,omitempty"`
+ Responses *Responses `json:"responses,omitempty"`
+}
+
+// MarshalJSON takes care of serializing operation properties to JSON
+//
+// We use a custom marhaller here to handle a special cases related to
+// the Security field. We need to preserve zero length slice
+// while omitting the field when the value is nil/unset.
+func (op OperationProps) MarshalJSON() ([]byte, error) {
+ type Alias OperationProps
+ if op.Security == nil {
+ return json.Marshal(&struct {
+ *Alias
+
+ Security []map[string][]string `json:"security,omitempty"`
+ }{
+ Alias: (*Alias)(&op),
+ Security: op.Security,
+ })
+ }
+
+ return json.Marshal(&struct {
+ *Alias
+
+ Security []map[string][]string `json:"security"`
+ }{
+ Alias: (*Alias)(&op),
+ Security: op.Security,
+ })
+}
+
+// Operation describes a single API operation on a path.
+//
+// For more information: http://goo.gl/8us55a#operationObject
+type Operation struct {
+ VendorExtensible
+ OperationProps
+}
+
+// NewOperation creates a new operation instance.
+// It expects an ID as parameter but not passing an ID is also valid.
+func NewOperation(id string) *Operation {
+ op := new(Operation)
+ op.ID = id
+ return op
+}
+
+// SuccessResponse gets a success response model
+func (o *Operation) SuccessResponse() (*Response, int, bool) {
+ if o.Responses == nil {
+ return nil, 0, false
+ }
+
+ responseCodes := make([]int, 0, len(o.Responses.StatusCodeResponses))
+ for k := range o.Responses.StatusCodeResponses {
+ if k >= 200 && k < 300 {
+ responseCodes = append(responseCodes, k)
+ }
+ }
+ if len(responseCodes) > 0 {
+ sort.Ints(responseCodes)
+ v := o.Responses.StatusCodeResponses[responseCodes[0]]
+ return &v, responseCodes[0], true
+ }
+
+ return o.Responses.Default, 0, false
+}
+
+// JSONLookup look up a value by the json property name
+func (o Operation) JSONLookup(token string) (any, error) {
+ if ex, ok := o.Extensions[token]; ok {
+ return &ex, nil
+ }
+ r, _, err := jsonpointer.GetForToken(o.OperationProps, token)
+ return r, err
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (o *Operation) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &o.OperationProps); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &o.VendorExtensible)
+}
+
+// MarshalJSON converts this items object to JSON
+func (o Operation) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(o.OperationProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(o.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ concated := jsonutils.ConcatJSON(b1, b2)
+ return concated, nil
+}
+
+// WithID sets the ID property on this operation, allows for chaining.
+func (o *Operation) WithID(id string) *Operation {
+ o.ID = id
+ return o
+}
+
+// WithDescription sets the description on this operation, allows for chaining
+func (o *Operation) WithDescription(description string) *Operation {
+ o.Description = description
+ return o
+}
+
+// WithSummary sets the summary on this operation, allows for chaining
+func (o *Operation) WithSummary(summary string) *Operation {
+ o.Summary = summary
+ return o
+}
+
+// WithExternalDocs sets/removes the external docs for/from this operation.
+// When you pass empty strings as params the external documents will be removed.
+// When you pass non-empty string as one value then those values will be used on the external docs object.
+// So when you pass a non-empty description, you should also pass the url and vice versa.
+func (o *Operation) WithExternalDocs(description, url string) *Operation {
+ if description == "" && url == "" {
+ o.ExternalDocs = nil
+ return o
+ }
+
+ if o.ExternalDocs == nil {
+ o.ExternalDocs = &ExternalDocumentation{}
+ }
+ o.ExternalDocs.Description = description
+ o.ExternalDocs.URL = url
+ return o
+}
+
+// Deprecate marks the operation as deprecated
+func (o *Operation) Deprecate() *Operation {
+ o.Deprecated = true
+ return o
+}
+
+// Undeprecate marks the operation as not deprected
+func (o *Operation) Undeprecate() *Operation {
+ o.Deprecated = false
+ return o
+}
+
+// WithConsumes adds media types for incoming body values
+func (o *Operation) WithConsumes(mediaTypes ...string) *Operation {
+ o.Consumes = append(o.Consumes, mediaTypes...)
+ return o
+}
+
+// WithProduces adds media types for outgoing body values
+func (o *Operation) WithProduces(mediaTypes ...string) *Operation {
+ o.Produces = append(o.Produces, mediaTypes...)
+ return o
+}
+
+// WithTags adds tags for this operation
+func (o *Operation) WithTags(tags ...string) *Operation {
+ o.Tags = append(o.Tags, tags...)
+ return o
+}
+
+// AddParam adds a parameter to this operation, when a parameter for that location
+// and with that name already exists it will be replaced
+func (o *Operation) AddParam(param *Parameter) *Operation {
+ if param == nil {
+ return o
+ }
+
+ for i, p := range o.Parameters {
+ if p.Name == param.Name && p.In == param.In {
+ params := make([]Parameter, 0, len(o.Parameters)+1)
+ params = append(params, o.Parameters[:i]...)
+ params = append(params, *param)
+ params = append(params, o.Parameters[i+1:]...)
+ o.Parameters = params
+
+ return o
+ }
+ }
+
+ o.Parameters = append(o.Parameters, *param)
+ return o
+}
+
+// RemoveParam removes a parameter from the operation
+func (o *Operation) RemoveParam(name, in string) *Operation {
+ for i, p := range o.Parameters {
+ if p.Name == name && p.In == in {
+ o.Parameters = append(o.Parameters[:i], o.Parameters[i+1:]...)
+ return o
+ }
+ }
+ return o
+}
+
+// SecuredWith adds a security scope to this operation.
+func (o *Operation) SecuredWith(name string, scopes ...string) *Operation {
+ o.Security = append(o.Security, map[string][]string{name: scopes})
+ return o
+}
+
+// WithDefaultResponse adds a default response to the operation.
+// Passing a nil value will remove the response
+func (o *Operation) WithDefaultResponse(response *Response) *Operation {
+ return o.RespondsWith(0, response)
+}
+
+// RespondsWith adds a status code response to the operation.
+// When the code is 0 the value of the response will be used as default response value.
+// When the value of the response is nil it will be removed from the operation
+func (o *Operation) RespondsWith(code int, response *Response) *Operation {
+ if o.Responses == nil {
+ o.Responses = new(Responses)
+ }
+ if code == 0 {
+ o.Responses.Default = response
+ return o
+ }
+ if response == nil {
+ delete(o.Responses.StatusCodeResponses, code)
+ return o
+ }
+ if o.Responses.StatusCodeResponses == nil {
+ o.Responses.StatusCodeResponses = make(map[int]Response)
+ }
+ o.Responses.StatusCodeResponses[code] = *response
+ return o
+}
+
+type opsAlias OperationProps
+
+type gobAlias struct {
+ Security []map[string]struct {
+ List []string
+ Pad bool
+ }
+ Alias *opsAlias
+ SecurityIsEmpty bool
+}
+
+// GobEncode provides a safe gob encoder for Operation, including empty security requirements
+func (o Operation) GobEncode() ([]byte, error) {
+ raw := struct {
+ Ext VendorExtensible
+ Props OperationProps
+ }{
+ Ext: o.VendorExtensible,
+ Props: o.OperationProps,
+ }
+ var b bytes.Buffer
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+}
+
+// GobDecode provides a safe gob decoder for Operation, including empty security requirements
+func (o *Operation) GobDecode(b []byte) error {
+ var raw struct {
+ Ext VendorExtensible
+ Props OperationProps
+ }
+
+ buf := bytes.NewBuffer(b)
+ err := gob.NewDecoder(buf).Decode(&raw)
+ if err != nil {
+ return err
+ }
+ o.VendorExtensible = raw.Ext
+ o.OperationProps = raw.Props
+ return nil
+}
+
+// GobEncode provides a safe gob encoder for Operation, including empty security requirements
+func (op OperationProps) GobEncode() ([]byte, error) {
+ raw := gobAlias{
+ Alias: (*opsAlias)(&op),
+ }
+
+ var b bytes.Buffer
+ if op.Security == nil {
+ // nil security requirement
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+ }
+
+ if len(op.Security) == 0 {
+ // empty, but non-nil security requirement
+ raw.SecurityIsEmpty = true
+ raw.Alias.Security = nil
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+ }
+
+ raw.Security = make([]map[string]struct {
+ List []string
+ Pad bool
+ }, 0, len(op.Security))
+ for _, req := range op.Security {
+ v := make(map[string]struct {
+ List []string
+ Pad bool
+ }, len(req))
+ for k, val := range req {
+ v[k] = struct {
+ List []string
+ Pad bool
+ }{
+ List: val,
+ }
+ }
+ raw.Security = append(raw.Security, v)
+ }
+
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+}
+
+// GobDecode provides a safe gob decoder for Operation, including empty security requirements
+func (op *OperationProps) GobDecode(b []byte) error {
+ var raw gobAlias
+
+ buf := bytes.NewBuffer(b)
+ err := gob.NewDecoder(buf).Decode(&raw)
+ if err != nil {
+ return err
+ }
+ if raw.Alias == nil {
+ return nil
+ }
+
+ switch {
+ case raw.SecurityIsEmpty:
+ // empty, but non-nil security requirement
+ raw.Alias.Security = []map[string][]string{}
+ case len(raw.Alias.Security) == 0:
+ // nil security requirement
+ raw.Alias.Security = nil
+ default:
+ raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security))
+ for _, req := range raw.Security {
+ v := make(map[string][]string, len(req))
+ for k, val := range req {
+ v[k] = make([]string, 0, len(val.List))
+ v[k] = append(v[k], val.List...)
+ }
+ raw.Alias.Security = append(raw.Alias.Security, v)
+ }
+ }
+
+ *op = *(*OperationProps)(raw.Alias)
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/spec/parameter.go b/vendor/github.com/go-openapi/spec/parameter.go
new file mode 100644
index 000000000000..b94b7682ac8e
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/parameter.go
@@ -0,0 +1,315 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// QueryParam creates a query parameter
+func QueryParam(name string) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name, In: "query"}}
+}
+
+// HeaderParam creates a header parameter, this is always required by default
+func HeaderParam(name string) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name, In: "header", Required: true}}
+}
+
+// PathParam creates a path parameter, this is always required
+func PathParam(name string) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name, In: "path", Required: true}}
+}
+
+// BodyParam creates a body parameter
+func BodyParam(name string, schema *Schema) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name, In: "body", Schema: schema}}
+}
+
+// FormDataParam creates a body parameter
+func FormDataParam(name string) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"}}
+}
+
+// FileParam creates a body parameter
+func FileParam(name string) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"},
+ SimpleSchema: SimpleSchema{Type: "file"}}
+}
+
+// SimpleArrayParam creates a param for a simple array (string, int, date etc)
+func SimpleArrayParam(name, tpe, fmt string) *Parameter {
+ return &Parameter{ParamProps: ParamProps{Name: name},
+ SimpleSchema: SimpleSchema{Type: jsonArray, CollectionFormat: "csv",
+ Items: &Items{SimpleSchema: SimpleSchema{Type: tpe, Format: fmt}}}}
+}
+
+// ParamRef creates a parameter that's a json reference
+func ParamRef(uri string) *Parameter {
+ p := new(Parameter)
+ p.Ref = MustCreateRef(uri)
+ return p
+}
+
+// ParamProps describes the specific attributes of an operation parameter
+//
+// NOTE:
+// - Schema is defined when "in" == "body": see validate
+// - AllowEmptyValue is allowed where "in" == "query" || "formData"
+type ParamProps struct {
+ Description string `json:"description,omitempty"`
+ Name string `json:"name,omitempty"`
+ In string `json:"in,omitempty"`
+ Required bool `json:"required,omitempty"`
+ Schema *Schema `json:"schema,omitempty"`
+ AllowEmptyValue bool `json:"allowEmptyValue,omitempty"`
+}
+
+// Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn).
+//
+// There are five possible parameter types.
+// - Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part
+// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`,
+// the path parameter is `itemId`.
+// - Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`.
+// - Header - Custom headers that are expected as part of the request.
+// - Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be
+// _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for
+// documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist
+// together for the same operation.
+// - Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or
+// `multipart/form-data` are used as the content type of the request (in Swagger's definition,
+// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used
+// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be
+// declared together with a body parameter for the same operation. Form parameters have a different format based on
+// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4).
+// - `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload.
+// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple
+// parameters that are being transferred.
+// - `multipart/form-data` - each parameter takes a section in the payload with an internal header.
+// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is
+// `submit-name`. This type of form parameters is more commonly used for file transfers.
+//
+// For more information: http://goo.gl/8us55a#parameterObject
+type Parameter struct {
+ Refable
+ CommonValidations
+ SimpleSchema
+ VendorExtensible
+ ParamProps
+}
+
+// JSONLookup look up a value by the json property name
+func (p Parameter) JSONLookup(token string) (any, error) {
+ if ex, ok := p.Extensions[token]; ok {
+ return &ex, nil
+ }
+ if token == jsonRef {
+ return &p.Ref, nil
+ }
+
+ r, _, err := jsonpointer.GetForToken(p.CommonValidations, token)
+ if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
+ return nil, err
+ }
+ if r != nil {
+ return r, nil
+ }
+ r, _, err = jsonpointer.GetForToken(p.SimpleSchema, token)
+ if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
+ return nil, err
+ }
+ if r != nil {
+ return r, nil
+ }
+ r, _, err = jsonpointer.GetForToken(p.ParamProps, token)
+ return r, err
+}
+
+// WithDescription a fluent builder method for the description of the parameter
+func (p *Parameter) WithDescription(description string) *Parameter {
+ p.Description = description
+ return p
+}
+
+// Named a fluent builder method to override the name of the parameter
+func (p *Parameter) Named(name string) *Parameter {
+ p.Name = name
+ return p
+}
+
+// WithLocation a fluent builder method to override the location of the parameter
+func (p *Parameter) WithLocation(in string) *Parameter {
+ p.In = in
+ return p
+}
+
+// Typed a fluent builder method for the type of the parameter value
+func (p *Parameter) Typed(tpe, format string) *Parameter {
+ p.Type = tpe
+ p.Format = format
+ return p
+}
+
+// CollectionOf a fluent builder method for an array parameter
+func (p *Parameter) CollectionOf(items *Items, format string) *Parameter {
+ p.Type = jsonArray
+ p.Items = items
+ p.CollectionFormat = format
+ return p
+}
+
+// WithDefault sets the default value on this parameter
+func (p *Parameter) WithDefault(defaultValue any) *Parameter {
+ p.AsOptional() // with default implies optional
+ p.Default = defaultValue
+ return p
+}
+
+// AllowsEmptyValues flags this parameter as being ok with empty values
+func (p *Parameter) AllowsEmptyValues() *Parameter {
+ p.AllowEmptyValue = true
+ return p
+}
+
+// NoEmptyValues flags this parameter as not liking empty values
+func (p *Parameter) NoEmptyValues() *Parameter {
+ p.AllowEmptyValue = false
+ return p
+}
+
+// AsOptional flags this parameter as optional
+func (p *Parameter) AsOptional() *Parameter {
+ p.Required = false
+ return p
+}
+
+// AsRequired flags this parameter as required
+func (p *Parameter) AsRequired() *Parameter {
+ if p.Default != nil { // with a default required makes no sense
+ return p
+ }
+ p.Required = true
+ return p
+}
+
+// WithMaxLength sets a max length value
+func (p *Parameter) WithMaxLength(maximum int64) *Parameter {
+ p.MaxLength = &maximum
+ return p
+}
+
+// WithMinLength sets a min length value
+func (p *Parameter) WithMinLength(minimum int64) *Parameter {
+ p.MinLength = &minimum
+ return p
+}
+
+// WithPattern sets a pattern value
+func (p *Parameter) WithPattern(pattern string) *Parameter {
+ p.Pattern = pattern
+ return p
+}
+
+// WithMultipleOf sets a multiple of value
+func (p *Parameter) WithMultipleOf(number float64) *Parameter {
+ p.MultipleOf = &number
+ return p
+}
+
+// WithMaximum sets a maximum number value
+func (p *Parameter) WithMaximum(maximum float64, exclusive bool) *Parameter {
+ p.Maximum = &maximum
+ p.ExclusiveMaximum = exclusive
+ return p
+}
+
+// WithMinimum sets a minimum number value
+func (p *Parameter) WithMinimum(minimum float64, exclusive bool) *Parameter {
+ p.Minimum = &minimum
+ p.ExclusiveMinimum = exclusive
+ return p
+}
+
+// WithEnum sets a the enum values (replace)
+func (p *Parameter) WithEnum(values ...any) *Parameter {
+ p.Enum = append([]any{}, values...)
+ return p
+}
+
+// WithMaxItems sets the max items
+func (p *Parameter) WithMaxItems(size int64) *Parameter {
+ p.MaxItems = &size
+ return p
+}
+
+// WithMinItems sets the min items
+func (p *Parameter) WithMinItems(size int64) *Parameter {
+ p.MinItems = &size
+ return p
+}
+
+// UniqueValues dictates that this array can only have unique items
+func (p *Parameter) UniqueValues() *Parameter {
+ p.UniqueItems = true
+ return p
+}
+
+// AllowDuplicates this array can have duplicates
+func (p *Parameter) AllowDuplicates() *Parameter {
+ p.UniqueItems = false
+ return p
+}
+
+// WithValidations is a fluent method to set parameter validations
+func (p *Parameter) WithValidations(val CommonValidations) *Parameter {
+ p.SetValidations(SchemaValidations{CommonValidations: val})
+ return p
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (p *Parameter) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &p.CommonValidations); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &p.Refable); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &p.SimpleSchema); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &p.VendorExtensible); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &p.ParamProps)
+}
+
+// MarshalJSON converts this items object to JSON
+func (p Parameter) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(p.CommonValidations)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(p.SimpleSchema)
+ if err != nil {
+ return nil, err
+ }
+ b3, err := json.Marshal(p.Refable)
+ if err != nil {
+ return nil, err
+ }
+ b4, err := json.Marshal(p.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ b5, err := json.Marshal(p.ParamProps)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b3, b1, b2, b4, b5), nil
+}
diff --git a/vendor/github.com/go-openapi/spec/path_item.go b/vendor/github.com/go-openapi/spec/path_item.go
new file mode 100644
index 000000000000..c692b89e46c6
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/path_item.go
@@ -0,0 +1,76 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// PathItemProps the path item specific properties
+type PathItemProps struct {
+ Get *Operation `json:"get,omitempty"`
+ Put *Operation `json:"put,omitempty"`
+ Post *Operation `json:"post,omitempty"`
+ Delete *Operation `json:"delete,omitempty"`
+ Options *Operation `json:"options,omitempty"`
+ Head *Operation `json:"head,omitempty"`
+ Patch *Operation `json:"patch,omitempty"`
+ Parameters []Parameter `json:"parameters,omitempty"`
+}
+
+// PathItem describes the operations available on a single path.
+// A Path Item may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering).
+// The path itself is still exposed to the documentation viewer but they will
+// not know which operations and parameters are available.
+//
+// For more information: http://goo.gl/8us55a#pathItemObject
+type PathItem struct {
+ Refable
+ VendorExtensible
+ PathItemProps
+}
+
+// JSONLookup look up a value by the json property name
+func (p PathItem) JSONLookup(token string) (any, error) {
+ if ex, ok := p.Extensions[token]; ok {
+ return &ex, nil
+ }
+ if token == jsonRef {
+ return &p.Ref, nil
+ }
+ r, _, err := jsonpointer.GetForToken(p.PathItemProps, token)
+ return r, err
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (p *PathItem) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &p.Refable); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &p.VendorExtensible); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &p.PathItemProps)
+}
+
+// MarshalJSON converts this items object to JSON
+func (p PathItem) MarshalJSON() ([]byte, error) {
+ b3, err := json.Marshal(p.Refable)
+ if err != nil {
+ return nil, err
+ }
+ b4, err := json.Marshal(p.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ b5, err := json.Marshal(p.PathItemProps)
+ if err != nil {
+ return nil, err
+ }
+ concated := jsonutils.ConcatJSON(b3, b4, b5)
+ return concated, nil
+}
diff --git a/vendor/github.com/go-openapi/spec/paths.go b/vendor/github.com/go-openapi/spec/paths.go
new file mode 100644
index 000000000000..b9e42184b19e
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/paths.go
@@ -0,0 +1,87 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// Paths holds the relative paths to the individual endpoints.
+// The path is appended to the [`basePath`](http://goo.gl/8us55a#swaggerBasePath) in order
+// to construct the full URL.
+// The Paths may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering).
+//
+// For more information: http://goo.gl/8us55a#pathsObject
+type Paths struct {
+ VendorExtensible
+
+ Paths map[string]PathItem `json:"-"` // custom serializer to flatten this, each entry must start with "/"
+}
+
+// JSONLookup look up a value by the json property name
+func (p Paths) JSONLookup(token string) (any, error) {
+ if pi, ok := p.Paths[token]; ok {
+ return &pi, nil
+ }
+ if ex, ok := p.Extensions[token]; ok {
+ return &ex, nil
+ }
+ return nil, fmt.Errorf("object has no field %q: %w", token, ErrSpec)
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (p *Paths) UnmarshalJSON(data []byte) error {
+ var res map[string]json.RawMessage
+ if err := json.Unmarshal(data, &res); err != nil {
+ return err
+ }
+ for k, v := range res {
+ if strings.HasPrefix(strings.ToLower(k), "x-") {
+ if p.Extensions == nil {
+ p.Extensions = make(map[string]any)
+ }
+ var d any
+ if err := json.Unmarshal(v, &d); err != nil {
+ return err
+ }
+ p.Extensions[k] = d
+ }
+ if strings.HasPrefix(k, "/") {
+ if p.Paths == nil {
+ p.Paths = make(map[string]PathItem)
+ }
+ var pi PathItem
+ if err := json.Unmarshal(v, &pi); err != nil {
+ return err
+ }
+ p.Paths[k] = pi
+ }
+ }
+ return nil
+}
+
+// MarshalJSON converts this items object to JSON
+func (p Paths) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(p.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+
+ pths := make(map[string]PathItem)
+ for k, v := range p.Paths {
+ if strings.HasPrefix(k, "/") {
+ pths[k] = v
+ }
+ }
+ b2, err := json.Marshal(pths)
+ if err != nil {
+ return nil, err
+ }
+ concated := jsonutils.ConcatJSON(b1, b2)
+ return concated, nil
+}
diff --git a/vendor/github.com/go-openapi/spec/properties.go b/vendor/github.com/go-openapi/spec/properties.go
new file mode 100644
index 000000000000..4142308dd397
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/properties.go
@@ -0,0 +1,95 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "bytes"
+ "encoding/json"
+ "reflect"
+ "sort"
+)
+
+// OrderSchemaItem holds a named schema (e.g. from a property of an object)
+type OrderSchemaItem struct {
+ Schema
+
+ Name string
+}
+
+// OrderSchemaItems is a sortable slice of named schemas.
+// The ordering is defined by the x-order schema extension.
+type OrderSchemaItems []OrderSchemaItem
+
+// MarshalJSON produces a json object with keys defined by the name schemas
+// of the OrderSchemaItems slice, keeping the original order of the slice.
+func (items OrderSchemaItems) MarshalJSON() ([]byte, error) {
+ buf := bytes.NewBuffer(nil)
+ buf.WriteString("{")
+ for i := range items {
+ if i > 0 {
+ buf.WriteString(",")
+ }
+ buf.WriteString("\"")
+ buf.WriteString(items[i].Name)
+ buf.WriteString("\":")
+ bs, err := json.Marshal(&items[i].Schema)
+ if err != nil {
+ return nil, err
+ }
+ buf.Write(bs)
+ }
+ buf.WriteString("}")
+ return buf.Bytes(), nil
+}
+
+func (items OrderSchemaItems) Len() int { return len(items) }
+func (items OrderSchemaItems) Swap(i, j int) { items[i], items[j] = items[j], items[i] }
+func (items OrderSchemaItems) Less(i, j int) (ret bool) {
+ ii, oki := items[i].Extensions.GetInt("x-order")
+ ij, okj := items[j].Extensions.GetInt("x-order")
+ if oki {
+ if okj {
+ defer func() {
+ if err := recover(); err != nil {
+ defer func() {
+ if err = recover(); err != nil {
+ ret = items[i].Name < items[j].Name
+ }
+ }()
+ ret = reflect.ValueOf(ii).String() < reflect.ValueOf(ij).String()
+ }
+ }()
+ return ii < ij
+ }
+ return true
+ } else if okj {
+ return false
+ }
+ return items[i].Name < items[j].Name
+}
+
+// SchemaProperties is a map representing the properties of a Schema object.
+// It knows how to transform its keys into an ordered slice.
+type SchemaProperties map[string]Schema
+
+// ToOrderedSchemaItems transforms the map of properties into a sortable slice
+func (properties SchemaProperties) ToOrderedSchemaItems() OrderSchemaItems {
+ items := make(OrderSchemaItems, 0, len(properties))
+ for k, v := range properties {
+ items = append(items, OrderSchemaItem{
+ Name: k,
+ Schema: v,
+ })
+ }
+ sort.Sort(items)
+ return items
+}
+
+// MarshalJSON produces properties as json, keeping their order.
+func (properties SchemaProperties) MarshalJSON() ([]byte, error) {
+ if properties == nil {
+ return []byte("null"), nil
+ }
+ return json.Marshal(properties.ToOrderedSchemaItems())
+}
diff --git a/vendor/github.com/go-openapi/spec/ref.go b/vendor/github.com/go-openapi/spec/ref.go
new file mode 100644
index 000000000000..c9279262942b
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/ref.go
@@ -0,0 +1,184 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/json"
+ "net/http"
+ "os"
+ "path/filepath"
+
+ "github.com/go-openapi/jsonreference"
+)
+
+// Refable is a struct for things that accept a $ref property
+type Refable struct {
+ Ref Ref
+}
+
+// MarshalJSON marshals the ref to json
+func (r Refable) MarshalJSON() ([]byte, error) {
+ return r.Ref.MarshalJSON()
+}
+
+// UnmarshalJSON unmarshalss the ref from json
+func (r *Refable) UnmarshalJSON(d []byte) error {
+ return json.Unmarshal(d, &r.Ref)
+}
+
+// Ref represents a json reference that is potentially resolved
+type Ref struct {
+ jsonreference.Ref
+}
+
+// NewRef creates a new instance of a ref object
+// returns an error when the reference uri is an invalid uri
+func NewRef(refURI string) (Ref, error) {
+ ref, err := jsonreference.New(refURI)
+ if err != nil {
+ return Ref{}, err
+ }
+
+ return Ref{Ref: ref}, nil
+}
+
+// MustCreateRef creates a ref object but panics when refURI is invalid.
+// Use the NewRef method for a version that returns an error.
+func MustCreateRef(refURI string) Ref {
+ return Ref{Ref: jsonreference.MustCreateRef(refURI)}
+}
+
+// RemoteURI gets the remote uri part of the ref
+func (r *Ref) RemoteURI() string {
+ if r.String() == "" {
+ return ""
+ }
+
+ u := *r.GetURL()
+ u.Fragment = ""
+ return u.String()
+}
+
+// IsValidURI returns true when the url the ref points to can be found
+func (r *Ref) IsValidURI(basepaths ...string) bool {
+ if r.String() == "" {
+ return true
+ }
+
+ v := r.RemoteURI()
+ if v == "" {
+ return true
+ }
+
+ if r.HasFullURL {
+ //nolint:noctx,gosec
+ rr, err := http.Get(v)
+ if err != nil {
+ return false
+ }
+ defer rr.Body.Close()
+
+ // true if the response is >= 200 and < 300
+ return rr.StatusCode/100 == 2 //nolint:mnd
+ }
+
+ if !r.HasFileScheme && !r.HasFullFilePath && !r.HasURLPathOnly {
+ return false
+ }
+
+ // check for local file
+ pth := v
+ if r.HasURLPathOnly {
+ base := "."
+ if len(basepaths) > 0 {
+ base = filepath.Dir(filepath.Join(basepaths...))
+ }
+ p, e := filepath.Abs(filepath.ToSlash(filepath.Join(base, pth)))
+ if e != nil {
+ return false
+ }
+ pth = p
+ }
+
+ fi, err := os.Stat(filepath.ToSlash(pth))
+ if err != nil {
+ return false
+ }
+
+ return !fi.IsDir()
+}
+
+// Inherits creates a new reference from a parent and a child
+// If the child cannot inherit from the parent, an error is returned
+func (r *Ref) Inherits(child Ref) (*Ref, error) {
+ ref, err := r.Ref.Inherits(child.Ref)
+ if err != nil {
+ return nil, err
+ }
+ return &Ref{Ref: *ref}, nil
+}
+
+// MarshalJSON marshals this ref into a JSON object
+func (r Ref) MarshalJSON() ([]byte, error) {
+ str := r.String()
+ if str == "" {
+ if r.IsRoot() {
+ return []byte(`{"$ref":""}`), nil
+ }
+ return []byte("{}"), nil
+ }
+ v := map[string]any{"$ref": str}
+ return json.Marshal(v)
+}
+
+// UnmarshalJSON unmarshals this ref from a JSON object
+func (r *Ref) UnmarshalJSON(d []byte) error {
+ var v map[string]any
+ if err := json.Unmarshal(d, &v); err != nil {
+ return err
+ }
+ return r.fromMap(v)
+}
+
+// GobEncode provides a safe gob encoder for Ref
+func (r Ref) GobEncode() ([]byte, error) {
+ var b bytes.Buffer
+ raw, err := r.MarshalJSON()
+ if err != nil {
+ return nil, err
+ }
+ err = gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+}
+
+// GobDecode provides a safe gob decoder for Ref
+func (r *Ref) GobDecode(b []byte) error {
+ var raw []byte
+ buf := bytes.NewBuffer(b)
+ err := gob.NewDecoder(buf).Decode(&raw)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(raw, r)
+}
+
+func (r *Ref) fromMap(v map[string]any) error {
+ if v == nil {
+ return nil
+ }
+
+ if vv, ok := v["$ref"]; ok {
+ if str, ok := vv.(string); ok {
+ ref, err := jsonreference.New(str)
+ if err != nil {
+ return err
+ }
+ *r = Ref{Ref: ref}
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/spec/resolver.go b/vendor/github.com/go-openapi/spec/resolver.go
new file mode 100644
index 000000000000..b82c18213325
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/resolver.go
@@ -0,0 +1,130 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "fmt"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+func resolveAnyWithBase(root any, ref *Ref, result any, options *ExpandOptions) error {
+ options = optionsOrDefault(options)
+ resolver := defaultSchemaLoader(root, options, nil, nil)
+
+ if err := resolver.Resolve(ref, result, options.RelativeBase); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// ResolveRefWithBase resolves a reference against a context root with preservation of base path
+func ResolveRefWithBase(root any, ref *Ref, options *ExpandOptions) (*Schema, error) {
+ result := new(Schema)
+
+ if err := resolveAnyWithBase(root, ref, result, options); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// ResolveRef resolves a reference for a schema against a context root
+// ref is guaranteed to be in root (no need to go to external files)
+//
+// ResolveRef is ONLY called from the code generation module
+func ResolveRef(root any, ref *Ref) (*Schema, error) {
+ res, _, err := ref.GetPointer().Get(root)
+ if err != nil {
+ return nil, err
+ }
+
+ switch sch := res.(type) {
+ case Schema:
+ return &sch, nil
+ case *Schema:
+ return sch, nil
+ case map[string]any:
+ newSch := new(Schema)
+ if err = jsonutils.FromDynamicJSON(sch, newSch); err != nil {
+ return nil, err
+ }
+ return newSch, nil
+ default:
+ return nil, fmt.Errorf("type: %T: %w", sch, ErrUnknownTypeForReference)
+ }
+}
+
+// ResolveParameterWithBase resolves a parameter reference against a context root and base path
+func ResolveParameterWithBase(root any, ref Ref, options *ExpandOptions) (*Parameter, error) {
+ result := new(Parameter)
+
+ if err := resolveAnyWithBase(root, &ref, result, options); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// ResolveParameter resolves a parameter reference against a context root
+func ResolveParameter(root any, ref Ref) (*Parameter, error) {
+ return ResolveParameterWithBase(root, ref, nil)
+}
+
+// ResolveResponseWithBase resolves response a reference against a context root and base path
+func ResolveResponseWithBase(root any, ref Ref, options *ExpandOptions) (*Response, error) {
+ result := new(Response)
+
+ err := resolveAnyWithBase(root, &ref, result, options)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// ResolveResponse resolves response a reference against a context root
+func ResolveResponse(root any, ref Ref) (*Response, error) {
+ return ResolveResponseWithBase(root, ref, nil)
+}
+
+// ResolvePathItemWithBase resolves response a path item against a context root and base path
+func ResolvePathItemWithBase(root any, ref Ref, options *ExpandOptions) (*PathItem, error) {
+ result := new(PathItem)
+
+ if err := resolveAnyWithBase(root, &ref, result, options); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// ResolvePathItem resolves response a path item against a context root and base path
+//
+// Deprecated: use ResolvePathItemWithBase instead
+func ResolvePathItem(root any, ref Ref, options *ExpandOptions) (*PathItem, error) {
+ return ResolvePathItemWithBase(root, ref, options)
+}
+
+// ResolveItemsWithBase resolves parameter items reference against a context root and base path.
+//
+// NOTE: stricly speaking, this construct is not supported by Swagger 2.0.
+// Similarly, $ref are forbidden in response headers.
+func ResolveItemsWithBase(root any, ref Ref, options *ExpandOptions) (*Items, error) {
+ result := new(Items)
+
+ if err := resolveAnyWithBase(root, &ref, result, options); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// ResolveItems resolves parameter items reference against a context root and base path.
+//
+// Deprecated: use ResolveItemsWithBase instead
+func ResolveItems(root any, ref Ref, options *ExpandOptions) (*Items, error) {
+ return ResolveItemsWithBase(root, ref, options)
+}
diff --git a/vendor/github.com/go-openapi/spec/response.go b/vendor/github.com/go-openapi/spec/response.go
new file mode 100644
index 000000000000..e5a7e5c40d43
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/response.go
@@ -0,0 +1,141 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// ResponseProps properties specific to a response
+type ResponseProps struct {
+ Description string `json:"description"`
+ Schema *Schema `json:"schema,omitempty"`
+ Headers map[string]Header `json:"headers,omitempty"`
+ Examples map[string]any `json:"examples,omitempty"`
+}
+
+// Response describes a single response from an API Operation.
+//
+// For more information: http://goo.gl/8us55a#responseObject
+type Response struct {
+ Refable
+ ResponseProps
+ VendorExtensible
+}
+
+// NewResponse creates a new response instance
+func NewResponse() *Response {
+ return new(Response)
+}
+
+// ResponseRef creates a response as a json reference
+func ResponseRef(url string) *Response {
+ resp := NewResponse()
+ resp.Ref = MustCreateRef(url)
+ return resp
+}
+
+// JSONLookup look up a value by the json property name
+func (r Response) JSONLookup(token string) (any, error) {
+ if ex, ok := r.Extensions[token]; ok {
+ return &ex, nil
+ }
+ if token == "$ref" {
+ return &r.Ref, nil
+ }
+ ptr, _, err := jsonpointer.GetForToken(r.ResponseProps, token)
+ return ptr, err
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (r *Response) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &r.ResponseProps); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &r.Refable); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &r.VendorExtensible)
+}
+
+// MarshalJSON converts this items object to JSON
+func (r Response) MarshalJSON() ([]byte, error) {
+ var (
+ b1 []byte
+ err error
+ )
+
+ if r.Ref.String() == "" {
+ // when there is no $ref, empty description is rendered as an empty string
+ b1, err = json.Marshal(r.ResponseProps)
+ } else {
+ // when there is $ref inside the schema, description should be omitempty-ied
+ b1, err = json.Marshal(struct {
+ Description string `json:"description,omitempty"`
+ Schema *Schema `json:"schema,omitempty"`
+ Headers map[string]Header `json:"headers,omitempty"`
+ Examples map[string]any `json:"examples,omitempty"`
+ }{
+ Description: r.Description,
+ Schema: r.Schema,
+ Examples: r.Examples,
+ })
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ b2, err := json.Marshal(r.Refable)
+ if err != nil {
+ return nil, err
+ }
+ b3, err := json.Marshal(r.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2, b3), nil
+}
+
+// WithDescription sets the description on this response, allows for chaining
+func (r *Response) WithDescription(description string) *Response {
+ r.Description = description
+ return r
+}
+
+// WithSchema sets the schema on this response, allows for chaining.
+// Passing a nil argument removes the schema from this response
+func (r *Response) WithSchema(schema *Schema) *Response {
+ r.Schema = schema
+ return r
+}
+
+// AddHeader adds a header to this response
+func (r *Response) AddHeader(name string, header *Header) *Response {
+ if header == nil {
+ return r.RemoveHeader(name)
+ }
+ if r.Headers == nil {
+ r.Headers = make(map[string]Header)
+ }
+ r.Headers[name] = *header
+ return r
+}
+
+// RemoveHeader removes a header from this response
+func (r *Response) RemoveHeader(name string) *Response {
+ delete(r.Headers, name)
+ return r
+}
+
+// AddExample adds an example to this response
+func (r *Response) AddExample(mediaType string, example any) *Response {
+ if r.Examples == nil {
+ r.Examples = make(map[string]any)
+ }
+ r.Examples[mediaType] = example
+ return r
+}
diff --git a/vendor/github.com/go-openapi/spec/responses.go b/vendor/github.com/go-openapi/spec/responses.go
new file mode 100644
index 000000000000..733a1315d02b
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/responses.go
@@ -0,0 +1,129 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// Responses is a container for the expected responses of an operation.
+// The container maps a HTTP response code to the expected response.
+// It is not expected from the documentation to necessarily cover all possible HTTP response codes,
+// since they may not be known in advance. However, it is expected from the documentation to cover
+// a successful operation response and any known errors.
+//
+// The `default` can be used a default response object for all HTTP codes that are not covered
+// individually by the specification.
+//
+// The `Responses Object` MUST contain at least one response code, and it SHOULD be the response
+// for a successful operation call.
+//
+// For more information: http://goo.gl/8us55a#responsesObject
+type Responses struct {
+ VendorExtensible
+ ResponsesProps
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (r Responses) JSONLookup(token string) (any, error) {
+ if token == "default" {
+ return r.Default, nil
+ }
+ if ex, ok := r.Extensions[token]; ok {
+ return &ex, nil
+ }
+ if i, err := strconv.Atoi(token); err == nil {
+ if scr, ok := r.StatusCodeResponses[i]; ok {
+ return scr, nil
+ }
+ }
+ return nil, fmt.Errorf("object has no field %q: %w", token, ErrSpec)
+}
+
+// UnmarshalJSON hydrates this items instance with the data from JSON
+func (r *Responses) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &r.ResponsesProps); err != nil {
+ return err
+ }
+
+ if err := json.Unmarshal(data, &r.VendorExtensible); err != nil {
+ return err
+ }
+ if reflect.DeepEqual(ResponsesProps{}, r.ResponsesProps) {
+ r.ResponsesProps = ResponsesProps{}
+ }
+ return nil
+}
+
+// MarshalJSON converts this items object to JSON
+func (r Responses) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(r.ResponsesProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(r.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ concated := jsonutils.ConcatJSON(b1, b2)
+ return concated, nil
+}
+
+// ResponsesProps describes all responses for an operation.
+// It tells what is the default response and maps all responses with a
+// HTTP status code.
+type ResponsesProps struct {
+ Default *Response
+ StatusCodeResponses map[int]Response
+}
+
+// MarshalJSON marshals responses as JSON
+func (r ResponsesProps) MarshalJSON() ([]byte, error) {
+ toser := map[string]Response{}
+ if r.Default != nil {
+ toser["default"] = *r.Default
+ }
+ for k, v := range r.StatusCodeResponses {
+ toser[strconv.Itoa(k)] = v
+ }
+ return json.Marshal(toser)
+}
+
+// UnmarshalJSON unmarshals responses from JSON
+func (r *ResponsesProps) UnmarshalJSON(data []byte) error {
+ var res map[string]json.RawMessage
+ if err := json.Unmarshal(data, &res); err != nil {
+ return err
+ }
+
+ if v, ok := res["default"]; ok {
+ var defaultRes Response
+ if err := json.Unmarshal(v, &defaultRes); err != nil {
+ return err
+ }
+ r.Default = &defaultRes
+ delete(res, "default")
+ }
+ for k, v := range res {
+ if !strings.HasPrefix(k, "x-") {
+ var statusCodeResp Response
+ if err := json.Unmarshal(v, &statusCodeResp); err != nil {
+ return err
+ }
+ if nk, err := strconv.Atoi(k); err == nil {
+ if r.StatusCodeResponses == nil {
+ r.StatusCodeResponses = map[int]Response{}
+ }
+ r.StatusCodeResponses[nk] = statusCodeResp
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/spec/schema.go b/vendor/github.com/go-openapi/spec/schema.go
new file mode 100644
index 000000000000..6623728a41af
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/schema.go
@@ -0,0 +1,636 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonname"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// BooleanProperty creates a boolean property
+func BooleanProperty() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"boolean"}}}
+}
+
+// BoolProperty creates a boolean property
+func BoolProperty() *Schema { return BooleanProperty() }
+
+// StringProperty creates a string property
+func StringProperty() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}
+}
+
+// CharProperty creates a string property
+func CharProperty() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}
+}
+
+// Float64Property creates a float64/double property
+func Float64Property() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "double"}}
+}
+
+// Float32Property creates a float32/float property
+func Float32Property() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "float"}}
+}
+
+// Int8Property creates an int8 property
+func Int8Property() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int8"}}
+}
+
+// Int16Property creates an int16 property
+func Int16Property() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int16"}}
+}
+
+// Int32Property creates an int32 property
+func Int32Property() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int32"}}
+}
+
+// Int64Property creates an int64 property
+func Int64Property() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int64"}}
+}
+
+// StrFmtProperty creates a property for the named string format
+func StrFmtProperty(format string) *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: format}}
+}
+
+// DateProperty creates a date property
+func DateProperty() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date"}}
+}
+
+// DateTimeProperty creates a date time property
+func DateTimeProperty() *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date-time"}}
+}
+
+// MapProperty creates a map property
+func MapProperty(property *Schema) *Schema {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"object"},
+ AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}}
+}
+
+// RefProperty creates a ref property
+func RefProperty(name string) *Schema {
+ return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}}
+}
+
+// RefSchema creates a ref property
+func RefSchema(name string) *Schema {
+ return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}}
+}
+
+// ArrayProperty creates an array property
+func ArrayProperty(items *Schema) *Schema {
+ if items == nil {
+ return &Schema{SchemaProps: SchemaProps{Type: []string{"array"}}}
+ }
+ return &Schema{SchemaProps: SchemaProps{Items: &SchemaOrArray{Schema: items}, Type: []string{"array"}}}
+}
+
+// ComposedSchema creates a schema with allOf
+func ComposedSchema(schemas ...Schema) *Schema {
+ s := new(Schema)
+ s.AllOf = schemas
+ return s
+}
+
+// SchemaURL represents a schema url
+type SchemaURL string
+
+// MarshalJSON marshal this to JSON
+func (r SchemaURL) MarshalJSON() ([]byte, error) {
+ if r == "" {
+ return []byte("{}"), nil
+ }
+ v := map[string]any{"$schema": string(r)}
+ return json.Marshal(v)
+}
+
+// UnmarshalJSON unmarshal this from JSON
+func (r *SchemaURL) UnmarshalJSON(data []byte) error {
+ var v map[string]any
+ if err := json.Unmarshal(data, &v); err != nil {
+ return err
+ }
+ return r.fromMap(v)
+}
+
+func (r *SchemaURL) fromMap(v map[string]any) error {
+ if v == nil {
+ return nil
+ }
+ if vv, ok := v["$schema"]; ok {
+ if str, ok := vv.(string); ok {
+ u, err := parseURL(str)
+ if err != nil {
+ return err
+ }
+
+ *r = SchemaURL(u.String())
+ }
+ }
+ return nil
+}
+
+// SchemaProps describes a JSON schema (draft 4)
+type SchemaProps struct {
+ ID string `json:"id,omitempty"`
+ Ref Ref `json:"-"`
+ Schema SchemaURL `json:"-"`
+ Description string `json:"description,omitempty"`
+ Type StringOrArray `json:"type,omitempty"`
+ Nullable bool `json:"nullable,omitempty"`
+ Format string `json:"format,omitempty"`
+ Title string `json:"title,omitempty"`
+ Default any `json:"default,omitempty"`
+ Maximum *float64 `json:"maximum,omitempty"`
+ ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"`
+ Minimum *float64 `json:"minimum,omitempty"`
+ ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"`
+ MaxLength *int64 `json:"maxLength,omitempty"`
+ MinLength *int64 `json:"minLength,omitempty"`
+ Pattern string `json:"pattern,omitempty"`
+ MaxItems *int64 `json:"maxItems,omitempty"`
+ MinItems *int64 `json:"minItems,omitempty"`
+ UniqueItems bool `json:"uniqueItems,omitempty"`
+ MultipleOf *float64 `json:"multipleOf,omitempty"`
+ Enum []any `json:"enum,omitempty"`
+ MaxProperties *int64 `json:"maxProperties,omitempty"`
+ MinProperties *int64 `json:"minProperties,omitempty"`
+ Required []string `json:"required,omitempty"`
+ Items *SchemaOrArray `json:"items,omitempty"`
+ AllOf []Schema `json:"allOf,omitempty"`
+ OneOf []Schema `json:"oneOf,omitempty"`
+ AnyOf []Schema `json:"anyOf,omitempty"`
+ Not *Schema `json:"not,omitempty"`
+ Properties SchemaProperties `json:"properties,omitempty"`
+ AdditionalProperties *SchemaOrBool `json:"additionalProperties,omitempty"`
+ PatternProperties SchemaProperties `json:"patternProperties,omitempty"`
+ Dependencies Dependencies `json:"dependencies,omitempty"`
+ AdditionalItems *SchemaOrBool `json:"additionalItems,omitempty"`
+ Definitions Definitions `json:"definitions,omitempty"`
+}
+
+// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4)
+type SwaggerSchemaProps struct {
+ Discriminator string `json:"discriminator,omitempty"`
+ ReadOnly bool `json:"readOnly,omitempty"`
+ XML *XMLObject `json:"xml,omitempty"`
+ ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
+ Example any `json:"example,omitempty"`
+}
+
+// Schema the schema object allows the definition of input and output data types.
+// These types can be objects, but also primitives and arrays.
+// This object is based on the [JSON Schema Specification Draft 4](http://json-schema.org/)
+// and uses a predefined subset of it.
+// On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
+//
+// For more information: http://goo.gl/8us55a#schemaObject
+type Schema struct {
+ VendorExtensible
+ SchemaProps
+ SwaggerSchemaProps
+
+ ExtraProps map[string]any `json:"-"`
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (s Schema) JSONLookup(token string) (any, error) {
+ if ex, ok := s.Extensions[token]; ok {
+ return &ex, nil
+ }
+
+ if ex, ok := s.ExtraProps[token]; ok {
+ return &ex, nil
+ }
+
+ r, _, err := jsonpointer.GetForToken(s.SchemaProps, token)
+ if r != nil || (err != nil && !strings.HasPrefix(err.Error(), "object has no field")) {
+ return r, err
+ }
+ r, _, err = jsonpointer.GetForToken(s.SwaggerSchemaProps, token)
+ return r, err
+}
+
+// WithID sets the id for this schema, allows for chaining
+func (s *Schema) WithID(id string) *Schema {
+ s.ID = id
+ return s
+}
+
+// WithTitle sets the title for this schema, allows for chaining
+func (s *Schema) WithTitle(title string) *Schema {
+ s.Title = title
+ return s
+}
+
+// WithDescription sets the description for this schema, allows for chaining
+func (s *Schema) WithDescription(description string) *Schema {
+ s.Description = description
+ return s
+}
+
+// WithProperties sets the properties for this schema
+func (s *Schema) WithProperties(schemas map[string]Schema) *Schema {
+ s.Properties = schemas
+ return s
+}
+
+// SetProperty sets a property on this schema
+func (s *Schema) SetProperty(name string, schema Schema) *Schema {
+ if s.Properties == nil {
+ s.Properties = make(map[string]Schema)
+ }
+ s.Properties[name] = schema
+ return s
+}
+
+// WithAllOf sets the all of property
+func (s *Schema) WithAllOf(schemas ...Schema) *Schema {
+ s.AllOf = schemas
+ return s
+}
+
+// WithMaxProperties sets the max number of properties an object can have
+func (s *Schema) WithMaxProperties(maximum int64) *Schema {
+ s.MaxProperties = &maximum
+ return s
+}
+
+// WithMinProperties sets the min number of properties an object must have
+func (s *Schema) WithMinProperties(minimum int64) *Schema {
+ s.MinProperties = &minimum
+ return s
+}
+
+// Typed sets the type of this schema for a single value item
+func (s *Schema) Typed(tpe, format string) *Schema {
+ s.Type = []string{tpe}
+ s.Format = format
+ return s
+}
+
+// AddType adds a type with potential format to the types for this schema
+func (s *Schema) AddType(tpe, format string) *Schema {
+ s.Type = append(s.Type, tpe)
+ if format != "" {
+ s.Format = format
+ }
+ return s
+}
+
+// AsNullable flags this schema as nullable.
+func (s *Schema) AsNullable() *Schema {
+ s.Nullable = true
+ return s
+}
+
+// CollectionOf a fluent builder method for an array parameter
+func (s *Schema) CollectionOf(items Schema) *Schema {
+ s.Type = []string{jsonArray}
+ s.Items = &SchemaOrArray{Schema: &items}
+ return s
+}
+
+// WithDefault sets the default value on this parameter
+func (s *Schema) WithDefault(defaultValue any) *Schema {
+ s.Default = defaultValue
+ return s
+}
+
+// WithRequired flags this parameter as required
+func (s *Schema) WithRequired(items ...string) *Schema {
+ s.Required = items
+ return s
+}
+
+// AddRequired adds field names to the required properties array
+func (s *Schema) AddRequired(items ...string) *Schema {
+ s.Required = append(s.Required, items...)
+ return s
+}
+
+// WithMaxLength sets a max length value
+func (s *Schema) WithMaxLength(maximum int64) *Schema {
+ s.MaxLength = &maximum
+ return s
+}
+
+// WithMinLength sets a min length value
+func (s *Schema) WithMinLength(minimum int64) *Schema {
+ s.MinLength = &minimum
+ return s
+}
+
+// WithPattern sets a pattern value
+func (s *Schema) WithPattern(pattern string) *Schema {
+ s.Pattern = pattern
+ return s
+}
+
+// WithMultipleOf sets a multiple of value
+func (s *Schema) WithMultipleOf(number float64) *Schema {
+ s.MultipleOf = &number
+ return s
+}
+
+// WithMaximum sets a maximum number value
+func (s *Schema) WithMaximum(maximum float64, exclusive bool) *Schema {
+ s.Maximum = &maximum
+ s.ExclusiveMaximum = exclusive
+ return s
+}
+
+// WithMinimum sets a minimum number value
+func (s *Schema) WithMinimum(minimum float64, exclusive bool) *Schema {
+ s.Minimum = &minimum
+ s.ExclusiveMinimum = exclusive
+ return s
+}
+
+// WithEnum sets a the enum values (replace)
+func (s *Schema) WithEnum(values ...any) *Schema {
+ s.Enum = append([]any{}, values...)
+ return s
+}
+
+// WithMaxItems sets the max items
+func (s *Schema) WithMaxItems(size int64) *Schema {
+ s.MaxItems = &size
+ return s
+}
+
+// WithMinItems sets the min items
+func (s *Schema) WithMinItems(size int64) *Schema {
+ s.MinItems = &size
+ return s
+}
+
+// UniqueValues dictates that this array can only have unique items
+func (s *Schema) UniqueValues() *Schema {
+ s.UniqueItems = true
+ return s
+}
+
+// AllowDuplicates this array can have duplicates
+func (s *Schema) AllowDuplicates() *Schema {
+ s.UniqueItems = false
+ return s
+}
+
+// AddToAllOf adds a schema to the allOf property
+func (s *Schema) AddToAllOf(schemas ...Schema) *Schema {
+ s.AllOf = append(s.AllOf, schemas...)
+ return s
+}
+
+// WithDiscriminator sets the name of the discriminator field
+func (s *Schema) WithDiscriminator(discriminator string) *Schema {
+ s.Discriminator = discriminator
+ return s
+}
+
+// AsReadOnly flags this schema as readonly
+func (s *Schema) AsReadOnly() *Schema {
+ s.ReadOnly = true
+ return s
+}
+
+// AsWritable flags this schema as writeable (not read-only)
+func (s *Schema) AsWritable() *Schema {
+ s.ReadOnly = false
+ return s
+}
+
+// WithExample sets the example for this schema
+func (s *Schema) WithExample(example any) *Schema {
+ s.Example = example
+ return s
+}
+
+// WithExternalDocs sets/removes the external docs for/from this schema.
+// When you pass empty strings as params the external documents will be removed.
+// When you pass non-empty string as one value then those values will be used on the external docs object.
+// So when you pass a non-empty description, you should also pass the url and vice versa.
+func (s *Schema) WithExternalDocs(description, url string) *Schema {
+ if description == "" && url == "" {
+ s.ExternalDocs = nil
+ return s
+ }
+
+ if s.ExternalDocs == nil {
+ s.ExternalDocs = &ExternalDocumentation{}
+ }
+ s.ExternalDocs.Description = description
+ s.ExternalDocs.URL = url
+ return s
+}
+
+// WithXMLName sets the xml name for the object
+func (s *Schema) WithXMLName(name string) *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Name = name
+ return s
+}
+
+// WithXMLNamespace sets the xml namespace for the object
+func (s *Schema) WithXMLNamespace(namespace string) *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Namespace = namespace
+ return s
+}
+
+// WithXMLPrefix sets the xml prefix for the object
+func (s *Schema) WithXMLPrefix(prefix string) *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Prefix = prefix
+ return s
+}
+
+// AsXMLAttribute flags this object as xml attribute
+func (s *Schema) AsXMLAttribute() *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Attribute = true
+ return s
+}
+
+// AsXMLElement flags this object as an xml node
+func (s *Schema) AsXMLElement() *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Attribute = false
+ return s
+}
+
+// AsWrappedXML flags this object as wrapped, this is mostly useful for array types
+func (s *Schema) AsWrappedXML() *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Wrapped = true
+ return s
+}
+
+// AsUnwrappedXML flags this object as an xml node
+func (s *Schema) AsUnwrappedXML() *Schema {
+ if s.XML == nil {
+ s.XML = new(XMLObject)
+ }
+ s.XML.Wrapped = false
+ return s
+}
+
+// SetValidations defines all schema validations.
+//
+// NOTE: Required, ReadOnly, AllOf, AnyOf, OneOf and Not are not considered.
+func (s *Schema) SetValidations(val SchemaValidations) {
+ s.Maximum = val.Maximum
+ s.ExclusiveMaximum = val.ExclusiveMaximum
+ s.Minimum = val.Minimum
+ s.ExclusiveMinimum = val.ExclusiveMinimum
+ s.MaxLength = val.MaxLength
+ s.MinLength = val.MinLength
+ s.Pattern = val.Pattern
+ s.MaxItems = val.MaxItems
+ s.MinItems = val.MinItems
+ s.UniqueItems = val.UniqueItems
+ s.MultipleOf = val.MultipleOf
+ s.Enum = val.Enum
+ s.MinProperties = val.MinProperties
+ s.MaxProperties = val.MaxProperties
+ s.PatternProperties = val.PatternProperties
+}
+
+// WithValidations is a fluent method to set schema validations
+func (s *Schema) WithValidations(val SchemaValidations) *Schema {
+ s.SetValidations(val)
+ return s
+}
+
+// Validations returns a clone of the validations for this schema
+func (s Schema) Validations() SchemaValidations {
+ return SchemaValidations{
+ CommonValidations: CommonValidations{
+ Maximum: s.Maximum,
+ ExclusiveMaximum: s.ExclusiveMaximum,
+ Minimum: s.Minimum,
+ ExclusiveMinimum: s.ExclusiveMinimum,
+ MaxLength: s.MaxLength,
+ MinLength: s.MinLength,
+ Pattern: s.Pattern,
+ MaxItems: s.MaxItems,
+ MinItems: s.MinItems,
+ UniqueItems: s.UniqueItems,
+ MultipleOf: s.MultipleOf,
+ Enum: s.Enum,
+ },
+ MinProperties: s.MinProperties,
+ MaxProperties: s.MaxProperties,
+ PatternProperties: s.PatternProperties,
+ }
+}
+
+// MarshalJSON marshal this to JSON
+func (s Schema) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(s.SchemaProps)
+ if err != nil {
+ return nil, fmt.Errorf("schema props %v: %w", err, ErrSpec)
+ }
+ b2, err := json.Marshal(s.VendorExtensible)
+ if err != nil {
+ return nil, fmt.Errorf("vendor props %v: %w", err, ErrSpec)
+ }
+ b3, err := s.Ref.MarshalJSON()
+ if err != nil {
+ return nil, fmt.Errorf("ref prop %v: %w", err, ErrSpec)
+ }
+ b4, err := s.Schema.MarshalJSON()
+ if err != nil {
+ return nil, fmt.Errorf("schema prop %v: %w", err, ErrSpec)
+ }
+ b5, err := json.Marshal(s.SwaggerSchemaProps)
+ if err != nil {
+ return nil, fmt.Errorf("common validations %v: %w", err, ErrSpec)
+ }
+ var b6 []byte
+ if s.ExtraProps != nil {
+ jj, err := json.Marshal(s.ExtraProps)
+ if err != nil {
+ return nil, fmt.Errorf("extra props %v: %w", err, ErrSpec)
+ }
+ b6 = jj
+ }
+ return jsonutils.ConcatJSON(b1, b2, b3, b4, b5, b6), nil
+}
+
+// UnmarshalJSON marshal this from JSON
+func (s *Schema) UnmarshalJSON(data []byte) error {
+ props := struct {
+ SchemaProps
+ SwaggerSchemaProps
+ }{}
+ if err := json.Unmarshal(data, &props); err != nil {
+ return err
+ }
+
+ sch := Schema{
+ SchemaProps: props.SchemaProps,
+ SwaggerSchemaProps: props.SwaggerSchemaProps,
+ }
+
+ var d map[string]any
+ if err := json.Unmarshal(data, &d); err != nil {
+ return err
+ }
+
+ _ = sch.Ref.fromMap(d)
+ _ = sch.Schema.fromMap(d)
+
+ delete(d, "$ref")
+ delete(d, "$schema")
+ for _, pn := range jsonname.DefaultJSONNameProvider.GetJSONNames(s) {
+ delete(d, pn)
+ }
+
+ for k, vv := range d {
+ lk := strings.ToLower(k)
+ if strings.HasPrefix(lk, "x-") {
+ if sch.Extensions == nil {
+ sch.Extensions = map[string]any{}
+ }
+ sch.Extensions[k] = vv
+ continue
+ }
+ if sch.ExtraProps == nil {
+ sch.ExtraProps = map[string]any{}
+ }
+ sch.ExtraProps[k] = vv
+ }
+
+ *s = sch
+
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/spec/schema_loader.go b/vendor/github.com/go-openapi/spec/schema_loader.go
new file mode 100644
index 000000000000..8d4a98532566
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/schema_loader.go
@@ -0,0 +1,322 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "net/url"
+ "reflect"
+ "strings"
+
+ "github.com/go-openapi/swag/jsonutils"
+ "github.com/go-openapi/swag/loading"
+ "github.com/go-openapi/swag/stringutils"
+)
+
+// PathLoader is a function to use when loading remote refs.
+//
+// This is a package level default. It may be overridden or bypassed by
+// specifying the loader in ExpandOptions.
+//
+// NOTE: if you are using the go-openapi/loads package, it will override
+// this value with its own default (a loader to retrieve YAML documents as
+// well as JSON ones).
+var PathLoader = func(pth string) (json.RawMessage, error) {
+ data, err := loading.LoadFromFileOrHTTP(pth)
+ if err != nil {
+ return nil, err
+ }
+ return json.RawMessage(data), nil
+}
+
+// resolverContext allows to share a context during spec processing.
+// At the moment, it just holds the index of circular references found.
+type resolverContext struct {
+ // circulars holds all visited circular references, to shortcircuit $ref resolution.
+ //
+ // This structure is privately instantiated and needs not be locked against
+ // concurrent access, unless we chose to implement a parallel spec walking.
+ circulars map[string]bool
+ basePath string
+ loadDoc func(string) (json.RawMessage, error)
+ rootID string
+}
+
+func newResolverContext(options *ExpandOptions) *resolverContext {
+ expandOptions := optionsOrDefault(options)
+
+ // path loader may be overridden by options
+ var loader func(string) (json.RawMessage, error)
+ if expandOptions.PathLoader == nil {
+ loader = PathLoader
+ } else {
+ loader = expandOptions.PathLoader
+ }
+
+ return &resolverContext{
+ circulars: make(map[string]bool),
+ basePath: expandOptions.RelativeBase, // keep the root base path in context
+ loadDoc: loader,
+ }
+}
+
+type schemaLoader struct {
+ root any
+ options *ExpandOptions
+ cache ResolutionCache
+ context *resolverContext
+}
+
+// Resolve resolves a reference against basePath and stores the result in target.
+//
+// Resolve is not in charge of following references: it only resolves ref by following its URL.
+//
+// If the schema the ref is referring to holds nested refs, Resolve doesn't resolve them.
+//
+// If basePath is an empty string, ref is resolved against the root schema stored in the schemaLoader struct
+func (r *schemaLoader) Resolve(ref *Ref, target any, basePath string) error {
+ return r.resolveRef(ref, target, basePath)
+}
+
+func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) *schemaLoader {
+ if ref.IsRoot() || ref.HasFragmentOnly {
+ return r
+ }
+
+ baseRef := MustCreateRef(basePath)
+ currentRef := normalizeRef(&ref, basePath)
+ if strings.HasPrefix(currentRef.String(), baseRef.String()) {
+ return r
+ }
+
+ // set a new root against which to resolve
+ rootURL := currentRef.GetURL()
+ rootURL.Fragment = ""
+ root, _ := r.cache.Get(rootURL.String())
+
+ // shallow copy of resolver options to set a new RelativeBase when
+ // traversing multiple documents
+ newOptions := r.options
+ newOptions.RelativeBase = rootURL.String()
+
+ return defaultSchemaLoader(root, newOptions, r.cache, r.context)
+}
+
+func (r *schemaLoader) updateBasePath(transitive *schemaLoader, basePath string) string {
+ if transitive != r {
+ if transitive.options != nil && transitive.options.RelativeBase != "" {
+ return normalizeBase(transitive.options.RelativeBase)
+ }
+ }
+
+ return basePath
+}
+
+func (r *schemaLoader) resolveRef(ref *Ref, target any, basePath string) error {
+ tgt := reflect.ValueOf(target)
+ if tgt.Kind() != reflect.Ptr {
+ return ErrResolveRefNeedsAPointer
+ }
+
+ if ref.GetURL() == nil {
+ return nil
+ }
+
+ var (
+ res any
+ data any
+ err error
+ )
+
+ // Resolve against the root if it isn't nil, and if ref is pointing at the root, or has a fragment only which means
+ // it is pointing somewhere in the root.
+ root := r.root
+ if (ref.IsRoot() || ref.HasFragmentOnly) && root == nil && basePath != "" {
+ if baseRef, erb := NewRef(basePath); erb == nil {
+ root, _, _, _ = r.load(baseRef.GetURL())
+ }
+ }
+
+ if (ref.IsRoot() || ref.HasFragmentOnly) && root != nil {
+ data = root
+ } else {
+ baseRef := normalizeRef(ref, basePath)
+ data, _, _, err = r.load(baseRef.GetURL())
+ if err != nil {
+ return err
+ }
+ }
+
+ res = data
+ if ref.String() != "" {
+ res, _, err = ref.GetPointer().Get(data)
+ if err != nil {
+ return err
+ }
+ }
+ return jsonutils.FromDynamicJSON(res, target)
+}
+
+func (r *schemaLoader) load(refURL *url.URL) (any, url.URL, bool, error) {
+ debugLog("loading schema from url: %s", refURL)
+ toFetch := *refURL
+ toFetch.Fragment = ""
+
+ var err error
+ pth := toFetch.String()
+ normalized := normalizeBase(pth)
+ debugLog("loading doc from: %s", normalized)
+
+ data, fromCache := r.cache.Get(normalized)
+ if fromCache {
+ return data, toFetch, fromCache, nil
+ }
+
+ b, err := r.context.loadDoc(normalized)
+ if err != nil {
+ return nil, url.URL{}, false, err
+ }
+
+ var doc any
+ if err := json.Unmarshal(b, &doc); err != nil {
+ return nil, url.URL{}, false, err
+ }
+ r.cache.Set(normalized, doc)
+
+ return doc, toFetch, fromCache, nil
+}
+
+// isCircular detects cycles in sequences of $ref.
+//
+// It relies on a private context (which needs not be locked).
+func (r *schemaLoader) isCircular(ref *Ref, basePath string, parentRefs ...string) (foundCycle bool) {
+ normalizedRef := normalizeURI(ref.String(), basePath)
+ if _, ok := r.context.circulars[normalizedRef]; ok {
+ // circular $ref has been already detected in another explored cycle
+ foundCycle = true
+ return
+ }
+ foundCycle = stringutils.ContainsStrings(parentRefs, normalizedRef) // normalized windows url's are lower cased
+ if foundCycle {
+ r.context.circulars[normalizedRef] = true
+ }
+ return
+}
+
+func (r *schemaLoader) deref(input any, parentRefs []string, basePath string) error {
+ var ref *Ref
+ switch refable := input.(type) {
+ case *Schema:
+ ref = &refable.Ref
+ case *Parameter:
+ ref = &refable.Ref
+ case *Response:
+ ref = &refable.Ref
+ case *PathItem:
+ ref = &refable.Ref
+ default:
+ return fmt.Errorf("unsupported type: %T: %w", input, ErrDerefUnsupportedType)
+ }
+
+ curRef := ref.String()
+ if curRef == "" {
+ return nil
+ }
+
+ normalizedRef := normalizeRef(ref, basePath)
+ normalizedBasePath := normalizedRef.RemoteURI()
+
+ if r.isCircular(normalizedRef, basePath, parentRefs...) {
+ return nil
+ }
+
+ if err := r.resolveRef(ref, input, basePath); r.shouldStopOnError(err) {
+ return err
+ }
+
+ if ref.String() == "" || ref.String() == curRef {
+ // done with rereferencing
+ return nil
+ }
+
+ parentRefs = append(parentRefs, normalizedRef.String())
+ return r.deref(input, parentRefs, normalizedBasePath)
+}
+
+func (r *schemaLoader) shouldStopOnError(err error) bool {
+ if err != nil && !r.options.ContinueOnError {
+ return true
+ }
+
+ if err != nil {
+ log.Println(err)
+ }
+
+ return false
+}
+
+func (r *schemaLoader) setSchemaID(target any, id, basePath string) (string, string) {
+ debugLog("schema has ID: %s", id)
+
+ // handling the case when id is a folder
+ // remember that basePath has to point to a file
+ var refPath string
+ if strings.HasSuffix(id, "/") {
+ // ensure this is detected as a file, not a folder
+ refPath = fmt.Sprintf("%s%s", id, "placeholder.json")
+ } else {
+ refPath = id
+ }
+
+ // updates the current base path
+ // * important: ID can be a relative path
+ // * registers target to be fetchable from the new base proposed by this id
+ newBasePath := normalizeURI(refPath, basePath)
+
+ // store found IDs for possible future reuse in $ref
+ r.cache.Set(newBasePath, target)
+
+ // the root document has an ID: all $ref relative to that ID may
+ // be rebased relative to the root document
+ if basePath == r.context.basePath {
+ debugLog("root document is a schema with ID: %s (normalized as:%s)", id, newBasePath)
+ r.context.rootID = newBasePath
+ }
+
+ return newBasePath, refPath
+}
+
+func defaultSchemaLoader(
+ root any,
+ expandOptions *ExpandOptions,
+ cache ResolutionCache,
+ context *resolverContext) *schemaLoader {
+
+ if expandOptions == nil {
+ expandOptions = &ExpandOptions{}
+ }
+
+ cache = cacheOrDefault(cache)
+
+ if expandOptions.RelativeBase == "" {
+ // if no relative base is provided, assume the root document
+ // contains all $ref, or at least, that the relative documents
+ // may be resolved from the current working directory.
+ expandOptions.RelativeBase = baseForRoot(root, cache)
+ }
+ debugLog("effective expander options: %#v", expandOptions)
+
+ if context == nil {
+ context = newResolverContext(expandOptions)
+ }
+
+ return &schemaLoader{
+ root: root,
+ options: expandOptions,
+ cache: cache,
+ context: context,
+ }
+}
diff --git a/vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json b/vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json
new file mode 100644
index 000000000000..bcbb84743e38
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json
@@ -0,0 +1,149 @@
+{
+ "id": "http://json-schema.org/draft-04/schema#",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "description": "Core schema meta-schema",
+ "definitions": {
+ "schemaArray": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#" }
+ },
+ "positiveInteger": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "positiveIntegerDefault0": {
+ "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
+ },
+ "simpleTypes": {
+ "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
+ },
+ "stringArray": {
+ "type": "array",
+ "items": { "type": "string" },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ },
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {},
+ "multipleOf": {
+ "type": "number",
+ "minimum": 0,
+ "exclusiveMinimum": true
+ },
+ "maximum": {
+ "type": "number"
+ },
+ "exclusiveMaximum": {
+ "type": "boolean",
+ "default": false
+ },
+ "minimum": {
+ "type": "number"
+ },
+ "exclusiveMinimum": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxLength": { "$ref": "#/definitions/positiveInteger" },
+ "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
+ "pattern": {
+ "type": "string",
+ "format": "regex"
+ },
+ "additionalItems": {
+ "anyOf": [
+ { "type": "boolean" },
+ { "$ref": "#" }
+ ],
+ "default": {}
+ },
+ "items": {
+ "anyOf": [
+ { "$ref": "#" },
+ { "$ref": "#/definitions/schemaArray" }
+ ],
+ "default": {}
+ },
+ "maxItems": { "$ref": "#/definitions/positiveInteger" },
+ "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
+ "uniqueItems": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxProperties": { "$ref": "#/definitions/positiveInteger" },
+ "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
+ "required": { "$ref": "#/definitions/stringArray" },
+ "additionalProperties": {
+ "anyOf": [
+ { "type": "boolean" },
+ { "$ref": "#" }
+ ],
+ "default": {}
+ },
+ "definitions": {
+ "type": "object",
+ "additionalProperties": { "$ref": "#" },
+ "default": {}
+ },
+ "properties": {
+ "type": "object",
+ "additionalProperties": { "$ref": "#" },
+ "default": {}
+ },
+ "patternProperties": {
+ "type": "object",
+ "additionalProperties": { "$ref": "#" },
+ "default": {}
+ },
+ "dependencies": {
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [
+ { "$ref": "#" },
+ { "$ref": "#/definitions/stringArray" }
+ ]
+ }
+ },
+ "enum": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true
+ },
+ "type": {
+ "anyOf": [
+ { "$ref": "#/definitions/simpleTypes" },
+ {
+ "type": "array",
+ "items": { "$ref": "#/definitions/simpleTypes" },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ ]
+ },
+ "format": { "type": "string" },
+ "allOf": { "$ref": "#/definitions/schemaArray" },
+ "anyOf": { "$ref": "#/definitions/schemaArray" },
+ "oneOf": { "$ref": "#/definitions/schemaArray" },
+ "not": { "$ref": "#" }
+ },
+ "dependencies": {
+ "exclusiveMaximum": [ "maximum" ],
+ "exclusiveMinimum": [ "minimum" ]
+ },
+ "default": {}
+}
diff --git a/vendor/github.com/go-openapi/spec/schemas/v2/schema.json b/vendor/github.com/go-openapi/spec/schemas/v2/schema.json
new file mode 100644
index 000000000000..ebe10ed32d60
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/schemas/v2/schema.json
@@ -0,0 +1,1607 @@
+{
+ "title": "A JSON Schema for Swagger 2.0 API.",
+ "id": "http://swagger.io/v2/schema.json#",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "required": [
+ "swagger",
+ "info",
+ "paths"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "swagger": {
+ "type": "string",
+ "enum": [
+ "2.0"
+ ],
+ "description": "The Swagger version of this document."
+ },
+ "info": {
+ "$ref": "#/definitions/info"
+ },
+ "host": {
+ "type": "string",
+ "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$",
+ "description": "The host (name or ip) of the API. Example: 'swagger.io'"
+ },
+ "basePath": {
+ "type": "string",
+ "pattern": "^/",
+ "description": "The base path to the API. Example: '/api'."
+ },
+ "schemes": {
+ "$ref": "#/definitions/schemesList"
+ },
+ "consumes": {
+ "description": "A list of MIME types accepted by the API.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/mediaTypeList"
+ }
+ ]
+ },
+ "produces": {
+ "description": "A list of MIME types the API can produce.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/mediaTypeList"
+ }
+ ]
+ },
+ "paths": {
+ "$ref": "#/definitions/paths"
+ },
+ "definitions": {
+ "$ref": "#/definitions/definitions"
+ },
+ "parameters": {
+ "$ref": "#/definitions/parameterDefinitions"
+ },
+ "responses": {
+ "$ref": "#/definitions/responseDefinitions"
+ },
+ "security": {
+ "$ref": "#/definitions/security"
+ },
+ "securityDefinitions": {
+ "$ref": "#/definitions/securityDefinitions"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/tag"
+ },
+ "uniqueItems": true
+ },
+ "externalDocs": {
+ "$ref": "#/definitions/externalDocs"
+ }
+ },
+ "definitions": {
+ "info": {
+ "type": "object",
+ "description": "General information about the API.",
+ "required": [
+ "version",
+ "title"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "A unique and precise title of the API."
+ },
+ "version": {
+ "type": "string",
+ "description": "A semantic version number of the API."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed."
+ },
+ "termsOfService": {
+ "type": "string",
+ "description": "The terms of service for the API."
+ },
+ "contact": {
+ "$ref": "#/definitions/contact"
+ },
+ "license": {
+ "$ref": "#/definitions/license"
+ }
+ }
+ },
+ "contact": {
+ "type": "object",
+ "description": "Contact information for the owners of the API.",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The identifying name of the contact person/organization."
+ },
+ "url": {
+ "type": "string",
+ "description": "The URL pointing to the contact information.",
+ "format": "uri"
+ },
+ "email": {
+ "type": "string",
+ "description": "The email address of the contact person/organization.",
+ "format": "email"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "license": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the license type. It's encouraged to use an OSI compatible license."
+ },
+ "url": {
+ "type": "string",
+ "description": "The URL pointing to the license.",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "paths": {
+ "type": "object",
+ "description": "Relative paths to the individual endpoints. They must be relative to the 'basePath'.",
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ },
+ "^/": {
+ "$ref": "#/definitions/pathItem"
+ }
+ },
+ "additionalProperties": false
+ },
+ "definitions": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/schema"
+ },
+ "description": "One or more JSON objects describing the schemas being consumed and produced by the API."
+ },
+ "parameterDefinitions": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/parameter"
+ },
+ "description": "One or more JSON representations for parameters"
+ },
+ "responseDefinitions": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/response"
+ },
+ "description": "One or more JSON representations for responses"
+ },
+ "externalDocs": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "information about external documentation",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "examples": {
+ "type": "object",
+ "additionalProperties": true
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the HTTP message."
+ },
+ "operation": {
+ "type": "object",
+ "required": [
+ "responses"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "tags": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "uniqueItems": true
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the operation."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the operation, GitHub Flavored Markdown is allowed."
+ },
+ "externalDocs": {
+ "$ref": "#/definitions/externalDocs"
+ },
+ "operationId": {
+ "type": "string",
+ "description": "A unique identifier of the operation."
+ },
+ "produces": {
+ "description": "A list of MIME types the API can produce.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/mediaTypeList"
+ }
+ ]
+ },
+ "consumes": {
+ "description": "A list of MIME types the API can consume.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/mediaTypeList"
+ }
+ ]
+ },
+ "parameters": {
+ "$ref": "#/definitions/parametersList"
+ },
+ "responses": {
+ "$ref": "#/definitions/responses"
+ },
+ "schemes": {
+ "$ref": "#/definitions/schemesList"
+ },
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "security": {
+ "$ref": "#/definitions/security"
+ }
+ }
+ },
+ "pathItem": {
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "$ref": {
+ "type": "string"
+ },
+ "get": {
+ "$ref": "#/definitions/operation"
+ },
+ "put": {
+ "$ref": "#/definitions/operation"
+ },
+ "post": {
+ "$ref": "#/definitions/operation"
+ },
+ "delete": {
+ "$ref": "#/definitions/operation"
+ },
+ "options": {
+ "$ref": "#/definitions/operation"
+ },
+ "head": {
+ "$ref": "#/definitions/operation"
+ },
+ "patch": {
+ "$ref": "#/definitions/operation"
+ },
+ "parameters": {
+ "$ref": "#/definitions/parametersList"
+ }
+ }
+ },
+ "responses": {
+ "type": "object",
+ "description": "Response objects names can either be any valid HTTP status code or 'default'.",
+ "minProperties": 1,
+ "additionalProperties": false,
+ "patternProperties": {
+ "^([0-9]{3})$|^(default)$": {
+ "$ref": "#/definitions/responseValue"
+ },
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "not": {
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ }
+ },
+ "responseValue": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/response"
+ },
+ {
+ "$ref": "#/definitions/jsonReference"
+ }
+ ]
+ },
+ "response": {
+ "type": "object",
+ "required": [
+ "description"
+ ],
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "schema": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/schema"
+ },
+ {
+ "$ref": "#/definitions/fileSchema"
+ }
+ ]
+ },
+ "headers": {
+ "$ref": "#/definitions/headers"
+ },
+ "examples": {
+ "$ref": "#/definitions/examples"
+ }
+ },
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "headers": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/header"
+ }
+ },
+ "header": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "number",
+ "integer",
+ "boolean",
+ "array"
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "items": {
+ "$ref": "#/definitions/primitivesItems"
+ },
+ "collectionFormat": {
+ "$ref": "#/definitions/collectionFormat"
+ },
+ "default": {
+ "$ref": "#/definitions/default"
+ },
+ "maximum": {
+ "$ref": "#/definitions/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "#/definitions/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "#/definitions/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "#/definitions/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/maxLength"
+ },
+ "minLength": {
+ "$ref": "#/definitions/minLength"
+ },
+ "pattern": {
+ "$ref": "#/definitions/pattern"
+ },
+ "maxItems": {
+ "$ref": "#/definitions/maxItems"
+ },
+ "minItems": {
+ "$ref": "#/definitions/minItems"
+ },
+ "uniqueItems": {
+ "$ref": "#/definitions/uniqueItems"
+ },
+ "enum": {
+ "$ref": "#/definitions/enum"
+ },
+ "multipleOf": {
+ "$ref": "#/definitions/multipleOf"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "vendorExtension": {
+ "description": "Any property starting with x- is valid.",
+ "additionalProperties": true,
+ "additionalItems": true
+ },
+ "bodyParameter": {
+ "type": "object",
+ "required": [
+ "name",
+ "in",
+ "schema"
+ ],
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "description": {
+ "type": "string",
+ "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the parameter."
+ },
+ "in": {
+ "type": "string",
+ "description": "Determines the location of the parameter.",
+ "enum": [
+ "body"
+ ]
+ },
+ "required": {
+ "type": "boolean",
+ "description": "Determines whether or not this parameter is required or optional.",
+ "default": false
+ },
+ "schema": {
+ "$ref": "#/definitions/schema"
+ }
+ },
+ "additionalProperties": false
+ },
+ "headerParameterSubSchema": {
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "required": {
+ "type": "boolean",
+ "description": "Determines whether or not this parameter is required or optional.",
+ "default": false
+ },
+ "in": {
+ "type": "string",
+ "description": "Determines the location of the parameter.",
+ "enum": [
+ "header"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the parameter."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "number",
+ "boolean",
+ "integer",
+ "array"
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "items": {
+ "$ref": "#/definitions/primitivesItems"
+ },
+ "collectionFormat": {
+ "$ref": "#/definitions/collectionFormat"
+ },
+ "default": {
+ "$ref": "#/definitions/default"
+ },
+ "maximum": {
+ "$ref": "#/definitions/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "#/definitions/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "#/definitions/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "#/definitions/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/maxLength"
+ },
+ "minLength": {
+ "$ref": "#/definitions/minLength"
+ },
+ "pattern": {
+ "$ref": "#/definitions/pattern"
+ },
+ "maxItems": {
+ "$ref": "#/definitions/maxItems"
+ },
+ "minItems": {
+ "$ref": "#/definitions/minItems"
+ },
+ "uniqueItems": {
+ "$ref": "#/definitions/uniqueItems"
+ },
+ "enum": {
+ "$ref": "#/definitions/enum"
+ },
+ "multipleOf": {
+ "$ref": "#/definitions/multipleOf"
+ }
+ }
+ },
+ "queryParameterSubSchema": {
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "required": {
+ "type": "boolean",
+ "description": "Determines whether or not this parameter is required or optional.",
+ "default": false
+ },
+ "in": {
+ "type": "string",
+ "description": "Determines the location of the parameter.",
+ "enum": [
+ "query"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the parameter."
+ },
+ "allowEmptyValue": {
+ "type": "boolean",
+ "default": false,
+ "description": "allows sending a parameter by name only or with an empty value."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "number",
+ "boolean",
+ "integer",
+ "array"
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "items": {
+ "$ref": "#/definitions/primitivesItems"
+ },
+ "collectionFormat": {
+ "$ref": "#/definitions/collectionFormatWithMulti"
+ },
+ "default": {
+ "$ref": "#/definitions/default"
+ },
+ "maximum": {
+ "$ref": "#/definitions/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "#/definitions/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "#/definitions/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "#/definitions/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/maxLength"
+ },
+ "minLength": {
+ "$ref": "#/definitions/minLength"
+ },
+ "pattern": {
+ "$ref": "#/definitions/pattern"
+ },
+ "maxItems": {
+ "$ref": "#/definitions/maxItems"
+ },
+ "minItems": {
+ "$ref": "#/definitions/minItems"
+ },
+ "uniqueItems": {
+ "$ref": "#/definitions/uniqueItems"
+ },
+ "enum": {
+ "$ref": "#/definitions/enum"
+ },
+ "multipleOf": {
+ "$ref": "#/definitions/multipleOf"
+ }
+ }
+ },
+ "formDataParameterSubSchema": {
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "required": {
+ "type": "boolean",
+ "description": "Determines whether or not this parameter is required or optional.",
+ "default": false
+ },
+ "in": {
+ "type": "string",
+ "description": "Determines the location of the parameter.",
+ "enum": [
+ "formData"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the parameter."
+ },
+ "allowEmptyValue": {
+ "type": "boolean",
+ "default": false,
+ "description": "allows sending a parameter by name only or with an empty value."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "number",
+ "boolean",
+ "integer",
+ "array",
+ "file"
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "items": {
+ "$ref": "#/definitions/primitivesItems"
+ },
+ "collectionFormat": {
+ "$ref": "#/definitions/collectionFormatWithMulti"
+ },
+ "default": {
+ "$ref": "#/definitions/default"
+ },
+ "maximum": {
+ "$ref": "#/definitions/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "#/definitions/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "#/definitions/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "#/definitions/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/maxLength"
+ },
+ "minLength": {
+ "$ref": "#/definitions/minLength"
+ },
+ "pattern": {
+ "$ref": "#/definitions/pattern"
+ },
+ "maxItems": {
+ "$ref": "#/definitions/maxItems"
+ },
+ "minItems": {
+ "$ref": "#/definitions/minItems"
+ },
+ "uniqueItems": {
+ "$ref": "#/definitions/uniqueItems"
+ },
+ "enum": {
+ "$ref": "#/definitions/enum"
+ },
+ "multipleOf": {
+ "$ref": "#/definitions/multipleOf"
+ }
+ }
+ },
+ "pathParameterSubSchema": {
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "required": [
+ "required"
+ ],
+ "properties": {
+ "required": {
+ "type": "boolean",
+ "enum": [
+ true
+ ],
+ "description": "Determines whether or not this parameter is required or optional."
+ },
+ "in": {
+ "type": "string",
+ "description": "Determines the location of the parameter.",
+ "enum": [
+ "path"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the parameter."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "number",
+ "boolean",
+ "integer",
+ "array"
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "items": {
+ "$ref": "#/definitions/primitivesItems"
+ },
+ "collectionFormat": {
+ "$ref": "#/definitions/collectionFormat"
+ },
+ "default": {
+ "$ref": "#/definitions/default"
+ },
+ "maximum": {
+ "$ref": "#/definitions/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "#/definitions/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "#/definitions/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "#/definitions/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/maxLength"
+ },
+ "minLength": {
+ "$ref": "#/definitions/minLength"
+ },
+ "pattern": {
+ "$ref": "#/definitions/pattern"
+ },
+ "maxItems": {
+ "$ref": "#/definitions/maxItems"
+ },
+ "minItems": {
+ "$ref": "#/definitions/minItems"
+ },
+ "uniqueItems": {
+ "$ref": "#/definitions/uniqueItems"
+ },
+ "enum": {
+ "$ref": "#/definitions/enum"
+ },
+ "multipleOf": {
+ "$ref": "#/definitions/multipleOf"
+ }
+ }
+ },
+ "nonBodyParameter": {
+ "type": "object",
+ "required": [
+ "name",
+ "in",
+ "type"
+ ],
+ "oneOf": [
+ {
+ "$ref": "#/definitions/headerParameterSubSchema"
+ },
+ {
+ "$ref": "#/definitions/formDataParameterSubSchema"
+ },
+ {
+ "$ref": "#/definitions/queryParameterSubSchema"
+ },
+ {
+ "$ref": "#/definitions/pathParameterSubSchema"
+ }
+ ]
+ },
+ "parameter": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/bodyParameter"
+ },
+ {
+ "$ref": "#/definitions/nonBodyParameter"
+ }
+ ]
+ },
+ "schema": {
+ "type": "object",
+ "description": "A deterministic version of a JSON Schema object.",
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "properties": {
+ "$ref": {
+ "type": "string"
+ },
+ "format": {
+ "type": "string"
+ },
+ "title": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/title"
+ },
+ "description": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/description"
+ },
+ "default": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/default"
+ },
+ "multipleOf": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
+ },
+ "maximum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+ },
+ "minLength": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+ },
+ "pattern": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
+ },
+ "maxItems": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+ },
+ "minItems": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+ },
+ "uniqueItems": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
+ },
+ "maxProperties": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+ },
+ "minProperties": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+ },
+ "required": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
+ },
+ "enum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
+ },
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/schema"
+ },
+ {
+ "type": "boolean"
+ }
+ ],
+ "default": {}
+ },
+ "type": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/type"
+ },
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/schema"
+ },
+ {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/definitions/schema"
+ }
+ }
+ ],
+ "default": {}
+ },
+ "allOf": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/definitions/schema"
+ }
+ },
+ "properties": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/schema"
+ },
+ "default": {}
+ },
+ "discriminator": {
+ "type": "string"
+ },
+ "readOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "xml": {
+ "$ref": "#/definitions/xml"
+ },
+ "externalDocs": {
+ "$ref": "#/definitions/externalDocs"
+ },
+ "example": {}
+ },
+ "additionalProperties": false
+ },
+ "fileSchema": {
+ "type": "object",
+ "description": "A deterministic version of a JSON Schema object.",
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "format": {
+ "type": "string"
+ },
+ "title": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/title"
+ },
+ "description": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/description"
+ },
+ "default": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/default"
+ },
+ "required": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "file"
+ ]
+ },
+ "readOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "externalDocs": {
+ "$ref": "#/definitions/externalDocs"
+ },
+ "example": {}
+ },
+ "additionalProperties": false
+ },
+ "primitivesItems": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "number",
+ "integer",
+ "boolean",
+ "array"
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "items": {
+ "$ref": "#/definitions/primitivesItems"
+ },
+ "collectionFormat": {
+ "$ref": "#/definitions/collectionFormat"
+ },
+ "default": {
+ "$ref": "#/definitions/default"
+ },
+ "maximum": {
+ "$ref": "#/definitions/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "#/definitions/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "#/definitions/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "#/definitions/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/maxLength"
+ },
+ "minLength": {
+ "$ref": "#/definitions/minLength"
+ },
+ "pattern": {
+ "$ref": "#/definitions/pattern"
+ },
+ "maxItems": {
+ "$ref": "#/definitions/maxItems"
+ },
+ "minItems": {
+ "$ref": "#/definitions/minItems"
+ },
+ "uniqueItems": {
+ "$ref": "#/definitions/uniqueItems"
+ },
+ "enum": {
+ "$ref": "#/definitions/enum"
+ },
+ "multipleOf": {
+ "$ref": "#/definitions/multipleOf"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "security": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/securityRequirement"
+ },
+ "uniqueItems": true
+ },
+ "securityRequirement": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "uniqueItems": true
+ }
+ },
+ "xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "prefix": {
+ "type": "string"
+ },
+ "attribute": {
+ "type": "boolean",
+ "default": false
+ },
+ "wrapped": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "tag": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "externalDocs": {
+ "$ref": "#/definitions/externalDocs"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "securityDefinitions": {
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/basicAuthenticationSecurity"
+ },
+ {
+ "$ref": "#/definitions/apiKeySecurity"
+ },
+ {
+ "$ref": "#/definitions/oauth2ImplicitSecurity"
+ },
+ {
+ "$ref": "#/definitions/oauth2PasswordSecurity"
+ },
+ {
+ "$ref": "#/definitions/oauth2ApplicationSecurity"
+ },
+ {
+ "$ref": "#/definitions/oauth2AccessCodeSecurity"
+ }
+ ]
+ }
+ },
+ "basicAuthenticationSecurity": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "basic"
+ ]
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "apiKeySecurity": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type",
+ "name",
+ "in"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "apiKey"
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "in": {
+ "type": "string",
+ "enum": [
+ "header",
+ "query"
+ ]
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "oauth2ImplicitSecurity": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type",
+ "flow",
+ "authorizationUrl"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oauth2"
+ ]
+ },
+ "flow": {
+ "type": "string",
+ "enum": [
+ "implicit"
+ ]
+ },
+ "scopes": {
+ "$ref": "#/definitions/oauth2Scopes"
+ },
+ "authorizationUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "oauth2PasswordSecurity": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type",
+ "flow",
+ "tokenUrl"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oauth2"
+ ]
+ },
+ "flow": {
+ "type": "string",
+ "enum": [
+ "password"
+ ]
+ },
+ "scopes": {
+ "$ref": "#/definitions/oauth2Scopes"
+ },
+ "tokenUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "oauth2ApplicationSecurity": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type",
+ "flow",
+ "tokenUrl"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oauth2"
+ ]
+ },
+ "flow": {
+ "type": "string",
+ "enum": [
+ "application"
+ ]
+ },
+ "scopes": {
+ "$ref": "#/definitions/oauth2Scopes"
+ },
+ "tokenUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "oauth2AccessCodeSecurity": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "type",
+ "flow",
+ "authorizationUrl",
+ "tokenUrl"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oauth2"
+ ]
+ },
+ "flow": {
+ "type": "string",
+ "enum": [
+ "accessCode"
+ ]
+ },
+ "scopes": {
+ "$ref": "#/definitions/oauth2Scopes"
+ },
+ "authorizationUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "tokenUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "$ref": "#/definitions/vendorExtension"
+ }
+ }
+ },
+ "oauth2Scopes": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "mediaTypeList": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/mimeType"
+ },
+ "uniqueItems": true
+ },
+ "parametersList": {
+ "type": "array",
+ "description": "The parameters needed to send a valid API call.",
+ "additionalItems": false,
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/parameter"
+ },
+ {
+ "$ref": "#/definitions/jsonReference"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "schemesList": {
+ "type": "array",
+ "description": "The transfer protocol of the API.",
+ "items": {
+ "type": "string",
+ "enum": [
+ "http",
+ "https",
+ "ws",
+ "wss"
+ ]
+ },
+ "uniqueItems": true
+ },
+ "collectionFormat": {
+ "type": "string",
+ "enum": [
+ "csv",
+ "ssv",
+ "tsv",
+ "pipes"
+ ],
+ "default": "csv"
+ },
+ "collectionFormatWithMulti": {
+ "type": "string",
+ "enum": [
+ "csv",
+ "ssv",
+ "tsv",
+ "pipes",
+ "multi"
+ ],
+ "default": "csv"
+ },
+ "title": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/title"
+ },
+ "description": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/description"
+ },
+ "default": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/default"
+ },
+ "multipleOf": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
+ },
+ "maximum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
+ },
+ "exclusiveMaximum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
+ },
+ "minimum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
+ },
+ "exclusiveMinimum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
+ },
+ "maxLength": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+ },
+ "minLength": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+ },
+ "pattern": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
+ },
+ "maxItems": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+ },
+ "minItems": {
+ "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+ },
+ "uniqueItems": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
+ },
+ "enum": {
+ "$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
+ },
+ "jsonReference": {
+ "type": "object",
+ "required": [
+ "$ref"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "$ref": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/go-openapi/spec/security_scheme.go b/vendor/github.com/go-openapi/spec/security_scheme.go
new file mode 100644
index 000000000000..46a4a7e2f9f8
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/security_scheme.go
@@ -0,0 +1,159 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+const (
+ basic = "basic"
+ apiKey = "apiKey"
+ oauth2 = "oauth2"
+ implicit = "implicit"
+ password = "password"
+ application = "application"
+ accessCode = "accessCode"
+)
+
+// BasicAuth creates a basic auth security scheme
+func BasicAuth() *SecurityScheme {
+ return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{Type: basic}}
+}
+
+// APIKeyAuth creates an api key auth security scheme
+func APIKeyAuth(fieldName, valueSource string) *SecurityScheme {
+ return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{Type: apiKey, Name: fieldName, In: valueSource}}
+}
+
+// OAuth2Implicit creates an implicit flow oauth2 security scheme
+func OAuth2Implicit(authorizationURL string) *SecurityScheme {
+ return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{
+ Type: oauth2,
+ Flow: implicit,
+ AuthorizationURL: authorizationURL,
+ }}
+}
+
+// OAuth2Password creates a password flow oauth2 security scheme
+func OAuth2Password(tokenURL string) *SecurityScheme {
+ return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{
+ Type: oauth2,
+ Flow: password,
+ TokenURL: tokenURL,
+ }}
+}
+
+// OAuth2Application creates an application flow oauth2 security scheme
+func OAuth2Application(tokenURL string) *SecurityScheme {
+ return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{
+ Type: oauth2,
+ Flow: application,
+ TokenURL: tokenURL,
+ }}
+}
+
+// OAuth2AccessToken creates an access token flow oauth2 security scheme
+func OAuth2AccessToken(authorizationURL, tokenURL string) *SecurityScheme {
+ return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{
+ Type: oauth2,
+ Flow: accessCode,
+ AuthorizationURL: authorizationURL,
+ TokenURL: tokenURL,
+ }}
+}
+
+// SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section
+type SecuritySchemeProps struct {
+ Description string `json:"description,omitempty"`
+ Type string `json:"type"`
+ Name string `json:"name,omitempty"` // api key
+ In string `json:"in,omitempty"` // api key
+ Flow string `json:"flow,omitempty"` // oauth2
+ AuthorizationURL string `json:"authorizationUrl"` // oauth2
+ TokenURL string `json:"tokenUrl,omitempty"` // oauth2
+ Scopes map[string]string `json:"scopes,omitempty"` // oauth2
+}
+
+// AddScope adds a scope to this security scheme
+func (s *SecuritySchemeProps) AddScope(scope, description string) {
+ if s.Scopes == nil {
+ s.Scopes = make(map[string]string)
+ }
+ s.Scopes[scope] = description
+}
+
+// SecurityScheme allows the definition of a security scheme that can be used by the operations.
+// Supported schemes are basic authentication, an API key (either as a header or as a query parameter)
+// and OAuth2's common flows (implicit, password, application and access code).
+//
+// For more information: http://goo.gl/8us55a#securitySchemeObject
+type SecurityScheme struct {
+ VendorExtensible
+ SecuritySchemeProps
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (s SecurityScheme) JSONLookup(token string) (any, error) {
+ if ex, ok := s.Extensions[token]; ok {
+ return &ex, nil
+ }
+
+ r, _, err := jsonpointer.GetForToken(s.SecuritySchemeProps, token)
+ return r, err
+}
+
+// MarshalJSON marshal this to JSON
+func (s SecurityScheme) MarshalJSON() ([]byte, error) {
+ var (
+ b1 []byte
+ err error
+ )
+
+ if s.Type == oauth2 && (s.Flow == "implicit" || s.Flow == "accessCode") {
+ // when oauth2 for implicit or accessCode flows, empty AuthorizationURL is added as empty string
+ b1, err = json.Marshal(s.SecuritySchemeProps)
+ } else {
+ // when not oauth2, empty AuthorizationURL should be omitted
+ b1, err = json.Marshal(struct {
+ Description string `json:"description,omitempty"`
+ Type string `json:"type"`
+ Name string `json:"name,omitempty"` // api key
+ In string `json:"in,omitempty"` // api key
+ Flow string `json:"flow,omitempty"` // oauth2
+ AuthorizationURL string `json:"authorizationUrl,omitempty"` // oauth2
+ TokenURL string `json:"tokenUrl,omitempty"` // oauth2
+ Scopes map[string]string `json:"scopes,omitempty"` // oauth2
+ }{
+ Description: s.Description,
+ Type: s.Type,
+ Name: s.Name,
+ In: s.In,
+ Flow: s.Flow,
+ AuthorizationURL: s.AuthorizationURL,
+ TokenURL: s.TokenURL,
+ Scopes: s.Scopes,
+ })
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ b2, err := json.Marshal(s.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2), nil
+}
+
+// UnmarshalJSON marshal this from JSON
+func (s *SecurityScheme) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &s.VendorExtensible)
+}
diff --git a/vendor/github.com/go-openapi/spec/spec.go b/vendor/github.com/go-openapi/spec/spec.go
new file mode 100644
index 000000000000..05c3fc775cf2
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/spec.go
@@ -0,0 +1,67 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+)
+
+//go:generate curl -L --progress -o ./schemas/v2/schema.json http://swagger.io/v2/schema.json
+//go:generate curl -L --progress -o ./schemas/jsonschema-draft-04.json http://json-schema.org/draft-04/schema
+//go:generate go-bindata -pkg=spec -prefix=./schemas -ignore=.*\.md ./schemas/...
+//go:generate perl -pi -e s,Json,JSON,g bindata.go
+
+const (
+ // SwaggerSchemaURL the url for the swagger 2.0 schema to validate specs
+ SwaggerSchemaURL = "http://swagger.io/v2/schema.json#"
+ // JSONSchemaURL the url for the json schema
+ JSONSchemaURL = "http://json-schema.org/draft-04/schema#"
+)
+
+// MustLoadJSONSchemaDraft04 panics when Swagger20Schema returns an error
+func MustLoadJSONSchemaDraft04() *Schema {
+ d, e := JSONSchemaDraft04()
+ if e != nil {
+ panic(e)
+ }
+ return d
+}
+
+// JSONSchemaDraft04 loads the json schema document for json shema draft04
+func JSONSchemaDraft04() (*Schema, error) {
+ b, err := jsonschemaDraft04JSONBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ schema := new(Schema)
+ if err := json.Unmarshal(b, schema); err != nil {
+ return nil, err
+ }
+ return schema, nil
+}
+
+// MustLoadSwagger20Schema panics when Swagger20Schema returns an error
+func MustLoadSwagger20Schema() *Schema {
+ d, e := Swagger20Schema()
+ if e != nil {
+ panic(e)
+ }
+ return d
+}
+
+// Swagger20Schema loads the swagger 2.0 schema from the embedded assets
+func Swagger20Schema() (*Schema, error) {
+
+ b, err := v2SchemaJSONBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ schema := new(Schema)
+ if err := json.Unmarshal(b, schema); err != nil {
+ return nil, err
+ }
+ return schema, nil
+}
diff --git a/vendor/github.com/go-openapi/spec/swagger.go b/vendor/github.com/go-openapi/spec/swagger.go
new file mode 100644
index 000000000000..f7cd0f608c24
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/swagger.go
@@ -0,0 +1,433 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/json"
+ "fmt"
+ "slices"
+ "strconv"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// Swagger this is the root document object for the API specification.
+// It combines what previously was the Resource Listing and API Declaration (version 1.2 and earlier)
+// together into one document.
+//
+// For more information: http://goo.gl/8us55a#swagger-object-
+type Swagger struct {
+ VendorExtensible
+ SwaggerProps
+}
+
+// JSONLookup look up a value by the json property name
+func (s Swagger) JSONLookup(token string) (any, error) {
+ if ex, ok := s.Extensions[token]; ok {
+ return &ex, nil
+ }
+ r, _, err := jsonpointer.GetForToken(s.SwaggerProps, token)
+ return r, err
+}
+
+// MarshalJSON marshals this swagger structure to json
+func (s Swagger) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(s.SwaggerProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(s.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2), nil
+}
+
+// UnmarshalJSON unmarshals a swagger spec from json
+func (s *Swagger) UnmarshalJSON(data []byte) error {
+ var sw Swagger
+ if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil {
+ return err
+ }
+ if err := json.Unmarshal(data, &sw.VendorExtensible); err != nil {
+ return err
+ }
+ *s = sw
+ return nil
+}
+
+// GobEncode provides a safe gob encoder for Swagger, including extensions
+func (s Swagger) GobEncode() ([]byte, error) {
+ var b bytes.Buffer
+ raw := struct {
+ Props SwaggerProps
+ Ext VendorExtensible
+ }{
+ Props: s.SwaggerProps,
+ Ext: s.VendorExtensible,
+ }
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+}
+
+// GobDecode provides a safe gob decoder for Swagger, including extensions
+func (s *Swagger) GobDecode(b []byte) error {
+ var raw struct {
+ Props SwaggerProps
+ Ext VendorExtensible
+ }
+ buf := bytes.NewBuffer(b)
+ err := gob.NewDecoder(buf).Decode(&raw)
+ if err != nil {
+ return err
+ }
+ s.SwaggerProps = raw.Props
+ s.VendorExtensible = raw.Ext
+ return nil
+}
+
+// SwaggerProps captures the top-level properties of an Api specification
+//
+// NOTE: validation rules
+// - the scheme, when present must be from [http, https, ws, wss]
+// - BasePath must start with a leading "/"
+// - Paths is required
+type SwaggerProps struct {
+ ID string `json:"id,omitempty"`
+ Consumes []string `json:"consumes,omitempty"`
+ Produces []string `json:"produces,omitempty"`
+ Schemes []string `json:"schemes,omitempty"`
+ Swagger string `json:"swagger,omitempty"`
+ Info *Info `json:"info,omitempty"`
+ Host string `json:"host,omitempty"`
+ BasePath string `json:"basePath,omitempty"`
+ Paths *Paths `json:"paths"`
+ Definitions Definitions `json:"definitions,omitempty"`
+ Parameters map[string]Parameter `json:"parameters,omitempty"`
+ Responses map[string]Response `json:"responses,omitempty"`
+ SecurityDefinitions SecurityDefinitions `json:"securityDefinitions,omitempty"`
+ Security []map[string][]string `json:"security,omitempty"`
+ Tags []Tag `json:"tags,omitempty"`
+ ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
+}
+
+type swaggerPropsAlias SwaggerProps
+
+type gobSwaggerPropsAlias struct {
+ Security []map[string]struct {
+ List []string
+ Pad bool
+ }
+ Alias *swaggerPropsAlias
+ SecurityIsEmpty bool
+}
+
+// GobEncode provides a safe gob encoder for SwaggerProps, including empty security requirements
+func (o SwaggerProps) GobEncode() ([]byte, error) {
+ raw := gobSwaggerPropsAlias{
+ Alias: (*swaggerPropsAlias)(&o),
+ }
+
+ var b bytes.Buffer
+ if o.Security == nil {
+ // nil security requirement
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+ }
+
+ if len(o.Security) == 0 {
+ // empty, but non-nil security requirement
+ raw.SecurityIsEmpty = true
+ raw.Alias.Security = nil
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+ }
+
+ raw.Security = make([]map[string]struct {
+ List []string
+ Pad bool
+ }, 0, len(o.Security))
+ for _, req := range o.Security {
+ v := make(map[string]struct {
+ List []string
+ Pad bool
+ }, len(req))
+ for k, val := range req {
+ v[k] = struct {
+ List []string
+ Pad bool
+ }{
+ List: val,
+ }
+ }
+ raw.Security = append(raw.Security, v)
+ }
+
+ err := gob.NewEncoder(&b).Encode(raw)
+ return b.Bytes(), err
+}
+
+// GobDecode provides a safe gob decoder for SwaggerProps, including empty security requirements
+func (o *SwaggerProps) GobDecode(b []byte) error {
+ var raw gobSwaggerPropsAlias
+
+ buf := bytes.NewBuffer(b)
+ err := gob.NewDecoder(buf).Decode(&raw)
+ if err != nil {
+ return err
+ }
+ if raw.Alias == nil {
+ return nil
+ }
+
+ switch {
+ case raw.SecurityIsEmpty:
+ // empty, but non-nil security requirement
+ raw.Alias.Security = []map[string][]string{}
+ case len(raw.Alias.Security) == 0:
+ // nil security requirement
+ raw.Alias.Security = nil
+ default:
+ raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security))
+ for _, req := range raw.Security {
+ v := make(map[string][]string, len(req))
+ for k, val := range req {
+ v[k] = make([]string, 0, len(val.List))
+ v[k] = append(v[k], val.List...)
+ }
+ raw.Alias.Security = append(raw.Alias.Security, v)
+ }
+ }
+
+ *o = *(*SwaggerProps)(raw.Alias)
+ return nil
+}
+
+// Dependencies represent a dependencies property
+type Dependencies map[string]SchemaOrStringArray
+
+// SchemaOrBool represents a schema or boolean value, is biased towards true for the boolean property
+type SchemaOrBool struct {
+ Allows bool
+ Schema *Schema
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (s SchemaOrBool) JSONLookup(token string) (any, error) {
+ if token == "allows" {
+ return s.Allows, nil
+ }
+ r, _, err := jsonpointer.GetForToken(s.Schema, token)
+ return r, err
+}
+
+var jsTrue = []byte("true")
+var jsFalse = []byte("false")
+
+// MarshalJSON convert this object to JSON
+func (s SchemaOrBool) MarshalJSON() ([]byte, error) {
+ if s.Schema != nil {
+ return json.Marshal(s.Schema)
+ }
+
+ if s.Schema == nil && !s.Allows {
+ return jsFalse, nil
+ }
+ return jsTrue, nil
+}
+
+// UnmarshalJSON converts this bool or schema object from a JSON structure
+func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
+ var nw SchemaOrBool
+ if len(data) > 0 {
+ if data[0] == '{' {
+ var sch Schema
+ if err := json.Unmarshal(data, &sch); err != nil {
+ return err
+ }
+ nw.Schema = &sch
+ }
+ nw.Allows = !bytes.Equal(data, []byte("false"))
+ }
+ *s = nw
+ return nil
+}
+
+// SchemaOrStringArray represents a schema or a string array
+type SchemaOrStringArray struct {
+ Schema *Schema
+ Property []string
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (s SchemaOrStringArray) JSONLookup(token string) (any, error) {
+ r, _, err := jsonpointer.GetForToken(s.Schema, token)
+ return r, err
+}
+
+// MarshalJSON converts this schema object or array into JSON structure
+func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) {
+ if len(s.Property) > 0 {
+ return json.Marshal(s.Property)
+ }
+ if s.Schema != nil {
+ return json.Marshal(s.Schema)
+ }
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON converts this schema object or array from a JSON structure
+func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error {
+ var first byte
+ if len(data) > 1 {
+ first = data[0]
+ }
+ var nw SchemaOrStringArray
+ if first == '{' {
+ var sch Schema
+ if err := json.Unmarshal(data, &sch); err != nil {
+ return err
+ }
+ nw.Schema = &sch
+ }
+ if first == '[' {
+ if err := json.Unmarshal(data, &nw.Property); err != nil {
+ return err
+ }
+ }
+ *s = nw
+ return nil
+}
+
+// Definitions contains the models explicitly defined in this spec
+// An object to hold data types that can be consumed and produced by operations.
+// These data types can be primitives, arrays or models.
+//
+// For more information: http://goo.gl/8us55a#definitionsObject
+type Definitions map[string]Schema
+
+// SecurityDefinitions a declaration of the security schemes available to be used in the specification.
+// This does not enforce the security schemes on the operations and only serves to provide
+// the relevant details for each scheme.
+//
+// For more information: http://goo.gl/8us55a#securityDefinitionsObject
+type SecurityDefinitions map[string]*SecurityScheme
+
+// StringOrArray represents a value that can either be a string
+// or an array of strings. Mainly here for serialization purposes
+type StringOrArray []string
+
+// Contains returns true when the value is contained in the slice
+func (s StringOrArray) Contains(value string) bool {
+ return slices.Contains(s, value)
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (s SchemaOrArray) JSONLookup(token string) (any, error) {
+ if _, err := strconv.Atoi(token); err == nil {
+ r, _, err := jsonpointer.GetForToken(s.Schemas, token)
+ return r, err
+ }
+ r, _, err := jsonpointer.GetForToken(s.Schema, token)
+ return r, err
+}
+
+// UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string
+func (s *StringOrArray) UnmarshalJSON(data []byte) error {
+ var first byte
+ if len(data) > 1 {
+ first = data[0]
+ }
+
+ if first == '[' {
+ var parsed []string
+ if err := json.Unmarshal(data, &parsed); err != nil {
+ return err
+ }
+ *s = StringOrArray(parsed)
+ return nil
+ }
+
+ var single any
+ if err := json.Unmarshal(data, &single); err != nil {
+ return err
+ }
+ if single == nil {
+ return nil
+ }
+ switch v := single.(type) {
+ case string:
+ *s = StringOrArray([]string{v})
+ return nil
+ default:
+ return fmt.Errorf("only string or array is allowed, not %T: %w", single, ErrSpec)
+ }
+}
+
+// MarshalJSON converts this string or array to a JSON array or JSON string
+func (s StringOrArray) MarshalJSON() ([]byte, error) {
+ if len(s) == 1 {
+ return json.Marshal([]string(s)[0])
+ }
+ return json.Marshal([]string(s))
+}
+
+// SchemaOrArray represents a value that can either be a Schema
+// or an array of Schema. Mainly here for serialization purposes
+type SchemaOrArray struct {
+ Schema *Schema
+ Schemas []Schema
+}
+
+// Len returns the number of schemas in this property
+func (s SchemaOrArray) Len() int {
+ if s.Schema != nil {
+ return 1
+ }
+ return len(s.Schemas)
+}
+
+// ContainsType returns true when one of the schemas is of the specified type
+func (s *SchemaOrArray) ContainsType(name string) bool {
+ if s.Schema != nil {
+ return s.Schema.Type != nil && s.Schema.Type.Contains(name)
+ }
+ return false
+}
+
+// MarshalJSON converts this schema object or array into JSON structure
+func (s SchemaOrArray) MarshalJSON() ([]byte, error) {
+ if len(s.Schemas) > 0 {
+ return json.Marshal(s.Schemas)
+ }
+ return json.Marshal(s.Schema)
+}
+
+// UnmarshalJSON converts this schema object or array from a JSON structure
+func (s *SchemaOrArray) UnmarshalJSON(data []byte) error {
+ var nw SchemaOrArray
+ var first byte
+ if len(data) > 1 {
+ first = data[0]
+ }
+ if first == '{' {
+ var sch Schema
+ if err := json.Unmarshal(data, &sch); err != nil {
+ return err
+ }
+ nw.Schema = &sch
+ }
+ if first == '[' {
+ if err := json.Unmarshal(data, &nw.Schemas); err != nil {
+ return err
+ }
+ }
+ *s = nw
+ return nil
+}
+
+// vim:set ft=go noet sts=2 sw=2 ts=2:
diff --git a/vendor/github.com/go-openapi/spec/tag.go b/vendor/github.com/go-openapi/spec/tag.go
new file mode 100644
index 000000000000..ae98fd985fb2
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/tag.go
@@ -0,0 +1,64 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// TagProps describe a tag entry in the top level tags section of a swagger spec
+type TagProps struct {
+ Description string `json:"description,omitempty"`
+ Name string `json:"name,omitempty"`
+ ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
+}
+
+// Tag allows adding meta data to a single tag that is used by the
+// [Operation Object](http://goo.gl/8us55a#operationObject).
+// It is not mandatory to have a Tag Object per tag used there.
+//
+// For more information: http://goo.gl/8us55a#tagObject
+type Tag struct {
+ VendorExtensible
+ TagProps
+}
+
+// NewTag creates a new tag
+func NewTag(name, description string, externalDocs *ExternalDocumentation) Tag {
+ return Tag{TagProps: TagProps{Description: description, Name: name, ExternalDocs: externalDocs}}
+}
+
+// JSONLookup implements an interface to customize json pointer lookup
+func (t Tag) JSONLookup(token string) (any, error) {
+ if ex, ok := t.Extensions[token]; ok {
+ return &ex, nil
+ }
+
+ r, _, err := jsonpointer.GetForToken(t.TagProps, token)
+ return r, err
+}
+
+// MarshalJSON marshal this to JSON
+func (t Tag) MarshalJSON() ([]byte, error) {
+ b1, err := json.Marshal(t.TagProps)
+ if err != nil {
+ return nil, err
+ }
+ b2, err := json.Marshal(t.VendorExtensible)
+ if err != nil {
+ return nil, err
+ }
+ return jsonutils.ConcatJSON(b1, b2), nil
+}
+
+// UnmarshalJSON marshal this from JSON
+func (t *Tag) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &t.TagProps); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, &t.VendorExtensible)
+}
diff --git a/vendor/github.com/go-openapi/spec/url_go19.go b/vendor/github.com/go-openapi/spec/url_go19.go
new file mode 100644
index 000000000000..8d0c81acd688
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/url_go19.go
@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+import "net/url"
+
+func parseURL(s string) (*url.URL, error) {
+ u, err := url.Parse(s)
+ if err == nil {
+ u.OmitHost = false
+ }
+ return u, err
+}
diff --git a/vendor/github.com/go-openapi/spec/validations.go b/vendor/github.com/go-openapi/spec/validations.go
new file mode 100644
index 000000000000..4f70e301732b
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/validations.go
@@ -0,0 +1,222 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+// CommonValidations describe common JSON-schema validations
+type CommonValidations struct {
+ Maximum *float64 `json:"maximum,omitempty"`
+ ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"`
+ Minimum *float64 `json:"minimum,omitempty"`
+ ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"`
+ MaxLength *int64 `json:"maxLength,omitempty"`
+ MinLength *int64 `json:"minLength,omitempty"`
+ Pattern string `json:"pattern,omitempty"`
+ MaxItems *int64 `json:"maxItems,omitempty"`
+ MinItems *int64 `json:"minItems,omitempty"`
+ UniqueItems bool `json:"uniqueItems,omitempty"`
+ MultipleOf *float64 `json:"multipleOf,omitempty"`
+ Enum []any `json:"enum,omitempty"`
+}
+
+// SetValidations defines all validations for a simple schema.
+//
+// NOTE: the input is the larger set of validations available for schemas.
+// For simple schemas, MinProperties and MaxProperties are ignored.
+func (v *CommonValidations) SetValidations(val SchemaValidations) {
+ v.Maximum = val.Maximum
+ v.ExclusiveMaximum = val.ExclusiveMaximum
+ v.Minimum = val.Minimum
+ v.ExclusiveMinimum = val.ExclusiveMinimum
+ v.MaxLength = val.MaxLength
+ v.MinLength = val.MinLength
+ v.Pattern = val.Pattern
+ v.MaxItems = val.MaxItems
+ v.MinItems = val.MinItems
+ v.UniqueItems = val.UniqueItems
+ v.MultipleOf = val.MultipleOf
+ v.Enum = val.Enum
+}
+
+type clearedValidation struct {
+ Validation string
+ Value any
+}
+
+type clearedValidations []clearedValidation
+
+func (c clearedValidations) apply(cbs []func(string, any)) {
+ for _, cb := range cbs {
+ for _, cleared := range c {
+ cb(cleared.Validation, cleared.Value)
+ }
+ }
+}
+
+// ClearNumberValidations clears all number validations.
+//
+// Some callbacks may be set by the caller to capture changed values.
+func (v *CommonValidations) ClearNumberValidations(cbs ...func(string, any)) {
+ const maxNumberValidations = 5
+ done := make(clearedValidations, 0, maxNumberValidations)
+ defer func() {
+ done.apply(cbs)
+ }()
+
+ if v.Minimum != nil {
+ done = append(done, clearedValidation{Validation: "minimum", Value: v.Minimum})
+ v.Minimum = nil
+ }
+ if v.Maximum != nil {
+ done = append(done, clearedValidation{Validation: "maximum", Value: v.Maximum})
+ v.Maximum = nil
+ }
+ if v.ExclusiveMaximum {
+ done = append(done, clearedValidation{Validation: "exclusiveMaximum", Value: v.ExclusiveMaximum})
+ v.ExclusiveMaximum = false
+ }
+ if v.ExclusiveMinimum {
+ done = append(done, clearedValidation{Validation: "exclusiveMinimum", Value: v.ExclusiveMinimum})
+ v.ExclusiveMinimum = false
+ }
+ if v.MultipleOf != nil {
+ done = append(done, clearedValidation{Validation: "multipleOf", Value: v.MultipleOf})
+ v.MultipleOf = nil
+ }
+}
+
+// ClearStringValidations clears all string validations.
+//
+// Some callbacks may be set by the caller to capture changed values.
+func (v *CommonValidations) ClearStringValidations(cbs ...func(string, any)) {
+ const maxStringValidations = 3
+ done := make(clearedValidations, 0, maxStringValidations)
+ defer func() {
+ done.apply(cbs)
+ }()
+
+ if v.Pattern != "" {
+ done = append(done, clearedValidation{Validation: "pattern", Value: v.Pattern})
+ v.Pattern = ""
+ }
+ if v.MinLength != nil {
+ done = append(done, clearedValidation{Validation: "minLength", Value: v.MinLength})
+ v.MinLength = nil
+ }
+ if v.MaxLength != nil {
+ done = append(done, clearedValidation{Validation: "maxLength", Value: v.MaxLength})
+ v.MaxLength = nil
+ }
+}
+
+// ClearArrayValidations clears all array validations.
+//
+// Some callbacks may be set by the caller to capture changed values.
+func (v *CommonValidations) ClearArrayValidations(cbs ...func(string, any)) {
+ const maxArrayValidations = 3
+ done := make(clearedValidations, 0, maxArrayValidations)
+ defer func() {
+ done.apply(cbs)
+ }()
+
+ if v.MaxItems != nil {
+ done = append(done, clearedValidation{Validation: "maxItems", Value: v.MaxItems})
+ v.MaxItems = nil
+ }
+ if v.MinItems != nil {
+ done = append(done, clearedValidation{Validation: "minItems", Value: v.MinItems})
+ v.MinItems = nil
+ }
+ if v.UniqueItems {
+ done = append(done, clearedValidation{Validation: "uniqueItems", Value: v.UniqueItems})
+ v.UniqueItems = false
+ }
+}
+
+// Validations returns a clone of the validations for a simple schema.
+//
+// NOTE: in the context of simple schema objects, MinProperties, MaxProperties
+// and PatternProperties remain unset.
+func (v CommonValidations) Validations() SchemaValidations {
+ return SchemaValidations{
+ CommonValidations: v,
+ }
+}
+
+// HasNumberValidations indicates if the validations are for numbers or integers
+func (v CommonValidations) HasNumberValidations() bool {
+ return v.Maximum != nil || v.Minimum != nil || v.MultipleOf != nil
+}
+
+// HasStringValidations indicates if the validations are for strings
+func (v CommonValidations) HasStringValidations() bool {
+ return v.MaxLength != nil || v.MinLength != nil || v.Pattern != ""
+}
+
+// HasArrayValidations indicates if the validations are for arrays
+func (v CommonValidations) HasArrayValidations() bool {
+ return v.MaxItems != nil || v.MinItems != nil || v.UniqueItems
+}
+
+// HasEnum indicates if the validation includes some enum constraint
+func (v CommonValidations) HasEnum() bool {
+ return len(v.Enum) > 0
+}
+
+// SchemaValidations describes the validation properties of a schema
+//
+// NOTE: at this moment, this is not embedded in SchemaProps because this would induce a breaking change
+// in the exported members: all initializers using litterals would fail.
+type SchemaValidations struct {
+ CommonValidations
+
+ PatternProperties SchemaProperties `json:"patternProperties,omitempty"`
+ MaxProperties *int64 `json:"maxProperties,omitempty"`
+ MinProperties *int64 `json:"minProperties,omitempty"`
+}
+
+// HasObjectValidations indicates if the validations are for objects
+func (v SchemaValidations) HasObjectValidations() bool {
+ return v.MaxProperties != nil || v.MinProperties != nil || v.PatternProperties != nil
+}
+
+// SetValidations for schema validations
+func (v *SchemaValidations) SetValidations(val SchemaValidations) {
+ v.CommonValidations.SetValidations(val)
+ v.PatternProperties = val.PatternProperties
+ v.MaxProperties = val.MaxProperties
+ v.MinProperties = val.MinProperties
+}
+
+// Validations for a schema
+func (v SchemaValidations) Validations() SchemaValidations {
+ val := v.CommonValidations.Validations()
+ val.PatternProperties = v.PatternProperties
+ val.MinProperties = v.MinProperties
+ val.MaxProperties = v.MaxProperties
+ return val
+}
+
+// ClearObjectValidations returns a clone of the validations with all object validations cleared.
+//
+// Some callbacks may be set by the caller to capture changed values.
+func (v *SchemaValidations) ClearObjectValidations(cbs ...func(string, any)) {
+ const maxObjectValidations = 3
+ done := make(clearedValidations, 0, maxObjectValidations)
+ defer func() {
+ done.apply(cbs)
+ }()
+
+ if v.MaxProperties != nil {
+ done = append(done, clearedValidation{Validation: "maxProperties", Value: v.MaxProperties})
+ v.MaxProperties = nil
+ }
+ if v.MinProperties != nil {
+ done = append(done, clearedValidation{Validation: "minProperties", Value: v.MinProperties})
+ v.MinProperties = nil
+ }
+ if v.PatternProperties != nil {
+ done = append(done, clearedValidation{Validation: "patternProperties", Value: v.PatternProperties})
+ v.PatternProperties = nil
+ }
+}
diff --git a/vendor/github.com/go-openapi/spec/xml_object.go b/vendor/github.com/go-openapi/spec/xml_object.go
new file mode 100644
index 000000000000..bf2f8f18b24c
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/xml_object.go
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package spec
+
+// XMLObject a metadata object that allows for more fine-tuned XML model definitions.
+//
+// For more information: http://goo.gl/8us55a#xmlObject
+type XMLObject struct {
+ Name string `json:"name,omitempty"`
+ Namespace string `json:"namespace,omitempty"`
+ Prefix string `json:"prefix,omitempty"`
+ Attribute bool `json:"attribute,omitempty"`
+ Wrapped bool `json:"wrapped,omitempty"`
+}
+
+// WithName sets the xml name for the object
+func (x *XMLObject) WithName(name string) *XMLObject {
+ x.Name = name
+ return x
+}
+
+// WithNamespace sets the xml namespace for the object
+func (x *XMLObject) WithNamespace(namespace string) *XMLObject {
+ x.Namespace = namespace
+ return x
+}
+
+// WithPrefix sets the xml prefix for the object
+func (x *XMLObject) WithPrefix(prefix string) *XMLObject {
+ x.Prefix = prefix
+ return x
+}
+
+// AsAttribute flags this object as xml attribute
+func (x *XMLObject) AsAttribute() *XMLObject {
+ x.Attribute = true
+ return x
+}
+
+// AsElement flags this object as an xml node
+func (x *XMLObject) AsElement() *XMLObject {
+ x.Attribute = false
+ return x
+}
+
+// AsWrapped flags this object as wrapped, this is mostly useful for array types
+func (x *XMLObject) AsWrapped() *XMLObject {
+ x.Wrapped = true
+ return x
+}
+
+// AsUnwrapped flags this object as an xml node
+func (x *XMLObject) AsUnwrapped() *XMLObject {
+ x.Wrapped = false
+ return x
+}
diff --git a/vendor/github.com/go-openapi/strfmt/.editorconfig b/vendor/github.com/go-openapi/strfmt/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/strfmt/.gitattributes b/vendor/github.com/go-openapi/strfmt/.gitattributes
new file mode 100644
index 000000000000..d020be8ea4e7
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/.gitattributes
@@ -0,0 +1,2 @@
+*.go text eol=lf
+
diff --git a/vendor/github.com/go-openapi/strfmt/.gitignore b/vendor/github.com/go-openapi/strfmt/.gitignore
new file mode 100644
index 000000000000..dd91ed6a04e6
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/.gitignore
@@ -0,0 +1,2 @@
+secrets.yml
+coverage.out
diff --git a/vendor/github.com/go-openapi/strfmt/.golangci.yml b/vendor/github.com/go-openapi/strfmt/.golangci.yml
new file mode 100644
index 000000000000..1ad5adf47e69
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/.golangci.yml
@@ -0,0 +1,75 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gosmopolitan
+ - inamedparam
+ - intrange
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/strfmt/LICENSE b/vendor/github.com/go-openapi/strfmt/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/strfmt/README.md b/vendor/github.com/go-openapi/strfmt/README.md
new file mode 100644
index 000000000000..de5afe137606
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/README.md
@@ -0,0 +1,92 @@
+# Strfmt [](https://github.com/go-openapi/strfmt/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/strfmt)
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/strfmt/master/LICENSE)
+[](http://godoc.org/github.com/go-openapi/strfmt)
+[](https://goreportcard.com/report/github.com/go-openapi/strfmt)
+
+This package exposes a registry of data types to support string formats in the go-openapi toolkit.
+
+strfmt represents a well known string format such as credit card or email. The go toolkit for OpenAPI specifications knows how to deal with those.
+
+## Supported data formats
+go-openapi/strfmt follows the swagger 2.0 specification with the following formats
+defined [here](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types).
+
+It also provides convenient extensions to go-openapi users.
+
+- [x] JSON-schema draft 4 formats
+ - date-time
+ - email
+ - hostname
+ - ipv4
+ - ipv6
+ - uri
+- [x] swagger 2.0 format extensions
+ - binary
+ - byte (e.g. base64 encoded string)
+ - date (e.g. "1970-01-01")
+ - password
+- [x] go-openapi custom format extensions
+ - bsonobjectid (BSON objectID)
+ - creditcard
+ - duration (e.g. "3 weeks", "1ms")
+ - hexcolor (e.g. "#FFFFFF")
+ - isbn, isbn10, isbn13
+ - mac (e.g "01:02:03:04:05:06")
+ - rgbcolor (e.g. "rgb(100,100,100)")
+ - ssn
+ - uuid, uuid3, uuid4, uuid5, uuid7
+ - cidr (e.g. "192.0.2.1/24", "2001:db8:a0b:12f0::1/32")
+ - ulid (e.g. "00000PP9HGSBSSDZ1JTEXBJ0PW", [spec](https://github.com/ulid/spec))
+
+> NOTE: as the name stands for, this package is intended to support string formatting only.
+> It does not provide validation for numerical values with swagger format extension for JSON types "number" or
+> "integer" (e.g. float, double, int32...).
+
+## Type conversion
+
+All types defined here are stringers and may be converted to strings with `.String()`.
+Note that most types defined by this package may be converted directly to string like `string(Email{})`.
+
+`Date` and `DateTime` may be converted directly to `time.Time` like `time.Time(Time{})`.
+Similarly, you can convert `Duration` to `time.Duration` as in `time.Duration(Duration{})`
+
+## Using pointers
+
+The `conv` subpackage provides helpers to convert the types to and from pointers, just like `go-openapi/swag` does
+with primitive types.
+
+## Format types
+Types defined in strfmt expose marshaling and validation capabilities.
+
+List of defined types:
+- Base64
+- CreditCard
+- Date
+- DateTime
+- Duration
+- Email
+- HexColor
+- Hostname
+- IPv4
+- IPv6
+- CIDR
+- ISBN
+- ISBN10
+- ISBN13
+- MAC
+- ObjectId
+- Password
+- RGBColor
+- SSN
+- URI
+- UUID
+- [UUID3](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-3)
+- [UUID4](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4)
+- [UUID5](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-5)
+- [UUID7](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7)
+- [ULID](https://github.com/ulid/spec)
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
diff --git a/vendor/github.com/go-openapi/strfmt/bson.go b/vendor/github.com/go-openapi/strfmt/bson.go
new file mode 100644
index 000000000000..0eec8f6432ce
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/bson.go
@@ -0,0 +1,115 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "database/sql/driver"
+ "fmt"
+
+ bsonprim "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func init() {
+ var id ObjectId
+ // register this format in the default registry
+ Default.Add("bsonobjectid", &id, IsBSONObjectID)
+}
+
+// IsBSONObjectID returns true when the string is a valid BSON.ObjectId
+func IsBSONObjectID(str string) bool {
+ _, err := bsonprim.ObjectIDFromHex(str)
+ return err == nil
+}
+
+// ObjectId represents a BSON object ID (alias to go.mongodb.org/mongo-driver/bson/primitive.ObjectID)
+//
+// swagger:strfmt bsonobjectid
+type ObjectId bsonprim.ObjectID //nolint:revive
+
+// NewObjectId creates a ObjectId from a Hex String
+func NewObjectId(hex string) ObjectId { //nolint:revive
+ oid, err := bsonprim.ObjectIDFromHex(hex)
+ if err != nil {
+ panic(err)
+ }
+ return ObjectId(oid)
+}
+
+// MarshalText turns this instance into text
+func (id ObjectId) MarshalText() ([]byte, error) {
+ oid := bsonprim.ObjectID(id)
+ if oid == bsonprim.NilObjectID {
+ return nil, nil
+ }
+ return []byte(oid.Hex()), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (id *ObjectId) UnmarshalText(data []byte) error { // validation is performed later on
+ if len(data) == 0 {
+ *id = ObjectId(bsonprim.NilObjectID)
+ return nil
+ }
+ oidstr := string(data)
+ oid, err := bsonprim.ObjectIDFromHex(oidstr)
+ if err != nil {
+ return err
+ }
+ *id = ObjectId(oid)
+ return nil
+}
+
+// Scan read a value from a database driver
+func (id *ObjectId) Scan(raw any) error {
+ var data []byte
+ switch v := raw.(type) {
+ case []byte:
+ data = v
+ case string:
+ data = []byte(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v: %w", v, ErrFormat)
+ }
+
+ return id.UnmarshalText(data)
+}
+
+// Value converts a value to a database driver value
+func (id ObjectId) Value() (driver.Value, error) {
+ return driver.Value(bsonprim.ObjectID(id).Hex()), nil
+}
+
+func (id ObjectId) String() string {
+ return bsonprim.ObjectID(id).Hex()
+}
+
+// MarshalJSON returns the ObjectId as JSON
+func (id ObjectId) MarshalJSON() ([]byte, error) {
+ return bsonprim.ObjectID(id).MarshalJSON()
+}
+
+// UnmarshalJSON sets the ObjectId from JSON
+func (id *ObjectId) UnmarshalJSON(data []byte) error {
+ var obj bsonprim.ObjectID
+ if err := obj.UnmarshalJSON(data); err != nil {
+ return err
+ }
+ *id = ObjectId(obj)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (id *ObjectId) DeepCopyInto(out *ObjectId) {
+ *out = *id
+}
+
+// DeepCopy copies the receiver into a new ObjectId.
+func (id *ObjectId) DeepCopy() *ObjectId {
+ if id == nil {
+ return nil
+ }
+ out := new(ObjectId)
+ id.DeepCopyInto(out)
+ return out
+}
diff --git a/vendor/github.com/go-openapi/strfmt/date.go b/vendor/github.com/go-openapi/strfmt/date.go
new file mode 100644
index 000000000000..8aa17b8ea551
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/date.go
@@ -0,0 +1,151 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "database/sql/driver"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+func init() {
+ d := Date{}
+ // register this format in the default registry
+ Default.Add("date", &d, IsDate)
+}
+
+// IsDate returns true when the string is a valid date
+func IsDate(str string) bool {
+ _, err := time.Parse(RFC3339FullDate, str)
+ return err == nil
+}
+
+const (
+ // RFC3339FullDate represents a full-date as specified by RFC3339
+ // See: http://goo.gl/xXOvVd
+ RFC3339FullDate = "2006-01-02"
+)
+
+// Date represents a date from the API
+//
+// swagger:strfmt date
+type Date time.Time
+
+// String converts this date into a string
+func (d Date) String() string {
+ return time.Time(d).Format(RFC3339FullDate)
+}
+
+// UnmarshalText parses a text representation into a date type
+func (d *Date) UnmarshalText(text []byte) error {
+ if len(text) == 0 {
+ return nil
+ }
+ dd, err := time.ParseInLocation(RFC3339FullDate, string(text), DefaultTimeLocation)
+ if err != nil {
+ return err
+ }
+ *d = Date(dd)
+ return nil
+}
+
+// MarshalText serializes this date type to string
+func (d Date) MarshalText() ([]byte, error) {
+ return []byte(d.String()), nil
+}
+
+// Scan scans a Date value from database driver type.
+func (d *Date) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ return d.UnmarshalText(v)
+ case string:
+ return d.UnmarshalText([]byte(v))
+ case time.Time:
+ *d = Date(v)
+ return nil
+ case nil:
+ *d = Date{}
+ return nil
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.Date from: %#v: %w", v, ErrFormat)
+ }
+}
+
+// Value converts Date to a primitive value ready to written to a database.
+func (d Date) Value() (driver.Value, error) {
+ return driver.Value(d.String()), nil
+}
+
+// MarshalJSON returns the Date as JSON
+func (d Date) MarshalJSON() ([]byte, error) {
+ return json.Marshal(time.Time(d).Format(RFC3339FullDate))
+}
+
+// UnmarshalJSON sets the Date from JSON
+func (d *Date) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var strdate string
+ if err := json.Unmarshal(data, &strdate); err != nil {
+ return err
+ }
+ tt, err := time.ParseInLocation(RFC3339FullDate, strdate, DefaultTimeLocation)
+ if err != nil {
+ return err
+ }
+ *d = Date(tt)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (d *Date) DeepCopyInto(out *Date) {
+ *out = *d
+}
+
+// DeepCopy copies the receiver into a new Date.
+func (d *Date) DeepCopy() *Date {
+ if d == nil {
+ return nil
+ }
+ out := new(Date)
+ d.DeepCopyInto(out)
+ return out
+}
+
+// GobEncode implements the gob.GobEncoder interface.
+func (d Date) GobEncode() ([]byte, error) {
+ return d.MarshalBinary()
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (d *Date) GobDecode(data []byte) error {
+ return d.UnmarshalBinary(data)
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (d Date) MarshalBinary() ([]byte, error) {
+ return time.Time(d).MarshalBinary()
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (d *Date) UnmarshalBinary(data []byte) error {
+ var original time.Time
+
+ err := original.UnmarshalBinary(data)
+ if err != nil {
+ return err
+ }
+
+ *d = Date(original)
+
+ return nil
+}
+
+// Equal checks if two Date instances are equal
+func (d Date) Equal(d2 Date) bool {
+ return time.Time(d).Equal(time.Time(d2))
+}
diff --git a/vendor/github.com/go-openapi/strfmt/default.go b/vendor/github.com/go-openapi/strfmt/default.go
new file mode 100644
index 000000000000..8a80cfbdb8ae
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/default.go
@@ -0,0 +1,2110 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "database/sql/driver"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "net"
+ "net/mail"
+ "net/netip"
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "github.com/google/uuid"
+ "golang.org/x/net/idna"
+)
+
+const (
+ // HostnamePattern http://json-schema.org/latest/json-schema-validation.html#anchor114.
+ //
+ // Deprecated: this package no longer uses regular expressions to validate hostnames.
+ HostnamePattern = `^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z0-9-\p{L}]){2,63})$`
+
+ // json null type
+ jsonNull = "null"
+)
+
+const (
+ // UUIDPattern Regex for UUID that allows uppercase
+ //
+ // Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
+ UUIDPattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{32}$)`
+
+ // UUID3Pattern Regex for UUID3 that allows uppercase
+ //
+ // Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
+ UUID3Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{12}3[0-9a-f]{3}?[0-9a-f]{16}$)`
+
+ // UUID4Pattern Regex for UUID4 that allows uppercase
+ //
+ // Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
+ UUID4Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$)`
+
+ // UUID5Pattern Regex for UUID5 that allows uppercase
+ //
+ // Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
+ UUID5Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}5[0-9a-f]{3}[89ab][0-9a-f]{15}$)`
+
+ isbn10Pattern string = "^(?:[0-9]{9}X|[0-9]{10})$"
+ isbn13Pattern string = "^(?:[0-9]{13})$"
+ usCardPattern string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$"
+ ssnPattern string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
+ hexColorPattern string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
+ rgbColorPattern string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
+)
+
+const (
+ isbnVersion10 = 10
+ isbnVersion13 = 13
+ decimalBase = 10
+)
+
+var (
+ idnaHostChecker = idna.New(
+ idna.ValidateForRegistration(), // shorthand for [idna.StrictDomainName], [idna.ValidateLabels], [idna.VerifyDNSLength], [idna.BidiRule]
+ )
+
+ whiteSpacesAndMinus = regexp.MustCompile(`[\s-]+`)
+ rxISBN10 = regexp.MustCompile(isbn10Pattern)
+ rxISBN13 = regexp.MustCompile(isbn13Pattern)
+ rxCreditCard = regexp.MustCompile(usCardPattern)
+ rxSSN = regexp.MustCompile(ssnPattern)
+ rxHexcolor = regexp.MustCompile(hexColorPattern)
+ rxRGBcolor = regexp.MustCompile(rgbColorPattern)
+)
+
+// IsHostname returns true when the string is a valid hostname.
+//
+// It follows the rules detailed at https://url.spec.whatwg.org/#concept-host-parser
+// and implemented by most modern web browsers.
+//
+// It supports IDNA rules regarding internationalized names with unicode.
+//
+// Besides:
+// * the empty string is not a valid host name
+// * a trailing dot is allowed in names and IPv4's (not IPv6)
+// * a host name can be a valid IPv4 (with decimal, octal or hexadecimal numbers) or IPv6 address
+// * IPv6 zones are disallowed
+// * top-level domains can be unicode (cf. https://www.iana.org/domains/root/db).
+//
+// NOTE: this validator doesn't check top-level domains against the IANA root database.
+// It merely ensures that a top-level domain in a FQDN is at least 2 code points long.
+func IsHostname(str string) bool {
+ if len(str) == 0 {
+ return false
+ }
+
+ // IP v6 check
+ if ipv6Cleaned, found := strings.CutPrefix(str, "["); found {
+ ipv6Cleaned, found = strings.CutSuffix(ipv6Cleaned, "]")
+ if !found {
+ return false
+ }
+
+ return isValidIPv6(ipv6Cleaned)
+ }
+
+ // IDNA check
+ res, err := idnaHostChecker.ToASCII(strings.ToLower(str))
+ if err != nil || res == "" {
+ return false
+ }
+
+ parts := strings.Split(res, ".")
+
+ // IP v4 check
+ lastPart, lastIndex, shouldBeIPv4 := domainEndsAsNumber(parts)
+ if shouldBeIPv4 {
+ // domain ends in a number: must be an IPv4
+ return isValidIPv4(parts[:lastIndex+1]) // if the last part is a trailing dot, remove it
+ }
+
+ // check TLD length (excluding trailing dot)
+ const minTLDLength = 2
+ if lastIndex > 0 && len(lastPart) < minTLDLength {
+ return false
+ }
+
+ return true
+}
+
+// domainEndsAsNumber determines if a domain name ends with a decimal, octal or hex digit,
+// accounting for a possible trailing dot (the last part being empty in that case).
+//
+// It returns the last non-trailing dot part and if that part consists only of (dec/hex/oct) digits.
+func domainEndsAsNumber(parts []string) (lastPart string, lastIndex int, ok bool) {
+ // NOTE: using ParseUint(x, 0, 32) is not an option, as the IPv4 format supported why WHATWG
+ // doesn't support notations such as "0b1001" (binary digits) or "0o666" (alternate notation for octal digits).
+ lastIndex = len(parts) - 1
+ lastPart = parts[lastIndex]
+ if len(lastPart) == 0 {
+ // trailing dot
+ if len(parts) == 1 { // dot-only string: normally already ruled out by the IDNA check above
+ return lastPart, lastIndex, false
+ }
+
+ lastIndex--
+ lastPart = parts[lastIndex]
+ }
+
+ if startOfHexDigit(lastPart) {
+ for _, b := range []byte(lastPart[2:]) {
+ if !isHexDigit(b) {
+ return lastPart, lastIndex, false
+ }
+ }
+
+ return lastPart, lastIndex, true
+ }
+
+ // check for decimal and octal
+ for _, b := range []byte(lastPart) {
+ if !isASCIIDigit(b) {
+ return lastPart, lastIndex, false
+ }
+ }
+
+ return lastPart, lastIndex, true
+}
+
+func startOfHexDigit(str string) bool {
+ return strings.HasPrefix(str, "0x") // the input has already been lower-cased
+}
+
+func startOfOctalDigit(str string) bool {
+ if str == "0" {
+ // a single "0" is considered decimal
+ return false
+ }
+
+ return strings.HasPrefix(str, "0")
+}
+
+func isValidIPv6(str string) bool {
+ // disallow empty ipv6 address
+ if len(str) == 0 {
+ return false
+ }
+
+ addr, err := netip.ParseAddr(str)
+ if err != nil {
+ return false
+ }
+
+ if !addr.Is6() {
+ return false
+ }
+
+ // explicit desupport of IPv6 zones
+ if addr.Zone() != "" {
+ return false
+ }
+
+ return true
+}
+
+// isValidIPv4 parses an IPv4 with deciaml, hex or octal digit parts.
+//
+// We can't rely on [netip.ParseAddr] because we may get a mix of decimal, octal and hex digits.
+//
+// Examples of valid addresses not supported by [netip.ParseAddr] or [net.ParseIP]:
+//
+// "192.0x00A80001"
+// "0300.0250.0340.001"
+// "1.0x.1.1"
+//
+// But not:
+//
+// "0b1010.2.3.4"
+// "0o07.2.3.4"
+func isValidIPv4(parts []string) bool {
+ // NOTE: using ParseUint(x, 0, 32) is not an option, even though it would simplify this code a lot.
+ // The IPv4 format supported why WHATWG doesn't support notations such as "0b1001" (binary digits)
+ // or "0o666" (alternate notation for octal digits).
+ const (
+ maxPartsInIPv4 = 4
+ maxDigitsInPart = 11 // max size of a 4-bytes hex or octal digit
+ )
+
+ if len(parts) == 0 || len(parts) > maxPartsInIPv4 {
+ return false
+ }
+
+ // we call this when we know that the last part is a digit part, so len(lastPart)>0
+
+ digits := make([]uint64, 0, maxPartsInIPv4)
+ for _, part := range parts {
+ if len(part) == 0 { // empty part: this case has normally been already ruled out by the IDNA check above
+ return false
+ }
+
+ if len(part) > maxDigitsInPart { // whether decimal, octal or hex, an address can't exceed that length
+ return false
+ }
+
+ if !isASCIIDigit(part[0]) { // start of an IPv4 part is always a digit
+ return false
+ }
+
+ switch {
+ case startOfHexDigit(part):
+ const hexDigitOffset = 2
+ hexString := part[hexDigitOffset:]
+ if len(hexString) == 0 { // 0x part: assume 0
+ digits = append(digits, 0)
+
+ continue
+ }
+
+ hexDigit, err := strconv.ParseUint(hexString, 16, 32)
+ if err != nil {
+ return false
+ }
+
+ digits = append(digits, hexDigit)
+
+ continue
+
+ case startOfOctalDigit(part):
+ const octDigitOffset = 1
+ octString := part[octDigitOffset:] // we know that this is not empty
+ octDigit, err := strconv.ParseUint(octString, 8, 32)
+ if err != nil {
+ return false
+ }
+
+ digits = append(digits, octDigit)
+
+ default: // assume decimal digits (0-255)
+ // we know that we don't have a leading 0 (would have been caught by octal digit)
+ decDigit, err := strconv.ParseUint(part, 10, 8)
+ if err != nil {
+ return false
+ }
+
+ digits = append(digits, decDigit)
+ }
+ }
+
+ // now check the digits: the last digit may encompass several parts of the address
+ lastDigit := digits[len(digits)-1]
+ if lastDigit > uint64(1)< 1 {
+ const maxUint8 = uint64(^uint8(0))
+
+ for i := range len(digits) - 2 {
+ if digits[i] > maxUint8 {
+ return false
+ }
+ }
+ }
+
+ return true
+}
+
+func isHexDigit(c byte) bool {
+ switch {
+ case '0' <= c && c <= '9':
+ return true
+ case 'a' <= c && c <= 'f': // assume the input string to be lower case
+ return true
+ }
+ return false
+}
+
+func isASCIIDigit(c byte) bool {
+ return c >= '0' && c <= '9'
+}
+
+// IsUUID returns true is the string matches a UUID (in any version, including v6 and v7), upper case is allowed
+func IsUUID(str string) bool {
+ _, err := uuid.Parse(str)
+ return err == nil
+}
+
+const (
+ uuidV3 = 3
+ uuidV4 = 4
+ uuidV5 = 5
+ uuidV7 = 7
+)
+
+// IsUUID3 returns true is the string matches a UUID v3, upper case is allowed
+func IsUUID3(str string) bool {
+ id, err := uuid.Parse(str)
+ return err == nil && id.Version() == uuid.Version(uuidV3)
+}
+
+// IsUUID4 returns true is the string matches a UUID v4, upper case is allowed
+func IsUUID4(str string) bool {
+ id, err := uuid.Parse(str)
+ return err == nil && id.Version() == uuid.Version(uuidV4)
+}
+
+// IsUUID5 returns true is the string matches a UUID v5, upper case is allowed
+func IsUUID5(str string) bool {
+ id, err := uuid.Parse(str)
+ return err == nil && id.Version() == uuid.Version(uuidV5)
+}
+
+// IsUUID7 returns true is the string matches a UUID v7, upper case is allowed
+func IsUUID7(str string) bool {
+ id, err := uuid.Parse(str)
+ return err == nil && id.Version() == uuid.Version(uuidV7)
+}
+
+// IsEmail validates an email address.
+func IsEmail(str string) bool {
+ addr, e := mail.ParseAddress(str)
+ return e == nil && addr.Address != ""
+}
+
+func init() {
+ // register formats in the default registry:
+ // - byte
+ // - creditcard
+ // - email
+ // - hexcolor
+ // - hostname
+ // - ipv4
+ // - ipv6
+ // - cidr
+ // - isbn
+ // - isbn10
+ // - isbn13
+ // - mac
+ // - password
+ // - rgbcolor
+ // - ssn
+ // - uri
+ // - uuid
+ // - uuid3
+ // - uuid4
+ // - uuid5
+ // - uuid7
+ u := URI("")
+ Default.Add("uri", &u, isRequestURI)
+
+ eml := Email("")
+ Default.Add("email", &eml, IsEmail)
+
+ hn := Hostname("")
+ Default.Add("hostname", &hn, IsHostname)
+
+ ip4 := IPv4("")
+ Default.Add("ipv4", &ip4, isIPv4)
+
+ ip6 := IPv6("")
+ Default.Add("ipv6", &ip6, isIPv6)
+
+ cidr := CIDR("")
+ Default.Add("cidr", &cidr, isCIDR)
+
+ mac := MAC("")
+ Default.Add("mac", &mac, isMAC)
+
+ uid := UUID("")
+ Default.Add("uuid", &uid, IsUUID)
+
+ uid3 := UUID3("")
+ Default.Add("uuid3", &uid3, IsUUID3)
+
+ uid4 := UUID4("")
+ Default.Add("uuid4", &uid4, IsUUID4)
+
+ uid5 := UUID5("")
+ Default.Add("uuid5", &uid5, IsUUID5)
+
+ uid7 := UUID7("")
+ Default.Add("uuid7", &uid7, IsUUID7)
+
+ isbn := ISBN("")
+ Default.Add("isbn", &isbn, func(str string) bool { return isISBN10(str) || isISBN13(str) })
+
+ isbn10 := ISBN10("")
+ Default.Add("isbn10", &isbn10, isISBN10)
+
+ isbn13 := ISBN13("")
+ Default.Add("isbn13", &isbn13, isISBN13)
+
+ cc := CreditCard("")
+ Default.Add("creditcard", &cc, isCreditCard)
+
+ ssn := SSN("")
+ Default.Add("ssn", &ssn, isSSN)
+
+ hc := HexColor("")
+ Default.Add("hexcolor", &hc, isHexcolor)
+
+ rc := RGBColor("")
+ Default.Add("rgbcolor", &rc, isRGBcolor)
+
+ b64 := Base64([]byte(nil))
+ Default.Add("byte", &b64, isBase64)
+
+ pw := Password("")
+ Default.Add("password", &pw, func(_ string) bool { return true })
+}
+
+// Base64 represents a base64 encoded string, using URLEncoding alphabet
+//
+// swagger:strfmt byte
+type Base64 []byte
+
+// MarshalText turns this instance into text
+func (b Base64) MarshalText() ([]byte, error) {
+ enc := base64.URLEncoding
+ src := []byte(b)
+ buf := make([]byte, enc.EncodedLen(len(src)))
+ enc.Encode(buf, src)
+ return buf, nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (b *Base64) UnmarshalText(data []byte) error { // validation is performed later on
+ enc := base64.URLEncoding
+ dbuf := make([]byte, enc.DecodedLen(len(data)))
+
+ n, err := enc.Decode(dbuf, data)
+ if err != nil {
+ return err
+ }
+
+ *b = dbuf[:n]
+ return nil
+}
+
+// Scan read a value from a database driver
+func (b *Base64) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(v)))
+ n, err := base64.StdEncoding.Decode(dbuf, v)
+ if err != nil {
+ return err
+ }
+ *b = dbuf[:n]
+ case string:
+ vv, err := base64.StdEncoding.DecodeString(v)
+ if err != nil {
+ return err
+ }
+ *b = Base64(vv)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.Base64 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (b Base64) Value() (driver.Value, error) {
+ return driver.Value(b.String()), nil
+}
+
+func (b Base64) String() string {
+ return base64.StdEncoding.EncodeToString([]byte(b))
+}
+
+// MarshalJSON returns the Base64 as JSON
+func (b Base64) MarshalJSON() ([]byte, error) {
+ return json.Marshal(b.String())
+}
+
+// UnmarshalJSON sets the Base64 from JSON
+func (b *Base64) UnmarshalJSON(data []byte) error {
+ var b64str string
+ if err := json.Unmarshal(data, &b64str); err != nil {
+ return err
+ }
+ vb, err := base64.StdEncoding.DecodeString(b64str)
+ if err != nil {
+ return err
+ }
+ *b = Base64(vb)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (b *Base64) DeepCopyInto(out *Base64) {
+ *out = *b
+}
+
+// DeepCopy copies the receiver into a new Base64.
+func (b *Base64) DeepCopy() *Base64 {
+ if b == nil {
+ return nil
+ }
+ out := new(Base64)
+ b.DeepCopyInto(out)
+ return out
+}
+
+// URI represents the uri string format as specified by the json schema spec
+//
+// swagger:strfmt uri
+type URI string
+
+// MarshalText turns this instance into text
+func (u URI) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *URI) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = URI(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *URI) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = URI(string(v))
+ case string:
+ *u = URI(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u URI) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u URI) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the URI as JSON
+func (u URI) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the URI from JSON
+func (u *URI) UnmarshalJSON(data []byte) error {
+ var uristr string
+ if err := json.Unmarshal(data, &uristr); err != nil {
+ return err
+ }
+ *u = URI(uristr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *URI) DeepCopyInto(out *URI) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new URI.
+func (u *URI) DeepCopy() *URI {
+ if u == nil {
+ return nil
+ }
+ out := new(URI)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// Email represents the email string format as specified by the json schema spec
+//
+// swagger:strfmt email
+type Email string
+
+// MarshalText turns this instance into text
+func (e Email) MarshalText() ([]byte, error) {
+ return []byte(string(e)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (e *Email) UnmarshalText(data []byte) error { // validation is performed later on
+ *e = Email(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (e *Email) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *e = Email(string(v))
+ case string:
+ *e = Email(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.Email from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (e Email) Value() (driver.Value, error) {
+ return driver.Value(string(e)), nil
+}
+
+func (e Email) String() string {
+ return string(e)
+}
+
+// MarshalJSON returns the Email as JSON
+func (e Email) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(e))
+}
+
+// UnmarshalJSON sets the Email from JSON
+func (e *Email) UnmarshalJSON(data []byte) error {
+ var estr string
+ if err := json.Unmarshal(data, &estr); err != nil {
+ return err
+ }
+ *e = Email(estr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (e *Email) DeepCopyInto(out *Email) {
+ *out = *e
+}
+
+// DeepCopy copies the receiver into a new Email.
+func (e *Email) DeepCopy() *Email {
+ if e == nil {
+ return nil
+ }
+ out := new(Email)
+ e.DeepCopyInto(out)
+ return out
+}
+
+// Hostname represents the hostname string format as specified by the json schema spec
+//
+// swagger:strfmt hostname
+type Hostname string
+
+// MarshalText turns this instance into text
+func (h Hostname) MarshalText() ([]byte, error) {
+ return []byte(string(h)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (h *Hostname) UnmarshalText(data []byte) error { // validation is performed later on
+ *h = Hostname(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (h *Hostname) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *h = Hostname(string(v))
+ case string:
+ *h = Hostname(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.Hostname from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (h Hostname) Value() (driver.Value, error) {
+ return driver.Value(string(h)), nil
+}
+
+func (h Hostname) String() string {
+ return string(h)
+}
+
+// MarshalJSON returns the Hostname as JSON
+func (h Hostname) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(h))
+}
+
+// UnmarshalJSON sets the Hostname from JSON
+func (h *Hostname) UnmarshalJSON(data []byte) error {
+ var hstr string
+ if err := json.Unmarshal(data, &hstr); err != nil {
+ return err
+ }
+ *h = Hostname(hstr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (h *Hostname) DeepCopyInto(out *Hostname) {
+ *out = *h
+}
+
+// DeepCopy copies the receiver into a new Hostname.
+func (h *Hostname) DeepCopy() *Hostname {
+ if h == nil {
+ return nil
+ }
+ out := new(Hostname)
+ h.DeepCopyInto(out)
+ return out
+}
+
+// IPv4 represents an IP v4 address
+//
+// swagger:strfmt ipv4
+type IPv4 string
+
+// MarshalText turns this instance into text
+func (u IPv4) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *IPv4) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = IPv4(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *IPv4) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = IPv4(string(v))
+ case string:
+ *u = IPv4(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.IPv4 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u IPv4) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u IPv4) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the IPv4 as JSON
+func (u IPv4) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the IPv4 from JSON
+func (u *IPv4) UnmarshalJSON(data []byte) error {
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = IPv4(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *IPv4) DeepCopyInto(out *IPv4) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new IPv4.
+func (u *IPv4) DeepCopy() *IPv4 {
+ if u == nil {
+ return nil
+ }
+ out := new(IPv4)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// IPv6 represents an IP v6 address
+//
+// swagger:strfmt ipv6
+type IPv6 string
+
+// MarshalText turns this instance into text
+func (u IPv6) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *IPv6) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = IPv6(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *IPv6) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = IPv6(string(v))
+ case string:
+ *u = IPv6(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.IPv6 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u IPv6) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u IPv6) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the IPv6 as JSON
+func (u IPv6) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the IPv6 from JSON
+func (u *IPv6) UnmarshalJSON(data []byte) error {
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = IPv6(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *IPv6) DeepCopyInto(out *IPv6) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new IPv6.
+func (u *IPv6) DeepCopy() *IPv6 {
+ if u == nil {
+ return nil
+ }
+ out := new(IPv6)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// CIDR represents a Classless Inter-Domain Routing notation
+//
+// swagger:strfmt cidr
+type CIDR string
+
+// MarshalText turns this instance into text
+func (u CIDR) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *CIDR) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = CIDR(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *CIDR) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = CIDR(string(v))
+ case string:
+ *u = CIDR(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.CIDR from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u CIDR) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u CIDR) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the CIDR as JSON
+func (u CIDR) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the CIDR from JSON
+func (u *CIDR) UnmarshalJSON(data []byte) error {
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = CIDR(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *CIDR) DeepCopyInto(out *CIDR) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new CIDR.
+func (u *CIDR) DeepCopy() *CIDR {
+ if u == nil {
+ return nil
+ }
+ out := new(CIDR)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// MAC represents a 48 bit MAC address
+//
+// swagger:strfmt mac
+type MAC string
+
+// MarshalText turns this instance into text
+func (u MAC) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *MAC) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = MAC(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *MAC) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = MAC(string(v))
+ case string:
+ *u = MAC(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.IPv4 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u MAC) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u MAC) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the MAC as JSON
+func (u MAC) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the MAC from JSON
+func (u *MAC) UnmarshalJSON(data []byte) error {
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = MAC(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *MAC) DeepCopyInto(out *MAC) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new MAC.
+func (u *MAC) DeepCopy() *MAC {
+ if u == nil {
+ return nil
+ }
+ out := new(MAC)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// UUID represents a uuid string format
+//
+// swagger:strfmt uuid
+type UUID string
+
+// MarshalText turns this instance into text
+func (u UUID) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *UUID) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = UUID(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *UUID) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = UUID(string(v))
+ case string:
+ *u = UUID(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.UUID from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u UUID) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u UUID) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the UUID as JSON
+func (u UUID) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the UUID from JSON
+func (u *UUID) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = UUID(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *UUID) DeepCopyInto(out *UUID) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new UUID.
+func (u *UUID) DeepCopy() *UUID {
+ if u == nil {
+ return nil
+ }
+ out := new(UUID)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// UUID3 represents a uuid3 string format
+//
+// swagger:strfmt uuid3
+type UUID3 string
+
+// MarshalText turns this instance into text
+func (u UUID3) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *UUID3) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = UUID3(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *UUID3) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = UUID3(string(v))
+ case string:
+ *u = UUID3(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.UUID3 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u UUID3) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u UUID3) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the UUID as JSON
+func (u UUID3) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the UUID from JSON
+func (u *UUID3) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = UUID3(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *UUID3) DeepCopyInto(out *UUID3) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new UUID3.
+func (u *UUID3) DeepCopy() *UUID3 {
+ if u == nil {
+ return nil
+ }
+ out := new(UUID3)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// UUID4 represents a uuid4 string format
+//
+// swagger:strfmt uuid4
+type UUID4 string
+
+// MarshalText turns this instance into text
+func (u UUID4) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *UUID4) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = UUID4(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *UUID4) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = UUID4(string(v))
+ case string:
+ *u = UUID4(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.UUID4 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u UUID4) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u UUID4) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the UUID as JSON
+func (u UUID4) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the UUID from JSON
+func (u *UUID4) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = UUID4(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *UUID4) DeepCopyInto(out *UUID4) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new UUID4.
+func (u *UUID4) DeepCopy() *UUID4 {
+ if u == nil {
+ return nil
+ }
+ out := new(UUID4)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// UUID5 represents a uuid5 string format
+//
+// swagger:strfmt uuid5
+type UUID5 string
+
+// MarshalText turns this instance into text
+func (u UUID5) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *UUID5) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = UUID5(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *UUID5) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = UUID5(string(v))
+ case string:
+ *u = UUID5(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.UUID5 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u UUID5) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u UUID5) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the UUID as JSON
+func (u UUID5) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the UUID from JSON
+func (u *UUID5) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = UUID5(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *UUID5) DeepCopyInto(out *UUID5) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new UUID5.
+func (u *UUID5) DeepCopy() *UUID5 {
+ if u == nil {
+ return nil
+ }
+ out := new(UUID5)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// UUID7 represents a uuid7 string format
+//
+// swagger:strfmt uuid7
+type UUID7 string
+
+// MarshalText turns this instance into text
+func (u UUID7) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *UUID7) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = UUID7(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *UUID7) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = UUID7(string(v))
+ case string:
+ *u = UUID7(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.UUID7 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u UUID7) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u UUID7) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the UUID as JSON
+func (u UUID7) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the UUID from JSON
+func (u *UUID7) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = UUID7(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *UUID7) DeepCopyInto(out *UUID7) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new UUID7.
+func (u *UUID7) DeepCopy() *UUID7 {
+ if u == nil {
+ return nil
+ }
+ out := new(UUID7)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// ISBN represents an isbn string format
+//
+// swagger:strfmt isbn
+type ISBN string
+
+// MarshalText turns this instance into text
+func (u ISBN) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *ISBN) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = ISBN(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *ISBN) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = ISBN(string(v))
+ case string:
+ *u = ISBN(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.ISBN from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u ISBN) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u ISBN) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the ISBN as JSON
+func (u ISBN) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the ISBN from JSON
+func (u *ISBN) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = ISBN(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *ISBN) DeepCopyInto(out *ISBN) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new ISBN.
+func (u *ISBN) DeepCopy() *ISBN {
+ if u == nil {
+ return nil
+ }
+ out := new(ISBN)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// ISBN10 represents an isbn 10 string format
+//
+// swagger:strfmt isbn10
+type ISBN10 string
+
+// MarshalText turns this instance into text
+func (u ISBN10) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *ISBN10) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = ISBN10(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *ISBN10) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = ISBN10(string(v))
+ case string:
+ *u = ISBN10(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.ISBN10 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u ISBN10) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u ISBN10) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the ISBN10 as JSON
+func (u ISBN10) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the ISBN10 from JSON
+func (u *ISBN10) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = ISBN10(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *ISBN10) DeepCopyInto(out *ISBN10) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new ISBN10.
+func (u *ISBN10) DeepCopy() *ISBN10 {
+ if u == nil {
+ return nil
+ }
+ out := new(ISBN10)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// ISBN13 represents an isbn 13 string format
+//
+// swagger:strfmt isbn13
+type ISBN13 string
+
+// MarshalText turns this instance into text
+func (u ISBN13) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *ISBN13) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = ISBN13(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *ISBN13) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = ISBN13(string(v))
+ case string:
+ *u = ISBN13(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.ISBN13 from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u ISBN13) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u ISBN13) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the ISBN13 as JSON
+func (u ISBN13) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the ISBN13 from JSON
+func (u *ISBN13) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = ISBN13(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *ISBN13) DeepCopyInto(out *ISBN13) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new ISBN13.
+func (u *ISBN13) DeepCopy() *ISBN13 {
+ if u == nil {
+ return nil
+ }
+ out := new(ISBN13)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// CreditCard represents a credit card string format
+//
+// swagger:strfmt creditcard
+type CreditCard string
+
+// MarshalText turns this instance into text
+func (u CreditCard) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *CreditCard) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = CreditCard(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *CreditCard) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = CreditCard(string(v))
+ case string:
+ *u = CreditCard(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.CreditCard from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u CreditCard) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u CreditCard) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the CreditCard as JSON
+func (u CreditCard) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the CreditCard from JSON
+func (u *CreditCard) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = CreditCard(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *CreditCard) DeepCopyInto(out *CreditCard) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new CreditCard.
+func (u *CreditCard) DeepCopy() *CreditCard {
+ if u == nil {
+ return nil
+ }
+ out := new(CreditCard)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// SSN represents a social security string format
+//
+// swagger:strfmt ssn
+type SSN string
+
+// MarshalText turns this instance into text
+func (u SSN) MarshalText() ([]byte, error) {
+ return []byte(string(u)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *SSN) UnmarshalText(data []byte) error { // validation is performed later on
+ *u = SSN(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (u *SSN) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *u = SSN(string(v))
+ case string:
+ *u = SSN(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.SSN from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (u SSN) Value() (driver.Value, error) {
+ return driver.Value(string(u)), nil
+}
+
+func (u SSN) String() string {
+ return string(u)
+}
+
+// MarshalJSON returns the SSN as JSON
+func (u SSN) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(u))
+}
+
+// UnmarshalJSON sets the SSN from JSON
+func (u *SSN) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *u = SSN(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *SSN) DeepCopyInto(out *SSN) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new SSN.
+func (u *SSN) DeepCopy() *SSN {
+ if u == nil {
+ return nil
+ }
+ out := new(SSN)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// HexColor represents a hex color string format
+//
+// swagger:strfmt hexcolor
+type HexColor string
+
+// MarshalText turns this instance into text
+func (h HexColor) MarshalText() ([]byte, error) {
+ return []byte(string(h)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (h *HexColor) UnmarshalText(data []byte) error { // validation is performed later on
+ *h = HexColor(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (h *HexColor) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *h = HexColor(string(v))
+ case string:
+ *h = HexColor(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.HexColor from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (h HexColor) Value() (driver.Value, error) {
+ return driver.Value(string(h)), nil
+}
+
+func (h HexColor) String() string {
+ return string(h)
+}
+
+// MarshalJSON returns the HexColor as JSON
+func (h HexColor) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(h))
+}
+
+// UnmarshalJSON sets the HexColor from JSON
+func (h *HexColor) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *h = HexColor(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (h *HexColor) DeepCopyInto(out *HexColor) {
+ *out = *h
+}
+
+// DeepCopy copies the receiver into a new HexColor.
+func (h *HexColor) DeepCopy() *HexColor {
+ if h == nil {
+ return nil
+ }
+ out := new(HexColor)
+ h.DeepCopyInto(out)
+ return out
+}
+
+// RGBColor represents a RGB color string format
+//
+// swagger:strfmt rgbcolor
+type RGBColor string
+
+// MarshalText turns this instance into text
+func (r RGBColor) MarshalText() ([]byte, error) {
+ return []byte(string(r)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (r *RGBColor) UnmarshalText(data []byte) error { // validation is performed later on
+ *r = RGBColor(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (r *RGBColor) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *r = RGBColor(string(v))
+ case string:
+ *r = RGBColor(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.RGBColor from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (r RGBColor) Value() (driver.Value, error) {
+ return driver.Value(string(r)), nil
+}
+
+func (r RGBColor) String() string {
+ return string(r)
+}
+
+// MarshalJSON returns the RGBColor as JSON
+func (r RGBColor) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(r))
+}
+
+// UnmarshalJSON sets the RGBColor from JSON
+func (r *RGBColor) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *r = RGBColor(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (r *RGBColor) DeepCopyInto(out *RGBColor) {
+ *out = *r
+}
+
+// DeepCopy copies the receiver into a new RGBColor.
+func (r *RGBColor) DeepCopy() *RGBColor {
+ if r == nil {
+ return nil
+ }
+ out := new(RGBColor)
+ r.DeepCopyInto(out)
+ return out
+}
+
+// Password represents a password.
+// This has no validations and is mainly used as a marker for UI components.
+//
+// swagger:strfmt password
+type Password string
+
+// MarshalText turns this instance into text
+func (r Password) MarshalText() ([]byte, error) {
+ return []byte(string(r)), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (r *Password) UnmarshalText(data []byte) error { // validation is performed later on
+ *r = Password(string(data))
+ return nil
+}
+
+// Scan read a value from a database driver
+func (r *Password) Scan(raw any) error {
+ switch v := raw.(type) {
+ case []byte:
+ *r = Password(string(v))
+ case string:
+ *r = Password(v)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.Password from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts a value to a database driver value
+func (r Password) Value() (driver.Value, error) {
+ return driver.Value(string(r)), nil
+}
+
+func (r Password) String() string {
+ return string(r)
+}
+
+// MarshalJSON returns the Password as JSON
+func (r Password) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(r))
+}
+
+// UnmarshalJSON sets the Password from JSON
+func (r *Password) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ *r = Password(ustr)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (r *Password) DeepCopyInto(out *Password) {
+ *out = *r
+}
+
+// DeepCopy copies the receiver into a new Password.
+func (r *Password) DeepCopy() *Password {
+ if r == nil {
+ return nil
+ }
+ out := new(Password)
+ r.DeepCopyInto(out)
+ return out
+}
+
+func isRequestURI(rawurl string) bool {
+ _, err := url.ParseRequestURI(rawurl)
+ return err == nil
+}
+
+// isIPv4 checks if the string is an IP version 4.
+func isIPv4(str string) bool {
+ ip := net.ParseIP(str)
+ return ip != nil && strings.Contains(str, ".")
+}
+
+// isIPv6 checks if the string is an IP version 6.
+func isIPv6(str string) bool {
+ ip := net.ParseIP(str)
+ return ip != nil && strings.Contains(str, ":")
+}
+
+// isCIDR checks if the string is an valid CIDR notiation (IPV4 & IPV6)
+func isCIDR(str string) bool {
+ _, _, err := net.ParseCIDR(str)
+ return err == nil
+}
+
+// isMAC checks if a string is valid MAC address.
+// Possible MAC formats:
+// 01:23:45:67:89:ab
+// 01:23:45:67:89:ab:cd:ef
+// 01-23-45-67-89-ab
+// 01-23-45-67-89-ab-cd-ef
+// 0123.4567.89ab
+// 0123.4567.89ab.cdef
+func isMAC(str string) bool {
+ _, err := net.ParseMAC(str)
+ return err == nil
+}
+
+// isISBN checks if the string is an ISBN (version 10 or 13).
+// If version value is not equal to 10 or 13, it will be checks both variants.
+func isISBN(str string, version int) bool {
+ sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
+ var checksum int32
+ var i int32
+
+ switch version {
+ case isbnVersion10:
+ if !rxISBN10.MatchString(sanitized) {
+ return false
+ }
+ for i = range isbnVersion10 - 1 {
+ checksum += (i + 1) * int32(sanitized[i]-'0')
+ }
+ if sanitized[isbnVersion10-1] == 'X' {
+ checksum += isbnVersion10 * isbnVersion10
+ } else {
+ checksum += isbnVersion10 * int32(sanitized[isbnVersion10-1]-'0')
+ }
+ if checksum%(isbnVersion10+1) == 0 {
+ return true
+ }
+ return false
+ case isbnVersion13:
+ if !rxISBN13.MatchString(sanitized) {
+ return false
+ }
+ factor := []int32{1, 3}
+ for i = range isbnVersion13 - 1 {
+ checksum += factor[i%2] * int32(sanitized[i]-'0')
+ }
+ return (int32(sanitized[isbnVersion13-1]-'0'))-((decimalBase-(checksum%decimalBase))%decimalBase) == 0
+ default:
+ return isISBN(str, isbnVersion10) || isISBN(str, isbnVersion13)
+ }
+}
+
+// isISBN10 checks if the string is an ISBN version 10.
+func isISBN10(str string) bool {
+ return isISBN(str, isbnVersion10)
+}
+
+// isISBN13 checks if the string is an ISBN version 13.
+func isISBN13(str string) bool {
+ return isISBN(str, isbnVersion13)
+}
+
+// isCreditCard checks if the string is a credit card.
+func isCreditCard(str string) bool {
+ sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
+ if !rxCreditCard.MatchString(sanitized) {
+ return false
+ }
+
+ number, err := strconv.ParseInt(sanitized, 0, 64)
+ if err != nil {
+ return false
+ }
+ number, lastDigit := number/decimalBase, number%decimalBase
+
+ var sum int64
+ for i := 0; number > 0; i++ {
+ digit := number % decimalBase
+
+ if i%2 == 0 {
+ digit *= 2
+ if digit > decimalBase-1 {
+ digit -= decimalBase - 1
+ }
+ }
+
+ sum += digit
+ number /= decimalBase
+ }
+
+ return (sum+lastDigit)%decimalBase == 0
+}
+
+// isSSN will validate the given string as a U.S. Social Security Number
+func isSSN(str string) bool {
+ if str == "" || len(str) != 11 {
+ return false
+ }
+ return rxSSN.MatchString(str)
+}
+
+// isHexcolor checks if the string is a hexadecimal color.
+func isHexcolor(str string) bool {
+ return rxHexcolor.MatchString(str)
+}
+
+// isRGBcolor checks if the string is a valid RGB color in form rgb(RRR, GGG, BBB).
+func isRGBcolor(str string) bool {
+ return rxRGBcolor.MatchString(str)
+}
+
+// isBase64 checks if a string is base64 encoded.
+func isBase64(str string) bool {
+ _, err := base64.StdEncoding.DecodeString(str)
+
+ return err == nil
+}
diff --git a/vendor/github.com/go-openapi/strfmt/doc.go b/vendor/github.com/go-openapi/strfmt/doc.go
new file mode 100644
index 000000000000..5825b72108ed
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/doc.go
@@ -0,0 +1,7 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package strfmt contains custom string formats
+//
+// TODO: add info on how to define and register a custom format
+package strfmt
diff --git a/vendor/github.com/go-openapi/strfmt/duration.go b/vendor/github.com/go-openapi/strfmt/duration.go
new file mode 100644
index 000000000000..908c1b02f3c8
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/duration.go
@@ -0,0 +1,206 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "database/sql/driver"
+ "encoding/json"
+ "fmt"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func init() {
+ d := Duration(0)
+ // register this format in the default registry
+ Default.Add("duration", &d, IsDuration)
+}
+
+const (
+ hoursInDay = 24
+ daysInWeek = 7
+)
+
+var (
+ timeUnits = [][]string{
+ {"ns", "nano"},
+ {"us", "µs", "micro"},
+ {"ms", "milli"},
+ {"s", "sec"},
+ {"m", "min"},
+ {"h", "hr", "hour"},
+ {"d", "day"},
+ {"w", "wk", "week"},
+ }
+
+ timeMultiplier = map[string]time.Duration{
+ "ns": time.Nanosecond,
+ "us": time.Microsecond,
+ "ms": time.Millisecond,
+ "s": time.Second,
+ "m": time.Minute,
+ "h": time.Hour,
+ "d": hoursInDay * time.Hour,
+ "w": hoursInDay * daysInWeek * time.Hour,
+ }
+
+ durationMatcher = regexp.MustCompile(`^(((?:-\s?)?\d+)(\.\d+)?\s*([A-Za-zµ]+))`)
+)
+
+// IsDuration returns true if the provided string is a valid duration
+func IsDuration(str string) bool {
+ _, err := ParseDuration(str)
+ return err == nil
+}
+
+// Duration represents a duration
+//
+// Duration stores a period of time as a nanosecond count, with the largest
+// repesentable duration being approximately 290 years.
+//
+// swagger:strfmt duration
+type Duration time.Duration
+
+// MarshalText turns this instance into text
+func (d Duration) MarshalText() ([]byte, error) {
+ return []byte(time.Duration(d).String()), nil
+}
+
+// UnmarshalText hydrates this instance from text
+func (d *Duration) UnmarshalText(data []byte) error { // validation is performed later on
+ dd, err := ParseDuration(string(data))
+ if err != nil {
+ return err
+ }
+ *d = Duration(dd)
+ return nil
+}
+
+// ParseDuration parses a duration from a string, compatible with scala duration syntax
+func ParseDuration(cand string) (time.Duration, error) {
+ if dur, err := time.ParseDuration(cand); err == nil {
+ return dur, nil
+ }
+
+ var dur time.Duration
+ ok := false
+ const expectGroups = 4
+ for _, match := range durationMatcher.FindAllStringSubmatch(cand, -1) {
+ if len(match) < expectGroups {
+ continue
+ }
+
+ // remove possible leading - and spaces
+ value, negative := strings.CutPrefix(match[2], "-")
+
+ // if the duration contains a decimal separator determine a divising factor
+ const neutral = 1.0
+ divisor := neutral
+ decimal, hasDecimal := strings.CutPrefix(match[3], ".")
+ if hasDecimal {
+ divisor = math.Pow10(len(decimal))
+ value += decimal // consider the value as an integer: will change units later on
+ }
+
+ // if the string is a valid duration, parse it
+ factor, err := strconv.Atoi(strings.TrimSpace(value)) // converts string to int
+ if err != nil {
+ return 0, err
+ }
+
+ if negative {
+ factor = -factor
+ }
+
+ unit := strings.ToLower(strings.TrimSpace(match[4]))
+
+ for _, variants := range timeUnits {
+ last := len(variants) - 1
+ multiplier := timeMultiplier[variants[0]]
+
+ for i, variant := range variants {
+ if (last == i && strings.HasPrefix(unit, variant)) || strings.EqualFold(variant, unit) {
+ ok = true
+ if divisor != neutral {
+ multiplier = time.Duration(float64(multiplier) / divisor) // convert to duration only after having reduced the scale
+ }
+ dur += (time.Duration(factor) * multiplier)
+ }
+ }
+ }
+ }
+
+ if ok {
+ return dur, nil
+ }
+ return 0, fmt.Errorf("unable to parse %s as duration: %w", cand, ErrFormat)
+}
+
+// Scan reads a Duration value from database driver type.
+func (d *Duration) Scan(raw any) error {
+ switch v := raw.(type) {
+ // TODO: case []byte: // ?
+ case int64:
+ *d = Duration(v)
+ case float64:
+ *d = Duration(int64(v))
+ case nil:
+ *d = Duration(0)
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.Duration from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts Duration to a primitive value ready to be written to a database.
+func (d Duration) Value() (driver.Value, error) {
+ return driver.Value(int64(d)), nil
+}
+
+// String converts this duration to a string
+func (d Duration) String() string {
+ return time.Duration(d).String()
+}
+
+// MarshalJSON returns the Duration as JSON
+func (d Duration) MarshalJSON() ([]byte, error) {
+ return json.Marshal(time.Duration(d).String())
+}
+
+// UnmarshalJSON sets the Duration from JSON
+func (d *Duration) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+
+ var dstr string
+ if err := json.Unmarshal(data, &dstr); err != nil {
+ return err
+ }
+ tt, err := ParseDuration(dstr)
+ if err != nil {
+ return err
+ }
+ *d = Duration(tt)
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (d *Duration) DeepCopyInto(out *Duration) {
+ *out = *d
+}
+
+// DeepCopy copies the receiver into a new Duration.
+func (d *Duration) DeepCopy() *Duration {
+ if d == nil {
+ return nil
+ }
+ out := new(Duration)
+ d.DeepCopyInto(out)
+ return out
+}
diff --git a/vendor/github.com/go-openapi/strfmt/errors.go b/vendor/github.com/go-openapi/strfmt/errors.go
new file mode 100644
index 000000000000..9faa37cf2e51
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/errors.go
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+type strfmtError string
+
+// ErrFormat is an error raised by the strfmt package
+const ErrFormat strfmtError = "format error"
+
+func (e strfmtError) Error() string {
+ return string(e)
+}
diff --git a/vendor/github.com/go-openapi/strfmt/format.go b/vendor/github.com/go-openapi/strfmt/format.go
new file mode 100644
index 000000000000..d9d9e04c2080
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/format.go
@@ -0,0 +1,297 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+ "slices"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-viper/mapstructure/v2"
+)
+
+// Default is the default formats registry
+var Default = NewSeededFormats(nil, nil)
+
+// Validator represents a validator for a string format.
+type Validator func(string) bool
+
+// NewFormats creates a new formats registry seeded with the values from the default
+func NewFormats() Registry {
+ //nolint:forcetypeassert
+ return NewSeededFormats(Default.(*defaultFormats).data, nil)
+}
+
+// NewSeededFormats creates a new formats registry
+func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry {
+ if normalizer == nil {
+ normalizer = DefaultNameNormalizer
+ }
+ // copy here, don't modify the original
+ return &defaultFormats{
+ data: slices.Clone(seeds),
+ normalizeName: normalizer,
+ }
+}
+
+type knownFormat struct {
+ Name string
+ OrigName string
+ Type reflect.Type
+ Validator Validator
+}
+
+// NameNormalizer is a function that normalizes a format name.
+type NameNormalizer func(string) string
+
+// DefaultNameNormalizer removes all dashes
+func DefaultNameNormalizer(name string) string {
+ return strings.ReplaceAll(name, "-", "")
+}
+
+type defaultFormats struct {
+ sync.Mutex
+
+ data []knownFormat
+ normalizeName NameNormalizer
+}
+
+// MapStructureHookFunc is a decode hook function for mapstructure
+func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc {
+ return func(from reflect.Type, to reflect.Type, obj any) (any, error) {
+ if from.Kind() != reflect.String {
+ return obj, nil
+ }
+ data, ok := obj.(string)
+ if !ok {
+ return nil, fmt.Errorf("failed to cast %+v to string: %w", obj, ErrFormat)
+ }
+
+ for _, v := range f.data {
+ tpe, _ := f.GetType(v.Name)
+ if to == tpe {
+ switch v.Name {
+ case "date":
+ d, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation)
+ if err != nil {
+ return nil, err
+ }
+ return Date(d), nil
+ case "datetime":
+ input := data
+ if len(input) == 0 {
+ return nil, fmt.Errorf("empty string is an invalid datetime format: %w", ErrFormat)
+ }
+ return ParseDateTime(input)
+ case "duration":
+ dur, err := ParseDuration(data)
+ if err != nil {
+ return nil, err
+ }
+ return Duration(dur), nil
+ case "uri":
+ return URI(data), nil
+ case "email":
+ return Email(data), nil
+ case "uuid":
+ return UUID(data), nil
+ case "uuid3":
+ return UUID3(data), nil
+ case "uuid4":
+ return UUID4(data), nil
+ case "uuid5":
+ return UUID5(data), nil
+ case "uuid7":
+ return UUID7(data), nil
+ case "hostname":
+ return Hostname(data), nil
+ case "ipv4":
+ return IPv4(data), nil
+ case "ipv6":
+ return IPv6(data), nil
+ case "cidr":
+ return CIDR(data), nil
+ case "mac":
+ return MAC(data), nil
+ case "isbn":
+ return ISBN(data), nil
+ case "isbn10":
+ return ISBN10(data), nil
+ case "isbn13":
+ return ISBN13(data), nil
+ case "creditcard":
+ return CreditCard(data), nil
+ case "ssn":
+ return SSN(data), nil
+ case "hexcolor":
+ return HexColor(data), nil
+ case "rgbcolor":
+ return RGBColor(data), nil
+ case "byte":
+ return Base64(data), nil
+ case "password":
+ return Password(data), nil
+ case "ulid":
+ ulid, err := ParseULID(data)
+ if err != nil {
+ return nil, err
+ }
+ return ulid, nil
+ default:
+ return nil, errors.InvalidTypeName(v.Name)
+ }
+ }
+ }
+ return data, nil
+ }
+}
+
+// Add adds a new format, return true if this was a new item instead of a replacement
+func (f *defaultFormats) Add(name string, strfmt Format, validator Validator) bool {
+ f.Lock()
+ defer f.Unlock()
+
+ nme := f.normalizeName(name)
+
+ tpe := reflect.TypeOf(strfmt)
+ if tpe.Kind() == reflect.Ptr {
+ tpe = tpe.Elem()
+ }
+
+ for i := range f.data {
+ v := &f.data[i]
+ if v.Name == nme {
+ v.Type = tpe
+ v.Validator = validator
+ return false
+ }
+ }
+
+ // turns out it's new after all
+ f.data = append(f.data, knownFormat{Name: nme, OrigName: name, Type: tpe, Validator: validator})
+ return true
+}
+
+// GetType gets the type for the specified name
+func (f *defaultFormats) GetType(name string) (reflect.Type, bool) {
+ f.Lock()
+ defer f.Unlock()
+ nme := f.normalizeName(name)
+ for _, v := range f.data {
+ if v.Name == nme {
+ return v.Type, true
+ }
+ }
+ return nil, false
+}
+
+// DelByName removes the format by the specified name, returns true when an item was actually removed
+func (f *defaultFormats) DelByName(name string) bool {
+ f.Lock()
+ defer f.Unlock()
+
+ nme := f.normalizeName(name)
+
+ for i, v := range f.data {
+ if v.Name == nme {
+ f.data[i] = knownFormat{} // release
+ f.data = append(f.data[:i], f.data[i+1:]...)
+ return true
+ }
+ }
+ return false
+}
+
+// DelByFormat removes the specified format, returns true when an item was actually removed
+func (f *defaultFormats) DelByFormat(strfmt Format) bool {
+ f.Lock()
+ defer f.Unlock()
+
+ tpe := reflect.TypeOf(strfmt)
+ if tpe.Kind() == reflect.Ptr {
+ tpe = tpe.Elem()
+ }
+
+ for i, v := range f.data {
+ if v.Type == tpe {
+ f.data[i] = knownFormat{} // release
+ f.data = append(f.data[:i], f.data[i+1:]...)
+ return true
+ }
+ }
+ return false
+}
+
+// ContainsName returns true if this registry contains the specified name
+func (f *defaultFormats) ContainsName(name string) bool {
+ f.Lock()
+ defer f.Unlock()
+ nme := f.normalizeName(name)
+ for _, v := range f.data {
+ if v.Name == nme {
+ return true
+ }
+ }
+ return false
+}
+
+// ContainsFormat returns true if this registry contains the specified format
+func (f *defaultFormats) ContainsFormat(strfmt Format) bool {
+ f.Lock()
+ defer f.Unlock()
+ tpe := reflect.TypeOf(strfmt)
+ if tpe.Kind() == reflect.Ptr {
+ tpe = tpe.Elem()
+ }
+
+ for _, v := range f.data {
+ if v.Type == tpe {
+ return true
+ }
+ }
+ return false
+}
+
+// Validates passed data against format.
+//
+// Note that the format name is automatically normalized, e.g. one may
+// use "date-time" to use the "datetime" format validator.
+func (f *defaultFormats) Validates(name, data string) bool {
+ f.Lock()
+ defer f.Unlock()
+ nme := f.normalizeName(name)
+ for _, v := range f.data {
+ if v.Name == nme {
+ return v.Validator(data)
+ }
+ }
+ return false
+}
+
+// Parse a string into the appropriate format representation type.
+//
+// E.g. parsing a string a "date" will return a Date type.
+func (f *defaultFormats) Parse(name, data string) (any, error) {
+ f.Lock()
+ defer f.Unlock()
+ nme := f.normalizeName(name)
+ for _, v := range f.data {
+ if v.Name == nme {
+ nw := reflect.New(v.Type).Interface()
+ if dec, ok := nw.(encoding.TextUnmarshaler); ok {
+ if err := dec.UnmarshalText([]byte(data)); err != nil {
+ return nil, err
+ }
+ return nw, nil
+ }
+ return nil, errors.InvalidTypeName(name)
+ }
+ }
+ return nil, errors.InvalidTypeName(name)
+}
diff --git a/vendor/github.com/go-openapi/strfmt/ifaces.go b/vendor/github.com/go-openapi/strfmt/ifaces.go
new file mode 100644
index 000000000000..1b9e72c64ebc
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/ifaces.go
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "encoding"
+ "reflect"
+
+ "github.com/go-viper/mapstructure/v2"
+)
+
+// Format represents a string format.
+//
+// All implementations of Format provide a string representation and text
+// marshaling/unmarshaling interface to be used by encoders (e.g. encoding/json).
+type Format interface {
+ String() string
+ encoding.TextMarshaler
+ encoding.TextUnmarshaler
+}
+
+// Registry is a registry of string formats, with a validation method.
+type Registry interface {
+ Add(string, Format, Validator) bool
+ DelByName(string) bool
+ GetType(string) (reflect.Type, bool)
+ ContainsName(string) bool
+ Validates(string, string) bool
+ Parse(string, string) (any, error)
+ MapStructureHookFunc() mapstructure.DecodeHookFunc
+}
diff --git a/vendor/github.com/go-openapi/strfmt/mongo.go b/vendor/github.com/go-openapi/strfmt/mongo.go
new file mode 100644
index 000000000000..641fed9b1a67
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/mongo.go
@@ -0,0 +1,646 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "encoding/base64"
+ "encoding/binary"
+ "fmt"
+ "time"
+
+ "github.com/oklog/ulid"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ bsonprim "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+var (
+ _ bson.Marshaler = Date{}
+ _ bson.Unmarshaler = &Date{}
+ _ bson.Marshaler = Base64{}
+ _ bson.Unmarshaler = &Base64{}
+ _ bson.Marshaler = Duration(0)
+ _ bson.Unmarshaler = (*Duration)(nil)
+ _ bson.Marshaler = DateTime{}
+ _ bson.Unmarshaler = &DateTime{}
+ _ bson.Marshaler = ULID{}
+ _ bson.Unmarshaler = &ULID{}
+ _ bson.Marshaler = URI("")
+ _ bson.Unmarshaler = (*URI)(nil)
+ _ bson.Marshaler = Email("")
+ _ bson.Unmarshaler = (*Email)(nil)
+ _ bson.Marshaler = Hostname("")
+ _ bson.Unmarshaler = (*Hostname)(nil)
+ _ bson.Marshaler = IPv4("")
+ _ bson.Unmarshaler = (*IPv4)(nil)
+ _ bson.Marshaler = IPv6("")
+ _ bson.Unmarshaler = (*IPv6)(nil)
+ _ bson.Marshaler = CIDR("")
+ _ bson.Unmarshaler = (*CIDR)(nil)
+ _ bson.Marshaler = MAC("")
+ _ bson.Unmarshaler = (*MAC)(nil)
+ _ bson.Marshaler = Password("")
+ _ bson.Unmarshaler = (*Password)(nil)
+ _ bson.Marshaler = UUID("")
+ _ bson.Unmarshaler = (*UUID)(nil)
+ _ bson.Marshaler = UUID3("")
+ _ bson.Unmarshaler = (*UUID3)(nil)
+ _ bson.Marshaler = UUID4("")
+ _ bson.Unmarshaler = (*UUID4)(nil)
+ _ bson.Marshaler = UUID5("")
+ _ bson.Unmarshaler = (*UUID5)(nil)
+ _ bson.Marshaler = UUID7("")
+ _ bson.Unmarshaler = (*UUID7)(nil)
+ _ bson.Marshaler = ISBN("")
+ _ bson.Unmarshaler = (*ISBN)(nil)
+ _ bson.Marshaler = ISBN10("")
+ _ bson.Unmarshaler = (*ISBN10)(nil)
+ _ bson.Marshaler = ISBN13("")
+ _ bson.Unmarshaler = (*ISBN13)(nil)
+ _ bson.Marshaler = CreditCard("")
+ _ bson.Unmarshaler = (*CreditCard)(nil)
+ _ bson.Marshaler = SSN("")
+ _ bson.Unmarshaler = (*SSN)(nil)
+ _ bson.Marshaler = HexColor("")
+ _ bson.Unmarshaler = (*HexColor)(nil)
+ _ bson.Marshaler = RGBColor("")
+ _ bson.Unmarshaler = (*RGBColor)(nil)
+ _ bson.Marshaler = ObjectId{}
+ _ bson.Unmarshaler = &ObjectId{}
+
+ _ bson.ValueMarshaler = DateTime{}
+ _ bson.ValueUnmarshaler = &DateTime{}
+ _ bson.ValueMarshaler = ObjectId{}
+ _ bson.ValueUnmarshaler = &ObjectId{}
+)
+
+const (
+ millisec = 1000
+ microsec = 1_000_000
+ bsonDateTimeSize = 8
+)
+
+func (d Date) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": d.String()})
+}
+
+func (d *Date) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if data, ok := m["data"].(string); ok {
+ rd, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation)
+ if err != nil {
+ return err
+ }
+ *d = Date(rd)
+ return nil
+ }
+
+ return fmt.Errorf("couldn't unmarshal bson bytes value as Date: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (b Base64) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": b.String()})
+}
+
+// UnmarshalBSON document into this value
+func (b *Base64) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if bd, ok := m["data"].(string); ok {
+ vb, err := base64.StdEncoding.DecodeString(bd)
+ if err != nil {
+ return err
+ }
+ *b = Base64(vb)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as base64: %w", ErrFormat)
+}
+
+func (d Duration) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": d.String()})
+}
+
+func (d *Duration) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if data, ok := m["data"].(string); ok {
+ rd, err := ParseDuration(data)
+ if err != nil {
+ return err
+ }
+ *d = Duration(rd)
+ return nil
+ }
+
+ return fmt.Errorf("couldn't unmarshal bson bytes value as Date: %w", ErrFormat)
+}
+
+// MarshalBSON renders the DateTime as a BSON document
+func (t DateTime) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": t})
+}
+
+// UnmarshalBSON reads the DateTime from a BSON document
+func (t *DateTime) UnmarshalBSON(data []byte) error {
+ var obj struct {
+ Data DateTime
+ }
+
+ if err := bson.Unmarshal(data, &obj); err != nil {
+ return err
+ }
+
+ *t = obj.Data
+
+ return nil
+}
+
+// MarshalBSONValue is an interface implemented by types that can marshal themselves
+// into a BSON document represented as bytes. The bytes returned must be a valid
+// BSON document if the error is nil.
+//
+// Marshals a DateTime as a bson.TypeDateTime, an int64 representing
+// milliseconds since epoch.
+func (t DateTime) MarshalBSONValue() (bsontype.Type, []byte, error) {
+ // UnixNano cannot be used directly, the result of calling UnixNano on the zero
+ // Time is undefined. Thats why we use time.Nanosecond() instead.
+
+ tNorm := NormalizeTimeForMarshal(time.Time(t))
+ i64 := tNorm.Unix()*millisec + int64(tNorm.Nanosecond())/microsec
+ buf := make([]byte, bsonDateTimeSize)
+ binary.LittleEndian.PutUint64(buf, uint64(i64)) //nolint:gosec // it's okay to handle negative int64 this way
+
+ return bson.TypeDateTime, buf, nil
+}
+
+// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
+// BSON value representation of themselves. The BSON bytes and type can be
+// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
+// wishes to retain the data after returning.
+func (t *DateTime) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error {
+ if tpe == bson.TypeNull {
+ *t = DateTime{}
+ return nil
+ }
+
+ if len(data) != bsonDateTimeSize {
+ return fmt.Errorf("bson date field length not exactly %d bytes: %w", bsonDateTimeSize, ErrFormat)
+ }
+
+ i64 := int64(binary.LittleEndian.Uint64(data)) //nolint:gosec // it's okay if we overflow and get a negative datetime
+ *t = DateTime(time.Unix(i64/millisec, i64%millisec*microsec))
+
+ return nil
+}
+
+// MarshalBSON document from this value
+func (u ULID) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *ULID) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ id, err := ulid.ParseStrict(ud)
+ if err != nil {
+ return fmt.Errorf("couldn't parse bson bytes as ULID: %w: %w", err, ErrFormat)
+ }
+ u.ULID = id
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as ULID: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u URI) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *URI) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = URI(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as uri: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (e Email) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": e.String()})
+}
+
+// UnmarshalBSON document into this value
+func (e *Email) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *e = Email(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as email: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (h Hostname) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": h.String()})
+}
+
+// UnmarshalBSON document into this value
+func (h *Hostname) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *h = Hostname(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as hostname: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u IPv4) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *IPv4) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = IPv4(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as ipv4: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u IPv6) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *IPv6) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = IPv6(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as ipv6: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u CIDR) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *CIDR) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = CIDR(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as CIDR: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u MAC) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *MAC) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = MAC(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as MAC: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (r Password) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": r.String()})
+}
+
+// UnmarshalBSON document into this value
+func (r *Password) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *r = Password(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as Password: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u UUID) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *UUID) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = UUID(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as UUID: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u UUID3) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *UUID3) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = UUID3(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as UUID3: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u UUID4) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *UUID4) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = UUID4(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as UUID4: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u UUID5) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *UUID5) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = UUID5(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as UUID5: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u UUID7) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *UUID7) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = UUID7(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as UUID7: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u ISBN) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *ISBN) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = ISBN(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as ISBN: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u ISBN10) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *ISBN10) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = ISBN10(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as ISBN10: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u ISBN13) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *ISBN13) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = ISBN13(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as ISBN13: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u CreditCard) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *CreditCard) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = CreditCard(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as CreditCard: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (u SSN) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": u.String()})
+}
+
+// UnmarshalBSON document into this value
+func (u *SSN) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *u = SSN(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as SSN: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (h HexColor) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": h.String()})
+}
+
+// UnmarshalBSON document into this value
+func (h *HexColor) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *h = HexColor(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as HexColor: %w", ErrFormat)
+}
+
+// MarshalBSON document from this value
+func (r RGBColor) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": r.String()})
+}
+
+// UnmarshalBSON document into this value
+func (r *RGBColor) UnmarshalBSON(data []byte) error {
+ var m bson.M
+ if err := bson.Unmarshal(data, &m); err != nil {
+ return err
+ }
+
+ if ud, ok := m["data"].(string); ok {
+ *r = RGBColor(ud)
+ return nil
+ }
+ return fmt.Errorf("couldn't unmarshal bson bytes as RGBColor: %w", ErrFormat)
+}
+
+// MarshalBSON renders the object id as a BSON document
+func (id ObjectId) MarshalBSON() ([]byte, error) {
+ return bson.Marshal(bson.M{"data": bsonprim.ObjectID(id)})
+}
+
+// UnmarshalBSON reads the objectId from a BSON document
+func (id *ObjectId) UnmarshalBSON(data []byte) error {
+ var obj struct {
+ Data bsonprim.ObjectID
+ }
+ if err := bson.Unmarshal(data, &obj); err != nil {
+ return err
+ }
+ *id = ObjectId(obj.Data)
+ return nil
+}
+
+// MarshalBSONValue is an interface implemented by types that can marshal themselves
+// into a BSON document represented as bytes. The bytes returned must be a valid
+// BSON document if the error is nil.
+func (id ObjectId) MarshalBSONValue() (bsontype.Type, []byte, error) {
+ oid := bsonprim.ObjectID(id)
+ return bson.TypeObjectID, oid[:], nil
+}
+
+// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
+// BSON value representation of themselves. The BSON bytes and type can be
+// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
+// wishes to retain the data after returning.
+func (id *ObjectId) UnmarshalBSONValue(_ bsontype.Type, data []byte) error {
+ var oid bsonprim.ObjectID
+ copy(oid[:], data)
+ *id = ObjectId(oid)
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/strfmt/time.go b/vendor/github.com/go-openapi/strfmt/time.go
new file mode 100644
index 000000000000..8085aaf69658
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/time.go
@@ -0,0 +1,258 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ "database/sql/driver"
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "strings"
+ "time"
+)
+
+var (
+ // UnixZero sets the zero unix UTC timestamp we want to compare against.
+ //
+ // Unix 0 for an EST timezone is not equivalent to a UTC timezone.
+ UnixZero = time.Unix(0, 0).UTC()
+)
+
+func init() {
+ dt := DateTime{}
+ Default.Add("datetime", &dt, IsDateTime)
+}
+
+// IsDateTime returns true when the string is a valid date-time.
+//
+// JSON datetime format consist of a date and a time separated by a "T", e.g. 2012-04-23T18:25:43.511Z.
+func IsDateTime(str string) bool {
+ const (
+ minDateTimeLength = 4
+ minParts = 2
+ )
+ if len(str) < minDateTimeLength {
+ return false
+ }
+ s := strings.Split(strings.ToLower(str), "t")
+ if len(s) < minParts || !IsDate(s[0]) {
+ return false
+ }
+
+ matches := rxDateTime.FindAllStringSubmatch(s[1], -1)
+ if len(matches) == 0 || len(matches[0]) == 0 {
+ return false
+ }
+ m := matches[0]
+ res := m[1] <= "23" && m[2] <= "59" && m[3] <= "59"
+ return res
+}
+
+const (
+ // RFC3339Millis represents a ISO8601 format to millis instead of to nanos
+ RFC3339Millis = "2006-01-02T15:04:05.000Z07:00"
+ // RFC3339MillisNoColon represents a ISO8601 format to millis instead of to nanos
+ RFC3339MillisNoColon = "2006-01-02T15:04:05.000Z0700"
+ // RFC3339Micro represents a ISO8601 format to micro instead of to nano
+ RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
+ // RFC3339MicroNoColon represents a ISO8601 format to micro instead of to nano
+ RFC3339MicroNoColon = "2006-01-02T15:04:05.000000Z0700"
+ // ISO8601LocalTime represents a ISO8601 format to ISO8601 in local time (no timezone)
+ ISO8601LocalTime = "2006-01-02T15:04:05"
+ // ISO8601TimeWithReducedPrecision represents a ISO8601 format with reduced precision (dropped secs)
+ ISO8601TimeWithReducedPrecision = "2006-01-02T15:04Z"
+ // ISO8601TimeWithReducedPrecisionLocaltime represents a ISO8601 format with reduced precision and no timezone (dropped seconds + no timezone)
+ ISO8601TimeWithReducedPrecisionLocaltime = "2006-01-02T15:04"
+ // ISO8601TimeUniversalSortableDateTimePattern represents a ISO8601 universal sortable date time pattern.
+ ISO8601TimeUniversalSortableDateTimePattern = "2006-01-02 15:04:05"
+ // ISO8601TimeUniversalSortableDateTimePatternShortForm is the short form of ISO8601TimeUniversalSortableDateTimePattern
+ ISO8601TimeUniversalSortableDateTimePatternShortForm = "2006-01-02"
+ // DateTimePattern pattern to match for the date-time format from http://tools.ietf.org/html/rfc3339#section-5.6
+ DateTimePattern = `^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$`
+)
+
+var (
+ rxDateTime = regexp.MustCompile(DateTimePattern)
+
+ // DateTimeFormats is the collection of formats used by ParseDateTime()
+ DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern, ISO8601TimeUniversalSortableDateTimePatternShortForm}
+
+ // MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds)
+ MarshalFormat = RFC3339Millis
+
+ // NormalizeTimeForMarshal provides a normalization function on time before marshalling (e.g. time.UTC).
+ // By default, the time value is not changed.
+ NormalizeTimeForMarshal = func(t time.Time) time.Time { return t }
+
+ // DefaultTimeLocation provides a location for a time when the time zone is not encoded in the string (ex: ISO8601 Local variants).
+ DefaultTimeLocation = time.UTC
+)
+
+// ParseDateTime parses a string that represents an ISO8601 time or a unix epoch
+func ParseDateTime(data string) (DateTime, error) {
+ if data == "" {
+ return NewDateTime(), nil
+ }
+ var lastError error
+ for _, layout := range DateTimeFormats {
+ dd, err := time.ParseInLocation(layout, data, DefaultTimeLocation)
+ if err != nil {
+ lastError = err
+ continue
+ }
+ return DateTime(dd), nil
+ }
+ return DateTime{}, lastError
+}
+
+// DateTime is a time but it serializes to ISO8601 format with millis.
+//
+// It knows how to read 3 different variations of a RFC3339 date time.
+// Most APIs we encounter want either millisecond or second precision times.
+// This just tries to make it worry-free.
+//
+// swagger:strfmt date-time
+type DateTime time.Time
+
+// NewDateTime is a representation of the UNIX epoch (January 1, 1970 00:00:00 UTC) for the [DateTime] type.
+//
+// Notice that this is not the zero value of the [DateTime] type.
+//
+// You may use [DateTime.IsUNIXZero] to check against this value.
+func NewDateTime() DateTime {
+ return DateTime(time.Unix(0, 0).UTC())
+}
+
+// MakeDateTime is a representation of the zero value of the [DateTime] type (January 1, year 1, 00:00:00 UTC).
+//
+// You may use [Datetime.IsZero] to check against this value.
+func MakeDateTime() DateTime {
+ return DateTime(time.Time{})
+}
+
+// String converts this time to a string
+func (t DateTime) String() string {
+ return NormalizeTimeForMarshal(time.Time(t)).Format(MarshalFormat)
+}
+
+// IsZero returns whether the date time is a zero value
+func (t DateTime) IsZero() bool {
+ return time.Time(t).IsZero()
+}
+
+// IsUnixZero returns whether the date time is equivalent to time.Unix(0, 0).UTC().
+func (t DateTime) IsUnixZero() bool {
+ return time.Time(t).Equal(UnixZero)
+}
+
+// MarshalText implements the text marshaller interface
+func (t DateTime) MarshalText() ([]byte, error) {
+ return []byte(t.String()), nil
+}
+
+// UnmarshalText implements the text unmarshaller interface
+func (t *DateTime) UnmarshalText(text []byte) error {
+ tt, err := ParseDateTime(string(text))
+ if err != nil {
+ return err
+ }
+ *t = tt
+ return nil
+}
+
+// Scan scans a DateTime value from database driver type.
+func (t *DateTime) Scan(raw any) error {
+ // TODO: case int64: and case float64: ?
+ switch v := raw.(type) {
+ case []byte:
+ return t.UnmarshalText(v)
+ case string:
+ return t.UnmarshalText([]byte(v))
+ case time.Time:
+ *t = DateTime(v)
+ case nil:
+ *t = DateTime{}
+ default:
+ return fmt.Errorf("cannot sql.Scan() strfmt.DateTime from: %#v: %w", v, ErrFormat)
+ }
+
+ return nil
+}
+
+// Value converts DateTime to a primitive value ready to written to a database.
+func (t DateTime) Value() (driver.Value, error) {
+ return driver.Value(t.String()), nil
+}
+
+// MarshalJSON returns the DateTime as JSON
+func (t DateTime) MarshalJSON() ([]byte, error) {
+ return json.Marshal(NormalizeTimeForMarshal(time.Time(t)).Format(MarshalFormat))
+}
+
+// UnmarshalJSON sets the DateTime from JSON
+func (t *DateTime) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+
+ var tstr string
+ if err := json.Unmarshal(data, &tstr); err != nil {
+ return err
+ }
+ tt, err := ParseDateTime(tstr)
+ if err != nil {
+ return err
+ }
+ *t = tt
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (t *DateTime) DeepCopyInto(out *DateTime) {
+ *out = *t
+}
+
+// DeepCopy copies the receiver into a new DateTime.
+func (t *DateTime) DeepCopy() *DateTime {
+ if t == nil {
+ return nil
+ }
+ out := new(DateTime)
+ t.DeepCopyInto(out)
+ return out
+}
+
+// GobEncode implements the gob.GobEncoder interface.
+func (t DateTime) GobEncode() ([]byte, error) {
+ return t.MarshalBinary()
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (t *DateTime) GobDecode(data []byte) error {
+ return t.UnmarshalBinary(data)
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (t DateTime) MarshalBinary() ([]byte, error) {
+ return NormalizeTimeForMarshal(time.Time(t)).MarshalBinary()
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (t *DateTime) UnmarshalBinary(data []byte) error {
+ var original time.Time
+
+ err := original.UnmarshalBinary(data)
+ if err != nil {
+ return err
+ }
+
+ *t = DateTime(original)
+
+ return nil
+}
+
+// Equal checks if two DateTime instances are equal using time.Time's Equal method
+func (t DateTime) Equal(t2 DateTime) bool {
+ return time.Time(t).Equal(time.Time(t2))
+}
diff --git a/vendor/github.com/go-openapi/strfmt/ulid.go b/vendor/github.com/go-openapi/strfmt/ulid.go
new file mode 100644
index 000000000000..85c5b53e6c7a
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/ulid.go
@@ -0,0 +1,208 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package strfmt
+
+import (
+ cryptorand "crypto/rand"
+ "database/sql/driver"
+ "encoding/json"
+ "fmt"
+ "io"
+ "sync"
+
+ "github.com/oklog/ulid"
+)
+
+// ULID represents a ulid string format
+// ref:
+//
+// https://github.com/ulid/spec
+//
+// impl:
+//
+// https://github.com/oklog/ulid
+//
+// swagger:strfmt ulid
+type ULID struct {
+ ulid.ULID
+}
+
+var (
+ ulidEntropyPool = sync.Pool{
+ New: func() any {
+ return cryptorand.Reader
+ },
+ }
+
+ ULIDScanDefaultFunc = func(raw any) (ULID, error) {
+ u := NewULIDZero()
+ switch x := raw.(type) {
+ case nil:
+ // zerp ulid
+ return u, nil
+ case string:
+ if x == "" {
+ // zero ulid
+ return u, nil
+ }
+ return u, u.UnmarshalText([]byte(x))
+ case []byte:
+ return u, u.UnmarshalText(x)
+ }
+
+ return u, fmt.Errorf("cannot sql.Scan() strfmt.ULID from: %#v: %w", raw, ulid.ErrScanValue)
+ }
+
+ // ULIDScanOverrideFunc allows you to override the Scan method of the ULID type
+ ULIDScanOverrideFunc = ULIDScanDefaultFunc
+
+ ULIDValueDefaultFunc = func(u ULID) (driver.Value, error) {
+ return driver.Value(u.String()), nil
+ }
+
+ // ULIDValueOverrideFunc allows you to override the Value method of the ULID type
+ ULIDValueOverrideFunc = ULIDValueDefaultFunc
+)
+
+func init() {
+ // register formats in the default registry:
+ // - ulid
+ ulid := ULID{}
+ Default.Add("ulid", &ulid, IsULID)
+}
+
+// IsULID checks if provided string is ULID format
+// Be noticed that this function considers overflowed ULID as non-ulid.
+// For more details see https://github.com/ulid/spec
+func IsULID(str string) bool {
+ _, err := ulid.ParseStrict(str)
+ return err == nil
+}
+
+// ParseULID parses a string that represents an valid ULID
+func ParseULID(str string) (ULID, error) {
+ var u ULID
+
+ return u, u.UnmarshalText([]byte(str))
+}
+
+// NewULIDZero returns a zero valued ULID type
+func NewULIDZero() ULID {
+ return ULID{}
+}
+
+// NewULID generates new unique ULID value and a error if any
+func NewULID() (ULID, error) {
+ var u ULID
+
+ obj := ulidEntropyPool.Get()
+ entropy, ok := obj.(io.Reader)
+ if !ok {
+ return u, fmt.Errorf("failed to cast %+v to io.Reader: %w", obj, ErrFormat)
+ }
+
+ id, err := ulid.New(ulid.Now(), entropy)
+ if err != nil {
+ return u, err
+ }
+ ulidEntropyPool.Put(entropy)
+
+ u.ULID = id
+ return u, nil
+}
+
+// GetULID returns underlying instance of ULID
+func (u *ULID) GetULID() any {
+ return u.ULID
+}
+
+// MarshalText returns this instance into text
+func (u ULID) MarshalText() ([]byte, error) {
+ return u.ULID.MarshalText()
+}
+
+// UnmarshalText hydrates this instance from text
+func (u *ULID) UnmarshalText(data []byte) error { // validation is performed later on
+ return u.ULID.UnmarshalText(data)
+}
+
+// Scan reads a value from a database driver
+func (u *ULID) Scan(raw any) error {
+ ul, err := ULIDScanOverrideFunc(raw)
+ if err == nil {
+ *u = ul
+ }
+ return err
+}
+
+// Value converts a value to a database driver value
+func (u ULID) Value() (driver.Value, error) {
+ return ULIDValueOverrideFunc(u)
+}
+
+func (u ULID) String() string {
+ return u.ULID.String()
+}
+
+// MarshalJSON returns the ULID as JSON
+func (u ULID) MarshalJSON() ([]byte, error) {
+ return json.Marshal(u.String())
+}
+
+// UnmarshalJSON sets the ULID from JSON
+func (u *ULID) UnmarshalJSON(data []byte) error {
+ if string(data) == jsonNull {
+ return nil
+ }
+ var ustr string
+ if err := json.Unmarshal(data, &ustr); err != nil {
+ return err
+ }
+ id, err := ulid.ParseStrict(ustr)
+ if err != nil {
+ return fmt.Errorf("couldn't parse JSON value as ULID: %w", err)
+ }
+ u.ULID = id
+ return nil
+}
+
+// DeepCopyInto copies the receiver and writes its value into out.
+func (u *ULID) DeepCopyInto(out *ULID) {
+ *out = *u
+}
+
+// DeepCopy copies the receiver into a new ULID.
+func (u *ULID) DeepCopy() *ULID {
+ if u == nil {
+ return nil
+ }
+ out := new(ULID)
+ u.DeepCopyInto(out)
+ return out
+}
+
+// GobEncode implements the gob.GobEncoder interface.
+func (u ULID) GobEncode() ([]byte, error) {
+ return u.ULID.MarshalBinary()
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (u *ULID) GobDecode(data []byte) error {
+ return u.ULID.UnmarshalBinary(data)
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (u ULID) MarshalBinary() ([]byte, error) {
+ return u.ULID.MarshalBinary()
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (u *ULID) UnmarshalBinary(data []byte) error {
+ return u.ULID.UnmarshalBinary(data)
+}
+
+// Equal checks if two ULID instances are equal by their underlying type
+func (u ULID) Equal(other ULID) bool {
+ return u.ULID == other.ULID
+}
diff --git a/vendor/github.com/go-openapi/swag/.codecov.yml b/vendor/github.com/go-openapi/swag/.codecov.yml
new file mode 100644
index 000000000000..3354f44b28e9
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/.codecov.yml
@@ -0,0 +1,4 @@
+ignore:
+ - jsonutils/fixtures_test
+ - jsonutils/adapters/ifaces/mocks
+ - jsonutils/adapters/testintegration/benchmarks
diff --git a/vendor/github.com/go-openapi/swag/.editorconfig b/vendor/github.com/go-openapi/swag/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/swag/.gitattributes b/vendor/github.com/go-openapi/swag/.gitattributes
new file mode 100644
index 000000000000..49ad52766abb
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/.gitattributes
@@ -0,0 +1,2 @@
+# gofmt always uses LF, whereas Git uses CRLF on Windows.
+*.go text eol=lf
diff --git a/vendor/github.com/go-openapi/swag/.gitignore b/vendor/github.com/go-openapi/swag/.gitignore
new file mode 100644
index 000000000000..c4b1b64f04e4
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/.gitignore
@@ -0,0 +1,5 @@
+secrets.yml
+vendor
+Godeps
+.idea
+*.out
diff --git a/vendor/github.com/go-openapi/swag/.golangci.yml b/vendor/github.com/go-openapi/swag/.golangci.yml
new file mode 100644
index 000000000000..126264a6b898
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/.golangci.yml
@@ -0,0 +1,78 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gomoddirectives
+ - gosmopolitan
+ - inamedparam
+ - intrange
+ - ireturn
+ - lll
+ - musttag
+ - modernize
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tagliatelle
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/swag/.mockery.yml b/vendor/github.com/go-openapi/swag/.mockery.yml
new file mode 100644
index 000000000000..8557cb58d331
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/.mockery.yml
@@ -0,0 +1,30 @@
+all: false
+dir: '{{.InterfaceDir}}'
+filename: mocks_test.go
+force-file-write: true
+formatter: goimports
+include-auto-generated: false
+log-level: info
+structname: '{{.Mock}}{{.InterfaceName}}'
+pkgname: '{{.SrcPackageName}}'
+recursive: false
+require-template-schema-exists: true
+template: matryer
+template-schema: '{{.Template}}.schema.json'
+packages:
+ github.com/go-openapi/swag/jsonutils/adapters/ifaces:
+ config:
+ dir: jsonutils/adapters/ifaces/mocks
+ filename: mocks.go
+ pkgname: 'mocks'
+ force-file-write: true
+ all: true
+ github.com/go-openapi/swag/jsonutils/adapters/testintegration:
+ config:
+ inpackage: true
+ dir: jsonutils/adapters/testintegration
+ force-file-write: true
+ all: true
+ interfaces:
+ EJMarshaler:
+ EJUnmarshaler:
diff --git a/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/swag/LICENSE b/vendor/github.com/go-openapi/swag/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/README.md b/vendor/github.com/go-openapi/swag/README.md
new file mode 100644
index 000000000000..b2b29f8fe2c9
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/README.md
@@ -0,0 +1,219 @@
+# Swag [](https://github.com/go-openapi/swag/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/swag)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/swag/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/swag)
+[](https://goreportcard.com/report/github.com/go-openapi/swag)
+
+Package `swag` contains a bunch of helper functions for go-openapi and go-swagger projects.
+
+You may also use it standalone for your projects.
+
+> **NOTE**
+> `swag` is one of the foundational building blocks of the go-openapi initiative.
+> Most repositories in `github.com/go-openapi/...` depend on it in some way.
+> And so does our CLI tool `github.com/go-swagger/go-swagger`,
+> as well as the code generated by this tool.
+
+* [Contents](#contents)
+* [Dependencies](#dependencies)
+* [Release Notes](#release-notes)
+* [Licensing](#licensing)
+* [Note to contributors](#note-to-contributors)
+* [TODOs, suggestions and plans](#todos-suggestions-and-plans)
+
+## Contents
+
+`go-openapi/swag` exposes a collection of relatively independent modules.
+
+Moving forward, no additional feature will be added to the `swag` API directly at the root package level,
+which remains there for backward-compatibility purposes. All exported top-level features are now deprecated.
+
+Child modules will continue to evolve and some new ones may be added in the future.
+
+| Module | Content | Main features |
+|---------------|---------|---------------|
+| `cmdutils` | utilities to work with CLIs ||
+| `conv` | type conversion utilities | convert between values and pointers for any types convert from string to builtin types (wraps `strconv`) require `./typeutils` (test dependency) |
+| `fileutils` | file utilities | |
+| `jsonname` | JSON utilities | infer JSON names from `go` properties |
+| `jsonutils` | JSON utilities | fast json concatenation read and write JSON from and to dynamic `go` data structures ~require `github.com/mailru/easyjson`~ |
+| `loading` | file loading | load from file or http require `./yamlutils` |
+| `mangling` | safe name generation | name mangling for `go` |
+| `netutils` | networking utilities | host, port from address |
+| `stringutils` | `string` utilities | search in slice (with case-insensitive) split/join query parameters as arrays |
+| `typeutils` | `go` types utilities | check the zero value for any type safe check for a nil value |
+| `yamlutils` | YAML utilities | converting YAML to JSON loading YAML into a dynamic YAML document maintaining the original order of keys in YAML objects require `./jsonutils` ~require `github.com/mailru/easyjson`~ require `go.yaml.in/yaml/v3` |
+
+---
+
+## Dependencies
+
+The root module `github.com/go-openapi/swag` at the repo level maintains a few
+dependencies outside of the standard library.
+
+* YAML utilities depend on `go.yaml.in/yaml/v3`
+* JSON utilities depend on their registered adapter module:
+ * by default, only the standard library is used
+ * `github.com/mailru/easyjson` is now only a dependency for module
+ `github.com/go-openapi/swag/jsonutils/adapters/easyjson/json`,
+ for users willing to import that module.
+ * integration tests and benchmarks use all the dependencies are published as their own module
+* other dependencies are test dependencies drawn from `github.com/stretchr/testify`
+
+## Release notes
+
+### v0.25.2 (draft, unpublished)
+
+Minor changes due to internal maintenance that don't affect the behavior of the library.
+
+* [x] removed indirect test dependencies by switching all tests to `go-openapi/testify`,
+ a fork of `stretch/testify` with zero-dependencies.
+* [x] improvements to CI to catch test reports.
+* [x] modernized licensing annotations in source code, using the more compact SPDX annotations
+ rather than the full license terms.
+* [x] simplified a bit JSON & YAML testing by using newly available assertions
+* started the journey to an OpenSSF score card badge:
+ * [x] explicited permissions in CI workflows
+ * [x] published security policy
+ * pinned dependencies to github actions
+ * introduced fuzzing in tests
+
+### v0.25.1
+
+* fixes a data race that could occur when using the standard library implementation of a JSON ordered map
+
+### v0.25.0
+
+**New with this release**:
+
+* requires `go1.24`, as iterators are being introduced
+* removes the dependency to `mailru/easyjson` by default (#68)
+ * functionality remains the same, but performance may somewhat degrade for applications
+ that relied on `easyjson`
+ * users of the JSON or YAML utilities who want to use `easyjson` as their preferred JSON serializer library
+ will be able to do so by registering this the corresponding JSON adapter at runtime. See below.
+ * ordered keys in JSON and YAML objects: this feature used to rely solely on `easyjson`.
+ With this release, an implementation relying on the standard `encoding/json` is provided.
+ * an independent [benchmark](./jsonutils/adapters/testintegration/benchmarks/README.md) to compare the different adapters
+* improves the "float is integer" check (`conv.IsFloat64AJSONInteger`) (#59)
+* removes the _direct_ dependency to `gopkg.in/yaml.v3` (indirect dependency is still incurred through `stretchr/testify`) (#127)
+* exposed `conv.IsNil()` (previously kept private): a safe nil check (accounting for the "non-nil interface with nil value" nonsensical go trick)
+
+**What coming next?**
+
+Moving forward, we want to :
+* provide an implementation of the JSON adapter based on `encoding/json/v2`, for `go1.25` builds.
+* provide similar implementations for `goccy/go-json` and `jsoniterator/go`, and perhaps some other
+ similar libraries may be interesting too.
+
+
+**How to explicitly register a dependency at runtime**?
+
+The following would maintain how JSON utilities proposed by `swag` used work, up to `v0.24.1`.
+
+ ```go
+ import (
+ "github.com/go-openapi/swag/jsonutils/adapters"
+ easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
+ )
+
+ func init() {
+ easyjson.Register(adapters.Registry)
+ }
+ ```
+
+Subsequent calls to `jsonutils.ReadJSON()` or `jsonutils.WriteJSON()` will switch to `easyjson`
+whenever the passed data structures implement the `easyjson.Unmarshaler` or `easyjson.Marshaler` respectively,
+or fallback to the standard library.
+
+For more details, you may also look at our
+[integration tests](jsonutils/adapters/testintegration/integration_suite_test.go#29).
+
+### v0.24.0
+
+With this release, we have largely modernized the API of `swag`:
+
+* The traditional `swag` API is still supported: code that imports `swag` will still
+ compile and work the same.
+* A deprecation notice is published to encourage consumers of this library to adopt
+ the newer API
+* **Deprecation notice**
+ * configuration through global variables is now deprecated, in favor of options passed as parameters
+ * all helper functions are moved to more specialized packages, which are exposed as
+ go modules. Importing such a module would reduce the footprint of dependencies.
+ * _all_ functions, variables, constants exposed by the deprecated API have now moved, so
+ that consumers of the new API no longer need to import github.com/go-openapi/swag, but
+ should import the desired sub-module(s).
+
+**New with this release**:
+
+* [x] type converters and pointer to value helpers now support generic types
+* [x] name mangling now support pluralized initialisms (issue #46)
+ Strings like "contact IDs" are now recognized as such a plural form and mangled as a linter would expect.
+* [x] performance: small improvements to reduce the overhead of convert/format wrappers (see issues #110, or PR #108)
+* [x] performance: name mangling utilities run ~ 10% faster (PR #115)
+
+---
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+## Note to contributors
+
+A mono-repo structure comes with some unavoidable extra pains...
+
+* Testing
+
+> The usual `go test ./...` command, run from the root of this repo won't work any longer to test all submodules.
+>
+> Each module constitutes an independant unit of test. So you have to run `go test` inside each module.
+> Or you may take a look at how this is achieved by CI
+> [here] https://github.com/go-openapi/swag/blob/master/.github/workflows/go-test.yml).
+>
+> There are also some alternative tricks using `go work`, for local development, if you feel comfortable with
+> go workspaces. Perhaps some day, we'll have a `go work test` to run all tests without any hack.
+
+* Releasing
+
+> Each module follows its own independant module versioning.
+>
+> So you have tags like `mangling/v0.24.0`, `fileutils/v0.24.0` etc that are used by `go mod` and `go get`
+> to refer to the tagged version of each module specifically.
+>
+> This means we may release patches etc to each module independently.
+>
+> We'd like to adopt the rule that modules in this repo would only differ by a patch version
+> (e.g. `v0.24.5` vs `v0.24.3`), and we'll level all modules whenever a minor version is introduced.
+>
+> A script in `./hack` is provided to tag all modules with the same version in one go.
+
+* Continuous integration
+
+> At this moment, all tests in all modules are systematically run over the full test matrix (3 platform x 2 go releases).
+> This generates quite a lot of jobs.
+>
+> We ought to reduce the number of jobs required to test a PR focused on only a few modules.
+
+## Todos, suggestions and plans
+
+All kinds of contributions are welcome.
+
+A few ideas:
+
+* [x] Complete the split of dependencies to isolate easyjson from the rest
+* [x] Improve CI to reduce needed tests
+* [x] Replace dependency to `gopkg.in/yaml.v3` (`yamlutil`)
+* [ ] Improve mangling utilities (improve readability, support for capitalized words,
+ better word substitution for non-letter symbols...)
+* [ ] Move back to this common shared pot a few of the technical features introduced by go-swagger independently
+ (e.g. mangle go package names, search package with go modules support, ...)
+* [ ] Apply a similar mono-repo approach to go-openapi/strfmt which suffer from similar woes: bloated API,
+ imposed dependency to some database driver.
+* [ ] Adapt `go-swagger` (incl. generated code) to the new `swag` API.
+* [ ] Factorize some tests, as there is a lot of redundant testing code in `jsonutils`
+* [ ] Benchmark & profiling: publish independently the tool built to analyze and chart benchmarks (e.g. similar to `benchvisual`)
+* [ ] more thorough testing for nil / null case
+* [ ] ci pipeline to manage releases
+* [ ] cleaner mockery generation (doesn't work out of the box for all sub-modules)
diff --git a/vendor/github.com/go-openapi/swag/SECURITY.md b/vendor/github.com/go-openapi/swag/SECURITY.md
new file mode 100644
index 000000000000..72296a83135d
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/SECURITY.md
@@ -0,0 +1,19 @@
+# Security Policy
+
+This policy outlines the commitment and practices of the go-openapi maintainers regarding security.
+
+## Supported Versions
+
+| Version | Supported |
+| ------- | ------------------ |
+| 0.25.x | :white_check_mark: |
+
+## Reporting a vulnerability
+
+If you become aware of a security vulnerability that affects the current repository,
+please report it privately to the maintainers.
+
+Please follow the instructions provided by github to
+[Privately report a security vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability).
+
+TL;DR: on Github, navigate to the project's "Security" tab then click on "Report a vulnerability".
diff --git a/vendor/github.com/go-openapi/swag/cmdutils/LICENSE b/vendor/github.com/go-openapi/swag/cmdutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/cmdutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/cmdutils/cmd_utils.go b/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go
new file mode 100644
index 000000000000..6c7bbb26f03d
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package cmdutils
+
+// CommandLineOptionsGroup represents a group of user-defined command line options.
+//
+// This is for instance used to configure command line arguments in API servers generated by go-swagger.
+type CommandLineOptionsGroup struct {
+ ShortDescription string
+ LongDescription string
+ Options any
+}
diff --git a/vendor/github.com/go-openapi/swag/cmdutils/doc.go b/vendor/github.com/go-openapi/swag/cmdutils/doc.go
new file mode 100644
index 000000000000..31f2c37538a0
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/cmdutils/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package cmdutils brings helpers for CLIs produced by go-openapi
+package cmdutils
diff --git a/vendor/github.com/go-openapi/swag/cmdutils_iface.go b/vendor/github.com/go-openapi/swag/cmdutils_iface.go
new file mode 100644
index 000000000000..bd0c1fc12802
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/cmdutils_iface.go
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import "github.com/go-openapi/swag/cmdutils"
+
+// CommandLineOptionsGroup represents a group of user-defined command line options.
+//
+// Deprecated: use [cmdutils.CommandLineOptionsGroup] instead.
+type CommandLineOptionsGroup = cmdutils.CommandLineOptionsGroup
diff --git a/vendor/github.com/go-openapi/swag/conv/LICENSE b/vendor/github.com/go-openapi/swag/conv/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/conv/convert.go b/vendor/github.com/go-openapi/swag/conv/convert.go
new file mode 100644
index 000000000000..f205c3913457
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/convert.go
@@ -0,0 +1,161 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package conv
+
+import (
+ "math"
+ "strconv"
+ "strings"
+)
+
+// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
+const (
+ maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
+ minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
+ epsilon float64 = 1e-9
+)
+
+// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive.
+func IsFloat64AJSONInteger(f float64) bool {
+ if math.IsNaN(f) || math.IsInf(f, 0) || f < minJSONFloat || f > maxJSONFloat {
+ return false
+ }
+ rounded := math.Round(f)
+ if f == rounded {
+ return true
+ }
+ if rounded == 0 { // f = 0.0 exited above
+ return false
+ }
+
+ diff := math.Abs(f - rounded)
+ if diff == 0 {
+ return true
+ }
+
+ // relative error Abs{f - Round(f)) / Round(f)} < ε ; Round(f)
+ return diff < epsilon*math.Abs(rounded)
+}
+
+// ConvertFloat turns a string into a float numerical value.
+func ConvertFloat[T Float](str string) (T, error) {
+ var v T
+ f, err := strconv.ParseFloat(str, bitsize(v))
+ if err != nil {
+ return 0, err
+ }
+
+ return T(f), nil
+}
+
+// ConvertInteger turns a string into a signed integer.
+func ConvertInteger[T Signed](str string) (T, error) {
+ var v T
+ f, err := strconv.ParseInt(str, 10, bitsize(v))
+ if err != nil {
+ return 0, err
+ }
+
+ return T(f), nil
+}
+
+// ConvertUinteger turns a string into an unsigned integer.
+func ConvertUinteger[T Unsigned](str string) (T, error) {
+ var v T
+ f, err := strconv.ParseUint(str, 10, bitsize(v))
+ if err != nil {
+ return 0, err
+ }
+
+ return T(f), nil
+}
+
+// ConvertBool turns a string into a boolean.
+//
+// It supports a few more "true" strings than [strconv.ParseBool]:
+//
+// - it is not case sensitive ("trUe" or "FalsE" work)
+// - "ok", "yes", "y", "on", "selected", "checked", "enabled" are all true
+// - everything that is not true is false: there is never an actual error returned
+func ConvertBool(str string) (bool, error) {
+ switch strings.ToLower(str) {
+ case "true",
+ "1",
+ "yes",
+ "ok",
+ "y",
+ "on",
+ "selected",
+ "checked",
+ "t",
+ "enabled":
+ return true, nil
+ default:
+ return false, nil
+ }
+}
+
+// ConvertFloat32 turns a string into a float32.
+func ConvertFloat32(str string) (float32, error) { return ConvertFloat[float32](str) }
+
+// ConvertFloat64 turns a string into a float64
+func ConvertFloat64(str string) (float64, error) { return ConvertFloat[float64](str) }
+
+// ConvertInt8 turns a string into an int8
+func ConvertInt8(str string) (int8, error) { return ConvertInteger[int8](str) }
+
+// ConvertInt16 turns a string into an int16
+func ConvertInt16(str string) (int16, error) {
+ i, err := strconv.ParseInt(str, 10, 16)
+ if err != nil {
+ return 0, err
+ }
+ return int16(i), nil
+}
+
+// ConvertInt32 turns a string into an int32
+func ConvertInt32(str string) (int32, error) {
+ i, err := strconv.ParseInt(str, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return int32(i), nil
+}
+
+// ConvertInt64 turns a string into an int64
+func ConvertInt64(str string) (int64, error) {
+ return strconv.ParseInt(str, 10, 64)
+}
+
+// ConvertUint8 turns a string into an uint8
+func ConvertUint8(str string) (uint8, error) {
+ i, err := strconv.ParseUint(str, 10, 8)
+ if err != nil {
+ return 0, err
+ }
+ return uint8(i), nil
+}
+
+// ConvertUint16 turns a string into an uint16
+func ConvertUint16(str string) (uint16, error) {
+ i, err := strconv.ParseUint(str, 10, 16)
+ if err != nil {
+ return 0, err
+ }
+ return uint16(i), nil
+}
+
+// ConvertUint32 turns a string into an uint32
+func ConvertUint32(str string) (uint32, error) {
+ i, err := strconv.ParseUint(str, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return uint32(i), nil
+}
+
+// ConvertUint64 turns a string into an uint64
+func ConvertUint64(str string) (uint64, error) {
+ return strconv.ParseUint(str, 10, 64)
+}
diff --git a/vendor/github.com/go-openapi/swag/conv/convert_types.go b/vendor/github.com/go-openapi/swag/conv/convert_types.go
new file mode 100644
index 000000000000..cf4c6495ebc9
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/convert_types.go
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package conv
+
+// Unlicensed credits (idea, concept)
+//
+// The idea to convert values to pointers and the other way around, was inspired, eons ago, by the aws go sdk.
+//
+// Nowadays, all sensible API sdk's expose a similar functionality.
+
+// Pointer returns a pointer to the value passed in.
+func Pointer[T any](v T) *T {
+ return &v
+}
+
+// Value returns a shallow copy of the value of the pointer passed in.
+//
+// If the pointer is nil, the returned value is the zero value.
+func Value[T any](v *T) T {
+ if v != nil {
+ return *v
+ }
+
+ var zero T
+ return zero
+}
+
+// PointerSlice converts a slice of values into a slice of pointers.
+func PointerSlice[T any](src []T) []*T {
+ dst := make([]*T, len(src))
+ for i := 0; i < len(src); i++ {
+ dst[i] = &(src[i])
+ }
+ return dst
+}
+
+// ValueSlice converts a slice of pointers into a slice of values.
+//
+// nil elements are zero values.
+func ValueSlice[T any](src []*T) []T {
+ dst := make([]T, len(src))
+ for i := 0; i < len(src); i++ {
+ if src[i] != nil {
+ dst[i] = *(src[i])
+ }
+ }
+ return dst
+}
+
+// PointerMap converts a map of values into a map of pointers.
+func PointerMap[K comparable, T any](src map[K]T) map[K]*T {
+ dst := make(map[K]*T)
+ for k, val := range src {
+ v := val
+ dst[k] = &v
+ }
+ return dst
+}
+
+// ValueMap converts a map of pointers into a map of values.
+//
+// nil elements are skipped.
+func ValueMap[K comparable, T any](src map[K]*T) map[K]T {
+ dst := make(map[K]T)
+ for k, val := range src {
+ if val != nil {
+ dst[k] = *val
+ }
+ }
+ return dst
+}
diff --git a/vendor/github.com/go-openapi/swag/conv/doc.go b/vendor/github.com/go-openapi/swag/conv/doc.go
new file mode 100644
index 000000000000..1bd6ead6e2d1
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/doc.go
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package conv exposes utilities to convert types.
+//
+// The Convert and Format families of functions are essentially a shorthand to [strconv] functions,
+// using the decimal representation of numbers.
+//
+// Features:
+//
+// - from string representation to value ("Convert*") and reciprocally ("Format*")
+// - from pointer to value ([Value]) and reciprocally ([Pointer])
+// - from slice of values to slice of pointers ([PointerSlice]) and reciprocally ([ValueSlice])
+// - from map of values to map of pointers ([PointerMap]) and reciprocally ([ValueMap])
+package conv
diff --git a/vendor/github.com/go-openapi/swag/conv/format.go b/vendor/github.com/go-openapi/swag/conv/format.go
new file mode 100644
index 000000000000..5b87b8e146bb
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/format.go
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package conv
+
+import (
+ "strconv"
+)
+
+// FormatInteger turns an integer type into a string.
+func FormatInteger[T Signed](value T) string {
+ return strconv.FormatInt(int64(value), 10)
+}
+
+// FormatUinteger turns an unsigned integer type into a string.
+func FormatUinteger[T Unsigned](value T) string {
+ return strconv.FormatUint(uint64(value), 10)
+}
+
+// FormatFloat turns a floating point numerical value into a string.
+func FormatFloat[T Float](value T) string {
+ return strconv.FormatFloat(float64(value), 'f', -1, bitsize(value))
+}
+
+// FormatBool turns a boolean into a string.
+func FormatBool(value bool) string {
+ return strconv.FormatBool(value)
+}
diff --git a/vendor/github.com/go-openapi/swag/conv/sizeof.go b/vendor/github.com/go-openapi/swag/conv/sizeof.go
new file mode 100644
index 000000000000..494346557381
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/sizeof.go
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package conv
+
+import "unsafe"
+
+// bitsize returns the size in bits of a type.
+//
+// NOTE: [unsafe.SizeOf] simply returns the size in bytes of the value.
+// For primitive types T, the generic stencil is precompiled and this value
+// is resolved at compile time, resulting in an immediate call to [strconv.ParseFloat].
+//
+// We may leave up to the go compiler to simplify this function into a
+// constant value, which happens in practice at least for primitive types
+// (e.g. numerical types).
+func bitsize[T Numerical](value T) int {
+ const bitsPerByte = 8
+ return int(unsafe.Sizeof(value)) * bitsPerByte
+}
diff --git a/vendor/github.com/go-openapi/swag/conv/type_constraints.go b/vendor/github.com/go-openapi/swag/conv/type_constraints.go
new file mode 100644
index 000000000000..81135e827e52
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv/type_constraints.go
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package conv
+
+type (
+ // these type constraints are redefined after golang.org/x/exp/constraints,
+ // because importing that package causes an undesired go upgrade.
+
+ // Signed integer types, cf. [golang.org/x/exp/constraints.Signed]
+ Signed interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64
+ }
+
+ // Unsigned integer types, cf. [golang.org/x/exp/constraints.Unsigned]
+ Unsigned interface {
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
+ }
+
+ // Float numerical types, cf. [golang.org/x/exp/constraints.Float]
+ Float interface {
+ ~float32 | ~float64
+ }
+
+ // Numerical types
+ Numerical interface {
+ Signed | Unsigned | Float
+ }
+)
diff --git a/vendor/github.com/go-openapi/swag/conv_iface.go b/vendor/github.com/go-openapi/swag/conv_iface.go
new file mode 100644
index 000000000000..eea7b2e56e33
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/conv_iface.go
@@ -0,0 +1,486 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import (
+ "time"
+
+ "github.com/go-openapi/swag/conv"
+)
+
+// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive.
+//
+// Deprecated: use [conv.IsFloat64AJSONInteger] instead.
+func IsFloat64AJSONInteger(f float64) bool { return conv.IsFloat64AJSONInteger(f) }
+
+// ConvertBool turns a string into a boolean.
+//
+// Deprecated: use [conv.ConvertBool] instead.
+func ConvertBool(str string) (bool, error) { return conv.ConvertBool(str) }
+
+// ConvertFloat32 turns a string into a float32.
+//
+// Deprecated: use [conv.ConvertFloat32] instead. Alternatively, you may use the generic version [conv.ConvertFloat].
+func ConvertFloat32(str string) (float32, error) { return conv.ConvertFloat[float32](str) }
+
+// ConvertFloat64 turns a string into a float64.
+//
+// Deprecated: use [conv.ConvertFloat64] instead. Alternatively, you may use the generic version [conv.ConvertFloat].
+func ConvertFloat64(str string) (float64, error) { return conv.ConvertFloat[float64](str) }
+
+// ConvertInt8 turns a string into an int8.
+//
+// Deprecated: use [conv.ConvertInt8] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
+func ConvertInt8(str string) (int8, error) { return conv.ConvertInteger[int8](str) }
+
+// ConvertInt16 turns a string into an int16.
+//
+// Deprecated: use [conv.ConvertInt16] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
+func ConvertInt16(str string) (int16, error) { return conv.ConvertInteger[int16](str) }
+
+// ConvertInt32 turns a string into an int32.
+//
+// Deprecated: use [conv.ConvertInt32] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
+func ConvertInt32(str string) (int32, error) { return conv.ConvertInteger[int32](str) }
+
+// ConvertInt64 turns a string into an int64.
+//
+// Deprecated: use [conv.ConvertInt64] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
+func ConvertInt64(str string) (int64, error) { return conv.ConvertInteger[int64](str) }
+
+// ConvertUint8 turns a string into an uint8.
+//
+// Deprecated: use [conv.ConvertUint8] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
+func ConvertUint8(str string) (uint8, error) { return conv.ConvertUinteger[uint8](str) }
+
+// ConvertUint16 turns a string into an uint16.
+//
+// Deprecated: use [conv.ConvertUint16] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
+func ConvertUint16(str string) (uint16, error) { return conv.ConvertUinteger[uint16](str) }
+
+// ConvertUint32 turns a string into an uint32.
+//
+// Deprecated: use [conv.ConvertUint32] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
+func ConvertUint32(str string) (uint32, error) { return conv.ConvertUinteger[uint32](str) }
+
+// ConvertUint64 turns a string into an uint64.
+//
+// Deprecated: use [conv.ConvertUint64] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
+func ConvertUint64(str string) (uint64, error) { return conv.ConvertUinteger[uint64](str) }
+
+// FormatBool turns a boolean into a string.
+//
+// Deprecated: use [conv.FormatBool] instead.
+func FormatBool(value bool) string { return conv.FormatBool(value) }
+
+// FormatFloat32 turns a float32 into a string.
+//
+// Deprecated: use [conv.FormatFloat] instead.
+func FormatFloat32(value float32) string { return conv.FormatFloat(value) }
+
+// FormatFloat64 turns a float64 into a string.
+//
+// Deprecated: use [conv.FormatFloat] instead.
+func FormatFloat64(value float64) string { return conv.FormatFloat(value) }
+
+// FormatInt8 turns an int8 into a string.
+//
+// Deprecated: use [conv.FormatInteger] instead.
+func FormatInt8(value int8) string { return conv.FormatInteger(value) }
+
+// FormatInt16 turns an int16 into a string.
+//
+// Deprecated: use [conv.FormatInteger] instead.
+func FormatInt16(value int16) string { return conv.FormatInteger(value) }
+
+// FormatInt32 turns an int32 into a string
+//
+// Deprecated: use [conv.FormatInteger] instead.
+func FormatInt32(value int32) string { return conv.FormatInteger(value) }
+
+// FormatInt64 turns an int64 into a string.
+//
+// Deprecated: use [conv.FormatInteger] instead.
+func FormatInt64(value int64) string { return conv.FormatInteger(value) }
+
+// FormatUint8 turns an uint8 into a string.
+//
+// Deprecated: use [conv.FormatUinteger] instead.
+func FormatUint8(value uint8) string { return conv.FormatUinteger(value) }
+
+// FormatUint16 turns an uint16 into a string.
+//
+// Deprecated: use [conv.FormatUinteger] instead.
+func FormatUint16(value uint16) string { return conv.FormatUinteger(value) }
+
+// FormatUint32 turns an uint32 into a string.
+//
+// Deprecated: use [conv.FormatUinteger] instead.
+func FormatUint32(value uint32) string { return conv.FormatUinteger(value) }
+
+// FormatUint64 turns an uint64 into a string.
+//
+// Deprecated: use [conv.FormatUinteger] instead.
+func FormatUint64(value uint64) string { return conv.FormatUinteger(value) }
+
+// String turn a pointer to of the string value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func String(v string) *string { return conv.Pointer(v) }
+
+// StringValue turn the value of the string pointer passed in or
+// "" if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func StringValue(v *string) string { return conv.Value(v) }
+
+// StringSlice converts a slice of string values into a slice of string pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func StringSlice(src []string) []*string { return conv.PointerSlice(src) }
+
+// StringValueSlice converts a slice of string pointers into a slice of string values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func StringValueSlice(src []*string) []string { return conv.ValueSlice(src) }
+
+// StringMap converts a string map of string values into a string map of string pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func StringMap(src map[string]string) map[string]*string { return conv.PointerMap(src) }
+
+// StringValueMap converts a string map of string pointers into a string map of string values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func StringValueMap(src map[string]*string) map[string]string { return conv.ValueMap(src) }
+
+// Bool turn a pointer to of the bool value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Bool(v bool) *bool { return conv.Pointer(v) }
+
+// BoolValue turn the value of the bool pointer passed in or false if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func BoolValue(v *bool) bool { return conv.Value(v) }
+
+// BoolSlice converts a slice of bool values into a slice of bool pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func BoolSlice(src []bool) []*bool { return conv.PointerSlice(src) }
+
+// BoolValueSlice converts a slice of bool pointers into a slice of bool values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func BoolValueSlice(src []*bool) []bool { return conv.ValueSlice(src) }
+
+// BoolMap converts a string map of bool values into a string map of bool pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func BoolMap(src map[string]bool) map[string]*bool { return conv.PointerMap(src) }
+
+// BoolValueMap converts a string map of bool pointers into a string map of bool values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func BoolValueMap(src map[string]*bool) map[string]bool { return conv.ValueMap(src) }
+
+// Int turn a pointer to of the int value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Int(v int) *int { return conv.Pointer(v) }
+
+// IntValue turn the value of the int pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func IntValue(v *int) int { return conv.Value(v) }
+
+// IntSlice converts a slice of int values into a slice of int pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func IntSlice(src []int) []*int { return conv.PointerSlice(src) }
+
+// IntValueSlice converts a slice of int pointers into a slice of int values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func IntValueSlice(src []*int) []int { return conv.ValueSlice(src) }
+
+// IntMap converts a string map of int values into a string map of int pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func IntMap(src map[string]int) map[string]*int { return conv.PointerMap(src) }
+
+// IntValueMap converts a string map of int pointers into a string map of int values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func IntValueMap(src map[string]*int) map[string]int { return conv.ValueMap(src) }
+
+// Int32 turn a pointer to of the int32 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Int32(v int32) *int32 { return conv.Pointer(v) }
+
+// Int32Value turn the value of the int32 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Int32Value(v *int32) int32 { return conv.Value(v) }
+
+// Int32Slice converts a slice of int32 values into a slice of int32 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Int32Slice(src []int32) []*int32 { return conv.PointerSlice(src) }
+
+// Int32ValueSlice converts a slice of int32 pointers into a slice of int32 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Int32ValueSlice(src []*int32) []int32 { return conv.ValueSlice(src) }
+
+// Int32Map converts a string map of int32 values into a string map of int32 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Int32Map(src map[string]int32) map[string]*int32 { return conv.PointerMap(src) }
+
+// Int32ValueMap converts a string map of int32 pointers into a string map of int32 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Int32ValueMap(src map[string]*int32) map[string]int32 { return conv.ValueMap(src) }
+
+// Int64 turn a pointer to of the int64 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Int64(v int64) *int64 { return conv.Pointer(v) }
+
+// Int64Value turn the value of the int64 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Int64Value(v *int64) int64 { return conv.Value(v) }
+
+// Int64Slice converts a slice of int64 values into a slice of int64 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Int64Slice(src []int64) []*int64 { return conv.PointerSlice(src) }
+
+// Int64ValueSlice converts a slice of int64 pointers into a slice of int64 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Int64ValueSlice(src []*int64) []int64 { return conv.ValueSlice(src) }
+
+// Int64Map converts a string map of int64 values into a string map of int64 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Int64Map(src map[string]int64) map[string]*int64 { return conv.PointerMap(src) }
+
+// Int64ValueMap converts a string map of int64 pointers into a string map of int64 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Int64ValueMap(src map[string]*int64) map[string]int64 { return conv.ValueMap(src) }
+
+// Uint16 turn a pointer to of the uint16 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Uint16(v uint16) *uint16 { return conv.Pointer(v) }
+
+// Uint16Value turn the value of the uint16 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Uint16Value(v *uint16) uint16 { return conv.Value(v) }
+
+// Uint16Slice converts a slice of uint16 values into a slice of uint16 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Uint16Slice(src []uint16) []*uint16 { return conv.PointerSlice(src) }
+
+// Uint16ValueSlice converts a slice of uint16 pointers into a slice of uint16 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Uint16ValueSlice(src []*uint16) []uint16 { return conv.ValueSlice(src) }
+
+// Uint16Map converts a string map of uint16 values into a string map of uint16 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Uint16Map(src map[string]uint16) map[string]*uint16 { return conv.PointerMap(src) }
+
+// Uint16ValueMap converts a string map of uint16 pointers into a string map of uint16 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Uint16ValueMap(src map[string]*uint16) map[string]uint16 { return conv.ValueMap(src) }
+
+// Uint turn a pointer to of the uint value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Uint(v uint) *uint { return conv.Pointer(v) }
+
+// UintValue turn the value of the uint pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func UintValue(v *uint) uint { return conv.Value(v) }
+
+// UintSlice converts a slice of uint values into a slice of uint pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func UintSlice(src []uint) []*uint { return conv.PointerSlice(src) }
+
+// UintValueSlice converts a slice of uint pointers into a slice of uint values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func UintValueSlice(src []*uint) []uint { return conv.ValueSlice(src) }
+
+// UintMap converts a string map of uint values into a string map of uint pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func UintMap(src map[string]uint) map[string]*uint { return conv.PointerMap(src) }
+
+// UintValueMap converts a string map of uint pointers into a string map of uint values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func UintValueMap(src map[string]*uint) map[string]uint { return conv.ValueMap(src) }
+
+// Uint32 turn a pointer to of the uint32 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Uint32(v uint32) *uint32 { return conv.Pointer(v) }
+
+// Uint32Value turn the value of the uint32 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Uint32Value(v *uint32) uint32 { return conv.Value(v) }
+
+// Uint32Slice converts a slice of uint32 values into a slice of uint32 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Uint32Slice(src []uint32) []*uint32 { return conv.PointerSlice(src) }
+
+// Uint32ValueSlice converts a slice of uint32 pointers into a slice of uint32 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Uint32ValueSlice(src []*uint32) []uint32 { return conv.ValueSlice(src) }
+
+// Uint32Map converts a string map of uint32 values into a string map of uint32 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Uint32Map(src map[string]uint32) map[string]*uint32 { return conv.PointerMap(src) }
+
+// Uint32ValueMap converts a string map of uint32 pointers into a string map of uint32 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Uint32ValueMap(src map[string]*uint32) map[string]uint32 { return conv.ValueMap(src) }
+
+// Uint64 turn a pointer to of the uint64 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Uint64(v uint64) *uint64 { return conv.Pointer(v) }
+
+// Uint64Value turn the value of the uint64 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Uint64Value(v *uint64) uint64 { return conv.Value(v) }
+
+// Uint64Slice converts a slice of uint64 values into a slice of uint64 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Uint64Slice(src []uint64) []*uint64 { return conv.PointerSlice(src) }
+
+// Uint64ValueSlice converts a slice of uint64 pointers into a slice of uint64 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Uint64ValueSlice(src []*uint64) []uint64 { return conv.ValueSlice(src) }
+
+// Uint64Map converts a string map of uint64 values into a string map of uint64 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Uint64Map(src map[string]uint64) map[string]*uint64 { return conv.PointerMap(src) }
+
+// Uint64ValueMap converts a string map of uint64 pointers into a string map of uint64 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Uint64ValueMap(src map[string]*uint64) map[string]uint64 { return conv.ValueMap(src) }
+
+// Float32 turn a pointer to of the float32 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Float32(v float32) *float32 { return conv.Pointer(v) }
+
+// Float32Value turn the value of the float32 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Float32Value(v *float32) float32 { return conv.Value(v) }
+
+// Float32Slice converts a slice of float32 values into a slice of float32 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Float32Slice(src []float32) []*float32 { return conv.PointerSlice(src) }
+
+// Float32ValueSlice converts a slice of float32 pointers into a slice of float32 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Float32ValueSlice(src []*float32) []float32 { return conv.ValueSlice(src) }
+
+// Float32Map converts a string map of float32 values into a string map of float32 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Float32Map(src map[string]float32) map[string]*float32 { return conv.PointerMap(src) }
+
+// Float32ValueMap converts a string map of float32 pointers into a string map of float32 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Float32ValueMap(src map[string]*float32) map[string]float32 { return conv.ValueMap(src) }
+
+// Float64 turn a pointer to of the float64 value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Float64(v float64) *float64 { return conv.Pointer(v) }
+
+// Float64Value turn the value of the float64 pointer passed in or 0 if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func Float64Value(v *float64) float64 { return conv.Value(v) }
+
+// Float64Slice converts a slice of float64 values into a slice of float64 pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func Float64Slice(src []float64) []*float64 { return conv.PointerSlice(src) }
+
+// Float64ValueSlice converts a slice of float64 pointers into a slice of float64 values.
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func Float64ValueSlice(src []*float64) []float64 { return conv.ValueSlice(src) }
+
+// Float64Map converts a string map of float64 values into a string map of float64 pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func Float64Map(src map[string]float64) map[string]*float64 { return conv.PointerMap(src) }
+
+// Float64ValueMap converts a string map of float64 pointers into a string map of float64 values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func Float64ValueMap(src map[string]*float64) map[string]float64 { return conv.ValueMap(src) }
+
+// Time turn a pointer to of the time.Time value passed in.
+//
+// Deprecated: use [conv.Pointer] instead.
+func Time(v time.Time) *time.Time { return conv.Pointer(v) }
+
+// TimeValue turn the value of the time.Time pointer passed in or time.Time{} if the pointer is nil.
+//
+// Deprecated: use [conv.Value] instead.
+func TimeValue(v *time.Time) time.Time { return conv.Value(v) }
+
+// TimeSlice converts a slice of time.Time values into a slice of time.Time pointers.
+//
+// Deprecated: use [conv.PointerSlice] instead.
+func TimeSlice(src []time.Time) []*time.Time { return conv.PointerSlice(src) }
+
+// TimeValueSlice converts a slice of time.Time pointers into a slice of time.Time values
+//
+// Deprecated: use [conv.ValueSlice] instead.
+func TimeValueSlice(src []*time.Time) []time.Time { return conv.ValueSlice(src) }
+
+// TimeMap converts a string map of time.Time values into a string map of time.Time pointers.
+//
+// Deprecated: use [conv.PointerMap] instead.
+func TimeMap(src map[string]time.Time) map[string]*time.Time { return conv.PointerMap(src) }
+
+// TimeValueMap converts a string map of time.Time pointers into a string map of time.Time values.
+//
+// Deprecated: use [conv.ValueMap] instead.
+func TimeValueMap(src map[string]*time.Time) map[string]time.Time { return conv.ValueMap(src) }
diff --git a/vendor/github.com/go-openapi/swag/doc.go b/vendor/github.com/go-openapi/swag/doc.go
new file mode 100644
index 000000000000..b54b57478af6
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/doc.go
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package swag contains a bunch of helper functions for go-openapi and go-swagger projects.
+//
+// You may also use it standalone for your projects.
+//
+// NOTE: all features that used to be exposed as package-level members (constants, variables,
+// functions and types) are now deprecated and are superseded by equivalent features in
+// more specialized sub-packages.
+// Moving forward, no additional feature will be added to the [swag] API directly at the root package level,
+// which remains there for backward-compatibility purposes.
+//
+// Child modules will continue to evolve or some new ones may be added in the future.
+//
+// # Modules
+//
+// - [cmdutils] utilities to work with CLIs
+//
+// - [conv] type conversion utilities
+//
+// - [fileutils] file utilities
+//
+// - [jsonname] JSON utilities
+//
+// - [jsonutils] JSON utilities
+//
+// - [loading] file loading
+//
+// - [mangling] safe name generation
+//
+// - [netutils] networking utilities
+//
+// - [stringutils] `string` utilities
+//
+// - [typeutils] `go` types utilities
+//
+// - [yamlutils] YAML utilities
+//
+// # Dependencies
+//
+// This repo has a few dependencies outside of the standard library:
+//
+// - YAML utilities depend on [go.yaml.in/yaml/v3]
+package swag
+
+//go:generate mockery
diff --git a/vendor/github.com/go-openapi/swag/fileutils/LICENSE b/vendor/github.com/go-openapi/swag/fileutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/fileutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/fileutils/doc.go b/vendor/github.com/go-openapi/swag/fileutils/doc.go
new file mode 100644
index 000000000000..859a200d8413
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/fileutils/doc.go
@@ -0,0 +1,10 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package fileutils exposes utilities to deal with files and paths.
+//
+// Currently, there is:
+// - [File] to represent an abstraction of an uploaded file.
+// For instance, this is used by [github.com/go-openapi/runtime.File].
+// - path search utilities (e.g. finding packages in the GO search path)
+package fileutils
diff --git a/vendor/github.com/go-openapi/swag/fileutils/file.go b/vendor/github.com/go-openapi/swag/fileutils/file.go
new file mode 100644
index 000000000000..5ad4cfaeafa4
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/fileutils/file.go
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package fileutils
+
+import "mime/multipart"
+
+// File represents an uploaded file.
+type File struct {
+ Data multipart.File
+ Header *multipart.FileHeader
+}
+
+// Read bytes from the file
+func (f *File) Read(p []byte) (n int, err error) {
+ return f.Data.Read(p)
+}
+
+// Close the file
+func (f *File) Close() error {
+ return f.Data.Close()
+}
diff --git a/vendor/github.com/go-openapi/swag/fileutils/path.go b/vendor/github.com/go-openapi/swag/fileutils/path.go
new file mode 100644
index 000000000000..dd09f690bf81
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/fileutils/path.go
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package fileutils
+
+import (
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+// GOPATHKey represents the env key for gopath
+const GOPATHKey = "GOPATH"
+
+// FindInSearchPath finds a package in a provided lists of paths
+func FindInSearchPath(searchPath, pkg string) string {
+ pathsList := filepath.SplitList(searchPath)
+ for _, path := range pathsList {
+ if evaluatedPath, err := filepath.EvalSymlinks(filepath.Join(path, "src", pkg)); err == nil {
+ if _, err := os.Stat(evaluatedPath); err == nil {
+ return evaluatedPath
+ }
+ }
+ }
+ return ""
+}
+
+// FindInGoSearchPath finds a package in the $GOPATH:$GOROOT
+//
+// Deprecated: this function is no longer relevant with modern go.
+// It uses [runtime.GOROOT] under the hood, which is deprecated as of go1.24.
+func FindInGoSearchPath(pkg string) string {
+ return FindInSearchPath(FullGoSearchPath(), pkg)
+}
+
+// FullGoSearchPath gets the search paths for finding packages
+//
+// Deprecated: this function is no longer relevant with modern go.
+// It uses [runtime.GOROOT] under the hood, which is deprecated as of go1.24.
+func FullGoSearchPath() string {
+ allPaths := os.Getenv(GOPATHKey)
+ if allPaths == "" {
+ allPaths = filepath.Join(os.Getenv("HOME"), "go")
+ }
+ if allPaths != "" {
+ allPaths = strings.Join([]string{allPaths, runtime.GOROOT()}, ":")
+ } else {
+ allPaths = runtime.GOROOT()
+ }
+ return allPaths
+}
diff --git a/vendor/github.com/go-openapi/swag/fileutils_iface.go b/vendor/github.com/go-openapi/swag/fileutils_iface.go
new file mode 100644
index 000000000000..f3e79a0e4bce
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/fileutils_iface.go
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import "github.com/go-openapi/swag/fileutils"
+
+// GOPATHKey represents the env key for gopath
+//
+// Deprecated: use [fileutils.GOPATHKey] instead.
+const GOPATHKey = fileutils.GOPATHKey
+
+// File represents an uploaded file.
+//
+// Deprecated: use [fileutils.File] instead.
+type File = fileutils.File
+
+// FindInSearchPath finds a package in a provided lists of paths.
+//
+// Deprecated: use [fileutils.FindInSearchPath] instead.
+func FindInSearchPath(searchPath, pkg string) string {
+ return fileutils.FindInSearchPath(searchPath, pkg)
+}
+
+// FindInGoSearchPath finds a package in the $GOPATH:$GOROOT
+//
+// Deprecated: use [fileutils.FindInGoSearchPath] instead.
+func FindInGoSearchPath(pkg string) string { return fileutils.FindInGoSearchPath(pkg) }
+
+// FullGoSearchPath gets the search paths for finding packages
+//
+// Deprecated: use [fileutils.FullGoSearchPath] instead.
+func FullGoSearchPath() string { return fileutils.FullGoSearchPath() }
diff --git a/vendor/github.com/go-openapi/swag/go.work b/vendor/github.com/go-openapi/swag/go.work
new file mode 100644
index 000000000000..1e537f0749b0
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/go.work
@@ -0,0 +1,20 @@
+use (
+ .
+ ./cmdutils
+ ./conv
+ ./fileutils
+ ./jsonname
+ ./jsonutils
+ ./jsonutils/adapters/easyjson
+ ./jsonutils/adapters/testintegration
+ ./jsonutils/adapters/testintegration/benchmarks
+ ./jsonutils/fixtures_test
+ ./loading
+ ./mangling
+ ./netutils
+ ./stringutils
+ ./typeutils
+ ./yamlutils
+)
+
+go 1.24.0
diff --git a/vendor/github.com/go-openapi/swag/go.work.sum b/vendor/github.com/go-openapi/swag/go.work.sum
new file mode 100644
index 000000000000..edaf71bb2b7b
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/go.work.sum
@@ -0,0 +1,9 @@
+github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
+github.com/go-openapi/testify/v2 v2.0.1/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
diff --git a/vendor/github.com/go-openapi/swag/jsonname/LICENSE b/vendor/github.com/go-openapi/swag/jsonname/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonname/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/jsonname/doc.go b/vendor/github.com/go-openapi/swag/jsonname/doc.go
new file mode 100644
index 000000000000..79232eaca476
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonname/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package jsonname is a provider of json property names from go properties.
+package jsonname
diff --git a/vendor/github.com/go-openapi/swag/jsonname/name_provider.go b/vendor/github.com/go-openapi/swag/jsonname/name_provider.go
new file mode 100644
index 000000000000..8eaf1bece8d6
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonname/name_provider.go
@@ -0,0 +1,138 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package jsonname
+
+import (
+ "reflect"
+ "strings"
+ "sync"
+)
+
+// DefaultJSONNameProvider is the default cache for types.
+var DefaultJSONNameProvider = NewNameProvider()
+
+// NameProvider represents an object capable of translating from go property names
+// to json property names.
+//
+// This type is thread-safe.
+//
+// See [github.com/go-openapi/jsonpointer.Pointer] for an example.
+type NameProvider struct {
+ lock *sync.Mutex
+ index map[reflect.Type]nameIndex
+}
+
+type nameIndex struct {
+ jsonNames map[string]string
+ goNames map[string]string
+}
+
+// NewNameProvider creates a new name provider
+func NewNameProvider() *NameProvider {
+ return &NameProvider{
+ lock: &sync.Mutex{},
+ index: make(map[reflect.Type]nameIndex),
+ }
+}
+
+func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) {
+ for i := 0; i < tpe.NumField(); i++ {
+ targetDes := tpe.Field(i)
+
+ if targetDes.PkgPath != "" { // unexported
+ continue
+ }
+
+ if targetDes.Anonymous { // walk embedded structures tree down first
+ buildnameIndex(targetDes.Type, idx, reverseIdx)
+ continue
+ }
+
+ if tag := targetDes.Tag.Get("json"); tag != "" {
+
+ parts := strings.Split(tag, ",")
+ if len(parts) == 0 {
+ continue
+ }
+
+ nm := parts[0]
+ if nm == "-" {
+ continue
+ }
+ if nm == "" { // empty string means we want to use the Go name
+ nm = targetDes.Name
+ }
+
+ idx[nm] = targetDes.Name
+ reverseIdx[targetDes.Name] = nm
+ }
+ }
+}
+
+func newNameIndex(tpe reflect.Type) nameIndex {
+ var idx = make(map[string]string, tpe.NumField())
+ var reverseIdx = make(map[string]string, tpe.NumField())
+
+ buildnameIndex(tpe, idx, reverseIdx)
+ return nameIndex{jsonNames: idx, goNames: reverseIdx}
+}
+
+// GetJSONNames gets all the json property names for a type
+func (n *NameProvider) GetJSONNames(subject any) []string {
+ n.lock.Lock()
+ defer n.lock.Unlock()
+ tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
+ names, ok := n.index[tpe]
+ if !ok {
+ names = n.makeNameIndex(tpe)
+ }
+
+ res := make([]string, 0, len(names.jsonNames))
+ for k := range names.jsonNames {
+ res = append(res, k)
+ }
+ return res
+}
+
+// GetJSONName gets the json name for a go property name
+func (n *NameProvider) GetJSONName(subject any, name string) (string, bool) {
+ tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
+ return n.GetJSONNameForType(tpe, name)
+}
+
+// GetJSONNameForType gets the json name for a go property name on a given type
+func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) {
+ n.lock.Lock()
+ defer n.lock.Unlock()
+ names, ok := n.index[tpe]
+ if !ok {
+ names = n.makeNameIndex(tpe)
+ }
+ nme, ok := names.goNames[name]
+ return nme, ok
+}
+
+// GetGoName gets the go name for a json property name
+func (n *NameProvider) GetGoName(subject any, name string) (string, bool) {
+ tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
+ return n.GetGoNameForType(tpe, name)
+}
+
+// GetGoNameForType gets the go name for a given type for a json property name
+func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) {
+ n.lock.Lock()
+ defer n.lock.Unlock()
+ names, ok := n.index[tpe]
+ if !ok {
+ names = n.makeNameIndex(tpe)
+ }
+ nme, ok := names.jsonNames[name]
+ return nme, ok
+}
+
+func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex {
+ names := newNameIndex(tpe)
+ n.index[tpe] = names
+ return names
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonname_iface.go b/vendor/github.com/go-openapi/swag/jsonname_iface.go
new file mode 100644
index 000000000000..303a007f6f4c
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonname_iface.go
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import (
+ "github.com/go-openapi/swag/jsonname"
+)
+
+// DefaultJSONNameProvider is the default cache for types
+//
+// Deprecated: use [jsonname.DefaultJSONNameProvider] instead.
+var DefaultJSONNameProvider = jsonname.DefaultJSONNameProvider
+
+// NameProvider represents an object capable of translating from go property names
+// to json property names.
+//
+// Deprecated: use [jsonname.NameProvider] instead.
+type NameProvider = jsonname.NameProvider
+
+// NewNameProvider creates a new name provider
+//
+// Deprecated: use [jsonname.NewNameProvider] instead.
+func NewNameProvider() *NameProvider { return jsonname.NewNameProvider() }
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/LICENSE b/vendor/github.com/go-openapi/swag/jsonutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/jsonutils/README.md b/vendor/github.com/go-openapi/swag/jsonutils/README.md
new file mode 100644
index 000000000000..d745cdb466e2
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/README.md
@@ -0,0 +1,108 @@
+ # jsonutils
+
+`jsonutils` exposes a few tools to work with JSON:
+
+- a fast, simple `Concat` to concatenate (not merge) JSON objects and arrays
+- `FromDynamicJSON` to convert a data structure into a "dynamic JSON" data structure
+- `ReadJSON` and `WriteJSON` behave like `json.Unmarshal` and `json.Marshal`,
+ with the ability to use another underlying serialization library through an `Adapter`
+ configured at runtime
+- a `JSONMapSlice` structure that may be used to store JSON objects with the order of keys maintained
+
+## Dynamic JSON
+
+We call "dynamic JSON" the go data structure that results from unmarshaling JSON like this:
+
+```go
+ var value any
+ jsonBytes := `{"a": 1, ... }`
+ _ = json.Unmarshal(jsonBytes, &value)
+```
+
+In this configuration, the standard library mappings are as follows:
+
+| JSON | go |
+|-----------|------------------|
+| `number` | `float64` |
+| `string` | `string` |
+| `boolean` | `bool` |
+| `null` | `nil` |
+| `object` | `map[string]any` |
+| `array` | `[]any` |
+
+## Map slices
+
+When using `JSONMapSlice`, the ordering of keys is ensured by replacing
+mappings to `map[string]any` by a `JSONMapSlice` which is an (ordered)
+slice of `JSONMapItem`s.
+
+Notice that a similar feature is available for YAML (see [`yamlutils`](../yamlutils)),
+with a `YAMLMapSlice` type based on the `JSONMapSlice`.
+
+`JSONMapSlice` is similar to an ordered map, but the keys are not retrieved
+in constant time.
+
+Another difference with the the above standard mappings is that numbers don't always map
+to a `float64`: if the value is a JSON integer, it unmarshals to `int64`.
+
+See also [some examples](https://pkg.go.dev/github.com/go-openapi/swag/jsonutils#pkg-examples)
+
+## Adapters
+
+`ReadJSON`, `WriteJSON` and `FromDynamicJSON` (which is a combination of the latter two)
+are wrappers on top of `json.Unmarshal` and `json.Marshal`.
+
+By default, the adapter merely wraps the standard library.
+
+The adapter may be used to register other JSON serialization libraries,
+possibly several ones at the same time.
+
+If the value passed is identified as an "ordered map" (i.e. implements `ifaces.Ordered`
+or `ifaces.SetOrdered`, the adapter favors the "ordered" JSON behavior and tries to
+find a registered implementation that support ordered keys in objects.
+
+Our standard library implementation supports this.
+
+As of `v0.25.0`, we support through such an adapter the popular `mailru/easyjson`
+library, which kicks in when the passed values support the `easyjson.Unmarshaler`
+or `easyjson.Marshaler` interfaces.
+
+In the future, we plan to add more similar libraries that compete on the go JSON
+serializers scene.
+
+## Registering an adapter
+
+In package `github.com/go-openapi/swag/easyjson/adapters`, several adapters are available.
+
+Each adapter is an independent go module. Hence you'll pick its dependencies only if you import it.
+
+At this moment we provide:
+* `stdlib`: JSON adapter based on the standard library
+* `easyjson`: JSON adapter based on the `github.com/mailru/easyjson`
+
+The adapters provide the basic `Marshal` and `Unmarshal` capabilities, plus an implementation
+of the `MapSlice` pattern.
+
+You may also build your own adapter based on your specific use-case. An adapter is not required to implement
+all capabilities.
+
+Every adapter comes with a `Register` function, possibly with some options, to register the adapter
+to a global registry.
+
+For example, to enable `easyjson` to be used in `ReadJSON` and `WriteJSON`, you would write something like:
+
+```go
+ import (
+ "github.com/go-openapi/swag/jsonutils/adapters"
+ easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
+ )
+
+ func init() {
+ easyjson.Register(adapters.Registry)
+ }
+```
+
+You may register several adapters. In this case, capability matching is evaluated from the last registered
+adapters (LIFO).
+
+## [Benchmarks](./adapters/testintegration/benchmarks/README.md)
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go
new file mode 100644
index 000000000000..76d3898fca5e
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go
@@ -0,0 +1,8 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package adapters exposes a registry of adapters to multiple
+// JSON serialization libraries.
+//
+// All interfaces are defined in package [ifaces.Adapter].
+package adapters
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go
new file mode 100644
index 000000000000..1fd43a1fad51
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package ifaces exposes all interfaces to work with adapters.
+package ifaces
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go
new file mode 100644
index 000000000000..7805e5e5e398
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go
@@ -0,0 +1,84 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package ifaces
+
+import (
+ _ "encoding/json" // for documentation purpose
+ "iter"
+)
+
+// Ordered knows how to iterate over the (key,value) pairs of a JSON object.
+type Ordered interface {
+ OrderedItems() iter.Seq2[string, any]
+}
+
+// SetOrdered knows how to append or update the keys of a JSON object,
+// given an iterator over (key,value) pairs.
+//
+// If the provided iterator is nil then the receiver should be set to nil.
+type SetOrdered interface {
+ SetOrderedItems(iter.Seq2[string, any])
+}
+
+// OrderedMap represent a JSON object (i.e. like a map[string,any]),
+// and knows how to serialize and deserialize JSON with the order of keys maintained.
+type OrderedMap interface {
+ Ordered
+ SetOrdered
+
+ OrderedMarshalJSON() ([]byte, error)
+ OrderedUnmarshalJSON([]byte) error
+}
+
+// MarshalAdapter behaves likes the standard library [json.Marshal].
+type MarshalAdapter interface {
+ Poolable
+
+ Marshal(any) ([]byte, error)
+}
+
+// OrderedMarshalAdapter behaves likes the standard library [json.Marshal], preserving the order of keys in objects.
+type OrderedMarshalAdapter interface {
+ Poolable
+
+ OrderedMarshal(Ordered) ([]byte, error)
+}
+
+// UnmarshalAdapter behaves likes the standard library [json.Unmarshal].
+type UnmarshalAdapter interface {
+ Poolable
+
+ Unmarshal([]byte, any) error
+}
+
+// OrderedUnmarshalAdapter behaves likes the standard library [json.Unmarshal], preserving the order of keys in objects.
+type OrderedUnmarshalAdapter interface {
+ Poolable
+
+ OrderedUnmarshal([]byte, SetOrdered) error
+}
+
+// Adapter exposes an interface like the standard [json] library.
+type Adapter interface {
+ MarshalAdapter
+ UnmarshalAdapter
+
+ OrderedAdapter
+}
+
+// OrderedAdapter exposes interfaces to process JSON and keep the order of object keys.
+type OrderedAdapter interface {
+ OrderedMarshalAdapter
+ OrderedUnmarshalAdapter
+ NewOrderedMap(capacity int) OrderedMap
+}
+
+type Poolable interface {
+ // Self-redeem: for [Adapter] s that are allocated from a pool.
+ // The [Adapter] must not be used after calling [Redeem].
+ Redeem()
+
+ // Reset the state of the [Adapter], if any.
+ Reset()
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go
new file mode 100644
index 000000000000..2d6c69f4e602
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package ifaces
+
+import (
+ "strings"
+)
+
+// Capability indicates what a JSON adapter is capable of.
+type Capability uint8
+
+const (
+ CapabilityMarshalJSON Capability = 1 << iota
+ CapabilityUnmarshalJSON
+ CapabilityOrderedMarshalJSON
+ CapabilityOrderedUnmarshalJSON
+ CapabilityOrderedMap
+)
+
+func (c Capability) String() string {
+ switch c {
+ case CapabilityMarshalJSON:
+ return "MarshalJSON"
+ case CapabilityUnmarshalJSON:
+ return "UnmarshalJSON"
+ case CapabilityOrderedMarshalJSON:
+ return "OrderedMarshalJSON"
+ case CapabilityOrderedUnmarshalJSON:
+ return "OrderedUnmarshalJSON"
+ case CapabilityOrderedMap:
+ return "OrderedMap"
+ default:
+ return ""
+ }
+}
+
+// Capabilities holds several unitary capability flags
+type Capabilities uint8
+
+// Has some capability flag enabled.
+func (c Capabilities) Has(capability Capability) bool {
+ return Capability(c)&capability > 0
+}
+
+func (c Capabilities) String() string {
+ var w strings.Builder
+
+ first := true
+ for _, capability := range []Capability{
+ CapabilityMarshalJSON,
+ CapabilityUnmarshalJSON,
+ CapabilityOrderedMarshalJSON,
+ CapabilityOrderedUnmarshalJSON,
+ CapabilityOrderedMap,
+ } {
+ if c.Has(capability) {
+ if !first {
+ w.WriteByte('|')
+ } else {
+ first = false
+ }
+ w.WriteString(capability.String())
+ }
+ }
+
+ return w.String()
+}
+
+const (
+ AllCapabilities Capabilities = Capabilities(uint8(CapabilityMarshalJSON) |
+ uint8(CapabilityUnmarshalJSON) |
+ uint8(CapabilityOrderedMarshalJSON) |
+ uint8(CapabilityOrderedUnmarshalJSON) |
+ uint8(CapabilityOrderedMap))
+
+ AllUnorderedCapabilities Capabilities = Capabilities(uint8(CapabilityMarshalJSON) | uint8(CapabilityUnmarshalJSON))
+)
+
+// RegistryEntry describes how any given adapter registers its capabilities to the [Registrar].
+type RegistryEntry struct {
+ Who string
+ What Capabilities
+ Constructor func() Adapter
+ Support func(what Capability, value any) bool
+}
+
+// Registrar is a type that knows how to keep registration calls from adapters.
+type Registrar interface {
+ RegisterFor(RegistryEntry)
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go
new file mode 100644
index 000000000000..3062acaff261
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go
@@ -0,0 +1,229 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package adapters
+
+import (
+ "fmt"
+ "reflect"
+ "slices"
+ "sync"
+
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+ stdlib "github.com/go-openapi/swag/jsonutils/adapters/stdlib/json"
+)
+
+// Registry holds the global registry for registered adapters.
+var Registry = NewRegistrar()
+
+var (
+ defaultRegistered = stdlib.Register
+
+ _ ifaces.Registrar = &Registrar{}
+)
+
+type registryError string
+
+func (e registryError) Error() string {
+ return string(e)
+}
+
+// ErrRegistry indicates an error returned by the [Registrar].
+var ErrRegistry registryError = "JSON adapters registry error"
+
+type registry []*ifaces.RegistryEntry
+
+// Registrar holds registered [ifaces.Adapters] for different serialization capabilities.
+//
+// Internally, it maintains a cache for data types that favor a given adapter.
+type Registrar struct {
+ marshalerRegistry registry
+ unmarshalerRegistry registry
+ orderedMarshalerRegistry registry
+ orderedUnmarshalerRegistry registry
+ orderedMapRegistry registry
+
+ gmx sync.RWMutex
+
+ // cache indexed by value type, so we don't have to lookup
+ marshalerCache map[reflect.Type]*ifaces.RegistryEntry
+ unmarshalerCache map[reflect.Type]*ifaces.RegistryEntry
+ orderedMarshalerCache map[reflect.Type]*ifaces.RegistryEntry
+ orderedUnmarshalerCache map[reflect.Type]*ifaces.RegistryEntry
+ orderedMapCache map[reflect.Type]*ifaces.RegistryEntry
+}
+
+func NewRegistrar() *Registrar {
+ r := &Registrar{}
+
+ r.marshalerRegistry = make(registry, 0, 1)
+ r.unmarshalerRegistry = make(registry, 0, 1)
+ r.orderedMarshalerRegistry = make(registry, 0, 1)
+ r.orderedUnmarshalerRegistry = make(registry, 0, 1)
+ r.orderedMapRegistry = make(registry, 0, 1)
+
+ r.marshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
+ r.unmarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
+ r.orderedMarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
+ r.orderedUnmarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
+ r.orderedMapCache = make(map[reflect.Type]*ifaces.RegistryEntry)
+
+ defaultRegistered(r)
+
+ return r
+}
+
+// ClearCache resets the internal type cache.
+func (r *Registrar) ClearCache() {
+ r.gmx.Lock()
+ r.clearCache()
+ r.gmx.Unlock()
+}
+
+// Reset the [Registrar] to its defaults.
+func (r *Registrar) Reset() {
+ r.gmx.Lock()
+ r.clearCache()
+ r.marshalerRegistry = r.marshalerRegistry[:0]
+ r.unmarshalerRegistry = r.unmarshalerRegistry[:0]
+ r.orderedMarshalerRegistry = r.orderedMarshalerRegistry[:0]
+ r.orderedUnmarshalerRegistry = r.orderedUnmarshalerRegistry[:0]
+ r.orderedMapRegistry = r.orderedMapRegistry[:0]
+ r.gmx.Unlock()
+
+ defaultRegistered(r)
+}
+
+// RegisterFor registers an adapter for some JSON capabilities.
+func (r *Registrar) RegisterFor(entry ifaces.RegistryEntry) {
+ r.gmx.Lock()
+ if entry.What.Has(ifaces.CapabilityMarshalJSON) {
+ e := entry
+ e.What &= ifaces.Capabilities(ifaces.CapabilityMarshalJSON)
+ r.marshalerRegistry = slices.Insert(r.marshalerRegistry, 0, &e)
+ }
+ if entry.What.Has(ifaces.CapabilityUnmarshalJSON) {
+ e := entry
+ e.What &= ifaces.Capabilities(ifaces.CapabilityUnmarshalJSON)
+ r.unmarshalerRegistry = slices.Insert(r.unmarshalerRegistry, 0, &e)
+ }
+ if entry.What.Has(ifaces.CapabilityOrderedMarshalJSON) {
+ e := entry
+ e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedMarshalJSON)
+ r.orderedMarshalerRegistry = slices.Insert(r.orderedMarshalerRegistry, 0, &e)
+ }
+ if entry.What.Has(ifaces.CapabilityOrderedUnmarshalJSON) {
+ e := entry
+ e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedUnmarshalJSON)
+ r.orderedUnmarshalerRegistry = slices.Insert(r.orderedUnmarshalerRegistry, 0, &e)
+ }
+ if entry.What.Has(ifaces.CapabilityOrderedMap) {
+ e := entry
+ e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedMap)
+ r.orderedMapRegistry = slices.Insert(r.orderedMapRegistry, 0, &e)
+ }
+ r.gmx.Unlock()
+}
+
+// AdapterFor returns an [ifaces.Adapter] that supports this capability for this type of value.
+//
+// The [ifaces.Adapter] may be redeemed to its pool using its Redeem() method, for adapters that support global
+// pooling. When this is not the case, the redeem function is just a no-operation.
+func (r *Registrar) AdapterFor(capability ifaces.Capability, value any) ifaces.Adapter {
+ entry := r.findFirstFor(capability, value)
+ if entry == nil {
+ return nil
+ }
+
+ return entry.Constructor()
+}
+
+func (r *Registrar) clearCache() {
+ clear(r.marshalerCache)
+ clear(r.unmarshalerCache)
+ clear(r.orderedMarshalerCache)
+ clear(r.orderedUnmarshalerCache)
+ clear(r.orderedMapCache)
+}
+
+func (r *Registrar) findFirstFor(capability ifaces.Capability, value any) *ifaces.RegistryEntry {
+ switch capability {
+ case ifaces.CapabilityMarshalJSON:
+ return r.findFirstInRegistryFor(r.marshalerRegistry, r.marshalerCache, capability, value)
+ case ifaces.CapabilityUnmarshalJSON:
+ return r.findFirstInRegistryFor(r.unmarshalerRegistry, r.unmarshalerCache, capability, value)
+ case ifaces.CapabilityOrderedMarshalJSON:
+ return r.findFirstInRegistryFor(r.orderedMarshalerRegistry, r.orderedMarshalerCache, capability, value)
+ case ifaces.CapabilityOrderedUnmarshalJSON:
+ return r.findFirstInRegistryFor(r.orderedUnmarshalerRegistry, r.orderedUnmarshalerCache, capability, value)
+ case ifaces.CapabilityOrderedMap:
+ return r.findFirstInRegistryFor(r.orderedMapRegistry, r.orderedMapCache, capability, value)
+ default:
+ panic(fmt.Errorf("unsupported capability %d: %w", capability, ErrRegistry))
+ }
+}
+
+func (r *Registrar) findFirstInRegistryFor(reg registry, cache map[reflect.Type]*ifaces.RegistryEntry, capability ifaces.Capability, value any) *ifaces.RegistryEntry {
+ r.gmx.RLock()
+ if len(reg) > 1 {
+ if entry, ok := cache[reflect.TypeOf(value)]; ok {
+ // cache hit
+ r.gmx.RUnlock()
+ return entry
+ }
+ }
+
+ for _, entry := range reg {
+ if !entry.Support(capability, value) {
+ continue
+ }
+
+ r.gmx.RUnlock()
+
+ // update the internal cache
+ r.gmx.Lock()
+ cache[reflect.TypeOf(value)] = entry
+ r.gmx.Unlock()
+
+ return entry
+ }
+
+ // no adapter found
+ r.gmx.RUnlock()
+
+ return nil
+}
+
+// MarshalAdapterFor returns the first adapter that knows how to Marshal this type of value.
+func MarshalAdapterFor(value any) ifaces.MarshalAdapter {
+ return Registry.AdapterFor(ifaces.CapabilityMarshalJSON, value)
+}
+
+// OrderedMarshalAdapterFor returns the first adapter that knows how to OrderedMarshal this type of value.
+func OrderedMarshalAdapterFor(value ifaces.Ordered) ifaces.OrderedMarshalAdapter {
+ return Registry.AdapterFor(ifaces.CapabilityOrderedMarshalJSON, value)
+}
+
+// UnmarshalAdapterFor returns the first adapter that knows how to Unmarshal this type of value.
+func UnmarshalAdapterFor(value any) ifaces.UnmarshalAdapter {
+ return Registry.AdapterFor(ifaces.CapabilityUnmarshalJSON, value)
+}
+
+// OrderedUnmarshalAdapterFor provides the first adapter that knows how to OrderedUnmarshal this type of value.
+func OrderedUnmarshalAdapterFor(value ifaces.SetOrdered) ifaces.OrderedUnmarshalAdapter {
+ return Registry.AdapterFor(ifaces.CapabilityOrderedUnmarshalJSON, value)
+}
+
+// NewOrderedMap provides the "ordered map" implementation provided by the registry.
+func NewOrderedMap(capacity int) ifaces.OrderedMap {
+ var v any
+ adapter := Registry.AdapterFor(ifaces.CapabilityOrderedUnmarshalJSON, v)
+ if adapter == nil {
+ return nil
+ }
+
+ defer adapter.Redeem()
+ return adapter.NewOrderedMap(capacity)
+}
+
+func noopRedeemer() {}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go
new file mode 100644
index 000000000000..0213ff5c29f1
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go
@@ -0,0 +1,115 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package json
+
+import (
+ stdjson "encoding/json"
+
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+ "github.com/go-openapi/swag/typeutils"
+)
+
+const sensibleBufferSize = 8192
+
+type jsonError string
+
+func (e jsonError) Error() string {
+ return string(e)
+}
+
+// ErrStdlib indicates that an error comes from the stdlib JSON adapter
+var ErrStdlib jsonError = "error from the JSON adapter stdlib"
+
+var _ ifaces.Adapter = &Adapter{}
+
+type Adapter struct {
+}
+
+// NewAdapter yields an [ifaces.Adapter] using the standard library.
+func NewAdapter() *Adapter {
+ return &Adapter{}
+}
+
+func (a *Adapter) Marshal(value any) ([]byte, error) {
+ return stdjson.Marshal(value)
+}
+
+func (a *Adapter) Unmarshal(data []byte, value any) error {
+ return stdjson.Unmarshal(data, value)
+}
+
+func (a *Adapter) OrderedMarshal(value ifaces.Ordered) ([]byte, error) {
+ w := poolOfWriters.Borrow()
+ defer func() {
+ poolOfWriters.Redeem(w)
+ }()
+
+ if typeutils.IsNil(value) {
+ w.RawString("null")
+
+ return w.BuildBytes()
+ }
+
+ w.RawByte('{')
+ first := true
+ for k, v := range value.OrderedItems() {
+ if first {
+ first = false
+ } else {
+ w.RawByte(',')
+ }
+
+ w.String(k)
+ w.RawByte(':')
+
+ switch val := v.(type) {
+ case ifaces.Ordered:
+ w.Raw(a.OrderedMarshal(val))
+ default:
+ w.Raw(stdjson.Marshal(v))
+ }
+ }
+
+ w.RawByte('}')
+
+ return w.BuildBytes()
+}
+
+func (a *Adapter) OrderedUnmarshal(data []byte, value ifaces.SetOrdered) error {
+ var m MapSlice
+ if err := m.OrderedUnmarshalJSON(data); err != nil {
+ return err
+ }
+
+ if typeutils.IsNil(m) {
+ // force input value to nil
+ value.SetOrderedItems(nil)
+
+ return nil
+ }
+
+ value.SetOrderedItems(m.OrderedItems())
+
+ return nil
+}
+
+func (a *Adapter) NewOrderedMap(capacity int) ifaces.OrderedMap {
+ m := make(MapSlice, 0, capacity)
+
+ return &m
+}
+
+// Redeem the [Adapter] when it comes from a pool.
+//
+// The adapter becomes immediately unusable once redeemed.
+func (a *Adapter) Redeem() {
+ if a == nil {
+ return
+ }
+
+ RedeemAdapter(a)
+}
+
+func (a *Adapter) Reset() {
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go
new file mode 100644
index 000000000000..5ea1b4404252
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package json implements an [ifaces.Adapter] using the standard library.
+package json
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go
new file mode 100644
index 000000000000..b5aa1c7972e7
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go
@@ -0,0 +1,320 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package json
+
+import (
+ stdjson "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "strconv"
+
+ "github.com/go-openapi/swag/conv"
+)
+
+type token struct {
+ stdjson.Token
+}
+
+func (t token) String() string {
+ if t == invalidToken {
+ return "invalid token"
+ }
+ if t == eofToken {
+ return "EOF"
+ }
+
+ return fmt.Sprintf("%v", t.Token)
+}
+
+func (t token) Kind() tokenKind {
+ switch t.Token.(type) {
+ case nil:
+ return tokenNull
+ case stdjson.Delim:
+ return tokenDelim
+ case bool:
+ return tokenBool
+ case float64:
+ return tokenFloat
+ case stdjson.Number:
+ return tokenNumber
+ case string:
+ return tokenString
+ default:
+ return tokenUndef
+ }
+}
+
+func (t token) Delim() byte {
+ r, ok := t.Token.(stdjson.Delim)
+ if !ok {
+ return 0
+ }
+
+ return byte(r)
+}
+
+type tokenKind uint8
+
+const (
+ tokenUndef tokenKind = iota
+ tokenString
+ tokenNumber
+ tokenFloat
+ tokenBool
+ tokenNull
+ tokenDelim
+)
+
+var (
+ invalidToken = token{
+ Token: stdjson.Token(struct{}{}),
+ }
+
+ eofToken = token{
+ Token: stdjson.Token(&struct{}{}),
+ }
+
+ undefToken = token{
+ Token: stdjson.Token(uint8(0)),
+ }
+)
+
+// jlexer apes easyjson's jlexer, but uses the standard library decoder under the hood.
+type jlexer struct {
+ buf *bytesReader
+ dec *stdjson.Decoder
+ err error
+ // current token
+ next token
+ // started bool
+}
+
+type bytesReader struct {
+ buf []byte
+ offset int
+}
+
+func (b *bytesReader) Reset() {
+ b.buf = nil
+ b.offset = 0
+}
+
+func (b *bytesReader) Read(p []byte) (int, error) {
+ if b.offset >= len(b.buf) {
+ return 0, io.EOF
+ }
+
+ n := len(p)
+ buf := b.buf[b.offset:]
+ m := len(buf)
+
+ if n >= m {
+ copy(p, buf)
+ b.offset += m
+
+ return m, nil
+ }
+
+ copy(p, buf[:n])
+ b.offset += n
+
+ return n, nil
+}
+
+var _ io.Reader = &bytesReader{}
+
+func newLexer(data []byte) *jlexer {
+ l := &jlexer{
+ // current: undefToken,
+ next: undefToken,
+ }
+ l.buf = &bytesReader{
+ buf: data,
+ }
+ l.dec = stdjson.NewDecoder(l.buf) // unfortunately, cannot pool this
+
+ return l
+}
+
+func (l *jlexer) Reset() {
+ l.err = nil
+ l.next = undefToken
+ // leave l.dec and l.buf alone, since they are replaced at every Borrow
+}
+
+func (l *jlexer) Error() error {
+ return l.err
+}
+
+func (l *jlexer) SetErr(err error) {
+ l.err = err
+}
+
+func (l *jlexer) Ok() bool {
+ return l.err == nil
+}
+
+// NextToken consumes a token
+func (l *jlexer) NextToken() token {
+ if !l.Ok() {
+ return invalidToken
+ }
+
+ if l.next != undefToken {
+ next := l.next
+ l.next = undefToken
+
+ return next
+ }
+
+ return l.fetchToken()
+}
+
+// PeekToken returns the next token without consuming it
+func (l *jlexer) PeekToken() token {
+ if l.next == undefToken {
+ l.next = l.fetchToken()
+ }
+
+ return l.next
+}
+
+func (l *jlexer) Skip() {
+ _ = l.NextToken()
+}
+
+func (l *jlexer) IsDelim(c byte) bool {
+ if !l.Ok() {
+ return false
+ }
+
+ next := l.PeekToken()
+ if next.Kind() != tokenDelim {
+ return false
+ }
+
+ if next.Delim() != c {
+ return false
+ }
+
+ return true
+}
+
+func (l *jlexer) IsNull() bool {
+ if !l.Ok() {
+ return false
+ }
+
+ next := l.PeekToken()
+
+ return next.Kind() == tokenNull
+}
+
+func (l *jlexer) Delim(c byte) {
+ if !l.Ok() {
+ return
+ }
+
+ tok := l.NextToken()
+ if tok.Kind() != tokenDelim {
+ l.err = fmt.Errorf("expected a delimiter token but got '%v': %w", tok, ErrStdlib)
+
+ return
+ }
+
+ if tok.Delim() != c {
+ l.err = fmt.Errorf("expected delimiter '%q' but got '%q': %w", c, tok.Delim(), ErrStdlib)
+ }
+}
+
+func (l *jlexer) Null() {
+ if !l.Ok() {
+ return
+ }
+
+ tok := l.NextToken()
+ if tok.Kind() != tokenNull {
+ l.err = fmt.Errorf("expected a null token but got '%v': %w", tok, ErrStdlib)
+ }
+}
+
+func (l *jlexer) Number() any {
+ if !l.Ok() {
+ return 0
+ }
+
+ tok := l.NextToken()
+
+ switch tok.Kind() { //nolint:exhaustive
+ case tokenNumber:
+ n := tok.Token.(stdjson.Number).String()
+ f, _ := strconv.ParseFloat(n, 64)
+ if conv.IsFloat64AJSONInteger(f) {
+ return int64(math.Trunc(f))
+ }
+
+ return f
+
+ case tokenFloat:
+ f := tok.Token.(float64)
+ if conv.IsFloat64AJSONInteger(f) {
+ return int64(math.Trunc(f))
+ }
+
+ return f
+
+ default:
+ l.err = fmt.Errorf("expected a number token but got '%v': %w", tok, ErrStdlib)
+
+ return 0
+ }
+}
+
+func (l *jlexer) Bool() bool {
+ if !l.Ok() {
+ return false
+ }
+
+ tok := l.NextToken()
+ if tok.Kind() != tokenBool {
+ l.err = fmt.Errorf("expected a bool token but got '%v': %w", tok, ErrStdlib)
+
+ return false
+ }
+
+ return tok.Token.(bool)
+}
+
+func (l *jlexer) String() string {
+ if !l.Ok() {
+ return ""
+ }
+
+ tok := l.NextToken()
+ if tok.Kind() != tokenString {
+ l.err = fmt.Errorf("expected a string token but got '%v': %w", tok, ErrStdlib)
+
+ return ""
+ }
+
+ return tok.Token.(string)
+}
+
+// Commas and colons are elided.
+func (l *jlexer) fetchToken() token {
+ jtok, err := l.dec.Token()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return eofToken
+ }
+
+ l.err = errors.Join(err, ErrStdlib)
+ return invalidToken
+ }
+
+ return token{Token: jtok}
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go
new file mode 100644
index 000000000000..54deef406f33
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go
@@ -0,0 +1,266 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package json
+
+import (
+ stdjson "encoding/json"
+ "fmt"
+ "iter"
+
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+)
+
+var _ ifaces.OrderedMap = &MapSlice{}
+
+// MapSlice represents a JSON object, with the order of keys maintained.
+type MapSlice []MapItem
+
+func (s MapSlice) OrderedItems() iter.Seq2[string, any] {
+ return func(yield func(string, any) bool) {
+ for _, item := range s {
+ if !yield(item.Key, item.Value) {
+ return
+ }
+ }
+ }
+}
+
+func (s *MapSlice) SetOrderedItems(items iter.Seq2[string, any]) {
+ if items == nil {
+ *s = nil
+
+ return
+ }
+
+ m := *s
+ if len(m) > 0 {
+ // update mode
+ idx := make(map[string]int, len(m))
+
+ for i, item := range m {
+ idx[item.Key] = i
+ }
+
+ for k, v := range items {
+ idx, ok := idx[k]
+ if ok {
+ m[idx].Value = v
+
+ continue
+ }
+ m = append(m, MapItem{Key: k, Value: v})
+ }
+
+ *s = m
+
+ return
+ }
+
+ for k, v := range items {
+ m = append(m, MapItem{Key: k, Value: v})
+ }
+
+ *s = m
+}
+
+// MarshalJSON renders a [MapSlice] as JSON bytes, preserving the order of keys.
+func (s MapSlice) MarshalJSON() ([]byte, error) {
+ return s.OrderedMarshalJSON()
+}
+
+func (s MapSlice) OrderedMarshalJSON() ([]byte, error) {
+ w := poolOfWriters.Borrow()
+ defer func() {
+ poolOfWriters.Redeem(w)
+ }()
+
+ s.marshalObject(w)
+
+ return w.BuildBytes() // this clones data, so it's okay to redeem the writer and its buffer
+}
+
+// UnmarshalJSON builds a [MapSlice] from JSON bytes, preserving the order of keys.
+//
+// Inner objects are unmarshaled as [MapSlice] slices and not map[string]any.
+func (s *MapSlice) UnmarshalJSON(data []byte) error {
+ return s.OrderedUnmarshalJSON(data)
+}
+
+func (s *MapSlice) OrderedUnmarshalJSON(data []byte) error {
+ l := poolOfLexers.Borrow(data)
+ defer func() {
+ poolOfLexers.Redeem(l)
+ }()
+
+ s.unmarshalObject(l)
+
+ return l.Error()
+}
+
+func (s MapSlice) marshalObject(w *jwriter) {
+ if s == nil {
+ w.RawString("null")
+
+ return
+ }
+
+ w.RawByte('{')
+
+ if len(s) == 0 {
+ w.RawByte('}')
+
+ return
+ }
+
+ s[0].marshalJSON(w)
+
+ for i := 1; i < len(s); i++ {
+ w.RawByte(',')
+ s[i].marshalJSON(w)
+ }
+
+ w.RawByte('}')
+}
+
+func (s *MapSlice) unmarshalObject(in *jlexer) {
+ if in.IsNull() {
+ in.Skip()
+
+ return
+ }
+
+ in.Delim('{') // consume token
+ if !in.Ok() {
+ return
+ }
+
+ result := make(MapSlice, 0)
+
+ for in.Ok() && !in.IsDelim('}') {
+ var mi MapItem
+
+ mi.unmarshalKeyValue(in)
+ result = append(result, mi)
+ }
+
+ in.Delim('}')
+
+ if !in.Ok() {
+ return
+ }
+
+ *s = result
+}
+
+// MapItem represents the value of a key in a JSON object held by [MapSlice].
+//
+// Notice that [MapItem] should not be marshaled to or unmarshaled from JSON directly,
+// use this type as part of a [MapSlice] when dealing with JSON bytes.
+type MapItem struct {
+ Key string
+ Value any
+}
+
+func (s MapItem) marshalJSON(w *jwriter) {
+ w.String(s.Key)
+ w.RawByte(':')
+ w.Raw(stdjson.Marshal(s.Value))
+}
+
+func (s *MapItem) unmarshalKeyValue(in *jlexer) {
+ key := in.String() // consume string
+ value := s.asInterface(in) // consume any value, including termination tokens '}' or ']'
+
+ if !in.Ok() {
+ return
+ }
+
+ s.Key = key
+ s.Value = value
+}
+
+func (s *MapItem) unmarshalArray(in *jlexer) []any {
+ if in.IsNull() {
+ in.Skip()
+
+ return nil
+ }
+
+ in.Delim('[') // consume token
+ if !in.Ok() {
+ return nil
+ }
+
+ ret := make([]any, 0)
+
+ for in.Ok() && !in.IsDelim(']') {
+ ret = append(ret, s.asInterface(in))
+ }
+
+ in.Delim(']')
+ if !in.Ok() {
+ return nil
+ }
+
+ return ret
+}
+
+// asInterface is very much like [jlexer.Lexer.Interface], but unmarshals an object
+// into a [MapSlice], not a map[string]any.
+//
+// We have to force parsing errors somehow, since [jlexer.Lexer] doesn't let us
+// set a parsing error directly.
+func (s *MapItem) asInterface(in *jlexer) any {
+ if !in.Ok() {
+ return nil
+ }
+
+ tok := in.PeekToken() // look-ahead what the next token looks like
+ kind := tok.Kind()
+
+ switch kind {
+ case tokenString:
+ return in.String() // consume string
+
+ case tokenNumber, tokenFloat:
+ return in.Number()
+
+ case tokenBool:
+ return in.Bool()
+
+ case tokenNull:
+ in.Null()
+
+ return nil
+
+ case tokenDelim:
+ switch tok.Delim() {
+ case '{': // not consumed yet
+ ret := make(MapSlice, 0)
+ ret.unmarshalObject(in) // consumes the terminating '}'
+
+ if in.Ok() {
+ return ret
+ }
+
+ // lexer is in an error state: will exhaust
+ return nil
+
+ case '[': // not consumed yet
+ return s.unmarshalArray(in) // consumes the terminating ']'
+ default:
+ in.SetErr(fmt.Errorf("unexpected delimiter: %v: %w", tok, ErrStdlib)) // force error
+ return nil
+ }
+
+ case tokenUndef:
+ fallthrough
+ default:
+ if in.Ok() {
+ in.SetErr(fmt.Errorf("unexpected token: %v: %w", tok, ErrStdlib)) // force error
+ }
+
+ return nil
+ }
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go
new file mode 100644
index 000000000000..709b97c3046b
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go
@@ -0,0 +1,143 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package json
+
+import (
+ "encoding/json"
+ "sync"
+
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+)
+
+type adaptersPool struct {
+ sync.Pool
+}
+
+func (p *adaptersPool) Borrow() *Adapter {
+ return p.Get().(*Adapter)
+}
+
+func (p *adaptersPool) BorrowIface() ifaces.Adapter {
+ return p.Get().(*Adapter)
+}
+
+func (p *adaptersPool) Redeem(a *Adapter) {
+ p.Put(a)
+}
+
+type writersPool struct {
+ sync.Pool
+}
+
+func (p *writersPool) Borrow() *jwriter {
+ ptr := p.Get()
+
+ jw := ptr.(*jwriter)
+ jw.Reset()
+
+ return jw
+}
+
+func (p *writersPool) Redeem(w *jwriter) {
+ p.Put(w)
+}
+
+type lexersPool struct {
+ sync.Pool
+}
+
+func (p *lexersPool) Borrow(data []byte) *jlexer {
+ ptr := p.Get()
+
+ l := ptr.(*jlexer)
+ l.buf = poolOfReaders.Borrow(data)
+ l.dec = json.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API
+ l.Reset()
+
+ return l
+}
+
+func (p *lexersPool) Redeem(l *jlexer) {
+ l.dec = nil
+ discard := l.buf
+ l.buf = nil
+ poolOfReaders.Redeem(discard)
+ p.Put(l)
+}
+
+type readersPool struct {
+ sync.Pool
+}
+
+func (p *readersPool) Borrow(data []byte) *bytesReader {
+ ptr := p.Get()
+
+ b := ptr.(*bytesReader)
+ b.Reset()
+ b.buf = data
+
+ return b
+}
+
+func (p *readersPool) Redeem(b *bytesReader) {
+ p.Put(b)
+}
+
+var (
+ poolOfAdapters = &adaptersPool{
+ Pool: sync.Pool{
+ New: func() any {
+ return NewAdapter()
+ },
+ },
+ }
+
+ poolOfWriters = &writersPool{
+ Pool: sync.Pool{
+ New: func() any {
+ return newJWriter()
+ },
+ },
+ }
+
+ poolOfLexers = &lexersPool{
+ Pool: sync.Pool{
+ New: func() any {
+ return newLexer(nil)
+ },
+ },
+ }
+
+ poolOfReaders = &readersPool{
+ Pool: sync.Pool{
+ New: func() any {
+ return &bytesReader{}
+ },
+ },
+ }
+)
+
+// BorrowAdapter borrows an [Adapter] from the pool, recycling already allocated instances.
+func BorrowAdapter() *Adapter {
+ return poolOfAdapters.Borrow()
+}
+
+// BorrowAdapterIface borrows a stdlib [Adapter] and converts it directly
+// to [ifaces.Adapter]. This is useful to avoid further allocations when
+// translating the concrete type into an interface.
+func BorrowAdapterIface() ifaces.Adapter {
+ return poolOfAdapters.BorrowIface()
+}
+
+// RedeemAdapter redeems an [Adapter] to the pool, so it may be recycled.
+func RedeemAdapter(a *Adapter) {
+ poolOfAdapters.Redeem(a)
+}
+
+func RedeemAdapterIface(a ifaces.Adapter) {
+ concrete, ok := a.(*Adapter)
+ if ok {
+ poolOfAdapters.Redeem(concrete)
+ }
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go
new file mode 100644
index 000000000000..fc8818694eae
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package json
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+)
+
+func Register(dispatcher ifaces.Registrar) {
+ t := reflect.TypeOf(Adapter{})
+ dispatcher.RegisterFor(
+ ifaces.RegistryEntry{
+ Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()),
+ What: ifaces.AllCapabilities,
+ Constructor: BorrowAdapterIface,
+ Support: support,
+ })
+}
+
+func support(_ ifaces.Capability, _ any) bool {
+ return true
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go
new file mode 100644
index 000000000000..dc2325c1a30f
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go
@@ -0,0 +1,75 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "strings"
+)
+
+type jwriter struct {
+ buf *bytes.Buffer
+ err error
+}
+
+func newJWriter() *jwriter {
+ buf := make([]byte, 0, sensibleBufferSize)
+
+ return &jwriter{buf: bytes.NewBuffer(buf)}
+}
+
+func (w *jwriter) Reset() {
+ w.buf.Reset()
+ w.err = nil
+}
+
+func (w *jwriter) RawString(s string) {
+ if w.err != nil {
+ return
+ }
+ w.buf.WriteString(s)
+}
+
+func (w *jwriter) Raw(b []byte, err error) {
+ if w.err != nil {
+ return
+ }
+ if err != nil {
+ w.err = err
+ return
+ }
+
+ _, _ = w.buf.Write(b)
+}
+
+func (w *jwriter) RawByte(c byte) {
+ if w.err != nil {
+ return
+ }
+ w.buf.WriteByte(c)
+}
+
+var quoteReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`)
+
+func (w *jwriter) String(s string) {
+ if w.err != nil {
+ return
+ }
+ // escape quotes and \
+ s = quoteReplacer.Replace(s)
+
+ _ = w.buf.WriteByte('"')
+ json.HTMLEscape(w.buf, []byte(s))
+ _ = w.buf.WriteByte('"')
+}
+
+// BuildBytes returns a clone of the internal buffer.
+func (w *jwriter) BuildBytes() ([]byte, error) {
+ if w.err != nil {
+ return nil, w.err
+ }
+
+ return bytes.Clone(w.buf.Bytes()), nil
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/concat.go b/vendor/github.com/go-openapi/swag/jsonutils/concat.go
new file mode 100644
index 000000000000..2068503af05b
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/concat.go
@@ -0,0 +1,92 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package jsonutils
+
+import (
+ "bytes"
+)
+
+// nullJSON represents a JSON object with null type
+var nullJSON = []byte("null")
+
+const comma = byte(',')
+
+var closers map[byte]byte
+
+func init() {
+ closers = map[byte]byte{
+ '{': '}',
+ '[': ']',
+ }
+}
+
+// ConcatJSON concatenates multiple json objects or arrays efficiently.
+//
+// Note that [ConcatJSON] performs a very simple (and fast) concatenation
+// operation: it does not attempt to merge objects.
+func ConcatJSON(blobs ...[]byte) []byte {
+ if len(blobs) == 0 {
+ return nil
+ }
+
+ last := len(blobs) - 1
+ for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
+ // strips trailing null objects
+ last--
+ if last < 0 {
+ // there was nothing but "null"s or nil...
+ return nil
+ }
+ }
+ if last == 0 {
+ return blobs[0]
+ }
+
+ var opening, closing byte
+ var idx, a int
+ buf := bytes.NewBuffer(nil)
+
+ for i, b := range blobs[:last+1] {
+ if b == nil || bytes.Equal(b, nullJSON) {
+ // a null object is in the list: skip it
+ continue
+ }
+ if len(b) > 0 && opening == 0 { // is this an array or an object?
+ opening, closing = b[0], closers[b[0]]
+ }
+
+ if opening != '{' && opening != '[' {
+ continue // don't know how to concatenate non container objects
+ }
+
+ const minLengthIfNotEmpty = 3
+ if len(b) < minLengthIfNotEmpty { // yep empty but also the last one, so closing this thing
+ if i == last && a > 0 {
+ _ = buf.WriteByte(closing) // never returns err != nil
+ }
+ continue
+ }
+
+ idx = 0
+ if a > 0 { // we need to join with a comma for everything beyond the first non-empty item
+ _ = buf.WriteByte(comma) // never returns err != nil
+ idx = 1 // this is not the first or the last so we want to drop the leading bracket
+ }
+
+ if i != last { // not the last one, strip brackets
+ _, _ = buf.Write(b[idx : len(b)-1]) // never returns err != nil
+ } else { // last one, strip only the leading bracket
+ _, _ = buf.Write(b[idx:])
+ }
+ a++
+ }
+
+ // somehow it ended up being empty, so provide a default value
+ if buf.Len() == 0 && (opening == '{' || opening == '[') {
+ _ = buf.WriteByte(opening) // never returns err != nil
+ _ = buf.WriteByte(closing)
+ }
+
+ return buf.Bytes()
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/doc.go
new file mode 100644
index 000000000000..3926cc58d1bc
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/doc.go
@@ -0,0 +1,7 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package jsonutils provides helpers to work with JSON.
+//
+// These utilities work with dynamic go structures to and from JSON.
+package jsonutils
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/json.go b/vendor/github.com/go-openapi/swag/jsonutils/json.go
new file mode 100644
index 000000000000..40753ce03fde
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/json.go
@@ -0,0 +1,116 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package jsonutils
+
+import (
+ "bytes"
+ "encoding/json"
+
+ "github.com/go-openapi/swag/jsonutils/adapters"
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+)
+
+// WriteJSON marshals a data structure as JSON.
+//
+// The difference with [json.Marshal] is that it may check among several alternatives
+// to do so.
+//
+// See [adapters.Registrar] for more details about how to configure
+// multiple serialization alternatives.
+//
+// NOTE: to allow types that are [easyjson.Marshaler] s to use that route to process JSON,
+// you now need to register the adapter for easyjson at runtime.
+func WriteJSON(value any) ([]byte, error) {
+ if orderedMap, isOrdered := value.(ifaces.Ordered); isOrdered {
+ orderedMarshaler := adapters.OrderedMarshalAdapterFor(orderedMap)
+
+ if orderedMarshaler != nil {
+ defer orderedMarshaler.Redeem()
+
+ return orderedMarshaler.OrderedMarshal(orderedMap)
+ }
+
+ // no support found in registered adapters, fallback to the default (unordered) case
+ }
+
+ marshaler := adapters.MarshalAdapterFor(value)
+ if marshaler != nil {
+ defer marshaler.Redeem()
+
+ return marshaler.Marshal(value)
+ }
+
+ // no support found in registered adapters, fallback to the default standard library.
+ //
+ // This only happens when tinkering with the global registry of adapters, since the default handles all the above cases.
+ return json.Marshal(value) // Codecov ignore // this is a safeguard not easily simulated in tests
+}
+
+// ReadJSON unmarshals JSON data into a data structure.
+//
+// The difference with [json.Unmarshal] is that it may check among several alternatives
+// to do so.
+//
+// See [adapters.Registrar] for more details about how to configure
+// multiple serialization alternatives.
+//
+// NOTE: value must be a pointer.
+//
+// If the provided value implements [ifaces.SetOrdered], it is a considered an "ordered map" and [ReadJSON]
+// will favor an adapter that supports the [ifaces.OrderedUnmarshal] feature, or fallback to
+// an unordered behavior if none is found.
+//
+// NOTE: to allow types that are [easyjson.Unmarshaler] s to use that route to process JSON,
+// you now need to register the adapter for easyjson at runtime.
+func ReadJSON(data []byte, value any) error {
+ trimmedData := bytes.Trim(data, "\x00")
+
+ if orderedMap, isOrdered := value.(ifaces.SetOrdered); isOrdered {
+ // if the value is an ordered map, favors support for OrderedUnmarshal.
+
+ orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(orderedMap)
+
+ if orderedUnmarshaler != nil {
+ defer orderedUnmarshaler.Redeem()
+
+ return orderedUnmarshaler.OrderedUnmarshal(trimmedData, orderedMap)
+ }
+
+ // no support found in registered adapters, fallback to the default (unordered) case
+ }
+
+ unmarshaler := adapters.UnmarshalAdapterFor(value)
+ if unmarshaler != nil {
+ defer unmarshaler.Redeem()
+
+ return unmarshaler.Unmarshal(trimmedData, value)
+ }
+
+ // no support found in registered adapters, fallback to the default standard library.
+ //
+ // This only happens when tinkering with the global registry of adapters, since the default handles all the above cases.
+ return json.Unmarshal(trimmedData, value) // Codecov ignore // this is a safeguard not easily simulated in tests
+}
+
+// FromDynamicJSON turns a go value into a properly JSON typed structure.
+//
+// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any,
+// i.e. objects are represented by map[string]any, arrays by []any, and
+// all numbers are represented as float64.
+//
+// NOTE: target must be a pointer.
+//
+// # Maintaining the order of keys in objects
+//
+// If source and target implement [ifaces.Ordered] and [ifaces.SetOrdered] respectively,
+// they are considered "ordered maps" and the order of keys is maintained in the
+// "jsonification" process. In that case, map[string]any values are replaced by (ordered) [JSONMapSlice] ones.
+func FromDynamicJSON(source, target any) error {
+ b, err := WriteJSON(source)
+ if err != nil {
+ return err
+ }
+
+ return ReadJSON(b, target)
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go
new file mode 100644
index 000000000000..38dd3e244426
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go
@@ -0,0 +1,114 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package jsonutils
+
+import (
+ "iter"
+
+ "github.com/go-openapi/swag/jsonutils/adapters"
+ "github.com/go-openapi/swag/typeutils"
+)
+
+// JSONMapSlice represents a JSON object, with the order of keys maintained.
+//
+// It behaves like an ordered map, but keys can't be accessed in constant time.
+type JSONMapSlice []JSONMapItem
+
+// OrderedItems iterates over all (key,value) pairs with the order of keys maintained.
+//
+// This implements the [ifaces.Ordered] interface, so that [ifaces.Adapter] s know how to marshal
+// keys in the desired order.
+func (s JSONMapSlice) OrderedItems() iter.Seq2[string, any] {
+ return func(yield func(string, any) bool) {
+ for _, item := range s {
+ if !yield(item.Key, item.Value) {
+ return
+ }
+ }
+ }
+}
+
+// SetOrderedItems sets keys in the [JSONMapSlice] objects, as presented by
+// the provided iterator.
+//
+// As a special case, if items is nil, this sets to receiver to a nil slice.
+//
+// This implements the [ifaces.SetOrdered] interface, so that [ifaces.Adapter] s know how to unmarshal
+// keys in the desired order.
+func (s *JSONMapSlice) SetOrderedItems(items iter.Seq2[string, any]) {
+ if items == nil {
+ // force receiver to be a nil slice
+ *s = nil
+
+ return
+ }
+
+ m := *s
+ if len(m) > 0 {
+ // update mode: short-circuited when unmarshaling fresh data structures
+ idx := make(map[string]int, len(m))
+
+ for i, item := range m {
+ idx[item.Key] = i
+ }
+
+ for k, v := range items {
+ idx, ok := idx[k]
+ if ok {
+ m[idx].Value = v
+
+ continue
+ }
+
+ m = append(m, JSONMapItem{Key: k, Value: v})
+ }
+
+ *s = m
+
+ return
+ }
+
+ for k, v := range items {
+ m = append(m, JSONMapItem{Key: k, Value: v})
+ }
+
+ *s = m
+}
+
+// MarshalJSON renders a [JSONMapSlice] as JSON bytes, preserving the order of keys.
+//
+// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library).
+func (s JSONMapSlice) MarshalJSON() ([]byte, error) {
+ orderedMarshaler := adapters.OrderedMarshalAdapterFor(s)
+ defer orderedMarshaler.Redeem()
+
+ return orderedMarshaler.OrderedMarshal(s)
+}
+
+// UnmarshalJSON builds a [JSONMapSlice] from JSON bytes, preserving the order of keys.
+//
+// Inner objects are unmarshaled as ordered [JSONMapSlice] slices and not map[string]any.
+//
+// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library).
+func (s *JSONMapSlice) UnmarshalJSON(data []byte) error {
+ if typeutils.IsNil(*s) {
+ // allow to unmarshal with a simple var declaration (nil slice)
+ *s = JSONMapSlice{}
+ }
+
+ orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(s)
+ defer orderedUnmarshaler.Redeem()
+
+ return orderedUnmarshaler.OrderedUnmarshal(data, s)
+}
+
+// JSONMapItem represents the value of a key in a JSON object held by [JSONMapSlice].
+//
+// Notice that JSONMapItem should not be marshaled to or unmarshaled from JSON directly.
+//
+// Use this type as part of a [JSONMapSlice] when dealing with JSON bytes.
+type JSONMapItem struct {
+ Key string
+ Value any
+}
diff --git a/vendor/github.com/go-openapi/swag/jsonutils_iface.go b/vendor/github.com/go-openapi/swag/jsonutils_iface.go
new file mode 100644
index 000000000000..7bd4105fa51a
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/jsonutils_iface.go
@@ -0,0 +1,65 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import (
+ "log"
+
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// JSONMapSlice represents a JSON object, with the order of keys maintained
+//
+// Deprecated: use [jsonutils.JSONMapSlice] instead, or [yamlutils.YAMLMapSlice] if you marshal YAML.
+type JSONMapSlice = jsonutils.JSONMapSlice
+
+// JSONMapItem represents a JSON object, with the order of keys maintained
+//
+// Deprecated: use [jsonutils.JSONMapItem] instead.
+type JSONMapItem = jsonutils.JSONMapItem
+
+// WriteJSON writes json data.
+//
+// Deprecated: use [jsonutils.WriteJSON] instead.
+func WriteJSON(data any) ([]byte, error) { return jsonutils.WriteJSON(data) }
+
+// ReadJSON reads json data.
+//
+// Deprecated: use [jsonutils.ReadJSON] instead.
+func ReadJSON(data []byte, value any) error { return jsonutils.ReadJSON(data, value) }
+
+// DynamicJSONToStruct converts an untyped JSON structure into a target data type.
+//
+// Deprecated: use [jsonutils.FromDynamicJSON] instead.
+func DynamicJSONToStruct(data any, target any) error {
+ return jsonutils.FromDynamicJSON(data, target)
+}
+
+// ConcatJSON concatenates multiple JSON objects efficiently.
+//
+// Deprecated: use [jsonutils.ConcatJSON] instead.
+func ConcatJSON(blobs ...[]byte) []byte { return jsonutils.ConcatJSON(blobs...) }
+
+// ToDynamicJSON turns a go value into a properly JSON untyped structure.
+//
+// It is the same as [FromDynamicJSON], but doesn't check for errors.
+//
+// Deprecated: this function is a misnomer and is unsafe. Use [jsonutils.FromDynamicJSON] instead.
+func ToDynamicJSON(value any) any {
+ var res any
+ if err := FromDynamicJSON(value, &res); err != nil {
+ log.Println(err)
+ }
+
+ return res
+}
+
+// FromDynamicJSON turns a go value into a properly JSON typed structure.
+//
+// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any,
+// i.e. objects are represented by map[string]any, arrays by []any, and all
+// scalar values are any.
+//
+// Deprecated: use [jsonutils.FromDynamicJSON] instead.
+func FromDynamicJSON(data, target any) error { return jsonutils.FromDynamicJSON(data, target) }
diff --git a/vendor/github.com/go-openapi/swag/loading/LICENSE b/vendor/github.com/go-openapi/swag/loading/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/loading/doc.go b/vendor/github.com/go-openapi/swag/loading/doc.go
new file mode 100644
index 000000000000..8cf7bcb8b9d4
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package loading provides tools to load a file from http or from a local file system.
+package loading
diff --git a/vendor/github.com/go-openapi/swag/loading/errors.go b/vendor/github.com/go-openapi/swag/loading/errors.go
new file mode 100644
index 000000000000..b3964289c742
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/errors.go
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loading
+
+type loadingError string
+
+const (
+ // ErrLoader is an error raised by the file loader utility
+ ErrLoader loadingError = "loader error"
+)
+
+func (e loadingError) Error() string {
+ return string(e)
+}
diff --git a/vendor/github.com/go-openapi/swag/loading/json.go b/vendor/github.com/go-openapi/swag/loading/json.go
new file mode 100644
index 000000000000..59db12f5cfdb
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/json.go
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loading
+
+import (
+ "encoding/json"
+ "errors"
+ "path/filepath"
+)
+
+// JSONMatcher matches json for a file loader.
+func JSONMatcher(path string) bool {
+ ext := filepath.Ext(path)
+ return ext == ".json" || ext == ".jsn" || ext == ".jso"
+}
+
+// JSONDoc loads a json document from either a file or a remote url.
+func JSONDoc(path string, opts ...Option) (json.RawMessage, error) {
+ data, err := LoadFromFileOrHTTP(path, opts...)
+ if err != nil {
+ return nil, errors.Join(err, ErrLoader)
+ }
+ return json.RawMessage(data), nil
+}
diff --git a/vendor/github.com/go-openapi/swag/loading/loading.go b/vendor/github.com/go-openapi/swag/loading/loading.go
new file mode 100644
index 000000000000..269fb74d1675
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/loading.go
@@ -0,0 +1,160 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loading
+
+import (
+ "context"
+ "embed"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "net/url"
+ "path"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in
+func LoadFromFileOrHTTP(pth string, opts ...Option) ([]byte, error) {
+ o := optionsWithDefaults(opts)
+ return LoadStrategy(pth, o.ReadFileFunc(), loadHTTPBytes(opts...), opts...)(pth)
+}
+
+// LoadStrategy returns a loader function for a given path or URI.
+//
+// The load strategy returns the remote load for any path starting with `http`.
+// So this works for any URI with a scheme `http` or `https`.
+//
+// The fallback strategy is to call the local loader.
+//
+// The local loader takes a local file system path (absolute or relative) as argument,
+// or alternatively a `file://...` URI, **without host** (see also below for windows).
+//
+// There are a few liberalities, initially intended to be tolerant regarding the URI syntax,
+// especially on windows.
+//
+// Before the local loader is called, the given path is transformed:
+// - percent-encoded characters are unescaped
+// - simple paths (e.g. `./folder/file`) are passed as-is
+// - on windows, occurrences of `/` are replaced by `\`, so providing a relative path such a `folder/file` works too.
+//
+// For paths provided as URIs with the "file" scheme, please note that:
+// - `file://` is simply stripped.
+// This means that the host part of the URI is not parsed at all.
+// For example, `file:///folder/file" becomes "/folder/file`,
+// but `file://localhost/folder/file` becomes `localhost/folder/file` on unix systems.
+// Similarly, `file://./folder/file` yields `./folder/file`.
+// - on windows, `file://...` can take a host so as to specify an UNC share location.
+//
+// Reminder about windows-specifics:
+// - `file://host/folder/file` becomes an UNC path like `\\host\folder\file` (no port specification is supported)
+// - `file:///c:/folder/file` becomes `C:\folder\file`
+// - `file://c:/folder/file` is tolerated (without leading `/`) and becomes `c:\folder\file`
+func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...Option) func(string) ([]byte, error) {
+ if strings.HasPrefix(pth, "http") {
+ return remote
+ }
+ o := optionsWithDefaults(opts)
+ _, isEmbedFS := o.fs.(embed.FS)
+
+ return func(p string) ([]byte, error) {
+ upth, err := url.PathUnescape(p)
+ if err != nil {
+ return nil, err
+ }
+
+ cpth, hasPrefix := strings.CutPrefix(upth, "file://")
+ if !hasPrefix || isEmbedFS || runtime.GOOS != "windows" {
+ // crude processing: trim the file:// prefix. This leaves full URIs with a host with a (mostly) unexpected result
+ // regular file path provided: just normalize slashes
+ if isEmbedFS {
+ // on windows, we need to slash the path if FS is an embed FS.
+ return local(strings.TrimLeft(filepath.ToSlash(cpth), "./")) // remove invalid leading characters for embed FS
+ }
+
+ return local(filepath.FromSlash(cpth))
+ }
+
+ // windows-only pre-processing of file://... URIs, excluding embed.FS
+
+ // support for canonical file URIs on windows.
+ u, err := url.Parse(filepath.ToSlash(upth))
+ if err != nil {
+ return nil, err
+ }
+
+ if u.Host != "" {
+ // assume UNC name (volume share)
+ // NOTE: UNC port not yet supported
+
+ // when the "host" segment is a drive letter:
+ // file://C:/folder/... => C:\folder
+ upth = path.Clean(strings.Join([]string{u.Host, u.Path}, `/`))
+ if !strings.HasSuffix(u.Host, ":") && u.Host[0] != '.' {
+ // tolerance: if we have a leading dot, this can't be a host
+ // file://host/share/folder\... ==> \\host\share\path\folder
+ upth = "//" + upth
+ }
+ } else {
+ // no host, let's figure out if this is a drive letter
+ upth = strings.TrimPrefix(upth, `file://`)
+ first, _, _ := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
+ if strings.HasSuffix(first, ":") {
+ // drive letter in the first segment:
+ // file:///c:/folder/... ==> strip the leading slash
+ upth = strings.TrimPrefix(upth, `/`)
+ }
+ }
+
+ return local(filepath.FromSlash(upth))
+ }
+}
+
+func loadHTTPBytes(opts ...Option) func(path string) ([]byte, error) {
+ o := optionsWithDefaults(opts)
+
+ return func(path string) ([]byte, error) {
+ client := o.client
+ timeoutCtx := context.Background()
+ var cancel func()
+
+ if o.httpTimeout > 0 {
+ timeoutCtx, cancel = context.WithTimeout(timeoutCtx, o.httpTimeout)
+ defer cancel()
+ }
+
+ req, err := http.NewRequestWithContext(timeoutCtx, http.MethodGet, path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if o.basicAuthUsername != "" && o.basicAuthPassword != "" {
+ req.SetBasicAuth(o.basicAuthUsername, o.basicAuthPassword)
+ }
+
+ for key, val := range o.customHeaders {
+ req.Header.Set(key, val)
+ }
+
+ resp, err := client.Do(req)
+ defer func() {
+ if resp != nil {
+ if e := resp.Body.Close(); e != nil {
+ log.Println(e)
+ }
+ }
+ }()
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("could not access document at %q [%s]: %w", path, resp.Status, ErrLoader)
+ }
+
+ return io.ReadAll(resp.Body)
+ }
+}
diff --git a/vendor/github.com/go-openapi/swag/loading/options.go b/vendor/github.com/go-openapi/swag/loading/options.go
new file mode 100644
index 000000000000..6674ac69e628
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/options.go
@@ -0,0 +1,125 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loading
+
+import (
+ "io/fs"
+ "net/http"
+ "os"
+ "time"
+)
+
+type (
+ // Option provides options for loading a file over HTTP or from a file.
+ Option func(*options)
+
+ httpOptions struct {
+ httpTimeout time.Duration
+ basicAuthUsername string
+ basicAuthPassword string
+ customHeaders map[string]string
+ client *http.Client
+ }
+
+ fileOptions struct {
+ fs fs.ReadFileFS
+ }
+
+ options struct {
+ httpOptions
+ fileOptions
+ }
+)
+
+func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) {
+ if fo.fs == nil {
+ return os.ReadFile
+ }
+
+ return fo.fs.ReadFile
+}
+
+// WithTimeout sets a timeout for the remote file loader.
+//
+// The default timeout is 30s.
+func WithTimeout(timeout time.Duration) Option {
+ return func(o *options) {
+ o.httpTimeout = timeout
+ }
+}
+
+// WithBasicAuth sets a basic authentication scheme for the remote file loader.
+func WithBasicAuth(username, password string) Option {
+ return func(o *options) {
+ o.basicAuthUsername = username
+ o.basicAuthPassword = password
+ }
+}
+
+// WithCustomHeaders sets custom headers for the remote file loader.
+func WithCustomHeaders(headers map[string]string) Option {
+ return func(o *options) {
+ if o.customHeaders == nil {
+ o.customHeaders = make(map[string]string, len(headers))
+ }
+
+ for header, value := range headers {
+ o.customHeaders[header] = value
+ }
+ }
+}
+
+// WithHTTPClient overrides the default HTTP client used to fetch a remote file.
+//
+// By default, [http.DefaultClient] is used.
+func WithHTTPClient(client *http.Client) Option {
+ return func(o *options) {
+ o.client = client
+ }
+}
+
+// WithFS sets a file system for the local file loader.
+//
+// If the provided file system is a [fs.ReadFileFS], the ReadFile function is used.
+// Otherwise, ReadFile is wrapped using [fs.ReadFile].
+//
+// By default, the file system is the one provided by the os package.
+//
+// For example, this may be set to consume from an embedded file system, or a rooted FS.
+func WithFS(filesystem fs.FS) Option {
+ return func(o *options) {
+ if rfs, ok := filesystem.(fs.ReadFileFS); ok {
+ o.fs = rfs
+
+ return
+ }
+ o.fs = readFileFS{FS: filesystem}
+ }
+}
+
+type readFileFS struct {
+ fs.FS
+}
+
+func (r readFileFS) ReadFile(name string) ([]byte, error) {
+ return fs.ReadFile(r.FS, name)
+}
+
+func optionsWithDefaults(opts []Option) options {
+ const defaultTimeout = 30 * time.Second
+
+ o := options{
+ // package level defaults
+ httpOptions: httpOptions{
+ httpTimeout: defaultTimeout,
+ client: http.DefaultClient,
+ },
+ }
+
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ return o
+}
diff --git a/vendor/github.com/go-openapi/swag/loading/yaml.go b/vendor/github.com/go-openapi/swag/loading/yaml.go
new file mode 100644
index 000000000000..3ebb53668c47
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading/yaml.go
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loading
+
+import (
+ "encoding/json"
+ "path/filepath"
+
+ "github.com/go-openapi/swag/yamlutils"
+)
+
+// YAMLMatcher matches yaml for a file loader.
+func YAMLMatcher(path string) bool {
+ ext := filepath.Ext(path)
+ return ext == ".yaml" || ext == ".yml"
+}
+
+// YAMLDoc loads a yaml document from either http or a file and converts it to json.
+func YAMLDoc(path string, opts ...Option) (json.RawMessage, error) {
+ yamlDoc, err := YAMLData(path, opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ return yamlutils.YAMLToJSON(yamlDoc)
+}
+
+// YAMLData loads a yaml document from either http or a file.
+func YAMLData(path string, opts ...Option) (any, error) {
+ data, err := LoadFromFileOrHTTP(path, opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ return yamlutils.BytesToYAMLDoc(data)
+}
diff --git a/vendor/github.com/go-openapi/swag/loading_iface.go b/vendor/github.com/go-openapi/swag/loading_iface.go
new file mode 100644
index 000000000000..27ec3fb8c37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/loading_iface.go
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import (
+ "encoding/json"
+ "time"
+
+ "github.com/go-openapi/swag/loading"
+)
+
+var (
+ // Package-level defaults for the file loading utilities (deprecated).
+
+ // LoadHTTPTimeout the default timeout for load requests.
+ //
+ // Deprecated: use [loading.WithTimeout] instead.
+ LoadHTTPTimeout = 30 * time.Second
+
+ // LoadHTTPBasicAuthUsername the username to use when load requests require basic auth.
+ //
+ // Deprecated: use [loading.WithBasicAuth] instead.
+ LoadHTTPBasicAuthUsername = ""
+
+ // LoadHTTPBasicAuthPassword the password to use when load requests require basic auth.
+ //
+ // Deprecated: use [loading.WithBasicAuth] instead.
+ LoadHTTPBasicAuthPassword = ""
+
+ // LoadHTTPCustomHeaders an optional collection of custom HTTP headers for load requests.
+ //
+ // Deprecated: use [loading.WithCustomHeaders] instead.
+ LoadHTTPCustomHeaders = map[string]string{}
+)
+
+// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the provided path.
+//
+// Deprecated: use [loading.LoadFromFileOrHTTP] instead.
+func LoadFromFileOrHTTP(pth string, opts ...loading.Option) ([]byte, error) {
+ return loading.LoadFromFileOrHTTP(pth, loadingOptionsWithDefaults(opts)...)
+}
+
+// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
+// timeout arg allows for per request overriding of the request timeout.
+//
+// Deprecated: use [loading.LoadFileOrHTTP] with the [loading.WithTimeout] option instead.
+func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration, opts ...loading.Option) ([]byte, error) {
+ opts = append(opts, loading.WithTimeout(timeout))
+
+ return LoadFromFileOrHTTP(pth, opts...)
+}
+
+// LoadStrategy returns a loader function for a given path or URL.
+//
+// Deprecated: use [loading.LoadStrategy] instead.
+func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...loading.Option) func(string) ([]byte, error) {
+ return loading.LoadStrategy(pth, local, remote, loadingOptionsWithDefaults(opts)...)
+}
+
+// YAMLMatcher matches yaml for a file loader.
+//
+// Deprecated: use [loading.YAMLMatcher] instead.
+func YAMLMatcher(path string) bool { return loading.YAMLMatcher(path) }
+
+// YAMLDoc loads a yaml document from either http or a file and converts it to json.
+//
+// Deprecated: use [loading.YAMLDoc] instead.
+func YAMLDoc(path string) (json.RawMessage, error) {
+ return loading.YAMLDoc(path)
+}
+
+// YAMLData loads a yaml document from either http or a file.
+//
+// Deprecated: use [loading.YAMLData] instead.
+func YAMLData(path string) (any, error) {
+ return loading.YAMLData(path)
+}
+
+// loadingOptionsWithDefaults bridges deprecated default settings that use package-level variables,
+// with the recommended use of loading.Option.
+func loadingOptionsWithDefaults(opts []loading.Option) []loading.Option {
+ o := []loading.Option{
+ loading.WithTimeout(LoadHTTPTimeout),
+ loading.WithBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword),
+ loading.WithCustomHeaders(LoadHTTPCustomHeaders),
+ }
+ o = append(o, opts...)
+
+ return o
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md b/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md
new file mode 100644
index 000000000000..6674c63b7294
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md
@@ -0,0 +1,90 @@
+# Benchmarking name mangling utilities
+
+```bash
+go test -bench XXX -run XXX -benchtime 30s
+```
+
+## Benchmarks at b3e7a5386f996177e4808f11acb2aa93a0f660df
+
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/swag
+cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
+BenchmarkToXXXName/ToGoName-4 862623 44101 ns/op 10450 B/op 732 allocs/op
+BenchmarkToXXXName/ToVarName-4 853656 40728 ns/op 10468 B/op 734 allocs/op
+BenchmarkToXXXName/ToFileName-4 1268312 27813 ns/op 9785 B/op 617 allocs/op
+BenchmarkToXXXName/ToCommandName-4 1276322 27903 ns/op 9785 B/op 617 allocs/op
+BenchmarkToXXXName/ToHumanNameLower-4 895334 40354 ns/op 10472 B/op 731 allocs/op
+BenchmarkToXXXName/ToHumanNameTitle-4 882441 40678 ns/op 10566 B/op 749 allocs/op
+```
+
+## Benchmarks after PR #79
+
+~ x10 performance improvement and ~ /100 memory allocations.
+
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/swag
+cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
+BenchmarkToXXXName/ToGoName-4 9595830 3991 ns/op 42 B/op 5 allocs/op
+BenchmarkToXXXName/ToVarName-4 9194276 3984 ns/op 62 B/op 7 allocs/op
+BenchmarkToXXXName/ToFileName-4 17002711 2123 ns/op 147 B/op 7 allocs/op
+BenchmarkToXXXName/ToCommandName-4 16772926 2111 ns/op 147 B/op 7 allocs/op
+BenchmarkToXXXName/ToHumanNameLower-4 9788331 3749 ns/op 92 B/op 6 allocs/op
+BenchmarkToXXXName/ToHumanNameTitle-4 9188260 3941 ns/op 104 B/op 6 allocs/op
+```
+
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/swag
+cpu: AMD Ryzen 7 5800X 8-Core Processor
+BenchmarkToXXXName/ToGoName-16 18527378 1972 ns/op 42 B/op 5 allocs/op
+BenchmarkToXXXName/ToVarName-16 15552692 2093 ns/op 62 B/op 7 allocs/op
+BenchmarkToXXXName/ToFileName-16 32161176 1117 ns/op 147 B/op 7 allocs/op
+BenchmarkToXXXName/ToCommandName-16 32256634 1137 ns/op 147 B/op 7 allocs/op
+BenchmarkToXXXName/ToHumanNameLower-16 18599661 1946 ns/op 92 B/op 6 allocs/op
+BenchmarkToXXXName/ToHumanNameTitle-16 17581353 2054 ns/op 105 B/op 6 allocs/op
+```
+
+## Benchmarks at d7d2d1b895f5b6747afaff312dd2a402e69e818b
+
+go1.24
+
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/swag
+cpu: AMD Ryzen 7 5800X 8-Core Processor
+BenchmarkToXXXName/ToGoName-16 19757858 1881 ns/op 42 B/op 5 allocs/op
+BenchmarkToXXXName/ToVarName-16 17494111 2094 ns/op 74 B/op 7 allocs/op
+BenchmarkToXXXName/ToFileName-16 28161226 1492 ns/op 158 B/op 7 allocs/op
+BenchmarkToXXXName/ToCommandName-16 23787333 1489 ns/op 158 B/op 7 allocs/op
+BenchmarkToXXXName/ToHumanNameLower-16 17537257 2030 ns/op 103 B/op 6 allocs/op
+BenchmarkToXXXName/ToHumanNameTitle-16 16977453 2156 ns/op 105 B/op 6 allocs/op
+```
+
+## Benchmarks after PR #106
+
+Moving the scope of everything down to a struct allowed to reduce a bit garbage and pooling.
+
+On top of that, ToGoName (and thus ToVarName) have been subject to a minor optimization, removing a few allocations.
+
+Overall timings improve by ~ -10%.
+
+go1.24
+
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/swag/mangling
+cpu: AMD Ryzen 7 5800X 8-Core Processor
+BenchmarkToXXXName/ToGoName-16 22496130 1618 ns/op 31 B/op 3 allocs/op
+BenchmarkToXXXName/ToVarName-16 22538068 1618 ns/op 33 B/op 3 allocs/op
+BenchmarkToXXXName/ToFileName-16 27722977 1236 ns/op 105 B/op 6 allocs/op
+BenchmarkToXXXName/ToCommandName-16 27967395 1258 ns/op 105 B/op 6 allocs/op
+BenchmarkToXXXName/ToHumanNameLower-16 18587901 1917 ns/op 103 B/op 6 allocs/op
+BenchmarkToXXXName/ToHumanNameTitle-16 17193208 2019 ns/op 108 B/op 7 allocs/op
+```
diff --git a/vendor/github.com/go-openapi/swag/mangling/LICENSE b/vendor/github.com/go-openapi/swag/mangling/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/mangling/doc.go b/vendor/github.com/go-openapi/swag/mangling/doc.go
new file mode 100644
index 000000000000..ce0d8904857a
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/doc.go
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package mangling provides name mangling capabilities.
+//
+// Name mangling is an important stage when generating code:
+// it helps construct safe program identifiers that abide by the language rules
+// and play along with linters.
+//
+// Examples:
+//
+// Suppose we get an object name taken from an API spec: "json_object",
+//
+// We may generate a legit go type name using [NameMangler.ToGoName]: "JsonObject".
+//
+// We may then locate this type in a source file named using [NameMangler.ToFileName]: "json_object.go".
+//
+// The methods exposed by the NameMangler are used to generate code in many different contexts, such as:
+//
+// - generating exported or unexported go identifiers from a JSON schema or an API spec
+// - generating file names
+// - generating human-readable comments for types and variables
+// - generating JSON-like API identifiers from go code
+// - ...
+package mangling
diff --git a/vendor/github.com/go-openapi/swag/mangling/initialism_index.go b/vendor/github.com/go-openapi/swag/mangling/initialism_index.go
new file mode 100644
index 000000000000..e5b70c149388
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/initialism_index.go
@@ -0,0 +1,270 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import (
+ "sort"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// DefaultInitialisms returns all the initialisms configured by default for this package.
+//
+// # Motivation
+//
+// Common initialisms are acronyms for which the ordinary camel-casing rules are altered and
+// for which we retain the original case.
+//
+// This is largely specific to the go naming conventions enforced by golint (now revive).
+//
+// # Example
+//
+// In go, "id" is a good-looking identifier, but "Id" is not and "ID" is preferred
+// (notice that this stems only from conventions: the go compiler accepts all of these).
+//
+// Similarly, we may use "http", but not "Http". In this case, "HTTP" is preferred.
+//
+// # Reference and customization
+//
+// The default list of these casing-style exceptions is taken from the [github.com/mgechev/revive] linter for go:
+// https://github.com/mgechev/revive/blob/master/lint/name.go#L93
+//
+// There are a few additions to the original list, such as IPv4, IPv6 and OAI ("OpenAPI").
+//
+// For these additions, "IPv4" would be preferred to "Ipv4" or "IPV4", and "OAI" to "Oai"
+//
+// You may redefine this list entirely using the mangler option [WithInitialisms], or simply add extra definitions
+// using [WithAdditionalInitialisms].
+//
+// # Mixed-case and plurals
+//
+// Notice that initialisms are not necessarily fully upper-cased: a mixed-case initialism indicates the preferred casing.
+//
+// Obviously, lower-case only initialisms do not make a lot of sense: if lower-case only initialisms are added,
+// they will be considered fully capitalized.
+//
+// Plural forms use mixed case like "IDs". And so do values like "IPv4" or "IPv6".
+//
+// The [NameMangler] automatically detects simple plurals for words such as "IDs" or "APIs",
+// so you don't need to configure these variants.
+//
+// At this moment, it doesn't support pluralization of terms that ends with an 's' (or 'S'), since there is
+// no clear consensus on whether a word like DNS should be pluralized as DNSes or remain invariant.
+// The [NameMangler] consider those invariant. Therefore DNSs or DNSes are not recognized as plurals for DNS.
+//
+// Besids, we don't want to support pluralization of terms which would otherwise conflict with another one,
+// like "HTTPs" vs "HTTPS". All these should be considered invariant. Hence: "Https" matches "HTTPS" and
+// "HTTPSS" is "HTTPS" followed by "S".
+func DefaultInitialisms() []string {
+ return []string{
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTPS",
+ "HTTP",
+ "ID",
+ "IP",
+ "IPv4", // prefer the mixed case outcome IPv4 over the capitalized IPV4
+ "IPv6", // prefer the mixed case outcome IPv6 over the capitalized IPV6
+ "JSON",
+ "LHS",
+ "OAI",
+ "QPS",
+ "RAM",
+ "RHS",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ }
+}
+
+type indexOfInitialisms struct {
+ initialismsCache
+
+ index map[string]struct{}
+}
+
+func newIndexOfInitialisms() *indexOfInitialisms {
+ return &indexOfInitialisms{
+ index: make(map[string]struct{}),
+ }
+}
+
+func (m *indexOfInitialisms) add(words ...string) *indexOfInitialisms {
+ for _, word := range words {
+ // sanitization of injected words: trimmed from blanks, and must start with a letter
+ trimmed := strings.TrimSpace(word)
+
+ firstRune, _ := utf8.DecodeRuneInString(trimmed)
+ if !unicode.IsLetter(firstRune) {
+ continue
+ }
+
+ // Initialisms are case-sensitive. This means that we support mixed-case words.
+ // However, if specified as a lower-case string, the initialism should be fully capitalized.
+ if trimmed == strings.ToLower(trimmed) {
+ m.index[strings.ToUpper(trimmed)] = struct{}{}
+
+ continue
+ }
+
+ m.index[trimmed] = struct{}{}
+ }
+ return m
+}
+
+func (m *indexOfInitialisms) sorted() []string {
+ result := make([]string, 0, len(m.index))
+ for k := range m.index {
+ result = append(result, k)
+ }
+ sort.Sort(sort.Reverse(byInitialism(result)))
+ return result
+}
+
+func (m *indexOfInitialisms) buildCache() {
+ m.build(m.sorted(), m.pluralForm)
+}
+
+// initialismsCache caches all needed pre-computed and converted initialism entries,
+// in the desired resolution order.
+type initialismsCache struct {
+ initialisms []string
+ initialismsRunes [][]rune
+ initialismsUpperCased [][]rune // initialisms cached in their trimmed, upper-cased version
+ initialismsPluralForm []pluralForm
+}
+
+func (c *initialismsCache) build(in []string, pluralfunc func(string) pluralForm) {
+ c.initialisms = in
+ c.initialismsRunes = asRunes(c.initialisms)
+ c.initialismsUpperCased = asUpperCased(c.initialisms)
+ c.initialismsPluralForm = asPluralForms(c.initialisms, pluralfunc)
+}
+
+// pluralForm denotes the kind of pluralization to be used for initialisms.
+//
+// At this moment, initialisms are either invariant or follow a simple plural form with an
+// extra (lower case) "s".
+type pluralForm uint8
+
+const (
+ notPlural pluralForm = iota
+ invariantPlural
+ simplePlural
+)
+
+func (f pluralForm) String() string {
+ switch f {
+ case notPlural:
+ return "notPlural"
+ case invariantPlural:
+ return "invariantPlural"
+ case simplePlural:
+ return "simplePlural"
+ default:
+ return ""
+ }
+}
+
+// pluralForm indicates how we want to pluralize a given initialism.
+//
+// Besides configured invariant forms (like HTTP and HTTPS),
+// an initialism is normally pluralized by adding a single 's', like in IDs.
+//
+// Initialisms ending with an 'S' or an 's' are configured as invariant (we don't
+// support plural forms like CSSes or DNSes, however the mechanism could be extended to
+// do just that).
+func (m *indexOfInitialisms) pluralForm(key string) pluralForm {
+ if _, ok := m.index[key]; !ok {
+ return notPlural
+ }
+
+ if strings.HasSuffix(strings.ToUpper(key), "S") {
+ return invariantPlural
+ }
+
+ if _, ok := m.index[key+"s"]; ok {
+ return invariantPlural
+ }
+
+ if _, ok := m.index[key+"S"]; ok {
+ return invariantPlural
+ }
+
+ return simplePlural
+}
+
+type byInitialism []string
+
+func (s byInitialism) Len() int {
+ return len(s)
+}
+func (s byInitialism) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+// Less specifies the order in which initialisms are prioritized:
+// 1. match longest first
+// 2. when equal length, match in reverse lexicographical order, lower case match comes first
+func (s byInitialism) Less(i, j int) bool {
+ if len(s[i]) != len(s[j]) {
+ return len(s[i]) < len(s[j])
+ }
+
+ return s[i] < s[j]
+}
+
+func asRunes(in []string) [][]rune {
+ out := make([][]rune, len(in))
+ for i, initialism := range in {
+ out[i] = []rune(initialism)
+ }
+
+ return out
+}
+
+func asUpperCased(in []string) [][]rune {
+ out := make([][]rune, len(in))
+
+ for i, initialism := range in {
+ out[i] = []rune(upper(trim(initialism)))
+ }
+
+ return out
+}
+
+// asPluralForms bakes an index of pluralization support.
+func asPluralForms(in []string, pluralFunc func(string) pluralForm) []pluralForm {
+ out := make([]pluralForm, len(in))
+ for i, initialism := range in {
+ out[i] = pluralFunc(initialism)
+ }
+
+ return out
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/name_lexem.go b/vendor/github.com/go-openapi/swag/mangling/name_lexem.go
new file mode 100644
index 000000000000..bc837e3b9f5d
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/name_lexem.go
@@ -0,0 +1,186 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import (
+ "bytes"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+type (
+ lexemKind uint8
+
+ nameLexem struct {
+ original string
+ matchedInitialism string
+ kind lexemKind
+ }
+)
+
+const (
+ lexemKindCasualName lexemKind = iota
+ lexemKindInitialismName
+)
+
+func newInitialismNameLexem(original, matchedInitialism string) nameLexem {
+ return nameLexem{
+ kind: lexemKindInitialismName,
+ original: original,
+ matchedInitialism: matchedInitialism,
+ }
+}
+
+func newCasualNameLexem(original string) nameLexem {
+ return nameLexem{
+ kind: lexemKindCasualName,
+ original: trim(original), // TODO: save on calls to trim
+ }
+}
+
+// WriteTitleized writes the titleized lexeme to a bytes.Buffer.
+//
+// If the first letter cannot be capitalized, it doesn't write anything and return false,
+// so the caller may attempt some workaround strategy.
+func (l nameLexem) WriteTitleized(w *bytes.Buffer, alwaysUpper bool) bool {
+ if l.kind == lexemKindInitialismName {
+ w.WriteString(l.matchedInitialism)
+
+ return true
+ }
+
+ if len(l.original) == 0 {
+ return true
+ }
+
+ if len(l.original) == 1 {
+ // identifier is too short: casing will depend on the context
+ firstByte := l.original[0]
+ switch {
+ case 'A' <= firstByte && firstByte <= 'Z':
+ // safe
+ w.WriteByte(firstByte)
+
+ return true
+ case alwaysUpper && 'a' <= firstByte && firstByte <= 'z':
+ w.WriteByte(firstByte - 'a' + 'A')
+
+ return true
+ default:
+
+ // not a letter: skip and let the caller decide
+ return false
+ }
+ }
+
+ if firstByte := l.original[0]; firstByte < utf8.RuneSelf {
+ // ASCII
+ switch {
+ case 'A' <= firstByte && firstByte <= 'Z':
+ // already an upper case letter
+ w.WriteString(l.original)
+
+ return true
+ case 'a' <= firstByte && firstByte <= 'z':
+ w.WriteByte(firstByte - 'a' + 'A')
+ w.WriteString(l.original[1:])
+
+ return true
+ default:
+ // not a good candidate: doesn't start with a letter
+ return false
+ }
+ }
+
+ // unicode
+ firstRune, idx := utf8.DecodeRuneInString(l.original)
+ if !unicode.IsLetter(firstRune) || !unicode.IsUpper(unicode.ToUpper(firstRune)) {
+ // not a good candidate: doesn't start with a letter
+ // or a rune for which case doesn't make sense (e.g. East-Asian runes etc)
+ return false
+ }
+
+ rest := l.original[idx:]
+ w.WriteRune(unicode.ToUpper(firstRune))
+ w.WriteString(strings.ToLower(rest))
+
+ return true
+}
+
+// WriteLower is like write titleized but it writes a lower-case version of the lexeme.
+//
+// Similarly, there is no writing if the casing of the first rune doesn't make sense.
+func (l nameLexem) WriteLower(w *bytes.Buffer, alwaysLower bool) bool {
+ if l.kind == lexemKindInitialismName {
+ w.WriteString(lower(l.matchedInitialism))
+
+ return true
+ }
+
+ if len(l.original) == 0 {
+ return true
+ }
+
+ if len(l.original) == 1 {
+ // identifier is too short: casing will depend on the context
+ firstByte := l.original[0]
+ switch {
+ case 'a' <= firstByte && firstByte <= 'z':
+ // safe
+ w.WriteByte(firstByte)
+
+ return true
+ case alwaysLower && 'A' <= firstByte && firstByte <= 'Z':
+ w.WriteByte(firstByte - 'A' + 'a')
+
+ return true
+ default:
+
+ // not a letter: skip and let the caller decide
+ return false
+ }
+ }
+
+ if firstByte := l.original[0]; firstByte < utf8.RuneSelf {
+ // ASCII
+ switch {
+ case 'a' <= firstByte && firstByte <= 'z':
+ // already a lower case letter
+ w.WriteString(l.original)
+
+ return true
+ case 'A' <= firstByte && firstByte <= 'Z':
+ w.WriteByte(firstByte - 'A' + 'a')
+ w.WriteString(l.original[1:])
+
+ return true
+ default:
+ // not a good candidate: doesn't start with a letter
+ return false
+ }
+ }
+
+ // unicode
+ firstRune, idx := utf8.DecodeRuneInString(l.original)
+ if !unicode.IsLetter(firstRune) || !unicode.IsLower(unicode.ToLower(firstRune)) {
+ // not a good candidate: doesn't start with a letter
+ // or a rune for which case doesn't make sense (e.g. East-Asian runes etc)
+ return false
+ }
+
+ rest := l.original[idx:]
+ w.WriteRune(unicode.ToLower(firstRune))
+ w.WriteString(rest)
+
+ return true
+}
+
+func (l nameLexem) GetOriginal() string {
+ return l.original
+}
+
+func (l nameLexem) IsInitialism() bool {
+ return l.kind == lexemKindInitialismName
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/name_mangler.go b/vendor/github.com/go-openapi/swag/mangling/name_mangler.go
new file mode 100644
index 000000000000..da685681d08c
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/name_mangler.go
@@ -0,0 +1,370 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import (
+ "strings"
+ "unicode"
+)
+
+// NameMangler knows how to transform sentences or words into
+// identifiers that are a better fit in contexts such as:
+//
+// - unexported or exported go variable identifiers
+// - file names
+// - camel cased identifiers
+// - ...
+//
+// The [NameMangler] is safe for concurrent use, save for its [NameMangler.AddInitialisms] method,
+// which is not.
+//
+// # Known limitations
+//
+// At this moment, the [NameMangler] doesn't play well with "all caps" text:
+//
+// unless every single upper-cased word is declared as an initialism, capitalized words would generally
+// not be transformed with the expected result, e.g.
+//
+// ToFileName("THIS_IS_ALL_CAPS")
+//
+// yields the weird outcome
+//
+// "t_h_i_s_i_s_a_l_l_c_a_p_s"
+type NameMangler struct {
+ options
+
+ index *indexOfInitialisms
+
+ splitter splitter
+ splitterWithPostSplit splitter
+
+ _ struct{}
+}
+
+// NewNameMangler builds a name mangler ready to convert strings.
+//
+// The default name mangler is configured with default common initialisms and all default options.
+func NewNameMangler(opts ...Option) NameMangler {
+ m := NameMangler{
+ options: optionsWithDefaults(opts),
+ index: newIndexOfInitialisms(),
+ }
+ m.addInitialisms(m.commonInitialisms...)
+
+ // a splitter that returns matches lexemes as ready-to-assemble strings:
+ // details of the lexemes are redeemed.
+ m.splitter = newSplitter(
+ withInitialismsCache(&m.index.initialismsCache),
+ withReplaceFunc(m.replaceFunc),
+ )
+
+ // a splitter that returns matches lexemes ready for post-processing
+ m.splitterWithPostSplit = newSplitter(
+ withInitialismsCache(&m.index.initialismsCache),
+ withReplaceFunc(m.replaceFunc),
+ withPostSplitInitialismCheck,
+ )
+
+ return m
+}
+
+// AddInitialisms declares extra initialisms to the mangler.
+//
+// It declares extra words as "initialisms" (i.e. words that won't be camel cased or titled cased),
+// on top of the existing list of common initialisms (such as ID, HTTP...).
+//
+// Added words must start with a (unicode) letter. If some don't, they are ignored.
+// Added words are either fully capitalized or mixed-cased. Lower-case only words are considered capitalized.
+//
+// It is typically used just after initializing the [NameMangler].
+//
+// When all initialisms are known at the time the mangler is initialized, it is preferable to
+// use [NewNameMangler] with the option [WithAdditionalInitialisms].
+//
+// Adding initialisms mutates the mangler and should not be carried out concurrently with other calls to the mangler.
+func (m *NameMangler) AddInitialisms(words ...string) {
+ m.addInitialisms(words...)
+}
+
+// Initialisms renders the list of initialisms supported by this mangler.
+func (m *NameMangler) Initialisms() []string {
+ return m.index.initialisms
+}
+
+// Camelize a single word.
+//
+// Example:
+//
+// - "HELLO" and "hello" become "Hello".
+func (m NameMangler) Camelize(word string) string {
+ ru := []rune(word)
+
+ switch len(ru) {
+ case 0:
+ return ""
+ case 1:
+ return string(unicode.ToUpper(ru[0]))
+ default:
+ camelized := poolOfBuffers.BorrowBuffer(len(word))
+ camelized.Grow(len(word))
+ defer func() {
+ poolOfBuffers.RedeemBuffer(camelized)
+ }()
+
+ camelized.WriteRune(unicode.ToUpper(ru[0]))
+ for _, ru := range ru[1:] {
+ camelized.WriteRune(unicode.ToLower(ru))
+ }
+
+ return camelized.String()
+ }
+}
+
+// ToFileName generates a suitable snake-case file name from a sentence.
+//
+// It lower-cases everything with underscore (_) as a word separator.
+//
+// Examples:
+//
+// - "Hello, Swagger" becomes "hello_swagger"
+// - "HelloSwagger" becomes "hello_swagger"
+func (m NameMangler) ToFileName(name string) string {
+ inptr := m.split(name)
+ in := *inptr
+ out := make([]string, 0, len(in))
+
+ for _, w := range in {
+ out = append(out, lower(w))
+ }
+ poolOfStrings.RedeemStrings(inptr)
+
+ return strings.Join(out, "_")
+}
+
+// ToCommandName generates a suitable CLI command name from a sentence.
+//
+// It lower-cases everything with dash (-) as a word separator.
+//
+// Examples:
+//
+// - "Hello, Swagger" becomes "hello-swagger"
+// - "HelloSwagger" becomes "hello-swagger"
+func (m NameMangler) ToCommandName(name string) string {
+ inptr := m.split(name)
+ in := *inptr
+ out := make([]string, 0, len(in))
+
+ for _, w := range in {
+ out = append(out, lower(w))
+ }
+ poolOfStrings.RedeemStrings(inptr)
+
+ return strings.Join(out, "-")
+}
+
+// ToHumanNameLower represents a code name as a human-readable series of words.
+//
+// It lower-cases everything with blank space as a word separator.
+//
+// NOTE: parts recognized as initialisms just keep their original casing.
+//
+// Examples:
+//
+// - "Hello, Swagger" becomes "hello swagger"
+// - "HelloSwagger" or "Hello-Swagger" become "hello swagger"
+func (m NameMangler) ToHumanNameLower(name string) string {
+ s := m.splitterWithPostSplit
+ in := s.split(name)
+ out := make([]string, 0, len(*in))
+
+ for _, w := range *in {
+ if !w.IsInitialism() {
+ out = append(out, lower(w.GetOriginal()))
+ } else {
+ out = append(out, trim(w.GetOriginal()))
+ }
+ }
+
+ poolOfLexems.RedeemLexems(in)
+
+ return strings.Join(out, " ")
+}
+
+// ToHumanNameTitle represents a code name as a human-readable series of titleized words.
+//
+// It titleizes every word with blank space as a word separator.
+//
+// Examples:
+//
+// - "hello, Swagger" becomes "Hello Swagger"
+// - "helloSwagger" becomes "Hello Swagger"
+func (m NameMangler) ToHumanNameTitle(name string) string {
+ s := m.splitterWithPostSplit
+ in := s.split(name)
+
+ out := make([]string, 0, len(*in))
+ for _, w := range *in {
+ original := trim(w.GetOriginal())
+ if !w.IsInitialism() {
+ out = append(out, m.Camelize(original))
+ } else {
+ out = append(out, original)
+ }
+ }
+ poolOfLexems.RedeemLexems(in)
+
+ return strings.Join(out, " ")
+}
+
+// ToJSONName generates a camelized single-word version of a sentence.
+//
+// The output assembles every camelized word, but for the first word, which
+// is lower-cased.
+//
+// Example:
+//
+// - "Hello_swagger" becomes "helloSwagger"
+func (m NameMangler) ToJSONName(name string) string {
+ inptr := m.split(name)
+ in := *inptr
+ out := make([]string, 0, len(in))
+
+ for i, w := range in {
+ if i == 0 {
+ out = append(out, lower(w))
+ continue
+ }
+ out = append(out, m.Camelize(trim(w)))
+ }
+
+ poolOfStrings.RedeemStrings(inptr)
+
+ return strings.Join(out, "")
+}
+
+// ToVarName generates a legit unexported go variable name from a sentence.
+//
+// The generated name plays well with linters (see also [NameMangler.ToGoName]).
+//
+// Examples:
+//
+// - "Hello_swagger" becomes "helloSwagger"
+// - "Http_server" becomes "httpServer"
+//
+// This name applies the same rules as [NameMangler.ToGoName] (legit exported variable), save the
+// capitalization of the initial rune.
+//
+// Special case: when the initial part is a recognized as an initialism (like in the example above),
+// the full part is lower-cased.
+func (m NameMangler) ToVarName(name string) string {
+ return m.goIdentifier(name, false)
+}
+
+// ToGoName generates a legit exported go variable name from a sentence.
+//
+// The generated name plays well with most linters.
+//
+// ToGoName abides by the go "exported" symbol rule starting with an upper-case letter.
+//
+// Examples:
+//
+// - "hello_swagger" becomes "HelloSwagger"
+// - "Http_server" becomes "HTTPServer"
+//
+// # Edge cases
+//
+// Whenever the first rune is not eligible to upper case, a special prefix is prepended to the resulting name.
+// By default this is simply "X" and you may customize this behavior using the [WithGoNamePrefixFunc] option.
+//
+// This happens when the first rune is not a letter, e.g. a digit, or a symbol that has no word transliteration
+// (see also [WithReplaceFunc] about symbol transliterations),
+// as well as for most East Asian or Devanagari runes, for which there is no such concept as upper-case.
+//
+// # Linting
+//
+// [revive], the successor of golint is the reference linter.
+//
+// This means that [NameMangler.ToGoName] supports the initialisms that revive checks (see also [DefaultInitialisms]).
+//
+// At this moment, there is no attempt to transliterate unicode into ascii, meaning that some linters
+// (e.g. asciicheck, gosmopolitan) may croak on go identifiers generated from unicode input.
+//
+// [revive]: https://github.com/mgechev/revive
+func (m NameMangler) ToGoName(name string) string {
+ return m.goIdentifier(name, true)
+}
+
+func (m NameMangler) goIdentifier(name string, exported bool) string {
+ s := m.splitterWithPostSplit
+ lexems := s.split(name)
+ defer func() {
+ poolOfLexems.RedeemLexems(lexems)
+ }()
+ lexemes := *lexems
+
+ if len(lexemes) == 0 {
+ return ""
+ }
+
+ result := poolOfBuffers.BorrowBuffer(len(name))
+ defer func() {
+ poolOfBuffers.RedeemBuffer(result)
+ }()
+
+ firstPart := lexemes[0]
+ if !exported {
+ if ok := firstPart.WriteLower(result, true); !ok {
+ // NOTE: an initialism as the first part is lower-cased: no longer generates stuff like hTTPxyz.
+ //
+ // same prefixing rule applied to unexported variable as to an exported one, so that we have consistent
+ // names, whether the generated identifier is exported or not.
+ result.WriteString(strings.ToLower(m.prefixFunc()(name)))
+ result.WriteString(lexemes[0].GetOriginal())
+ }
+ } else {
+ if ok := firstPart.WriteTitleized(result, true); !ok {
+ // "repairs" a lexeme that doesn't start with a letter to become
+ // the start a legit go name. The current strategy is very crude and simply adds a fixed prefix,
+ // e.g. "X".
+ // For instance "1_sesame_street" would be split into lexemes ["1", "sesame", "street"] and
+ // the first one ("1") would result in something like "X1" (with the default prefix function).
+ //
+ // NOTE: no longer forcing the first part to be fully upper-cased
+ result.WriteString(m.prefixFunc()(name))
+ result.WriteString(lexemes[0].GetOriginal())
+ }
+ }
+
+ for _, lexem := range lexemes[1:] {
+ // NOTE: no longer forcing initialism parts to be fully upper-cased:
+ // * pluralized initialism preserve their trailing "s"
+ // * mixed-cased initialisms, such as IPv4, are preserved
+ if ok := lexem.WriteTitleized(result, false); !ok {
+ // it's not titleized: perhaps it's too short, perhaps the first rune is not a letter.
+ // write anyway
+ result.WriteString(lexem.GetOriginal())
+ }
+ }
+
+ return result.String()
+}
+
+func (m *NameMangler) addInitialisms(words ...string) {
+ m.index.add(words...)
+ m.index.buildCache()
+}
+
+// split calls the inner splitter.
+func (m NameMangler) split(str string) *[]string {
+ s := m.splitter
+ lexems := s.split(str)
+ result := poolOfStrings.BorrowStrings()
+
+ for _, lexem := range *lexems {
+ *result = append(*result, lexem.GetOriginal())
+ }
+ poolOfLexems.RedeemLexems(lexems)
+
+ return result
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/options.go b/vendor/github.com/go-openapi/swag/mangling/options.go
new file mode 100644
index 000000000000..3c92b2f18bf1
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/options.go
@@ -0,0 +1,150 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+type (
+ // PrefixFunc defines a safeguard rule (that may depend on the input string), to prefix
+ // a generated go name (in [NameMangler.ToGoName] and [NameMangler.ToVarName]).
+ //
+ // See [NameMangler.ToGoName] for more about which edge cases the prefix function covers.
+ PrefixFunc func(string) string
+
+ // ReplaceFunc is a transliteration function to replace special runes by a word.
+ ReplaceFunc func(r rune) (string, bool)
+
+ // Option to configure a [NameMangler].
+ Option func(*options)
+
+ options struct {
+ commonInitialisms []string
+
+ goNamePrefixFunc PrefixFunc
+ goNamePrefixFuncPtr *PrefixFunc
+ replaceFunc func(r rune) (string, bool)
+ }
+)
+
+func (o *options) prefixFunc() PrefixFunc {
+ if o.goNamePrefixFuncPtr != nil && *o.goNamePrefixFuncPtr != nil {
+ return *o.goNamePrefixFuncPtr
+ }
+
+ return o.goNamePrefixFunc
+}
+
+// WithGoNamePrefixFunc overrides the default prefix rule to safeguard generated go names.
+//
+// Example:
+//
+// This helps convert "123" into "{prefix}123" (a very crude strategy indeed, but it works).
+//
+// See [github.com/go-swagger/go-swagger/generator.DefaultFuncMap] for an example.
+//
+// The prefix function is assumed to return a string that starts with an upper case letter.
+//
+// The default is to prefix with "X".
+//
+// See [NameMangler.ToGoName] for more about which edge cases the prefix function covers.
+func WithGoNamePrefixFunc(fn PrefixFunc) Option {
+ return func(o *options) {
+ o.goNamePrefixFunc = fn
+ }
+}
+
+// WithGoNamePrefixFuncPtr is like [WithGoNamePrefixFunc] but it specifies a pointer to a function.
+//
+// [WithGoNamePrefixFunc] should be preferred in most situations. This option should only serve the
+// purpose of handling special situations where the prefix function is not an internal variable
+// (e.g. an exported package global).
+//
+// [WithGoNamePrefixFuncPtr] supersedes [WithGoNamePrefixFunc] if it also specified.
+//
+// If the provided pointer is nil or points to a nil value, this option has no effect.
+//
+// The caller should ensure that no undesirable concurrent changes are applied to the function pointed to.
+func WithGoNamePrefixFuncPtr(ptr *PrefixFunc) Option {
+ return func(o *options) {
+ o.goNamePrefixFuncPtr = ptr
+ }
+}
+
+// WithInitialisms declares the initialisms this mangler supports.
+//
+// This supersedes any pre-loaded defaults (see [DefaultInitialisms] for more about what initialisms are).
+//
+// It declares words to be recognized as "initialisms" (i.e. words that won't be camel cased or titled cased).
+//
+// Words must start with a (unicode) letter. If some don't, they are ignored.
+// Words are either fully capitalized or mixed-cased. Lower-case only words are considered capitalized.
+func WithInitialisms(words ...string) Option {
+ return func(o *options) {
+ o.commonInitialisms = words
+ }
+}
+
+// WithAdditionalInitialisms adds new initialisms to the currently supported list (see [DefaultInitialisms]).
+//
+// The same sanitization rules apply as those described for [WithInitialisms].
+func WithAdditionalInitialisms(words ...string) Option {
+ return func(o *options) {
+ o.commonInitialisms = append(o.commonInitialisms, words...)
+ }
+}
+
+// WithReplaceFunc specifies a custom transliteration function instead of the default.
+//
+// The default translates the following characters into words as follows:
+//
+// - '@' -> 'At'
+// - '&' -> 'And'
+// - '|' -> 'Pipe'
+// - '$' -> 'Dollar'
+// - '!' -> 'Bang'
+//
+// Notice that the outcome of a transliteration should always be titleized.
+func WithReplaceFunc(fn ReplaceFunc) Option {
+ return func(o *options) {
+ o.replaceFunc = fn
+ }
+}
+
+func defaultPrefixFunc(_ string) string {
+ return "X"
+}
+
+// defaultReplaceTable finds a word representation for special characters.
+func defaultReplaceTable(r rune) (string, bool) {
+ switch r {
+ case '@':
+ return "At ", true
+ case '&':
+ return "And ", true
+ case '|':
+ return "Pipe ", true
+ case '$':
+ return "Dollar ", true
+ case '!':
+ return "Bang ", true
+ case '-':
+ return "", true
+ case '_':
+ return "", true
+ default:
+ return "", false
+ }
+}
+
+func optionsWithDefaults(opts []Option) options {
+ o := options{
+ commonInitialisms: DefaultInitialisms(),
+ goNamePrefixFunc: defaultPrefixFunc,
+ replaceFunc: defaultReplaceTable,
+ }
+
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ return o
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/pools.go b/vendor/github.com/go-openapi/swag/mangling/pools.go
new file mode 100644
index 000000000000..f8104351445d
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/pools.go
@@ -0,0 +1,123 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import (
+ "bytes"
+ "sync"
+)
+
+const maxAllocMatches = 8
+
+type (
+ // memory pools of temporary objects.
+ //
+ // These are used to recycle temporarily allocated objects
+ // and relieve the GC from undue pressure.
+
+ matchesPool struct {
+ *sync.Pool
+ }
+
+ buffersPool struct {
+ *sync.Pool
+ }
+
+ lexemsPool struct {
+ *sync.Pool
+ }
+
+ stringsPool struct {
+ *sync.Pool
+ }
+)
+
+var (
+ // poolOfMatches holds temporary slices for recycling during the initialism match process
+ poolOfMatches = matchesPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := make(initialismMatches, 0, maxAllocMatches)
+
+ return &s
+ },
+ },
+ }
+
+ poolOfBuffers = buffersPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ return new(bytes.Buffer)
+ },
+ },
+ }
+
+ poolOfLexems = lexemsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := make([]nameLexem, 0, maxAllocMatches)
+
+ return &s
+ },
+ },
+ }
+
+ poolOfStrings = stringsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := make([]string, 0, maxAllocMatches)
+
+ return &s
+ },
+ },
+ }
+)
+
+func (p matchesPool) BorrowMatches() *initialismMatches {
+ s := p.Get().(*initialismMatches)
+ *s = (*s)[:0] // reset slice, keep allocated capacity
+
+ return s
+}
+
+func (p buffersPool) BorrowBuffer(size int) *bytes.Buffer {
+ s := p.Get().(*bytes.Buffer)
+ s.Reset()
+
+ if s.Cap() < size {
+ s.Grow(size)
+ }
+
+ return s
+}
+
+func (p lexemsPool) BorrowLexems() *[]nameLexem {
+ s := p.Get().(*[]nameLexem)
+ *s = (*s)[:0] // reset slice, keep allocated capacity
+
+ return s
+}
+
+func (p stringsPool) BorrowStrings() *[]string {
+ s := p.Get().(*[]string)
+ *s = (*s)[:0] // reset slice, keep allocated capacity
+
+ return s
+}
+
+func (p matchesPool) RedeemMatches(s *initialismMatches) {
+ p.Put(s)
+}
+
+func (p buffersPool) RedeemBuffer(s *bytes.Buffer) {
+ p.Put(s)
+}
+
+func (p lexemsPool) RedeemLexems(s *[]nameLexem) {
+ p.Put(s)
+}
+
+func (p stringsPool) RedeemStrings(s *[]string) {
+ p.Put(s)
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/split.go b/vendor/github.com/go-openapi/swag/mangling/split.go
new file mode 100644
index 000000000000..ad0dec1708ec
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/split.go
@@ -0,0 +1,306 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import (
+ "unicode"
+)
+
+type splitterOption func(*splitter)
+
+// withPostSplitInitialismCheck allows to catch initialisms after main split process
+func withPostSplitInitialismCheck(s *splitter) {
+ s.postSplitInitialismCheck = true
+}
+
+func withReplaceFunc(fn ReplaceFunc) func(*splitter) {
+ return func(s *splitter) {
+ s.replaceFunc = fn
+ }
+}
+
+func withInitialismsCache(c *initialismsCache) splitterOption {
+ return func(s *splitter) {
+ s.initialismsCache = c
+ }
+}
+
+type (
+ initialismMatch struct {
+ body []rune
+ start, end int
+ complete bool
+ hasPlural pluralForm
+ }
+ initialismMatches []initialismMatch
+)
+
+func (m initialismMatch) isZero() bool {
+ return m.start == 0 && m.end == 0
+}
+
+type splitter struct {
+ *initialismsCache
+
+ postSplitInitialismCheck bool
+ replaceFunc ReplaceFunc
+}
+
+func newSplitter(options ...splitterOption) splitter {
+ var s splitter
+
+ for _, option := range options {
+ option(&s)
+ }
+
+ if s.replaceFunc == nil {
+ s.replaceFunc = defaultReplaceTable
+ }
+
+ return s
+}
+
+func (s splitter) split(name string) *[]nameLexem {
+ nameRunes := []rune(name)
+ matches := s.gatherInitialismMatches(nameRunes)
+ if matches == nil {
+ return poolOfLexems.BorrowLexems()
+ }
+
+ return s.mapMatchesToNameLexems(nameRunes, matches)
+}
+
+func (s splitter) gatherInitialismMatches(nameRunes []rune) *initialismMatches {
+ var matches *initialismMatches
+
+ for currentRunePosition, currentRune := range nameRunes {
+ // recycle these allocations as we loop over runes
+ // with such recycling, only 2 slices should be allocated per call
+ // instead of o(n).
+ newMatches := poolOfMatches.BorrowMatches()
+
+ // check current initialism matches
+ if matches != nil { // skip first iteration
+ for _, match := range *matches {
+ if keepCompleteMatch := match.complete; keepCompleteMatch {
+ *newMatches = append(*newMatches, match)
+
+ // the match is complete: keep it then move on to next rune
+ continue
+ }
+
+ if currentRunePosition-match.start == len(match.body) {
+ // unmatched: skip
+ continue
+ }
+
+ currentMatchRune := match.body[currentRunePosition-match.start]
+ if currentMatchRune != currentRune {
+ // failed match, move on to next rune
+ continue
+ }
+
+ // try to complete ongoing match
+ if currentRunePosition-match.start == len(match.body)-1 {
+ // we are close; the next step is to check the symbol ahead
+ // if it is a lowercase letter, then it is not the end of match
+ // but the beginning of the next word.
+ //
+ // NOTE(fredbi): this heuristic sometimes leads to counterintuitive splits and
+ // perhaps (not sure yet) we should check against case _alternance_.
+ //
+ // Example:
+ //
+ // In the current version, in the sentence "IDS initialism", "ID" is recognized as an initialism,
+ // leading to a split like "id_s_initialism" (or IDSInitialism),
+ // whereas in the sentence "IDx initialism", it is not and produces something like
+ // "i_d_x_initialism" (or IDxInitialism). The generated file name is not great.
+ //
+ // Both go identifiers are tolerated by linters.
+ //
+ // Notice that the slightly different input "IDs initialism" is correctly detected
+ // as a pluralized initialism and produces something like "ids_initialism" (or IDsInitialism).
+
+ if currentRunePosition < len(nameRunes)-1 {
+ nextRune := nameRunes[currentRunePosition+1]
+
+ // recognize a plural form for this initialism (only simple pluralization is supported)
+ if nextRune == 's' && match.hasPlural == simplePlural {
+ // detected a pluralized initialism
+ match.body = append(match.body, nextRune)
+ currentRunePosition++
+ if currentRunePosition < len(nameRunes)-1 {
+ nextRune = nameRunes[currentRunePosition+1]
+ if newWord := unicode.IsLower(nextRune); newWord {
+ // it is the start of a new word.
+ // Match is only partial and the initialism is not recognized : move on
+ continue
+ }
+ }
+
+ // this is a pluralized match: keep it
+ match.complete = true
+ match.hasPlural = simplePlural
+ match.end = currentRunePosition
+ *newMatches = append(*newMatches, match)
+
+ // match is complete: keep it then move on to next rune
+ continue
+ }
+
+ if newWord := unicode.IsLower(nextRune); newWord {
+ // it is the start of a new word
+ // Match is only partial and the initialism is not recognized : move on
+ continue
+ }
+ }
+
+ match.complete = true
+ match.end = currentRunePosition
+ }
+
+ // append the ongoing matching attempt (not necessarily complete)
+ *newMatches = append(*newMatches, match)
+ }
+ }
+
+ // check for new initialism matches, based on the first character
+ for i, r := range s.initialismsRunes {
+ if r[0] == currentRune {
+ *newMatches = append(*newMatches, initialismMatch{
+ start: currentRunePosition,
+ body: r,
+ complete: false,
+ hasPlural: s.initialismsPluralForm[i],
+ })
+ }
+ }
+
+ if matches != nil {
+ poolOfMatches.RedeemMatches(matches)
+ }
+ matches = newMatches
+ }
+
+ // up to the caller to redeem this last slice
+ return matches
+}
+
+func (s splitter) mapMatchesToNameLexems(nameRunes []rune, matches *initialismMatches) *[]nameLexem {
+ nameLexems := poolOfLexems.BorrowLexems()
+
+ var lastAcceptedMatch initialismMatch
+ for _, match := range *matches {
+ if !match.complete {
+ continue
+ }
+
+ if firstMatch := lastAcceptedMatch.isZero(); firstMatch {
+ s.appendBrokenDownCasualString(nameLexems, nameRunes[:match.start])
+ *nameLexems = append(*nameLexems, s.breakInitialism(string(match.body)))
+
+ lastAcceptedMatch = match
+
+ continue
+ }
+
+ if overlappedMatch := match.start <= lastAcceptedMatch.end; overlappedMatch {
+ continue
+ }
+
+ middle := nameRunes[lastAcceptedMatch.end+1 : match.start]
+ s.appendBrokenDownCasualString(nameLexems, middle)
+ *nameLexems = append(*nameLexems, s.breakInitialism(string(match.body)))
+
+ lastAcceptedMatch = match
+ }
+
+ // we have not found any accepted matches
+ if lastAcceptedMatch.isZero() {
+ *nameLexems = (*nameLexems)[:0]
+ s.appendBrokenDownCasualString(nameLexems, nameRunes)
+ } else if lastAcceptedMatch.end+1 != len(nameRunes) {
+ rest := nameRunes[lastAcceptedMatch.end+1:]
+ s.appendBrokenDownCasualString(nameLexems, rest)
+ }
+
+ poolOfMatches.RedeemMatches(matches)
+
+ return nameLexems
+}
+
+func (s splitter) breakInitialism(original string) nameLexem {
+ return newInitialismNameLexem(original, original)
+}
+
+func (s splitter) appendBrokenDownCasualString(segments *[]nameLexem, str []rune) {
+ currentSegment := poolOfBuffers.BorrowBuffer(len(str)) // unlike strings.Builder, bytes.Buffer initial storage can reused
+ defer func() {
+ poolOfBuffers.RedeemBuffer(currentSegment)
+ }()
+
+ addCasualNameLexem := func(original string) {
+ *segments = append(*segments, newCasualNameLexem(original))
+ }
+
+ addInitialismNameLexem := func(original, match string) {
+ *segments = append(*segments, newInitialismNameLexem(original, match))
+ }
+
+ var addNameLexem func(string)
+ if s.postSplitInitialismCheck {
+ addNameLexem = func(original string) {
+ for i := range s.initialisms {
+ if isEqualFoldIgnoreSpace(s.initialismsUpperCased[i], original) {
+ addInitialismNameLexem(original, s.initialisms[i])
+
+ return
+ }
+ }
+
+ addCasualNameLexem(original)
+ }
+ } else {
+ addNameLexem = addCasualNameLexem
+ }
+
+ // NOTE: (performance). The few remaining non-amortized allocations
+ // lay in the code below: using String() forces
+ for _, rn := range str {
+ if replace, found := s.replaceFunc(rn); found {
+ if currentSegment.Len() > 0 {
+ addNameLexem(currentSegment.String())
+ currentSegment.Reset()
+ }
+
+ if replace != "" {
+ addNameLexem(replace)
+ }
+
+ continue
+ }
+
+ if !unicode.In(rn, unicode.L, unicode.M, unicode.N, unicode.Pc) {
+ if currentSegment.Len() > 0 {
+ addNameLexem(currentSegment.String())
+ currentSegment.Reset()
+ }
+
+ continue
+ }
+
+ if unicode.IsUpper(rn) {
+ if currentSegment.Len() > 0 {
+ addNameLexem(currentSegment.String())
+ }
+ currentSegment.Reset()
+ }
+
+ currentSegment.WriteRune(rn)
+ }
+
+ if currentSegment.Len() > 0 {
+ addNameLexem(currentSegment.String())
+ }
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/string_bytes.go b/vendor/github.com/go-openapi/swag/mangling/string_bytes.go
new file mode 100644
index 000000000000..28daaf72b1a1
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/string_bytes.go
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import "unsafe"
+
+// hackStringBytes returns the (unsafe) underlying bytes slice of a string.
+func hackStringBytes(str string) []byte {
+ return unsafe.Slice(unsafe.StringData(str), len(str))
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling/util.go b/vendor/github.com/go-openapi/swag/mangling/util.go
new file mode 100644
index 000000000000..0636417e360b
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling/util.go
@@ -0,0 +1,118 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package mangling
+
+import (
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// Removes leading whitespaces
+func trim(str string) string { return strings.TrimSpace(str) }
+
+// upper is strings.ToUpper() combined with trim
+func upper(str string) string {
+ return strings.ToUpper(trim(str))
+}
+
+// lower is strings.ToLower() combined with trim
+func lower(str string) string {
+ return strings.ToLower(trim(str))
+}
+
+// isEqualFoldIgnoreSpace is the same as strings.EqualFold, but
+// it ignores leading and trailing blank spaces in the compared
+// string.
+//
+// base is assumed to be composed of upper-cased runes, and be already
+// trimmed.
+//
+// This code is heavily inspired from strings.EqualFold.
+func isEqualFoldIgnoreSpace(base []rune, str string) bool {
+ var i, baseIndex int
+ // equivalent to b := []byte(str), but without data copy
+ b := hackStringBytes(str)
+
+ for i < len(b) {
+ if c := b[i]; c < utf8.RuneSelf {
+ // fast path for ASCII
+ if c != ' ' && c != '\t' {
+ break
+ }
+ i++
+
+ continue
+ }
+
+ // unicode case
+ r, size := utf8.DecodeRune(b[i:])
+ if !unicode.IsSpace(r) {
+ break
+ }
+ i += size
+ }
+
+ if i >= len(b) {
+ return len(base) == 0
+ }
+
+ for _, baseRune := range base {
+ if i >= len(b) {
+ break
+ }
+
+ if c := b[i]; c < utf8.RuneSelf {
+ // single byte rune case (ASCII)
+ if baseRune >= utf8.RuneSelf {
+ return false
+ }
+
+ baseChar := byte(baseRune)
+ if c != baseChar && ((c < 'a') || (c > 'z') || (c-'a'+'A' != baseChar)) {
+ return false
+ }
+
+ baseIndex++
+ i++
+
+ continue
+ }
+
+ // unicode case
+ r, size := utf8.DecodeRune(b[i:])
+ if unicode.ToUpper(r) != baseRune {
+ return false
+ }
+ baseIndex++
+ i += size
+ }
+
+ if baseIndex != len(base) {
+ return false
+ }
+
+ // all passed: now we should only have blanks
+ for i < len(b) {
+ if c := b[i]; c < utf8.RuneSelf {
+ // fast path for ASCII
+ if c != ' ' && c != '\t' {
+ return false
+ }
+ i++
+
+ continue
+ }
+
+ // unicode case
+ r, size := utf8.DecodeRune(b[i:])
+ if !unicode.IsSpace(r) {
+ return false
+ }
+
+ i += size
+ }
+
+ return true
+}
diff --git a/vendor/github.com/go-openapi/swag/mangling_iface.go b/vendor/github.com/go-openapi/swag/mangling_iface.go
new file mode 100644
index 000000000000..98b9a9992930
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/mangling_iface.go
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import "github.com/go-openapi/swag/mangling"
+
+// GoNamePrefixFunc sets an optional rule to prefix go names
+// which do not start with a letter.
+//
+// GoNamePrefixFunc should not be written to while concurrently using the other mangling functions of this package.
+//
+// Deprecated: use [mangling.WithGoNamePrefixFunc] instead.
+var GoNamePrefixFunc mangling.PrefixFunc
+
+// swagNameMangler is a global instance of the name mangler specifically alloted
+// to support deprecated functions.
+var swagNameMangler = mangling.NewNameMangler(
+ mangling.WithGoNamePrefixFuncPtr(&GoNamePrefixFunc),
+)
+
+// AddInitialisms adds additional initialisms to the default list (see [mangling.DefaultInitialisms]).
+//
+// AddInitialisms is not safe to be called concurrently.
+//
+// Deprecated: use [mangling.WithAdditionalInitialisms] instead.
+func AddInitialisms(words ...string) {
+ swagNameMangler.AddInitialisms(words...)
+}
+
+// Camelize a single word.
+//
+// Deprecated: use [mangling.NameMangler.Camelize] instead.
+func Camelize(word string) string { return swagNameMangler.Camelize(word) }
+
+// ToFileName lowercases and underscores a go type name.
+//
+// Deprecated: use [mangling.NameMangler.ToFileName] instead.
+func ToFileName(name string) string { return swagNameMangler.ToFileName(name) }
+
+// ToCommandName lowercases and underscores a go type name.
+//
+// Deprecated: use [mangling.NameMangler.ToCommandName] instead.
+func ToCommandName(name string) string { return swagNameMangler.ToCommandName(name) }
+
+// ToHumanNameLower represents a code name as a human series of words.
+//
+// Deprecated: use [mangling.NameMangler.ToHumanNameLower] instead.
+func ToHumanNameLower(name string) string { return swagNameMangler.ToHumanNameLower(name) }
+
+// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized.
+//
+// Deprecated: use [mangling.NameMangler.ToHumanNameTitle] instead.
+func ToHumanNameTitle(name string) string { return swagNameMangler.ToHumanNameTitle(name) }
+
+// ToJSONName camel-cases a name which can be underscored or pascal-cased.
+//
+// Deprecated: use [mangling.NameMangler.ToJSONName] instead.
+func ToJSONName(name string) string { return swagNameMangler.ToJSONName(name) }
+
+// ToVarName camel-cases a name which can be underscored or pascal-cased.
+//
+// Deprecated: use [mangling.NameMangler.ToVarName] instead.
+func ToVarName(name string) string { return swagNameMangler.ToVarName(name) }
+
+// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes.
+//
+// Deprecated: use [mangling.NameMangler.ToGoName] instead.
+func ToGoName(name string) string { return swagNameMangler.ToGoName(name) }
diff --git a/vendor/github.com/go-openapi/swag/netutils/LICENSE b/vendor/github.com/go-openapi/swag/netutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/netutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/netutils/doc.go b/vendor/github.com/go-openapi/swag/netutils/doc.go
new file mode 100644
index 000000000000..74282f8e51c5
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/netutils/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package netutils provides helpers for network-related tasks.
+package netutils
diff --git a/vendor/github.com/go-openapi/swag/netutils/net.go b/vendor/github.com/go-openapi/swag/netutils/net.go
new file mode 100644
index 000000000000..82a1544af7bf
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/netutils/net.go
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package netutils
+
+import (
+ "net"
+ "strconv"
+)
+
+// SplitHostPort splits a network address into a host and a port.
+//
+// The difference with the standard net.SplitHostPort is that the port is converted to an int.
+//
+// The port is -1 when there is no port to be found.
+func SplitHostPort(addr string) (host string, port int, err error) {
+ h, p, err := net.SplitHostPort(addr)
+ if err != nil {
+ return "", -1, err
+ }
+ if p == "" {
+ return "", -1, &net.AddrError{Err: "missing port in address", Addr: addr}
+ }
+
+ pi, err := strconv.Atoi(p)
+ if err != nil {
+ return "", -1, err
+ }
+
+ return h, pi, nil
+}
diff --git a/vendor/github.com/go-openapi/swag/netutils_iface.go b/vendor/github.com/go-openapi/swag/netutils_iface.go
new file mode 100644
index 000000000000..d658de25b3f3
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/netutils_iface.go
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import "github.com/go-openapi/swag/netutils"
+
+// SplitHostPort splits a network address into a host and a port.
+//
+// Deprecated: use [netutils.SplitHostPort] instead.
+func SplitHostPort(addr string) (host string, port int, err error) {
+ return netutils.SplitHostPort(addr)
+}
diff --git a/vendor/github.com/go-openapi/swag/stringutils/LICENSE b/vendor/github.com/go-openapi/swag/stringutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/stringutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/stringutils/collection_formats.go b/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go
new file mode 100644
index 000000000000..28056ad25c38
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go
@@ -0,0 +1,74 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package stringutils
+
+import "strings"
+
+const (
+ // collectionFormatComma = "csv"
+ collectionFormatSpace = "ssv"
+ collectionFormatTab = "tsv"
+ collectionFormatPipe = "pipes"
+ collectionFormatMulti = "multi"
+
+ collectionFormatDefaultSep = ","
+)
+
+// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute):
+//
+// ssv: space separated value
+// tsv: tab separated value
+// pipes: pipe (|) separated value
+// csv: comma separated value (default)
+func JoinByFormat(data []string, format string) []string {
+ if len(data) == 0 {
+ return data
+ }
+ var sep string
+ switch format {
+ case collectionFormatSpace:
+ sep = " "
+ case collectionFormatTab:
+ sep = "\t"
+ case collectionFormatPipe:
+ sep = "|"
+ case collectionFormatMulti:
+ return data
+ default:
+ sep = collectionFormatDefaultSep
+ }
+ return []string{strings.Join(data, sep)}
+}
+
+// SplitByFormat splits a string by a known format:
+//
+// ssv: space separated value
+// tsv: tab separated value
+// pipes: pipe (|) separated value
+// csv: comma separated value (default)
+func SplitByFormat(data, format string) []string {
+ if data == "" {
+ return nil
+ }
+ var sep string
+ switch format {
+ case collectionFormatSpace:
+ sep = " "
+ case collectionFormatTab:
+ sep = "\t"
+ case collectionFormatPipe:
+ sep = "|"
+ case collectionFormatMulti:
+ return nil
+ default:
+ sep = collectionFormatDefaultSep
+ }
+ var result []string
+ for _, s := range strings.Split(data, sep) {
+ if ts := strings.TrimSpace(s); ts != "" {
+ result = append(result, ts)
+ }
+ }
+ return result
+}
diff --git a/vendor/github.com/go-openapi/swag/stringutils/doc.go b/vendor/github.com/go-openapi/swag/stringutils/doc.go
new file mode 100644
index 000000000000..c6d17a1160bd
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/stringutils/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package stringutils exposes helpers to search and process strings.
+package stringutils
diff --git a/vendor/github.com/go-openapi/swag/stringutils/strings.go b/vendor/github.com/go-openapi/swag/stringutils/strings.go
new file mode 100644
index 000000000000..cd792b7d0834
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/stringutils/strings.go
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package stringutils
+
+import (
+ "slices"
+ "strings"
+)
+
+// ContainsStrings searches a slice of strings for a case-sensitive match
+//
+// Now equivalent to the standard library [slice.Contains].
+func ContainsStrings(coll []string, item string) bool {
+ return slices.Contains(coll, item)
+}
+
+// ContainsStringsCI searches a slice of strings for a case-insensitive match
+func ContainsStringsCI(coll []string, item string) bool {
+ return slices.ContainsFunc(coll, func(e string) bool {
+ return strings.EqualFold(e, item)
+ })
+}
diff --git a/vendor/github.com/go-openapi/swag/stringutils_iface.go b/vendor/github.com/go-openapi/swag/stringutils_iface.go
new file mode 100644
index 000000000000..dbfa48484306
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/stringutils_iface.go
@@ -0,0 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import "github.com/go-openapi/swag/stringutils"
+
+// ContainsStrings searches a slice of strings for a case-sensitive match.
+//
+// Deprecated: use [slices.Contains] or [stringutils.ContainsStrings] instead.
+func ContainsStrings(coll []string, item string) bool {
+ return stringutils.ContainsStrings(coll, item)
+}
+
+// ContainsStringsCI searches a slice of strings for a case-insensitive match.
+//
+// Deprecated: use [stringutils.ContainsStringsCI] instead.
+func ContainsStringsCI(coll []string, item string) bool {
+ return stringutils.ContainsStringsCI(coll, item)
+}
+
+// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute).
+//
+// Deprecated: use [stringutils.JoinByFormat] instead.
+func JoinByFormat(data []string, format string) []string {
+ return stringutils.JoinByFormat(data, format)
+}
+
+// SplitByFormat splits a string by a known format.
+//
+// Deprecated: use [stringutils.SplitByFormat] instead.
+func SplitByFormat(data, format string) []string {
+ return stringutils.SplitByFormat(data, format)
+}
diff --git a/vendor/github.com/go-openapi/swag/typeutils/LICENSE b/vendor/github.com/go-openapi/swag/typeutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/typeutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/typeutils/doc.go b/vendor/github.com/go-openapi/swag/typeutils/doc.go
new file mode 100644
index 000000000000..66bed20dff0e
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/typeutils/doc.go
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package typeutils exposes utilities to inspect generic types.
+package typeutils
diff --git a/vendor/github.com/go-openapi/swag/typeutils/types.go b/vendor/github.com/go-openapi/swag/typeutils/types.go
new file mode 100644
index 000000000000..55487a673c4b
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/typeutils/types.go
@@ -0,0 +1,80 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package typeutils
+
+import "reflect"
+
+type zeroable interface {
+ IsZero() bool
+}
+
+// IsZero returns true when the value passed into the function is a zero value.
+// This allows for safer checking of interface values.
+func IsZero(data any) bool {
+ v := reflect.ValueOf(data)
+ // check for nil data
+ switch v.Kind() { //nolint:exhaustive
+ case
+ reflect.Interface,
+ reflect.Func,
+ reflect.Chan,
+ reflect.Pointer,
+ reflect.UnsafePointer,
+ reflect.Map,
+ reflect.Slice:
+ if v.IsNil() {
+ return true
+ }
+ }
+
+ // check for things that have an IsZero method instead
+ if vv, ok := data.(zeroable); ok {
+ return vv.IsZero()
+ }
+
+ // continue with slightly more complex reflection
+ switch v.Kind() { //nolint:exhaustive
+ case reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Struct, reflect.Array:
+ return reflect.DeepEqual(data, reflect.Zero(v.Type()).Interface())
+ case reflect.Invalid:
+ return true
+ default:
+ return false
+ }
+}
+
+// IsNil checks if input is nil.
+//
+// For types chan, func, interface, map, pointer, or slice it returns true if its argument is nil.
+//
+// See [reflect.Value.IsNil].
+func IsNil(input any) bool {
+ if input == nil {
+ return true
+ }
+
+ kind := reflect.TypeOf(input).Kind()
+ switch kind { //nolint:exhaustive
+ case reflect.Pointer,
+ reflect.UnsafePointer,
+ reflect.Map,
+ reflect.Slice,
+ reflect.Chan,
+ reflect.Interface,
+ reflect.Func:
+ return reflect.ValueOf(input).IsNil()
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/go-openapi/swag/typeutils_iface.go b/vendor/github.com/go-openapi/swag/typeutils_iface.go
new file mode 100644
index 000000000000..b63813ea408e
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/typeutils_iface.go
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import "github.com/go-openapi/swag/typeutils"
+
+// IsZero returns true when the value passed into the function is a zero value.
+// This allows for safer checking of interface values.
+//
+// Deprecated: use [typeutils.IsZero] instead.
+func IsZero(data any) bool { return typeutils.IsZero(data) }
diff --git a/vendor/github.com/go-openapi/swag/yamlutils/LICENSE b/vendor/github.com/go-openapi/swag/yamlutils/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/yamlutils/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/swag/yamlutils/doc.go b/vendor/github.com/go-openapi/swag/yamlutils/doc.go
new file mode 100644
index 000000000000..7bb92a82f1b0
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/yamlutils/doc.go
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package yamlutils provides utilities to work with YAML documents.
+//
+// - [BytesToYAMLDoc] to construct a [yaml.Node] document
+// - [YAMLToJSON] to convert a [yaml.Node] document to JSON bytes
+// - [YAMLMapSlice] to serialize and deserialize YAML with the order of keys maintained
+package yamlutils
+
+import (
+ _ "go.yaml.in/yaml/v3" // for documentation purpose only
+)
diff --git a/vendor/github.com/go-openapi/swag/yamlutils/errors.go b/vendor/github.com/go-openapi/swag/yamlutils/errors.go
new file mode 100644
index 000000000000..e87bc5e8beb3
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/yamlutils/errors.go
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package yamlutils
+
+type yamlError string
+
+const (
+ // ErrYAML is an error raised by YAML utilities
+ ErrYAML yamlError = "yaml error"
+)
+
+func (e yamlError) Error() string {
+ return string(e)
+}
diff --git a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go
new file mode 100644
index 000000000000..3daf68dbba0c
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go
@@ -0,0 +1,316 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package yamlutils
+
+import (
+ "fmt"
+ "iter"
+ "slices"
+ "sort"
+ "strconv"
+
+ "github.com/go-openapi/swag/conv"
+ "github.com/go-openapi/swag/jsonutils"
+ "github.com/go-openapi/swag/jsonutils/adapters/ifaces"
+ "github.com/go-openapi/swag/typeutils"
+ yaml "go.yaml.in/yaml/v3"
+)
+
+var (
+ _ yaml.Marshaler = YAMLMapSlice{}
+ _ yaml.Unmarshaler = &YAMLMapSlice{}
+)
+
+// YAMLMapSlice represents a YAML object, with the order of keys maintained.
+//
+// It is similar to [jsonutils.JSONMapSlice] and also knows how to marshal and unmarshal YAML.
+//
+// It behaves like an ordered map, but keys can't be accessed in constant time.
+type YAMLMapSlice []YAMLMapItem
+
+// YAMLMapItem represents the value of a key in a YAML object held by [YAMLMapSlice].
+//
+// It is entirely equivalent to [jsonutils.JSONMapItem], with the same limitation that
+// you should not Marshal or Unmarshal directly this type, outside of a [YAMLMapSlice].
+type YAMLMapItem = jsonutils.JSONMapItem
+
+func (s YAMLMapSlice) OrderedItems() iter.Seq2[string, any] {
+ return func(yield func(string, any) bool) {
+ for _, item := range s {
+ if !yield(item.Key, item.Value) {
+ return
+ }
+ }
+ }
+}
+
+// SetOrderedItems implements [ifaces.SetOrdered]: it merges keys passed by the iterator argument
+// into the [YAMLMapSlice].
+func (s *YAMLMapSlice) SetOrderedItems(items iter.Seq2[string, any]) {
+ if items == nil {
+ // force receiver to be a nil slice
+ *s = nil
+
+ return
+ }
+
+ m := *s
+ if len(m) > 0 {
+ // update mode: short-circuited when unmarshaling fresh data structures
+ idx := make(map[string]int, len(m))
+
+ for i, item := range m {
+ idx[item.Key] = i
+ }
+
+ for k, v := range items {
+ idx, ok := idx[k]
+ if ok {
+ m[idx].Value = v
+
+ continue
+ }
+
+ m = append(m, YAMLMapItem{Key: k, Value: v})
+ }
+
+ *s = m
+
+ return
+ }
+
+ for k, v := range items {
+ m = append(m, YAMLMapItem{Key: k, Value: v})
+ }
+
+ *s = m
+}
+
+// MarshalJSON renders this YAML object as JSON bytes.
+//
+// The difference with standard JSON marshaling is that the order of keys is maintained.
+func (s YAMLMapSlice) MarshalJSON() ([]byte, error) {
+ return jsonutils.JSONMapSlice(s).MarshalJSON()
+}
+
+// UnmarshalJSON builds this YAML object from JSON bytes.
+//
+// The difference with standard JSON marshaling is that the order of keys is maintained.
+func (s *YAMLMapSlice) UnmarshalJSON(data []byte) error {
+ js := jsonutils.JSONMapSlice(*s)
+
+ if err := js.UnmarshalJSON(data); err != nil {
+ return err
+ }
+
+ *s = YAMLMapSlice(js)
+
+ return nil
+}
+
+// MarshalYAML produces a YAML document as bytes
+//
+// The difference with standard YAML marshaling is that the order of keys is maintained.
+//
+// It implements [yaml.Marshaler].
+func (s YAMLMapSlice) MarshalYAML() (any, error) {
+ if typeutils.IsNil(s) {
+ return []byte("null\n"), nil
+ }
+ var n yaml.Node
+ n.Kind = yaml.DocumentNode
+ var nodes []*yaml.Node
+
+ for _, item := range s {
+ nn, err := json2yaml(item.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ ns := []*yaml.Node{
+ {
+ Kind: yaml.ScalarNode,
+ Tag: yamlStringScalar,
+ Value: item.Key,
+ },
+ nn,
+ }
+ nodes = append(nodes, ns...)
+ }
+
+ n.Content = []*yaml.Node{
+ {
+ Kind: yaml.MappingNode,
+ Content: nodes,
+ },
+ }
+
+ return yaml.Marshal(&n)
+}
+
+// UnmarshalYAML builds a YAMLMapSlice object from a YAML document [yaml.Node].
+//
+// It implements [yaml.Unmarshaler].
+func (s *YAMLMapSlice) UnmarshalYAML(node *yaml.Node) error {
+ if typeutils.IsNil(*s) {
+ // allow to unmarshal with a simple var declaration (nil slice)
+ *s = YAMLMapSlice{}
+ }
+ if node == nil {
+ *s = nil
+ return nil
+ }
+
+ const sensibleAllocDivider = 2
+ m := slices.Grow(*s, len(node.Content)/sensibleAllocDivider)
+ m = m[:0]
+
+ for i := 0; i < len(node.Content); i += 2 {
+ var nmi YAMLMapItem
+ k, err := yamlStringScalarC(node.Content[i])
+ if err != nil {
+ return fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML)
+ }
+ nmi.Key = k
+ v, err := yamlNode(node.Content[i+1])
+ if err != nil {
+ return fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML)
+ }
+ nmi.Value = v
+ m = append(m, nmi)
+ }
+
+ *s = m
+
+ return nil
+}
+
+func json2yaml(item any) (*yaml.Node, error) {
+ if typeutils.IsNil(item) {
+ return &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "null",
+ }, nil
+ }
+
+ switch val := item.(type) {
+ case ifaces.Ordered:
+ return orderedYAML(val)
+
+ case map[string]any:
+ var n yaml.Node
+ n.Kind = yaml.MappingNode
+ keys := make([]string, 0, len(val))
+ for k := range val {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ for _, k := range keys {
+ v := val[k]
+ childNode, err := json2yaml(v)
+ if err != nil {
+ return nil, err
+ }
+ n.Content = append(n.Content, &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlStringScalar,
+ Value: k,
+ }, childNode)
+ }
+ return &n, nil
+
+ case []any:
+ var n yaml.Node
+ n.Kind = yaml.SequenceNode
+ for i := range val {
+ childNode, err := json2yaml(val[i])
+ if err != nil {
+ return nil, err
+ }
+ n.Content = append(n.Content, childNode)
+ }
+ return &n, nil
+ case string:
+ return &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlStringScalar,
+ Value: val,
+ }, nil
+ case float32:
+ return floatNode(val)
+ case float64:
+ return floatNode(val)
+ case int:
+ return integerNode(val)
+ case int8:
+ return integerNode(val)
+ case int16:
+ return integerNode(val)
+ case int32:
+ return integerNode(val)
+ case int64:
+ return integerNode(val)
+ case uint:
+ return uintegerNode(val)
+ case uint8:
+ return uintegerNode(val)
+ case uint16:
+ return uintegerNode(val)
+ case uint32:
+ return uintegerNode(val)
+ case uint64:
+ return uintegerNode(val)
+ case bool:
+ return &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlBoolScalar,
+ Value: strconv.FormatBool(val),
+ }, nil
+ default:
+ return nil, fmt.Errorf("unhandled type: %T: %w", val, ErrYAML)
+ }
+}
+
+func floatNode[T conv.Float](val T) (*yaml.Node, error) {
+ return &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlFloatScalar,
+ Value: conv.FormatFloat(val),
+ }, nil
+}
+
+func integerNode[T conv.Signed](val T) (*yaml.Node, error) {
+ return &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlIntScalar,
+ Value: conv.FormatInteger(val),
+ }, nil
+}
+
+func uintegerNode[T conv.Unsigned](val T) (*yaml.Node, error) {
+ return &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlIntScalar,
+ Value: conv.FormatUinteger(val),
+ }, nil
+}
+
+func orderedYAML[T ifaces.Ordered](val T) (*yaml.Node, error) {
+ var n yaml.Node
+ n.Kind = yaml.MappingNode
+ for key, value := range val.OrderedItems() {
+ childNode, err := json2yaml(value)
+ if err != nil {
+ return nil, err
+ }
+
+ n.Content = append(n.Content, &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: yamlStringScalar,
+ Value: key,
+ }, childNode)
+ }
+ return &n, nil
+}
diff --git a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go
new file mode 100644
index 000000000000..e3aff3c2fde9
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go
@@ -0,0 +1,211 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package yamlutils
+
+import (
+ json "encoding/json"
+ "fmt"
+ "strconv"
+
+ "github.com/go-openapi/swag/jsonutils"
+ yaml "go.yaml.in/yaml/v3"
+)
+
+// YAMLToJSON converts a YAML document into JSON bytes.
+//
+// Note: a YAML document is the output from a [yaml.Marshaler], e.g a pointer to a [yaml.Node].
+//
+// [YAMLToJSON] is typically called after [BytesToYAMLDoc].
+func YAMLToJSON(value any) (json.RawMessage, error) {
+ jm, err := transformData(value)
+ if err != nil {
+ return nil, err
+ }
+
+ b, err := jsonutils.WriteJSON(jm)
+
+ return json.RawMessage(b), err
+}
+
+// BytesToYAMLDoc converts a byte slice into a YAML document.
+//
+// This function only supports root documents that are objects.
+//
+// A YAML document is a pointer to a [yaml.Node].
+func BytesToYAMLDoc(data []byte) (any, error) {
+ var document yaml.Node // preserve order that is present in the document
+ if err := yaml.Unmarshal(data, &document); err != nil {
+ return nil, err
+ }
+ if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode {
+ return nil, fmt.Errorf("only YAML documents that are objects are supported: %w", ErrYAML)
+ }
+ return &document, nil
+}
+
+func yamlNode(root *yaml.Node) (any, error) {
+ switch root.Kind {
+ case yaml.DocumentNode:
+ return yamlDocument(root)
+ case yaml.SequenceNode:
+ return yamlSequence(root)
+ case yaml.MappingNode:
+ return yamlMapping(root)
+ case yaml.ScalarNode:
+ return yamlScalar(root)
+ case yaml.AliasNode:
+ return yamlNode(root.Alias)
+ default:
+ return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML)
+ }
+}
+
+func yamlDocument(node *yaml.Node) (any, error) {
+ if len(node.Content) != 1 {
+ return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML)
+ }
+ return yamlNode(node.Content[0])
+}
+
+func yamlMapping(node *yaml.Node) (any, error) {
+ const sensibleAllocDivider = 2 // nodes concatenate (key,value) sequences
+ m := make(YAMLMapSlice, len(node.Content)/sensibleAllocDivider)
+
+ if err := m.UnmarshalYAML(node); err != nil {
+ return nil, err
+ }
+
+ return m, nil
+}
+
+func yamlSequence(node *yaml.Node) (any, error) {
+ s := make([]any, 0)
+
+ for i := range len(node.Content) {
+ v, err := yamlNode(node.Content[i])
+ if err != nil {
+ return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML)
+ }
+ s = append(s, v)
+ }
+ return s, nil
+}
+
+const ( // See https://yaml.org/type/
+ yamlStringScalar = "tag:yaml.org,2002:str"
+ yamlIntScalar = "tag:yaml.org,2002:int"
+ yamlBoolScalar = "tag:yaml.org,2002:bool"
+ yamlFloatScalar = "tag:yaml.org,2002:float"
+ yamlTimestamp = "tag:yaml.org,2002:timestamp"
+ yamlNull = "tag:yaml.org,2002:null"
+)
+
+func yamlScalar(node *yaml.Node) (any, error) {
+ switch node.LongTag() {
+ case yamlStringScalar:
+ return node.Value, nil
+ case yamlBoolScalar:
+ b, err := strconv.ParseBool(node.Value)
+ if err != nil {
+ return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w: %w", node.Value, err, ErrYAML)
+ }
+ return b, nil
+ case yamlIntScalar:
+ i, err := strconv.ParseInt(node.Value, 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w: %w", node.Value, err, ErrYAML)
+ }
+ return i, nil
+ case yamlFloatScalar:
+ f, err := strconv.ParseFloat(node.Value, 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w: %w", node.Value, err, ErrYAML)
+ }
+ return f, nil
+ case yamlTimestamp:
+ // YAML timestamp is marshaled as string, not time
+ return node.Value, nil
+ case yamlNull:
+ return nil, nil //nolint:nilnil
+ default:
+ return nil, fmt.Errorf("YAML tag %q is not supported: %w", node.LongTag(), ErrYAML)
+ }
+}
+
+func yamlStringScalarC(node *yaml.Node) (string, error) {
+ if node.Kind != yaml.ScalarNode {
+ return "", fmt.Errorf("expecting a string scalar but got %q: %w", node.Kind, ErrYAML)
+ }
+ switch node.LongTag() {
+ case yamlStringScalar, yamlIntScalar, yamlFloatScalar:
+ return node.Value, nil
+ default:
+ return "", fmt.Errorf("YAML tag %q is not supported as map key: %w", node.LongTag(), ErrYAML)
+ }
+}
+
+func format(t any) (string, error) {
+ switch k := t.(type) {
+ case string:
+ return k, nil
+ case uint:
+ return strconv.FormatUint(uint64(k), 10), nil
+ case uint8:
+ return strconv.FormatUint(uint64(k), 10), nil
+ case uint16:
+ return strconv.FormatUint(uint64(k), 10), nil
+ case uint32:
+ return strconv.FormatUint(uint64(k), 10), nil
+ case uint64:
+ return strconv.FormatUint(k, 10), nil
+ case int:
+ return strconv.Itoa(k), nil
+ case int8:
+ return strconv.FormatInt(int64(k), 10), nil
+ case int16:
+ return strconv.FormatInt(int64(k), 10), nil
+ case int32:
+ return strconv.FormatInt(int64(k), 10), nil
+ case int64:
+ return strconv.FormatInt(k, 10), nil
+ default:
+ return "", fmt.Errorf("unexpected map key type, got: %T: %w", k, ErrYAML)
+ }
+}
+
+func transformData(input any) (out any, err error) {
+ switch in := input.(type) {
+ case yaml.Node:
+ return yamlNode(&in)
+ case *yaml.Node:
+ return yamlNode(in)
+ case map[any]any:
+ o := make(YAMLMapSlice, 0, len(in))
+ for ke, va := range in {
+ var nmi YAMLMapItem
+ if nmi.Key, err = format(ke); err != nil {
+ return nil, err
+ }
+
+ v, ert := transformData(va)
+ if ert != nil {
+ return nil, ert
+ }
+ nmi.Value = v
+ o = append(o, nmi)
+ }
+ return o, nil
+ case []any:
+ len1 := len(in)
+ o := make([]any, len1)
+ for i := range len1 {
+ o[i], err = transformData(in[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+ return o, nil
+ }
+ return input, nil
+}
diff --git a/vendor/github.com/go-openapi/swag/yamlutils_iface.go b/vendor/github.com/go-openapi/swag/yamlutils_iface.go
new file mode 100644
index 000000000000..57767efc567f
--- /dev/null
+++ b/vendor/github.com/go-openapi/swag/yamlutils_iface.go
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package swag
+
+import (
+ "encoding/json"
+
+ "github.com/go-openapi/swag/yamlutils"
+)
+
+// YAMLToJSON converts YAML unmarshaled data into json compatible data
+//
+// Deprecated: use [yamlutils.YAMLToJSON] instead.
+func YAMLToJSON(data any) (json.RawMessage, error) { return yamlutils.YAMLToJSON(data) }
+
+// BytesToYAMLDoc converts a byte slice into a YAML document
+//
+// Deprecated: use [yamlutils.BytesToYAMLDoc] instead.
+func BytesToYAMLDoc(data []byte) (any, error) { return yamlutils.BytesToYAMLDoc(data) }
diff --git a/vendor/github.com/go-openapi/validate/.editorconfig b/vendor/github.com/go-openapi/validate/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/validate/.gitattributes b/vendor/github.com/go-openapi/validate/.gitattributes
new file mode 100644
index 000000000000..49ad52766abb
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/.gitattributes
@@ -0,0 +1,2 @@
+# gofmt always uses LF, whereas Git uses CRLF on Windows.
+*.go text eol=lf
diff --git a/vendor/github.com/go-openapi/validate/.gitignore b/vendor/github.com/go-openapi/validate/.gitignore
new file mode 100644
index 000000000000..fea8b84eca99
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/.gitignore
@@ -0,0 +1,5 @@
+secrets.yml
+coverage.out
+*.cov
+*.out
+playground
diff --git a/vendor/github.com/go-openapi/validate/.golangci.yml b/vendor/github.com/go-openapi/validate/.golangci.yml
new file mode 100644
index 000000000000..10c513342fce
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/.golangci.yml
@@ -0,0 +1,76 @@
+version: "2"
+linters:
+ default: all
+ disable:
+ - cyclop
+ - depguard
+ - errchkjson
+ - errorlint
+ - exhaustruct
+ - forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - godot
+ - godox
+ - gomoddirectives
+ - gosmopolitan
+ - inamedparam
+ - intrange
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nlreturn
+ - nonamedreturns
+ - noinlineerr
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+issues:
+ # Maximum issues count per one linter.
+ # Set to 0 to disable.
+ # Default: 50
+ max-issues-per-linter: 0
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 0
diff --git a/vendor/github.com/go-openapi/validate/BENCHMARK.md b/vendor/github.com/go-openapi/validate/BENCHMARK.md
new file mode 100644
index 000000000000..79cf6a077ba2
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/BENCHMARK.md
@@ -0,0 +1,31 @@
+# Benchmark
+
+Validating the Kubernetes Swagger API
+
+## v0.22.6: 60,000,000 allocs
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/validate
+cpu: AMD Ryzen 7 5800X 8-Core Processor
+Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 8549863982 ns/op 7067424936 B/op 59583275 allocs/op
+```
+
+## After refact PR: minor but noticable improvements: 25,000,000 allocs
+```
+go test -bench Spec
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/validate
+cpu: AMD Ryzen 7 5800X 8-Core Processor
+Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 4064535557 ns/op 3379715592 B/op 25320330 allocs/op
+```
+
+## After reduce GC pressure PR: 17,000,000 allocs
+```
+goos: linux
+goarch: amd64
+pkg: github.com/go-openapi/validate
+cpu: AMD Ryzen 7 5800X 8-Core Processor
+Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 3758414145 ns/op 2593881496 B/op 17111373 allocs/op
+```
diff --git a/vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..9322b065e37a
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/github.com/go-openapi/validate/LICENSE b/vendor/github.com/go-openapi/validate/LICENSE
new file mode 100644
index 000000000000..d64569567334
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/github.com/go-openapi/validate/README.md b/vendor/github.com/go-openapi/validate/README.md
new file mode 100644
index 000000000000..73d87ce4f01f
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/README.md
@@ -0,0 +1,40 @@
+# Validation helpers [](https://github.com/go-openapi/validate/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/validate)
+
+[](https://slackin.goswagger.io)
+[](https://raw.githubusercontent.com/go-openapi/validate/master/LICENSE)
+[](https://pkg.go.dev/github.com/go-openapi/validate)
+[](https://goreportcard.com/report/github.com/go-openapi/validate)
+
+This package provides helpers to validate Swagger 2.0. specification (aka OpenAPI 2.0).
+
+Reference can be found here: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md.
+
+## What's inside?
+
+* A validator for Swagger specifications
+* A validator for JSON schemas draft4
+* Helper functions to validate individual values (used by code generated by [go-swagger](https://github.com/go-swagger/go-swagger)).
+ * Required, RequiredNumber, RequiredString
+ * ReadOnly
+ * UniqueItems, MaxItems, MinItems
+ * Enum, EnumCase
+ * Pattern, MinLength, MaxLength
+ * Minimum, Maximum, MultipleOf
+ * FormatOf
+
+[Documentation](https://pkg.go.dev/github.com/go-openapi/validate)
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+## FAQ
+
+* Does this library support OpenAPI 3?
+
+> No.
+> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
+> There is no plan to make it evolve toward supporting OpenAPI 3.x.
+> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
+>
+> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3
diff --git a/vendor/github.com/go-openapi/validate/context.go b/vendor/github.com/go-openapi/validate/context.go
new file mode 100644
index 000000000000..b4587dcd560f
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/context.go
@@ -0,0 +1,59 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "context"
+)
+
+// validateCtxKey is the key type of context key in this pkg
+type validateCtxKey string
+
+const (
+ operationTypeKey validateCtxKey = "operationTypeKey"
+)
+
+type operationType string
+
+const (
+ request operationType = "request"
+ response operationType = "response"
+ none operationType = "none" // not specified in ctx
+)
+
+var operationTypeEnum = []operationType{request, response, none}
+
+// WithOperationRequest returns a new context with operationType request
+// in context value
+func WithOperationRequest(ctx context.Context) context.Context {
+ return withOperation(ctx, request)
+}
+
+// WithOperationResponse returns a new context with operationType response
+// in context value
+func WithOperationResponse(ctx context.Context) context.Context {
+ return withOperation(ctx, response)
+}
+
+func withOperation(ctx context.Context, operation operationType) context.Context {
+ return context.WithValue(ctx, operationTypeKey, operation)
+}
+
+// extractOperationType extracts the operation type from ctx
+// if not specified or of unknown value, return none operation type
+func extractOperationType(ctx context.Context) operationType {
+ v := ctx.Value(operationTypeKey)
+ if v == nil {
+ return none
+ }
+ res, ok := v.(operationType)
+ if !ok {
+ return none
+ }
+ // validate the value is in operation enum
+ if err := Enum("", "", res, operationTypeEnum); err != nil {
+ return none
+ }
+ return res
+}
diff --git a/vendor/github.com/go-openapi/validate/debug.go b/vendor/github.com/go-openapi/validate/debug.go
new file mode 100644
index 000000000000..79145a4495d2
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/debug.go
@@ -0,0 +1,36 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+)
+
+var (
+ // Debug is true when the SWAGGER_DEBUG env var is not empty.
+ // It enables a more verbose logging of validators.
+ Debug = os.Getenv("SWAGGER_DEBUG") != ""
+ // validateLogger is a debug logger for this package
+ validateLogger *log.Logger
+)
+
+func init() {
+ debugOptions()
+}
+
+func debugOptions() {
+ validateLogger = log.New(os.Stdout, "validate:", log.LstdFlags)
+}
+
+func debugLog(msg string, args ...any) {
+ // A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog()
+ if Debug {
+ _, file1, pos1, _ := runtime.Caller(1)
+ validateLogger.Printf("%s:%d: %s", filepath.Base(file1), pos1, fmt.Sprintf(msg, args...))
+ }
+}
diff --git a/vendor/github.com/go-openapi/validate/default_validator.go b/vendor/github.com/go-openapi/validate/default_validator.go
new file mode 100644
index 000000000000..79a431677e45
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/default_validator.go
@@ -0,0 +1,294 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/go-openapi/spec"
+)
+
+// defaultValidator validates default values in a spec.
+// According to Swagger spec, default values MUST validate their schema.
+type defaultValidator struct {
+ SpecValidator *SpecValidator
+ visitedSchemas map[string]struct{}
+ schemaOptions *SchemaValidatorOptions
+}
+
+// Validate validates the default values declared in the swagger spec
+func (d *defaultValidator) Validate() *Result {
+ errs := pools.poolOfResults.BorrowResult() // will redeem when merged
+
+ if d == nil || d.SpecValidator == nil {
+ return errs
+ }
+ d.resetVisited()
+ errs.Merge(d.validateDefaultValueValidAgainstSchema()) // error -
+ return errs
+}
+
+// resetVisited resets the internal state of visited schemas
+func (d *defaultValidator) resetVisited() {
+ if d.visitedSchemas == nil {
+ d.visitedSchemas = make(map[string]struct{})
+
+ return
+ }
+
+ // TODO(go1.21): clear(ex.visitedSchemas)
+ for k := range d.visitedSchemas {
+ delete(d.visitedSchemas, k)
+ }
+}
+
+func isVisited(path string, visitedSchemas map[string]struct{}) bool {
+ _, found := visitedSchemas[path]
+ if found {
+ return true
+ }
+
+ // search for overlapping paths
+ var (
+ parent string
+ suffix string
+ )
+ const backtrackFromEnd = 2
+ for i := len(path) - backtrackFromEnd; i >= 0; i-- {
+ r := path[i]
+ if r != '.' {
+ continue
+ }
+
+ parent = path[0:i]
+ suffix = path[i+1:]
+
+ if strings.HasSuffix(parent, suffix) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// beingVisited asserts a schema is being visited
+func (d *defaultValidator) beingVisited(path string) {
+ d.visitedSchemas[path] = struct{}{}
+}
+
+// isVisited tells if a path has already been visited
+func (d *defaultValidator) isVisited(path string) bool {
+ return isVisited(path, d.visitedSchemas)
+}
+
+func (d *defaultValidator) validateDefaultValueValidAgainstSchema() *Result {
+ // every default value that is specified must validate against the schema for that property
+ // headers, items, parameters, schema
+
+ res := pools.poolOfResults.BorrowResult() // will redeem when merged
+ s := d.SpecValidator
+
+ for method, pathItem := range s.expandedAnalyzer().Operations() {
+ for path, op := range pathItem {
+ // parameters
+ for _, param := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+ if param.Default != nil && param.Required {
+ res.AddWarnings(requiredHasDefaultMsg(param.Name, param.In))
+ }
+
+ // reset explored schemas to get depth-first recursive-proof exploration
+ d.resetVisited()
+
+ // Check simple parameters first
+ // default values provided must validate against their inline definition (no explicit schema)
+ if param.Default != nil && param.Schema == nil {
+ // check param default value is valid
+ red := newParamValidator(¶m, s.KnownFormats, d.schemaOptions).Validate(param.Default) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddErrors(defaultValueDoesNotValidateMsg(param.Name, param.In))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ // Recursively follows Items and Schemas
+ if param.Items != nil {
+ red := d.validateDefaultValueItemsAgainstSchema(param.Name, param.In, ¶m, param.Items) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddErrors(defaultValueItemsDoesNotValidateMsg(param.Name, param.In))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ if param.Schema != nil {
+ // Validate default value against schema
+ red := d.validateDefaultValueSchemaAgainstSchema(param.Name, param.In, param.Schema)
+ if red.HasErrorsOrWarnings() {
+ res.AddErrors(defaultValueDoesNotValidateMsg(param.Name, param.In))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+ }
+
+ if op.Responses != nil {
+ if op.Responses.Default != nil {
+ // Same constraint on default Response
+ res.Merge(d.validateDefaultInResponse(op.Responses.Default, jsonDefault, path, 0, op.ID))
+ }
+ // Same constraint on regular Responses
+ if op.Responses.StatusCodeResponses != nil { // Safeguard
+ for code, r := range op.Responses.StatusCodeResponses {
+ res.Merge(d.validateDefaultInResponse(&r, "response", path, code, op.ID)) //#nosec
+ }
+ }
+ } else if op.ID != "" {
+ // Empty op.ID means there is no meaningful operation: no need to report a specific message
+ res.AddErrors(noValidResponseMsg(op.ID))
+ }
+ }
+ }
+ if s.spec.Spec().Definitions != nil { // Safeguard
+ // reset explored schemas to get depth-first recursive-proof exploration
+ d.resetVisited()
+ for nm, sch := range s.spec.Spec().Definitions {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema("definitions."+nm, "body", &sch)) //#nosec
+ }
+ }
+ return res
+}
+
+func (d *defaultValidator) validateDefaultInResponse(resp *spec.Response, responseType, path string, responseCode int, operationID string) *Result {
+ s := d.SpecValidator
+
+ response, res := responseHelp.expandResponseRef(resp, path, s)
+ if !res.IsValid() {
+ return res
+ }
+
+ responseName, responseCodeAsStr := responseHelp.responseMsgVariants(responseType, responseCode)
+
+ if response.Headers != nil { // Safeguard
+ for nm, h := range response.Headers {
+ // reset explored schemas to get depth-first recursive-proof exploration
+ d.resetVisited()
+
+ if h.Default != nil {
+ red := newHeaderValidator(nm, &h, s.KnownFormats, d.schemaOptions).Validate(h.Default) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddErrors(defaultValueHeaderDoesNotValidateMsg(operationID, nm, responseName))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ // Headers have inline definition, like params
+ if h.Items != nil {
+ red := d.validateDefaultValueItemsAgainstSchema(nm, "header", &h, h.Items) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddErrors(defaultValueHeaderItemsDoesNotValidateMsg(operationID, nm, responseName))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ if _, err := compileRegexp(h.Pattern); err != nil {
+ res.AddErrors(invalidPatternInHeaderMsg(operationID, nm, responseName, h.Pattern, err))
+ }
+
+ // Headers don't have schema
+ }
+ }
+ if response.Schema != nil {
+ // reset explored schemas to get depth-first recursive-proof exploration
+ d.resetVisited()
+
+ red := d.validateDefaultValueSchemaAgainstSchema(responseCodeAsStr, "response", response.Schema)
+ if red.HasErrorsOrWarnings() {
+ // Additional message to make sure the context of the error is not lost
+ res.AddErrors(defaultValueInDoesNotValidateMsg(operationID, responseName))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+ return res
+}
+
+func (d *defaultValidator) validateDefaultValueSchemaAgainstSchema(path, in string, schema *spec.Schema) *Result {
+ if schema == nil || d.isVisited(path) {
+ // Avoids recursing if we are already done with that check
+ return nil
+ }
+ d.beingVisited(path)
+ res := pools.poolOfResults.BorrowResult()
+ s := d.SpecValidator
+
+ if schema.Default != nil {
+ res.Merge(
+ newSchemaValidator(schema, s.spec.Spec(), path+".default", s.KnownFormats, d.schemaOptions).Validate(schema.Default),
+ )
+ }
+ if schema.Items != nil {
+ if schema.Items.Schema != nil {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+".items.default", in, schema.Items.Schema))
+ }
+ // Multiple schemas in items
+ if schema.Items.Schemas != nil { // Safeguard
+ for i, sch := range schema.Items.Schemas {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("%s.items[%d].default", path, i), in, &sch)) //#nosec
+ }
+ }
+ }
+ if _, err := compileRegexp(schema.Pattern); err != nil {
+ res.AddErrors(invalidPatternInMsg(path, in, schema.Pattern))
+ }
+ if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
+ // NOTE: we keep validating values, even though additionalItems is not supported by Swagger 2.0 (and 3.0 as well)
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+".additionalItems", in, schema.AdditionalItems.Schema))
+ }
+ for propName, prop := range schema.Properties {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+"."+propName, in, &prop)) //#nosec
+ }
+ for propName, prop := range schema.PatternProperties {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+"."+propName, in, &prop)) //#nosec
+ }
+ if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+".additionalProperties", in, schema.AdditionalProperties.Schema))
+ }
+ if schema.AllOf != nil {
+ for i, aoSch := range schema.AllOf {
+ res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("%s.allOf[%d]", path, i), in, &aoSch)) //#nosec
+ }
+ }
+ return res
+}
+
+// TODO: Temporary duplicated code. Need to refactor with examples
+
+func (d *defaultValidator) validateDefaultValueItemsAgainstSchema(path, in string, root any, items *spec.Items) *Result {
+ res := pools.poolOfResults.BorrowResult()
+ s := d.SpecValidator
+ if items != nil {
+ if items.Default != nil {
+ res.Merge(
+ newItemsValidator(path, in, items, root, s.KnownFormats, d.schemaOptions).Validate(0, items.Default),
+ )
+ }
+ if items.Items != nil {
+ res.Merge(d.validateDefaultValueItemsAgainstSchema(path+"[0].default", in, root, items.Items))
+ }
+ if _, err := compileRegexp(items.Pattern); err != nil {
+ res.AddErrors(invalidPatternInMsg(path, in, items.Pattern))
+ }
+ }
+ return res
+}
diff --git a/vendor/github.com/go-openapi/validate/doc.go b/vendor/github.com/go-openapi/validate/doc.go
new file mode 100644
index 000000000000..a99893e1a383
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/doc.go
@@ -0,0 +1,76 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+Package validate provides methods to validate a swagger specification,
+as well as tools to validate data against their schema.
+
+This package follows Swagger 2.0. specification (aka OpenAPI 2.0). Reference
+can be found here: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md.
+
+# Validating a specification
+
+Validates a spec document (from JSON or YAML) against the JSON schema for swagger,
+then checks a number of extra rules that can't be expressed in JSON schema.
+
+Entry points:
+ - Spec()
+ - NewSpecValidator()
+ - SpecValidator.Validate()
+
+Reported as errors:
+
+ [x] definition can't declare a property that's already defined by one of its ancestors
+ [x] definition's ancestor can't be a descendant of the same model
+ [x] path uniqueness: each api path should be non-verbatim (account for path param names) unique per method. Validation can be laxed by disabling StrictPathParamUniqueness.
+ [x] each security reference should contain only unique scopes
+ [x] each security scope in a security definition should be unique
+ [x] parameters in path must be unique
+ [x] each path parameter must correspond to a parameter placeholder and vice versa
+ [x] each referenceable definition must have references
+ [x] each definition property listed in the required array must be defined in the properties of the model
+ [x] each parameter should have a unique `name` and `type` combination
+ [x] each operation should have only 1 parameter of type body
+ [x] each reference must point to a valid object
+ [x] every default value that is specified must validate against the schema for that property
+ [x] items property is required for all schemas/definitions of type `array`
+ [x] path parameters must be declared a required
+ [x] headers must not contain $ref
+ [x] schema and property examples provided must validate against their respective object's schema
+ [x] examples provided must validate their schema
+
+Reported as warnings:
+
+ [x] path parameters should not contain any of [{,},\w]
+ [x] empty path
+ [x] unused definitions
+ [x] unsupported validation of examples on non-JSON media types
+ [x] examples in response without schema
+ [x] readOnly properties should not be required
+
+# Validating a schema
+
+The schema validation toolkit validates data against JSON-schema-draft 04 schema.
+
+It is tested against the full json-schema-testing-suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite),
+except for the optional part (bignum, ECMA regexp, ...).
+
+It supports the complete JSON-schema vocabulary, including keywords not supported by Swagger (e.g. additionalItems, ...)
+
+Entry points:
+ - AgainstSchema()
+ - ...
+
+# Known limitations
+
+With the current version of this package, the following aspects of swagger are not yet supported:
+
+ [ ] errors and warnings are not reported with key/line number in spec
+ [ ] default values and examples on responses only support application/json producer type
+ [ ] invalid numeric constraints (such as Minimum, etc..) are not checked except for default and example values
+ [ ] rules for collectionFormat are not implemented
+ [ ] no validation rule for polymorphism support (discriminator) [not done here]
+ [ ] valid js ECMA regexp not supported by Go regexp engine are considered invalid
+ [ ] arbitrary large numbers are not supported: max is math.MaxFloat64
+*/
+package validate
diff --git a/vendor/github.com/go-openapi/validate/example_validator.go b/vendor/github.com/go-openapi/validate/example_validator.go
new file mode 100644
index 000000000000..e4ef52c6dc16
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/example_validator.go
@@ -0,0 +1,288 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+
+ "github.com/go-openapi/spec"
+)
+
+// ExampleValidator validates example values defined in a spec
+type exampleValidator struct {
+ SpecValidator *SpecValidator
+ visitedSchemas map[string]struct{}
+ schemaOptions *SchemaValidatorOptions
+}
+
+// Validate validates the example values declared in the swagger spec
+// Example values MUST conform to their schema.
+//
+// With Swagger 2.0, examples are supported in:
+// - schemas
+// - individual property
+// - responses
+func (ex *exampleValidator) Validate() *Result {
+ errs := pools.poolOfResults.BorrowResult()
+
+ if ex == nil || ex.SpecValidator == nil {
+ return errs
+ }
+ ex.resetVisited()
+ errs.Merge(ex.validateExampleValueValidAgainstSchema()) // error -
+
+ return errs
+}
+
+// resetVisited resets the internal state of visited schemas
+func (ex *exampleValidator) resetVisited() {
+ if ex.visitedSchemas == nil {
+ ex.visitedSchemas = make(map[string]struct{})
+
+ return
+ }
+
+ // TODO(go1.21): clear(ex.visitedSchemas)
+ for k := range ex.visitedSchemas {
+ delete(ex.visitedSchemas, k)
+ }
+}
+
+// beingVisited asserts a schema is being visited
+func (ex *exampleValidator) beingVisited(path string) {
+ ex.visitedSchemas[path] = struct{}{}
+}
+
+// isVisited tells if a path has already been visited
+func (ex *exampleValidator) isVisited(path string) bool {
+ return isVisited(path, ex.visitedSchemas)
+}
+
+func (ex *exampleValidator) validateExampleValueValidAgainstSchema() *Result {
+ // every example value that is specified must validate against the schema for that property
+ // in: schemas, properties, object, items
+ // not in: headers, parameters without schema
+
+ res := pools.poolOfResults.BorrowResult()
+ s := ex.SpecValidator
+
+ for method, pathItem := range s.expandedAnalyzer().Operations() {
+ for path, op := range pathItem {
+ // parameters
+ for _, param := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+
+ // As of swagger 2.0, Examples are not supported in simple parameters
+ // However, it looks like it is supported by go-openapi
+
+ // reset explored schemas to get depth-first recursive-proof exploration
+ ex.resetVisited()
+
+ // Check simple parameters first
+ // default values provided must validate against their inline definition (no explicit schema)
+ if param.Example != nil && param.Schema == nil {
+ // check param default value is valid
+ red := newParamValidator(¶m, s.KnownFormats, ex.schemaOptions).Validate(param.Example) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddWarnings(exampleValueDoesNotValidateMsg(param.Name, param.In))
+ res.MergeAsWarnings(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ // Recursively follows Items and Schemas
+ if param.Items != nil {
+ red := ex.validateExampleValueItemsAgainstSchema(param.Name, param.In, ¶m, param.Items) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddWarnings(exampleValueItemsDoesNotValidateMsg(param.Name, param.In))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ if param.Schema != nil {
+ // Validate example value against schema
+ red := ex.validateExampleValueSchemaAgainstSchema(param.Name, param.In, param.Schema)
+ if red.HasErrorsOrWarnings() {
+ res.AddWarnings(exampleValueDoesNotValidateMsg(param.Name, param.In))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+ }
+
+ if op.Responses != nil {
+ if op.Responses.Default != nil {
+ // Same constraint on default Response
+ res.Merge(ex.validateExampleInResponse(op.Responses.Default, jsonDefault, path, 0, op.ID))
+ }
+ // Same constraint on regular Responses
+ if op.Responses.StatusCodeResponses != nil { // Safeguard
+ for code, r := range op.Responses.StatusCodeResponses {
+ res.Merge(ex.validateExampleInResponse(&r, "response", path, code, op.ID)) //#nosec
+ }
+ }
+ } else if op.ID != "" {
+ // Empty op.ID means there is no meaningful operation: no need to report a specific message
+ res.AddErrors(noValidResponseMsg(op.ID))
+ }
+ }
+ }
+ if s.spec.Spec().Definitions != nil { // Safeguard
+ // reset explored schemas to get depth-first recursive-proof exploration
+ ex.resetVisited()
+ for nm, sch := range s.spec.Spec().Definitions {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema("definitions."+nm, "body", &sch)) //#nosec
+ }
+ }
+ return res
+}
+
+func (ex *exampleValidator) validateExampleInResponse(resp *spec.Response, responseType, path string, responseCode int, operationID string) *Result {
+ s := ex.SpecValidator
+
+ response, res := responseHelp.expandResponseRef(resp, path, s)
+ if !res.IsValid() { // Safeguard
+ return res
+ }
+
+ responseName, responseCodeAsStr := responseHelp.responseMsgVariants(responseType, responseCode)
+
+ if response.Headers != nil { // Safeguard
+ for nm, h := range response.Headers {
+ // reset explored schemas to get depth-first recursive-proof exploration
+ ex.resetVisited()
+
+ if h.Example != nil {
+ red := newHeaderValidator(nm, &h, s.KnownFormats, ex.schemaOptions).Validate(h.Example) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddWarnings(exampleValueHeaderDoesNotValidateMsg(operationID, nm, responseName))
+ res.MergeAsWarnings(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ // Headers have inline definition, like params
+ if h.Items != nil {
+ red := ex.validateExampleValueItemsAgainstSchema(nm, "header", &h, h.Items) //#nosec
+ if red.HasErrorsOrWarnings() {
+ res.AddWarnings(exampleValueHeaderItemsDoesNotValidateMsg(operationID, nm, responseName))
+ res.MergeAsWarnings(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ if _, err := compileRegexp(h.Pattern); err != nil {
+ res.AddErrors(invalidPatternInHeaderMsg(operationID, nm, responseName, h.Pattern, err))
+ }
+
+ // Headers don't have schema
+ }
+ }
+ if response.Schema != nil {
+ // reset explored schemas to get depth-first recursive-proof exploration
+ ex.resetVisited()
+
+ red := ex.validateExampleValueSchemaAgainstSchema(responseCodeAsStr, "response", response.Schema)
+ if red.HasErrorsOrWarnings() {
+ // Additional message to make sure the context of the error is not lost
+ res.AddWarnings(exampleValueInDoesNotValidateMsg(operationID, responseName))
+ res.Merge(red)
+ } else if red.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(red)
+ }
+ }
+
+ if response.Examples != nil {
+ if response.Schema != nil {
+ if example, ok := response.Examples["application/json"]; ok {
+ res.MergeAsWarnings(
+ newSchemaValidator(response.Schema, s.spec.Spec(), path+".examples", s.KnownFormats, s.schemaOptions).Validate(example),
+ )
+ } else {
+ // TODO: validate other media types too
+ res.AddWarnings(examplesMimeNotSupportedMsg(operationID, responseName))
+ }
+ } else {
+ res.AddWarnings(examplesWithoutSchemaMsg(operationID, responseName))
+ }
+ }
+ return res
+}
+
+func (ex *exampleValidator) validateExampleValueSchemaAgainstSchema(path, in string, schema *spec.Schema) *Result {
+ if schema == nil || ex.isVisited(path) {
+ // Avoids recursing if we are already done with that check
+ return nil
+ }
+ ex.beingVisited(path)
+ s := ex.SpecValidator
+ res := pools.poolOfResults.BorrowResult()
+
+ if schema.Example != nil {
+ res.MergeAsWarnings(
+ newSchemaValidator(schema, s.spec.Spec(), path+".example", s.KnownFormats, ex.schemaOptions).Validate(schema.Example),
+ )
+ }
+ if schema.Items != nil {
+ if schema.Items.Schema != nil {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+".items.example", in, schema.Items.Schema))
+ }
+ // Multiple schemas in items
+ if schema.Items.Schemas != nil { // Safeguard
+ for i, sch := range schema.Items.Schemas {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("%s.items[%d].example", path, i), in, &sch)) //#nosec
+ }
+ }
+ }
+ if _, err := compileRegexp(schema.Pattern); err != nil {
+ res.AddErrors(invalidPatternInMsg(path, in, schema.Pattern))
+ }
+ if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
+ // NOTE: we keep validating values, even though additionalItems is unsupported in Swagger 2.0 (and 3.0 as well)
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+".additionalItems", in, schema.AdditionalItems.Schema))
+ }
+ for propName, prop := range schema.Properties {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+"."+propName, in, &prop)) //#nosec
+ }
+ for propName, prop := range schema.PatternProperties {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+"."+propName, in, &prop)) //#nosec
+ }
+ if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+".additionalProperties", in, schema.AdditionalProperties.Schema))
+ }
+ if schema.AllOf != nil {
+ for i, aoSch := range schema.AllOf {
+ res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("%s.allOf[%d]", path, i), in, &aoSch)) //#nosec
+ }
+ }
+ return res
+}
+
+// TODO: Temporary duplicated code. Need to refactor with examples
+//
+
+func (ex *exampleValidator) validateExampleValueItemsAgainstSchema(path, in string, root any, items *spec.Items) *Result {
+ res := pools.poolOfResults.BorrowResult()
+ s := ex.SpecValidator
+ if items != nil {
+ if items.Example != nil {
+ res.MergeAsWarnings(
+ newItemsValidator(path, in, items, root, s.KnownFormats, ex.schemaOptions).Validate(0, items.Example),
+ )
+ }
+ if items.Items != nil {
+ res.Merge(ex.validateExampleValueItemsAgainstSchema(path+"[0].example", in, root, items.Items))
+ }
+ if _, err := compileRegexp(items.Pattern); err != nil {
+ res.AddErrors(invalidPatternInMsg(path, in, items.Pattern))
+ }
+ }
+
+ return res
+}
diff --git a/vendor/github.com/go-openapi/validate/formats.go b/vendor/github.com/go-openapi/validate/formats.go
new file mode 100644
index 000000000000..85ee63494186
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/formats.go
@@ -0,0 +1,88 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "reflect"
+
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+type formatValidator struct {
+ Path string
+ In string
+ Format string
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+func newFormatValidator(path, in, format string, formats strfmt.Registry, opts *SchemaValidatorOptions) *formatValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var f *formatValidator
+ if opts.recycleValidators {
+ f = pools.poolOfFormatValidators.BorrowValidator()
+ } else {
+ f = new(formatValidator)
+ }
+
+ f.Path = path
+ f.In = in
+ f.Format = format
+ f.KnownFormats = formats
+ f.Options = opts
+
+ return f
+}
+
+func (f *formatValidator) SetPath(path string) {
+ f.Path = path
+}
+
+func (f *formatValidator) Applies(source any, kind reflect.Kind) bool {
+ if source == nil || f.KnownFormats == nil {
+ return false
+ }
+
+ switch source := source.(type) {
+ case *spec.Items:
+ return kind == reflect.String && f.KnownFormats.ContainsName(source.Format)
+ case *spec.Parameter:
+ return kind == reflect.String && f.KnownFormats.ContainsName(source.Format)
+ case *spec.Schema:
+ return kind == reflect.String && f.KnownFormats.ContainsName(source.Format)
+ case *spec.Header:
+ return kind == reflect.String && f.KnownFormats.ContainsName(source.Format)
+ default:
+ return false
+ }
+}
+
+func (f *formatValidator) Validate(val any) *Result {
+ if f.Options.recycleValidators {
+ defer func() {
+ f.redeem()
+ }()
+ }
+
+ var result *Result
+ if f.Options.recycleResult {
+ result = pools.poolOfResults.BorrowResult()
+ } else {
+ result = new(Result)
+ }
+
+ if err := FormatOf(f.Path, f.In, f.Format, val.(string), f.KnownFormats); err != nil {
+ result.AddErrors(err)
+ }
+
+ return result
+}
+
+func (f *formatValidator) redeem() {
+ pools.poolOfFormatValidators.RedeemValidator(f)
+}
diff --git a/vendor/github.com/go-openapi/validate/helpers.go b/vendor/github.com/go-openapi/validate/helpers.go
new file mode 100644
index 000000000000..49b130473a9a
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/helpers.go
@@ -0,0 +1,322 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+// TODO: define this as package validate/internal
+// This must be done while keeping CI intact with all tests and test coverage
+
+import (
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+)
+
+const (
+ swaggerBody = "body"
+ swaggerExample = "example"
+ swaggerExamples = "examples"
+)
+
+const (
+ objectType = "object"
+ arrayType = "array"
+ stringType = "string"
+ integerType = "integer"
+ numberType = "number"
+ booleanType = "boolean"
+ fileType = "file"
+ nullType = "null"
+)
+
+const (
+ jsonProperties = "properties"
+ jsonItems = "items"
+ jsonType = "type"
+ // jsonSchema = "schema"
+ jsonDefault = "default"
+)
+
+const (
+ stringFormatDate = "date"
+ stringFormatDateTime = "date-time"
+ stringFormatPassword = "password"
+ stringFormatByte = "byte"
+ // stringFormatBinary = "binary"
+ stringFormatCreditCard = "creditcard"
+ stringFormatDuration = "duration"
+ stringFormatEmail = "email"
+ stringFormatHexColor = "hexcolor"
+ stringFormatHostname = "hostname"
+ stringFormatIPv4 = "ipv4"
+ stringFormatIPv6 = "ipv6"
+ stringFormatISBN = "isbn"
+ stringFormatISBN10 = "isbn10"
+ stringFormatISBN13 = "isbn13"
+ stringFormatMAC = "mac"
+ stringFormatBSONObjectID = "bsonobjectid"
+ stringFormatRGBColor = "rgbcolor"
+ stringFormatSSN = "ssn"
+ stringFormatURI = "uri"
+ stringFormatUUID = "uuid"
+ stringFormatUUID3 = "uuid3"
+ stringFormatUUID4 = "uuid4"
+ stringFormatUUID5 = "uuid5"
+
+ integerFormatInt32 = "int32"
+ integerFormatInt64 = "int64"
+ integerFormatUInt32 = "uint32"
+ integerFormatUInt64 = "uint64"
+
+ numberFormatFloat32 = "float32"
+ numberFormatFloat64 = "float64"
+ numberFormatFloat = "float"
+ numberFormatDouble = "double"
+)
+
+// Helpers available at the package level
+var (
+ pathHelp *pathHelper
+ valueHelp *valueHelper
+ errorHelp *errorHelper
+ paramHelp *paramHelper
+ responseHelp *responseHelper
+)
+
+type errorHelper struct {
+ // A collection of unexported helpers for error construction
+}
+
+func (h *errorHelper) sErr(err errors.Error, recycle bool) *Result {
+ // Builds a Result from standard errors.Error
+ var result *Result
+ if recycle {
+ result = pools.poolOfResults.BorrowResult()
+ } else {
+ result = new(Result)
+ }
+ result.Errors = []error{err}
+
+ return result
+}
+
+func (h *errorHelper) addPointerError(res *Result, err error, ref string, fromPath string) *Result {
+ // Provides more context on error messages
+ // reported by the jsoinpointer package by altering the passed Result
+ if err != nil {
+ res.AddErrors(cannotResolveRefMsg(fromPath, ref, err))
+ }
+ return res
+}
+
+type pathHelper struct {
+ // A collection of unexported helpers for path validation
+}
+
+func (h *pathHelper) stripParametersInPath(path string) string {
+ // Returns a path stripped from all path parameters, with multiple or trailing slashes removed.
+ //
+ // Stripping is performed on a slash-separated basis, e.g '/a{/b}' remains a{/b} and not /a.
+ // - Trailing "/" make a difference, e.g. /a/ !~ /a (ex: canary/bitbucket.org/swagger.json)
+ // - presence or absence of a parameter makes a difference, e.g. /a/{log} !~ /a/ (ex: canary/kubernetes/swagger.json)
+
+ // Regexp to extract parameters from path, with surrounding {}.
+ // NOTE: important non-greedy modifier
+ rexParsePathParam := mustCompileRegexp(`{[^{}]+?}`)
+ strippedSegments := []string{}
+
+ for segment := range strings.SplitSeq(path, "/") {
+ strippedSegments = append(strippedSegments, rexParsePathParam.ReplaceAllString(segment, "X"))
+ }
+ return strings.Join(strippedSegments, "/")
+}
+
+func (h *pathHelper) extractPathParams(path string) (params []string) {
+ // Extracts all params from a path, with surrounding "{}"
+ rexParsePathParam := mustCompileRegexp(`{[^{}]+?}`)
+
+ for segment := range strings.SplitSeq(path, "/") {
+ for _, v := range rexParsePathParam.FindAllStringSubmatch(segment, -1) {
+ params = append(params, v...)
+ }
+ }
+ return
+}
+
+type valueHelper struct {
+ // A collection of unexported helpers for value validation
+}
+
+func (h *valueHelper) asInt64(val any) int64 {
+ // Number conversion function for int64, without error checking
+ // (implements an implicit type upgrade).
+ v := reflect.ValueOf(val)
+ switch v.Kind() { //nolint:exhaustive
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return int64(v.Uint()) //nolint:gosec
+ case reflect.Float32, reflect.Float64:
+ return int64(v.Float())
+ default:
+ // panic("Non numeric value in asInt64()")
+ return 0
+ }
+}
+
+func (h *valueHelper) asUint64(val any) uint64 {
+ // Number conversion function for uint64, without error checking
+ // (implements an implicit type upgrade).
+ v := reflect.ValueOf(val)
+ switch v.Kind() { //nolint:exhaustive
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return uint64(v.Int()) //nolint:gosec
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return v.Uint()
+ case reflect.Float32, reflect.Float64:
+ return uint64(v.Float())
+ default:
+ // panic("Non numeric value in asUint64()")
+ return 0
+ }
+}
+
+// Same for unsigned floats
+func (h *valueHelper) asFloat64(val any) float64 {
+ // Number conversion function for float64, without error checking
+ // (implements an implicit type upgrade).
+ v := reflect.ValueOf(val)
+ switch v.Kind() { //nolint:exhaustive
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(v.Int())
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return float64(v.Uint())
+ case reflect.Float32, reflect.Float64:
+ return v.Float()
+ default:
+ // panic("Non numeric value in asFloat64()")
+ return 0
+ }
+}
+
+type paramHelper struct {
+ // A collection of unexported helpers for parameters resolution
+}
+
+func (h *paramHelper) safeExpandedParamsFor(path, method, operationID string, res *Result, s *SpecValidator) (params []spec.Parameter) {
+ operation, ok := s.expandedAnalyzer().OperationFor(method, path)
+ if ok {
+ // expand parameters first if necessary
+ resolvedParams := []spec.Parameter{}
+ for _, ppr := range operation.Parameters {
+ resolvedParam, red := h.resolveParam(path, method, operationID, &ppr, s) //#nosec
+ res.Merge(red)
+ if resolvedParam != nil {
+ resolvedParams = append(resolvedParams, *resolvedParam)
+ }
+ }
+ // remove params with invalid expansion from Slice
+ operation.Parameters = resolvedParams
+
+ for _, ppr := range s.expandedAnalyzer().SafeParamsFor(method, path,
+ func(_ spec.Parameter, err error) bool {
+ // since params have already been expanded, there are few causes for error
+ res.AddErrors(someParametersBrokenMsg(path, method, operationID))
+ // original error from analyzer
+ res.AddErrors(err)
+ return true
+ }) {
+ params = append(params, ppr)
+ }
+ }
+ return
+}
+
+func (h *paramHelper) resolveParam(path, method, operationID string, param *spec.Parameter, s *SpecValidator) (*spec.Parameter, *Result) {
+ // Ensure parameter is expanded
+ var err error
+ res := new(Result)
+ isRef := param.Ref.String() != ""
+ if s.spec.SpecFilePath() == "" {
+ err = spec.ExpandParameterWithRoot(param, s.spec.Spec(), nil)
+ } else {
+ err = spec.ExpandParameter(param, s.spec.SpecFilePath())
+
+ }
+ if err != nil { // Safeguard
+ // NOTE: we may enter here when the whole parameter is an unresolved $ref
+ refPath := strings.Join([]string{"\"" + path + "\"", method}, ".")
+ errorHelp.addPointerError(res, err, param.Ref.String(), refPath)
+ return nil, res
+ }
+ res.Merge(h.checkExpandedParam(param, param.Name, param.In, operationID, isRef))
+ return param, res
+}
+
+func (h *paramHelper) checkExpandedParam(pr *spec.Parameter, path, in, operation string, isRef bool) *Result {
+ // Secure parameter structure after $ref resolution
+ res := new(Result)
+ simpleZero := spec.SimpleSchema{}
+ // Try to explain why... best guess
+ switch {
+ case pr.In == swaggerBody && (pr.SimpleSchema != simpleZero && pr.Type != objectType):
+ if isRef {
+ // Most likely, a $ref with a sibling is an unwanted situation: in itself this is a warning...
+ // but we detect it because of the following error:
+ // schema took over Parameter for an unexplained reason
+ res.AddWarnings(refShouldNotHaveSiblingsMsg(path, operation))
+ }
+ res.AddErrors(invalidParameterDefinitionMsg(path, in, operation))
+ case pr.In != swaggerBody && pr.Schema != nil:
+ if isRef {
+ res.AddWarnings(refShouldNotHaveSiblingsMsg(path, operation))
+ }
+ res.AddErrors(invalidParameterDefinitionAsSchemaMsg(path, in, operation))
+ case (pr.In == swaggerBody && pr.Schema == nil) || (pr.In != swaggerBody && pr.SimpleSchema == simpleZero):
+ // Other unexpected mishaps
+ res.AddErrors(invalidParameterDefinitionMsg(path, in, operation))
+ }
+ return res
+}
+
+type responseHelper struct {
+ // A collection of unexported helpers for response resolution
+}
+
+func (r *responseHelper) expandResponseRef(
+ response *spec.Response,
+ path string, s *SpecValidator) (*spec.Response, *Result) {
+ // Ensure response is expanded
+ var err error
+ res := new(Result)
+ if s.spec.SpecFilePath() == "" {
+ // there is no physical document to resolve $ref in response
+ err = spec.ExpandResponseWithRoot(response, s.spec.Spec(), nil)
+ } else {
+ err = spec.ExpandResponse(response, s.spec.SpecFilePath())
+ }
+ if err != nil { // Safeguard
+ // NOTE: we may enter here when the whole response is an unresolved $ref.
+ errorHelp.addPointerError(res, err, response.Ref.String(), path)
+ return nil, res
+ }
+
+ return response, res
+}
+
+func (r *responseHelper) responseMsgVariants(
+ responseType string,
+ responseCode int) (responseName, responseCodeAsStr string) {
+ // Path variants for messages
+ if responseType == jsonDefault {
+ responseCodeAsStr = jsonDefault
+ responseName = "default response"
+ } else {
+ responseCodeAsStr = strconv.Itoa(responseCode)
+ responseName = "response " + responseCodeAsStr
+ }
+ return
+}
diff --git a/vendor/github.com/go-openapi/validate/object_validator.go b/vendor/github.com/go-openapi/validate/object_validator.go
new file mode 100644
index 000000000000..cf98ed377d54
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/object_validator.go
@@ -0,0 +1,420 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+type objectValidator struct {
+ Path string
+ In string
+ MaxProperties *int64
+ MinProperties *int64
+ Required []string
+ Properties map[string]spec.Schema
+ AdditionalProperties *spec.SchemaOrBool
+ PatternProperties map[string]spec.Schema
+ Root any
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+ splitPath []string
+}
+
+func newObjectValidator(path, in string,
+ maxProperties, minProperties *int64, required []string, properties spec.SchemaProperties,
+ additionalProperties *spec.SchemaOrBool, patternProperties spec.SchemaProperties,
+ root any, formats strfmt.Registry, opts *SchemaValidatorOptions) *objectValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var v *objectValidator
+ if opts.recycleValidators {
+ v = pools.poolOfObjectValidators.BorrowValidator()
+ } else {
+ v = new(objectValidator)
+ }
+
+ v.Path = path
+ v.In = in
+ v.MaxProperties = maxProperties
+ v.MinProperties = minProperties
+ v.Required = required
+ v.Properties = properties
+ v.AdditionalProperties = additionalProperties
+ v.PatternProperties = patternProperties
+ v.Root = root
+ v.KnownFormats = formats
+ v.Options = opts
+ v.splitPath = strings.Split(v.Path, ".")
+
+ return v
+}
+
+func (o *objectValidator) Validate(data any) *Result {
+ if o.Options.recycleValidators {
+ defer func() {
+ o.redeem()
+ }()
+ }
+
+ var val map[string]any
+ if data != nil {
+ var ok bool
+ val, ok = data.(map[string]any)
+ if !ok {
+ return errorHelp.sErr(invalidObjectMsg(o.Path, o.In), o.Options.recycleResult)
+ }
+ }
+ numKeys := int64(len(val))
+
+ if o.MinProperties != nil && numKeys < *o.MinProperties {
+ return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties), o.Options.recycleResult)
+ }
+ if o.MaxProperties != nil && numKeys > *o.MaxProperties {
+ return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties), o.Options.recycleResult)
+ }
+
+ var res *Result
+ if o.Options.recycleResult {
+ res = pools.poolOfResults.BorrowResult()
+ } else {
+ res = new(Result)
+ }
+
+ o.precheck(res, val)
+
+ // check validity of field names
+ if o.AdditionalProperties != nil && !o.AdditionalProperties.Allows {
+ // Case: additionalProperties: false
+ o.validateNoAdditionalProperties(val, res)
+ } else {
+ // Cases: empty additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <> }
+ o.validateAdditionalProperties(val, res)
+ }
+
+ o.validatePropertiesSchema(val, res)
+
+ // Check patternProperties
+ // TODO: it looks like we have done that twice in many cases
+ for key, value := range val {
+ _, regularProperty := o.Properties[key]
+ matched, _, patterns := o.validatePatternProperty(key, value, res) // applies to regular properties as well
+ if regularProperty || !matched {
+ continue
+ }
+
+ for _, pName := range patterns {
+ if v, ok := o.PatternProperties[pName]; ok {
+ r := newSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats, o.Options).Validate(value)
+ res.mergeForField(data.(map[string]any), key, r)
+ }
+ }
+ }
+
+ return res
+}
+
+func (o *objectValidator) SetPath(path string) {
+ o.Path = path
+ o.splitPath = strings.Split(path, ".")
+}
+
+func (o *objectValidator) Applies(source any, kind reflect.Kind) bool {
+ // TODO: this should also work for structs
+ // there is a problem in the type validator where it will be unhappy about null values
+ // so that requires more testing
+ _, isSchema := source.(*spec.Schema)
+ return isSchema && (kind == reflect.Map || kind == reflect.Struct)
+}
+
+func (o *objectValidator) isProperties() bool {
+ p := o.splitPath
+ return len(p) > 1 && p[len(p)-1] == jsonProperties && p[len(p)-2] != jsonProperties
+}
+
+func (o *objectValidator) isDefault() bool {
+ p := o.splitPath
+ return len(p) > 1 && p[len(p)-1] == jsonDefault && p[len(p)-2] != jsonDefault
+}
+
+func (o *objectValidator) isExample() bool {
+ p := o.splitPath
+ return len(p) > 1 && (p[len(p)-1] == swaggerExample || p[len(p)-1] == swaggerExamples) && p[len(p)-2] != swaggerExample
+}
+
+func (o *objectValidator) checkArrayMustHaveItems(res *Result, val map[string]any) {
+ // for swagger 2.0 schemas, there is an additional constraint to have array items defined explicitly.
+ // with pure jsonschema draft 4, one may have arrays with undefined items (i.e. any type).
+ if val == nil {
+ return
+ }
+
+ t, typeFound := val[jsonType]
+ if !typeFound {
+ return
+ }
+
+ tpe, isString := t.(string)
+ if !isString || tpe != arrayType {
+ return
+ }
+
+ item, itemsKeyFound := val[jsonItems]
+ if itemsKeyFound {
+ return
+ }
+
+ res.AddErrors(errors.Required(jsonItems, o.Path, item))
+}
+
+func (o *objectValidator) checkItemsMustBeTypeArray(res *Result, val map[string]any) {
+ if val == nil {
+ return
+ }
+
+ if o.isProperties() || o.isDefault() || o.isExample() {
+ return
+ }
+
+ _, itemsKeyFound := val[jsonItems]
+ if !itemsKeyFound {
+ return
+ }
+
+ t, typeFound := val[jsonType]
+ if !typeFound {
+ // there is no type
+ res.AddErrors(errors.Required(jsonType, o.Path, t))
+ }
+
+ if tpe, isString := t.(string); !isString || tpe != arrayType {
+ res.AddErrors(errors.InvalidType(o.Path, o.In, arrayType, nil))
+ }
+}
+
+func (o *objectValidator) precheck(res *Result, val map[string]any) {
+ if o.Options.EnableArrayMustHaveItemsCheck {
+ o.checkArrayMustHaveItems(res, val)
+ }
+ if o.Options.EnableObjectArrayTypeCheck {
+ o.checkItemsMustBeTypeArray(res, val)
+ }
+}
+
+func (o *objectValidator) validateNoAdditionalProperties(val map[string]any, res *Result) {
+ for k := range val {
+ if k == "$schema" || k == "id" {
+ // special properties "$schema" and "id" are ignored
+ continue
+ }
+
+ _, regularProperty := o.Properties[k]
+ if regularProperty {
+ continue
+ }
+
+ matched := false
+ for pk := range o.PatternProperties {
+ re, err := compileRegexp(pk)
+ if err != nil {
+ continue
+ }
+ if matches := re.MatchString(k); matches {
+ matched = true
+ break
+ }
+ }
+ if matched {
+ continue
+ }
+
+ res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k))
+
+ // BUG(fredbi): This section should move to a part dedicated to spec validation as
+ // it will conflict with regular schemas where a property "headers" is defined.
+
+ //
+ // Croaks a more explicit message on top of the standard one
+ // on some recognized cases.
+ //
+ // NOTE: edge cases with invalid type assertion are simply ignored here.
+ // NOTE: prefix your messages here by "IMPORTANT!" so there are not filtered
+ // by higher level callers (the IMPORTANT! tag will be eventually
+ // removed).
+ if k != "headers" || val[k] == nil {
+ continue
+ }
+
+ // $ref is forbidden in header
+ headers, mapOk := val[k].(map[string]any)
+ if !mapOk {
+ continue
+ }
+
+ for headerKey, headerBody := range headers {
+ if headerBody == nil {
+ continue
+ }
+
+ headerSchema, mapOfMapOk := headerBody.(map[string]any)
+ if !mapOfMapOk {
+ continue
+ }
+
+ _, found := headerSchema["$ref"]
+ if !found {
+ continue
+ }
+
+ refString, stringOk := headerSchema["$ref"].(string)
+ if !stringOk {
+ continue
+ }
+
+ msg := strings.Join([]string{", one may not use $ref=\":", refString, "\""}, "")
+ res.AddErrors(refNotAllowedInHeaderMsg(o.Path, headerKey, msg))
+ /*
+ case "$ref":
+ if val[k] != nil {
+ // TODO: check context of that ref: warn about siblings, check against invalid context
+ }
+ */
+ }
+ }
+}
+
+func (o *objectValidator) validateAdditionalProperties(val map[string]any, res *Result) {
+ for key, value := range val {
+ _, regularProperty := o.Properties[key]
+ if regularProperty {
+ continue
+ }
+
+ // Validates property against "patternProperties" if applicable
+ // BUG(fredbi): succeededOnce is always false
+
+ // NOTE: how about regular properties which do not match patternProperties?
+ matched, succeededOnce, _ := o.validatePatternProperty(key, value, res)
+ if matched || succeededOnce {
+ continue
+ }
+
+ if o.AdditionalProperties == nil || o.AdditionalProperties.Schema == nil {
+ continue
+ }
+
+ // Cases: properties which are not regular properties and have not been matched by the PatternProperties validator
+ // AdditionalProperties as Schema
+ r := newSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats, o.Options).Validate(value)
+ res.mergeForField(val, key, r)
+ }
+ // Valid cases: additionalProperties: true or undefined
+}
+
+func (o *objectValidator) validatePropertiesSchema(val map[string]any, res *Result) {
+ createdFromDefaults := map[string]struct{}{}
+
+ // Property types:
+ // - regular Property
+ pSchema := pools.poolOfSchemas.BorrowSchema() // recycle a spec.Schema object which lifespan extends only to the validation of properties
+ defer func() {
+ pools.poolOfSchemas.RedeemSchema(pSchema)
+ }()
+
+ for pName := range o.Properties {
+ *pSchema = o.Properties[pName]
+ var rName string
+ if o.Path == "" {
+ rName = pName
+ } else {
+ rName = o.Path + "." + pName
+ }
+
+ // Recursively validates each property against its schema
+ v, ok := val[pName]
+ if ok {
+ r := newSchemaValidator(pSchema, o.Root, rName, o.KnownFormats, o.Options).Validate(v)
+ res.mergeForField(val, pName, r)
+
+ continue
+ }
+
+ if pSchema.Default != nil {
+ // if a default value is defined, creates the property from defaults
+ // NOTE: JSON schema does not enforce default values to be valid against schema. Swagger does.
+ createdFromDefaults[pName] = struct{}{}
+ if !o.Options.skipSchemataResult {
+ res.addPropertySchemata(val, pName, pSchema) // this shallow-clones the content of the pSchema pointer
+ }
+ }
+ }
+
+ if len(o.Required) == 0 {
+ return
+ }
+
+ // Check required properties
+ for _, k := range o.Required {
+ v, ok := val[k]
+ if ok {
+ continue
+ }
+ _, isCreatedFromDefaults := createdFromDefaults[k]
+ if isCreatedFromDefaults {
+ continue
+ }
+
+ res.AddErrors(errors.Required(fmt.Sprintf("%s.%s", o.Path, k), o.In, v))
+ }
+}
+
+// TODO: succeededOnce is not used anywhere
+func (o *objectValidator) validatePatternProperty(key string, value any, result *Result) (bool, bool, []string) {
+ if len(o.PatternProperties) == 0 {
+ return false, false, nil
+ }
+
+ matched := false
+ succeededOnce := false
+ patterns := make([]string, 0, len(o.PatternProperties))
+
+ schema := pools.poolOfSchemas.BorrowSchema()
+ defer func() {
+ pools.poolOfSchemas.RedeemSchema(schema)
+ }()
+
+ for k := range o.PatternProperties {
+ re, err := compileRegexp(k)
+ if err != nil {
+ continue
+ }
+
+ match := re.MatchString(key)
+ if !match {
+ continue
+ }
+
+ *schema = o.PatternProperties[k]
+ patterns = append(patterns, k)
+ matched = true
+ validator := newSchemaValidator(schema, o.Root, fmt.Sprintf("%s.%s", o.Path, key), o.KnownFormats, o.Options)
+
+ res := validator.Validate(value)
+ result.Merge(res)
+ }
+
+ return matched, succeededOnce, patterns
+}
+
+func (o *objectValidator) redeem() {
+ pools.poolOfObjectValidators.RedeemValidator(o)
+}
diff --git a/vendor/github.com/go-openapi/validate/options.go b/vendor/github.com/go-openapi/validate/options.go
new file mode 100644
index 000000000000..f5e7f7131c72
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/options.go
@@ -0,0 +1,51 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import "sync"
+
+// Opts specifies validation options for a SpecValidator.
+//
+// NOTE: other options might be needed, for example a go-swagger specific mode.
+type Opts struct {
+ ContinueOnErrors bool // true: continue reporting errors, even if spec is invalid
+
+ // StrictPathParamUniqueness enables a strict validation of paths that include
+ // path parameters. When true, it will enforce that for each method, the path
+ // is unique, regardless of path parameters such that GET:/petstore/{id} and
+ // GET:/petstore/{pet} anre considered duplicate paths.
+ //
+ // Consider disabling if path parameters can include slashes such as
+ // GET:/v1/{shelve} and GET:/v1/{book}, where the IDs are "shelve/*" and
+ // /"shelve/*/book/*" respectively.
+ StrictPathParamUniqueness bool
+ SkipSchemataResult bool
+}
+
+var (
+ defaultOpts = Opts{
+ // default is to stop validation on errors
+ ContinueOnErrors: false,
+
+ // StrictPathParamUniqueness is defaulted to true. This maintains existing
+ // behavior.
+ StrictPathParamUniqueness: true,
+ }
+
+ defaultOptsMutex = &sync.Mutex{}
+)
+
+// SetContinueOnErrors sets global default behavior regarding spec validation errors reporting.
+//
+// For extended error reporting, you most likely want to set it to true.
+// For faster validation, it's better to give up early when a spec is detected as invalid: set it to false (this is the default).
+//
+// Setting this mode does NOT affect the validation status.
+//
+// NOTE: this method affects global defaults. It is not suitable for a concurrent usage.
+func SetContinueOnErrors(c bool) {
+ defer defaultOptsMutex.Unlock()
+ defaultOptsMutex.Lock()
+ defaultOpts.ContinueOnErrors = c
+}
diff --git a/vendor/github.com/go-openapi/validate/pools.go b/vendor/github.com/go-openapi/validate/pools.go
new file mode 100644
index 000000000000..1e734be493be
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/pools.go
@@ -0,0 +1,369 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+//go:build !validatedebug
+
+package validate
+
+import (
+ "sync"
+
+ "github.com/go-openapi/spec"
+)
+
+var pools allPools
+
+func init() {
+ resetPools()
+}
+
+func resetPools() {
+ // NOTE: for testing purpose, we might want to reset pools after calling Validate twice.
+ // The pool is corrupted in that case: calling Put twice inserts a duplicate in the pool
+ // and further calls to Get are mishandled.
+
+ pools = allPools{
+ poolOfSchemaValidators: schemaValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &SchemaValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfObjectValidators: objectValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &objectValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfSliceValidators: sliceValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &schemaSliceValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfItemsValidators: itemsValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &itemsValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfBasicCommonValidators: basicCommonValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &basicCommonValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfHeaderValidators: headerValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &HeaderValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfParamValidators: paramValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &ParamValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfBasicSliceValidators: basicSliceValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &basicSliceValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfNumberValidators: numberValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &numberValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfStringValidators: stringValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &stringValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfSchemaPropsValidators: schemaPropsValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &schemaPropsValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfFormatValidators: formatValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &formatValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfTypeValidators: typeValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &typeValidator{}
+
+ return s
+ },
+ },
+ },
+ poolOfSchemas: schemasPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &spec.Schema{}
+
+ return s
+ },
+ },
+ },
+ poolOfResults: resultsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &Result{}
+
+ return s
+ },
+ },
+ },
+ }
+}
+
+type (
+ allPools struct {
+ // memory pools for all validator objects.
+ //
+ // Each pool can be borrowed from and redeemed to.
+ poolOfSchemaValidators schemaValidatorsPool
+ poolOfObjectValidators objectValidatorsPool
+ poolOfSliceValidators sliceValidatorsPool
+ poolOfItemsValidators itemsValidatorsPool
+ poolOfBasicCommonValidators basicCommonValidatorsPool
+ poolOfHeaderValidators headerValidatorsPool
+ poolOfParamValidators paramValidatorsPool
+ poolOfBasicSliceValidators basicSliceValidatorsPool
+ poolOfNumberValidators numberValidatorsPool
+ poolOfStringValidators stringValidatorsPool
+ poolOfSchemaPropsValidators schemaPropsValidatorsPool
+ poolOfFormatValidators formatValidatorsPool
+ poolOfTypeValidators typeValidatorsPool
+ poolOfSchemas schemasPool
+ poolOfResults resultsPool
+ }
+
+ schemaValidatorsPool struct {
+ *sync.Pool
+ }
+
+ objectValidatorsPool struct {
+ *sync.Pool
+ }
+
+ sliceValidatorsPool struct {
+ *sync.Pool
+ }
+
+ itemsValidatorsPool struct {
+ *sync.Pool
+ }
+
+ basicCommonValidatorsPool struct {
+ *sync.Pool
+ }
+
+ headerValidatorsPool struct {
+ *sync.Pool
+ }
+
+ paramValidatorsPool struct {
+ *sync.Pool
+ }
+
+ basicSliceValidatorsPool struct {
+ *sync.Pool
+ }
+
+ numberValidatorsPool struct {
+ *sync.Pool
+ }
+
+ stringValidatorsPool struct {
+ *sync.Pool
+ }
+
+ schemaPropsValidatorsPool struct {
+ *sync.Pool
+ }
+
+ formatValidatorsPool struct {
+ *sync.Pool
+ }
+
+ typeValidatorsPool struct {
+ *sync.Pool
+ }
+
+ schemasPool struct {
+ *sync.Pool
+ }
+
+ resultsPool struct {
+ *sync.Pool
+ }
+)
+
+func (p schemaValidatorsPool) BorrowValidator() *SchemaValidator {
+ return p.Get().(*SchemaValidator)
+}
+
+func (p schemaValidatorsPool) RedeemValidator(s *SchemaValidator) {
+ // NOTE: s might be nil. In that case, Put is a noop.
+ p.Put(s)
+}
+
+func (p objectValidatorsPool) BorrowValidator() *objectValidator {
+ return p.Get().(*objectValidator)
+}
+
+func (p objectValidatorsPool) RedeemValidator(s *objectValidator) {
+ p.Put(s)
+}
+
+func (p sliceValidatorsPool) BorrowValidator() *schemaSliceValidator {
+ return p.Get().(*schemaSliceValidator)
+}
+
+func (p sliceValidatorsPool) RedeemValidator(s *schemaSliceValidator) {
+ p.Put(s)
+}
+
+func (p itemsValidatorsPool) BorrowValidator() *itemsValidator {
+ return p.Get().(*itemsValidator)
+}
+
+func (p itemsValidatorsPool) RedeemValidator(s *itemsValidator) {
+ p.Put(s)
+}
+
+func (p basicCommonValidatorsPool) BorrowValidator() *basicCommonValidator {
+ return p.Get().(*basicCommonValidator)
+}
+
+func (p basicCommonValidatorsPool) RedeemValidator(s *basicCommonValidator) {
+ p.Put(s)
+}
+
+func (p headerValidatorsPool) BorrowValidator() *HeaderValidator {
+ return p.Get().(*HeaderValidator)
+}
+
+func (p headerValidatorsPool) RedeemValidator(s *HeaderValidator) {
+ p.Put(s)
+}
+
+func (p paramValidatorsPool) BorrowValidator() *ParamValidator {
+ return p.Get().(*ParamValidator)
+}
+
+func (p paramValidatorsPool) RedeemValidator(s *ParamValidator) {
+ p.Put(s)
+}
+
+func (p basicSliceValidatorsPool) BorrowValidator() *basicSliceValidator {
+ return p.Get().(*basicSliceValidator)
+}
+
+func (p basicSliceValidatorsPool) RedeemValidator(s *basicSliceValidator) {
+ p.Put(s)
+}
+
+func (p numberValidatorsPool) BorrowValidator() *numberValidator {
+ return p.Get().(*numberValidator)
+}
+
+func (p numberValidatorsPool) RedeemValidator(s *numberValidator) {
+ p.Put(s)
+}
+
+func (p stringValidatorsPool) BorrowValidator() *stringValidator {
+ return p.Get().(*stringValidator)
+}
+
+func (p stringValidatorsPool) RedeemValidator(s *stringValidator) {
+ p.Put(s)
+}
+
+func (p schemaPropsValidatorsPool) BorrowValidator() *schemaPropsValidator {
+ return p.Get().(*schemaPropsValidator)
+}
+
+func (p schemaPropsValidatorsPool) RedeemValidator(s *schemaPropsValidator) {
+ p.Put(s)
+}
+
+func (p formatValidatorsPool) BorrowValidator() *formatValidator {
+ return p.Get().(*formatValidator)
+}
+
+func (p formatValidatorsPool) RedeemValidator(s *formatValidator) {
+ p.Put(s)
+}
+
+func (p typeValidatorsPool) BorrowValidator() *typeValidator {
+ return p.Get().(*typeValidator)
+}
+
+func (p typeValidatorsPool) RedeemValidator(s *typeValidator) {
+ p.Put(s)
+}
+
+func (p schemasPool) BorrowSchema() *spec.Schema {
+ return p.Get().(*spec.Schema)
+}
+
+func (p schemasPool) RedeemSchema(s *spec.Schema) {
+ p.Put(s)
+}
+
+func (p resultsPool) BorrowResult() *Result {
+ return p.Get().(*Result).cleared()
+}
+
+func (p resultsPool) RedeemResult(s *Result) {
+ if s == emptyResult {
+ return
+ }
+ p.Put(s)
+}
diff --git a/vendor/github.com/go-openapi/validate/pools_debug.go b/vendor/github.com/go-openapi/validate/pools_debug.go
new file mode 100644
index 000000000000..d123ed4093fe
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/pools_debug.go
@@ -0,0 +1,1015 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+//go:build validatedebug
+
+package validate
+
+import (
+ "fmt"
+ "runtime"
+ "sync"
+ "testing"
+
+ "github.com/go-openapi/spec"
+)
+
+// This version of the pools is to be used for debugging and testing, with build tag "validatedebug".
+//
+// In this mode, the pools are tracked for allocation and redemption of borrowed objects, so we can
+// verify a few behaviors of the validators. The debug pools panic when an invalid usage pattern is detected.
+
+var pools allPools
+
+func init() {
+ resetPools()
+}
+
+func resetPools() {
+ // NOTE: for testing purpose, we might want to reset pools after calling Validate twice.
+ // The pool is corrupted in that case: calling Put twice inserts a duplicate in the pool
+ // and further calls to Get are mishandled.
+
+ pools = allPools{
+ poolOfSchemaValidators: schemaValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &SchemaValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*SchemaValidator]status),
+ allocMap: make(map[*SchemaValidator]string),
+ redeemMap: make(map[*SchemaValidator]string),
+ },
+ poolOfObjectValidators: objectValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &objectValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*objectValidator]status),
+ allocMap: make(map[*objectValidator]string),
+ redeemMap: make(map[*objectValidator]string),
+ },
+ poolOfSliceValidators: sliceValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &schemaSliceValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*schemaSliceValidator]status),
+ allocMap: make(map[*schemaSliceValidator]string),
+ redeemMap: make(map[*schemaSliceValidator]string),
+ },
+ poolOfItemsValidators: itemsValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &itemsValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*itemsValidator]status),
+ allocMap: make(map[*itemsValidator]string),
+ redeemMap: make(map[*itemsValidator]string),
+ },
+ poolOfBasicCommonValidators: basicCommonValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &basicCommonValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*basicCommonValidator]status),
+ allocMap: make(map[*basicCommonValidator]string),
+ redeemMap: make(map[*basicCommonValidator]string),
+ },
+ poolOfHeaderValidators: headerValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &HeaderValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*HeaderValidator]status),
+ allocMap: make(map[*HeaderValidator]string),
+ redeemMap: make(map[*HeaderValidator]string),
+ },
+ poolOfParamValidators: paramValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &ParamValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*ParamValidator]status),
+ allocMap: make(map[*ParamValidator]string),
+ redeemMap: make(map[*ParamValidator]string),
+ },
+ poolOfBasicSliceValidators: basicSliceValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &basicSliceValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*basicSliceValidator]status),
+ allocMap: make(map[*basicSliceValidator]string),
+ redeemMap: make(map[*basicSliceValidator]string),
+ },
+ poolOfNumberValidators: numberValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &numberValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*numberValidator]status),
+ allocMap: make(map[*numberValidator]string),
+ redeemMap: make(map[*numberValidator]string),
+ },
+ poolOfStringValidators: stringValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &stringValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*stringValidator]status),
+ allocMap: make(map[*stringValidator]string),
+ redeemMap: make(map[*stringValidator]string),
+ },
+ poolOfSchemaPropsValidators: schemaPropsValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &schemaPropsValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*schemaPropsValidator]status),
+ allocMap: make(map[*schemaPropsValidator]string),
+ redeemMap: make(map[*schemaPropsValidator]string),
+ },
+ poolOfFormatValidators: formatValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &formatValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*formatValidator]status),
+ allocMap: make(map[*formatValidator]string),
+ redeemMap: make(map[*formatValidator]string),
+ },
+ poolOfTypeValidators: typeValidatorsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &typeValidator{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*typeValidator]status),
+ allocMap: make(map[*typeValidator]string),
+ redeemMap: make(map[*typeValidator]string),
+ },
+ poolOfSchemas: schemasPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &spec.Schema{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*spec.Schema]status),
+ allocMap: make(map[*spec.Schema]string),
+ redeemMap: make(map[*spec.Schema]string),
+ },
+ poolOfResults: resultsPool{
+ Pool: &sync.Pool{
+ New: func() any {
+ s := &Result{}
+
+ return s
+ },
+ },
+ debugMap: make(map[*Result]status),
+ allocMap: make(map[*Result]string),
+ redeemMap: make(map[*Result]string),
+ },
+ }
+}
+
+const (
+ statusFresh status = iota + 1
+ statusRecycled
+ statusRedeemed
+)
+
+func (s status) String() string {
+ switch s {
+ case statusFresh:
+ return "fresh"
+ case statusRecycled:
+ return "recycled"
+ case statusRedeemed:
+ return "redeemed"
+ default:
+ panic(fmt.Errorf("invalid status: %d", s))
+ }
+}
+
+type (
+ // Debug
+ status uint8
+
+ allPools struct {
+ // memory pools for all validator objects.
+ //
+ // Each pool can be borrowed from and redeemed to.
+ poolOfSchemaValidators schemaValidatorsPool
+ poolOfObjectValidators objectValidatorsPool
+ poolOfSliceValidators sliceValidatorsPool
+ poolOfItemsValidators itemsValidatorsPool
+ poolOfBasicCommonValidators basicCommonValidatorsPool
+ poolOfHeaderValidators headerValidatorsPool
+ poolOfParamValidators paramValidatorsPool
+ poolOfBasicSliceValidators basicSliceValidatorsPool
+ poolOfNumberValidators numberValidatorsPool
+ poolOfStringValidators stringValidatorsPool
+ poolOfSchemaPropsValidators schemaPropsValidatorsPool
+ poolOfFormatValidators formatValidatorsPool
+ poolOfTypeValidators typeValidatorsPool
+ poolOfSchemas schemasPool
+ poolOfResults resultsPool
+ }
+
+ schemaValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*SchemaValidator]status
+ allocMap map[*SchemaValidator]string
+ redeemMap map[*SchemaValidator]string
+ mx sync.Mutex
+ }
+
+ objectValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*objectValidator]status
+ allocMap map[*objectValidator]string
+ redeemMap map[*objectValidator]string
+ mx sync.Mutex
+ }
+
+ sliceValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*schemaSliceValidator]status
+ allocMap map[*schemaSliceValidator]string
+ redeemMap map[*schemaSliceValidator]string
+ mx sync.Mutex
+ }
+
+ itemsValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*itemsValidator]status
+ allocMap map[*itemsValidator]string
+ redeemMap map[*itemsValidator]string
+ mx sync.Mutex
+ }
+
+ basicCommonValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*basicCommonValidator]status
+ allocMap map[*basicCommonValidator]string
+ redeemMap map[*basicCommonValidator]string
+ mx sync.Mutex
+ }
+
+ headerValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*HeaderValidator]status
+ allocMap map[*HeaderValidator]string
+ redeemMap map[*HeaderValidator]string
+ mx sync.Mutex
+ }
+
+ paramValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*ParamValidator]status
+ allocMap map[*ParamValidator]string
+ redeemMap map[*ParamValidator]string
+ mx sync.Mutex
+ }
+
+ basicSliceValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*basicSliceValidator]status
+ allocMap map[*basicSliceValidator]string
+ redeemMap map[*basicSliceValidator]string
+ mx sync.Mutex
+ }
+
+ numberValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*numberValidator]status
+ allocMap map[*numberValidator]string
+ redeemMap map[*numberValidator]string
+ mx sync.Mutex
+ }
+
+ stringValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*stringValidator]status
+ allocMap map[*stringValidator]string
+ redeemMap map[*stringValidator]string
+ mx sync.Mutex
+ }
+
+ schemaPropsValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*schemaPropsValidator]status
+ allocMap map[*schemaPropsValidator]string
+ redeemMap map[*schemaPropsValidator]string
+ mx sync.Mutex
+ }
+
+ formatValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*formatValidator]status
+ allocMap map[*formatValidator]string
+ redeemMap map[*formatValidator]string
+ mx sync.Mutex
+ }
+
+ typeValidatorsPool struct {
+ *sync.Pool
+ debugMap map[*typeValidator]status
+ allocMap map[*typeValidator]string
+ redeemMap map[*typeValidator]string
+ mx sync.Mutex
+ }
+
+ schemasPool struct {
+ *sync.Pool
+ debugMap map[*spec.Schema]status
+ allocMap map[*spec.Schema]string
+ redeemMap map[*spec.Schema]string
+ mx sync.Mutex
+ }
+
+ resultsPool struct {
+ *sync.Pool
+ debugMap map[*Result]status
+ allocMap map[*Result]string
+ redeemMap map[*Result]string
+ mx sync.Mutex
+ }
+)
+
+func (p *schemaValidatorsPool) BorrowValidator() *SchemaValidator {
+ s := p.Get().(*SchemaValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled schema should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *schemaValidatorsPool) RedeemValidator(s *SchemaValidator) {
+ // NOTE: s might be nil. In that case, Put is a noop.
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed schema should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed schema should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *objectValidatorsPool) BorrowValidator() *objectValidator {
+ s := p.Get().(*objectValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled object should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *objectValidatorsPool) RedeemValidator(s *objectValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed object should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed object should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *sliceValidatorsPool) BorrowValidator() *schemaSliceValidator {
+ s := p.Get().(*schemaSliceValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled schemaSliceValidator should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *sliceValidatorsPool) RedeemValidator(s *schemaSliceValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed schemaSliceValidator should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed schemaSliceValidator should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *itemsValidatorsPool) BorrowValidator() *itemsValidator {
+ s := p.Get().(*itemsValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled itemsValidator should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *itemsValidatorsPool) RedeemValidator(s *itemsValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed itemsValidator should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed itemsValidator should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *basicCommonValidatorsPool) BorrowValidator() *basicCommonValidator {
+ s := p.Get().(*basicCommonValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled basicCommonValidator should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *basicCommonValidatorsPool) RedeemValidator(s *basicCommonValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed basicCommonValidator should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed basicCommonValidator should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *headerValidatorsPool) BorrowValidator() *HeaderValidator {
+ s := p.Get().(*HeaderValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled HeaderValidator should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *headerValidatorsPool) RedeemValidator(s *HeaderValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed header should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed header should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *paramValidatorsPool) BorrowValidator() *ParamValidator {
+ s := p.Get().(*ParamValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled param should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *paramValidatorsPool) RedeemValidator(s *ParamValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed param should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed param should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *basicSliceValidatorsPool) BorrowValidator() *basicSliceValidator {
+ s := p.Get().(*basicSliceValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled basicSliceValidator should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *basicSliceValidatorsPool) RedeemValidator(s *basicSliceValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed basicSliceValidator should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed basicSliceValidator should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *numberValidatorsPool) BorrowValidator() *numberValidator {
+ s := p.Get().(*numberValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled number should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *numberValidatorsPool) RedeemValidator(s *numberValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed number should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed number should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *stringValidatorsPool) BorrowValidator() *stringValidator {
+ s := p.Get().(*stringValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled string should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *stringValidatorsPool) RedeemValidator(s *stringValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed string should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed string should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *schemaPropsValidatorsPool) BorrowValidator() *schemaPropsValidator {
+ s := p.Get().(*schemaPropsValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled param should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *schemaPropsValidatorsPool) RedeemValidator(s *schemaPropsValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed schemaProps should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed schemaProps should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *formatValidatorsPool) BorrowValidator() *formatValidator {
+ s := p.Get().(*formatValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled format should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *formatValidatorsPool) RedeemValidator(s *formatValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed format should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed format should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *typeValidatorsPool) BorrowValidator() *typeValidator {
+ s := p.Get().(*typeValidator)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled type should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *typeValidatorsPool) RedeemValidator(s *typeValidator) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed type should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic(fmt.Errorf("redeemed type should have been allocated from a fresh or recycled pointer. Got status %s, already redeamed at: %s", x, p.redeemMap[s]))
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *schemasPool) BorrowSchema() *spec.Schema {
+ s := p.Get().(*spec.Schema)
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled spec.Schema should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *schemasPool) RedeemSchema(s *spec.Schema) {
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed spec.Schema should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed spec.Schema should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *resultsPool) BorrowResult() *Result {
+ s := p.Get().(*Result).cleared()
+
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ p.debugMap[s] = statusFresh
+ } else {
+ if x != statusRedeemed {
+ panic("recycled result should have been redeemed")
+ }
+ p.debugMap[s] = statusRecycled
+ }
+ p.allocMap[s] = caller()
+
+ return s
+}
+
+func (p *resultsPool) RedeemResult(s *Result) {
+ if s == emptyResult {
+ if len(s.Errors) > 0 || len(s.Warnings) > 0 {
+ panic("empty result should not mutate")
+ }
+ return
+ }
+ p.mx.Lock()
+ defer p.mx.Unlock()
+ x, ok := p.debugMap[s]
+ if !ok {
+ panic("redeemed Result should have been allocated")
+ }
+ if x != statusRecycled && x != statusFresh {
+ panic("redeemed Result should have been allocated from a fresh or recycled pointer")
+ }
+ p.debugMap[s] = statusRedeemed
+ p.redeemMap[s] = caller()
+ p.Put(s)
+}
+
+func (p *allPools) allIsRedeemed(t testing.TB) bool {
+ outcome := true
+ for k, v := range p.poolOfSchemaValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("schemaValidator should be redeemed. Allocated by: %s", p.poolOfSchemaValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfObjectValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("objectValidator should be redeemed. Allocated by: %s", p.poolOfObjectValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfSliceValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("sliceValidator should be redeemed. Allocated by: %s", p.poolOfSliceValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfItemsValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("itemsValidator should be redeemed. Allocated by: %s", p.poolOfItemsValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfBasicCommonValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("basicCommonValidator should be redeemed. Allocated by: %s", p.poolOfBasicCommonValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfHeaderValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("headerValidator should be redeemed. Allocated by: %s", p.poolOfHeaderValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfParamValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("paramValidator should be redeemed. Allocated by: %s", p.poolOfParamValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfBasicSliceValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("basicSliceValidator should be redeemed. Allocated by: %s", p.poolOfBasicSliceValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfNumberValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("numberValidator should be redeemed. Allocated by: %s", p.poolOfNumberValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfStringValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("stringValidator should be redeemed. Allocated by: %s", p.poolOfStringValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfSchemaPropsValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("schemaPropsValidator should be redeemed. Allocated by: %s", p.poolOfSchemaPropsValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfFormatValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("formatValidator should be redeemed. Allocated by: %s", p.poolOfFormatValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfTypeValidators.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("typeValidator should be redeemed. Allocated by: %s", p.poolOfTypeValidators.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfSchemas.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("schemas should be redeemed. Allocated by: %s", p.poolOfSchemas.allocMap[k])
+ outcome = false
+ }
+ for k, v := range p.poolOfResults.debugMap {
+ if v == statusRedeemed {
+ continue
+ }
+ t.Logf("result should be redeemed. Allocated by: %s", p.poolOfResults.allocMap[k])
+ outcome = false
+ }
+
+ return outcome
+}
+
+func caller() string {
+ pc, _, _, _ := runtime.Caller(3) //nolint:dogsled
+ from, line := runtime.FuncForPC(pc).FileLine(pc)
+
+ return fmt.Sprintf("%s:%d", from, line)
+}
diff --git a/vendor/github.com/go-openapi/validate/result.go b/vendor/github.com/go-openapi/validate/result.go
new file mode 100644
index 000000000000..69219e99823b
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/result.go
@@ -0,0 +1,560 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ stderrors "errors"
+ "reflect"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+)
+
+var emptyResult = &Result{MatchCount: 1}
+
+// Result represents a validation result set, composed of
+// errors and warnings.
+//
+// It is used to keep track of all detected errors and warnings during
+// the validation of a specification.
+//
+// Matchcount is used to determine
+// which errors are relevant in the case of AnyOf, OneOf
+// schema validation. Results from the validation branch
+// with most matches get eventually selected.
+//
+// TODO: keep path of key originating the error
+type Result struct {
+ Errors []error
+ Warnings []error
+ MatchCount int
+
+ // the object data
+ data any
+
+ // Schemata for the root object
+ rootObjectSchemata schemata
+ // Schemata for object fields
+ fieldSchemata []fieldSchemata
+ // Schemata for slice items
+ itemSchemata []itemSchemata
+
+ cachedFieldSchemata map[FieldKey][]*spec.Schema
+ cachedItemSchemata map[ItemKey][]*spec.Schema
+
+ wantsRedeemOnMerge bool
+}
+
+// FieldKey is a pair of an object and a field, usable as a key for a map.
+type FieldKey struct {
+ object reflect.Value // actually a map[string]any, but the latter cannot be a key
+ field string
+}
+
+// ItemKey is a pair of a slice and an index, usable as a key for a map.
+type ItemKey struct {
+ slice reflect.Value // actually a []any, but the latter cannot be a key
+ index int
+}
+
+// NewFieldKey returns a pair of an object and field usable as a key of a map.
+func NewFieldKey(obj map[string]any, field string) FieldKey {
+ return FieldKey{object: reflect.ValueOf(obj), field: field}
+}
+
+// Object returns the underlying object of this key.
+func (fk *FieldKey) Object() map[string]any {
+ return fk.object.Interface().(map[string]any)
+}
+
+// Field returns the underlying field of this key.
+func (fk *FieldKey) Field() string {
+ return fk.field
+}
+
+// NewItemKey returns a pair of a slice and index usable as a key of a map.
+func NewItemKey(slice any, i int) ItemKey {
+ return ItemKey{slice: reflect.ValueOf(slice), index: i}
+}
+
+// Slice returns the underlying slice of this key.
+func (ik *ItemKey) Slice() []any {
+ return ik.slice.Interface().([]any)
+}
+
+// Index returns the underlying index of this key.
+func (ik *ItemKey) Index() int {
+ return ik.index
+}
+
+type fieldSchemata struct {
+ obj map[string]any
+ field string
+ schemata schemata
+}
+
+type itemSchemata struct {
+ slice reflect.Value
+ index int
+ schemata schemata
+}
+
+// Merge merges this result with the other one(s), preserving match counts etc.
+func (r *Result) Merge(others ...*Result) *Result {
+ for _, other := range others {
+ if other == nil {
+ continue
+ }
+ r.mergeWithoutRootSchemata(other)
+ r.rootObjectSchemata.Append(other.rootObjectSchemata)
+ if other.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(other)
+ }
+ }
+ return r
+}
+
+// Data returns the original data object used for validation. Mutating this renders
+// the result invalid.
+func (r *Result) Data() any {
+ return r.data
+}
+
+// RootObjectSchemata returns the schemata which apply to the root object.
+func (r *Result) RootObjectSchemata() []*spec.Schema {
+ return r.rootObjectSchemata.Slice()
+}
+
+// FieldSchemata returns the schemata which apply to fields in objects.
+func (r *Result) FieldSchemata() map[FieldKey][]*spec.Schema {
+ if r.cachedFieldSchemata != nil {
+ return r.cachedFieldSchemata
+ }
+
+ ret := make(map[FieldKey][]*spec.Schema, len(r.fieldSchemata))
+ for _, fs := range r.fieldSchemata {
+ key := NewFieldKey(fs.obj, fs.field)
+ if fs.schemata.one != nil {
+ ret[key] = append(ret[key], fs.schemata.one)
+ } else if len(fs.schemata.multiple) > 0 {
+ ret[key] = append(ret[key], fs.schemata.multiple...)
+ }
+ }
+ r.cachedFieldSchemata = ret
+
+ return ret
+}
+
+// ItemSchemata returns the schemata which apply to items in slices.
+func (r *Result) ItemSchemata() map[ItemKey][]*spec.Schema {
+ if r.cachedItemSchemata != nil {
+ return r.cachedItemSchemata
+ }
+
+ ret := make(map[ItemKey][]*spec.Schema, len(r.itemSchemata))
+ for _, ss := range r.itemSchemata {
+ key := NewItemKey(ss.slice, ss.index)
+ if ss.schemata.one != nil {
+ ret[key] = append(ret[key], ss.schemata.one)
+ } else if len(ss.schemata.multiple) > 0 {
+ ret[key] = append(ret[key], ss.schemata.multiple...)
+ }
+ }
+ r.cachedItemSchemata = ret
+ return ret
+}
+
+// MergeAsErrors merges this result with the other one(s), preserving match counts etc.
+//
+// Warnings from input are merged as Errors in the returned merged Result.
+func (r *Result) MergeAsErrors(others ...*Result) *Result {
+ for _, other := range others {
+ if other != nil {
+ r.resetCaches()
+ r.AddErrors(other.Errors...)
+ r.AddErrors(other.Warnings...)
+ r.MatchCount += other.MatchCount
+ if other.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(other)
+ }
+ }
+ }
+ return r
+}
+
+// MergeAsWarnings merges this result with the other one(s), preserving match counts etc.
+//
+// Errors from input are merged as Warnings in the returned merged Result.
+func (r *Result) MergeAsWarnings(others ...*Result) *Result {
+ for _, other := range others {
+ if other != nil {
+ r.resetCaches()
+ r.AddWarnings(other.Errors...)
+ r.AddWarnings(other.Warnings...)
+ r.MatchCount += other.MatchCount
+ if other.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(other)
+ }
+ }
+ }
+ return r
+}
+
+// AddErrors adds errors to this validation result (if not already reported).
+//
+// Since the same check may be passed several times while exploring the
+// spec structure (via $ref, ...) reported messages are kept
+// unique.
+func (r *Result) AddErrors(errors ...error) {
+ for _, e := range errors {
+ found := false
+ if e != nil {
+ for _, isReported := range r.Errors {
+ if e.Error() == isReported.Error() {
+ found = true
+ break
+ }
+ }
+ if !found {
+ r.Errors = append(r.Errors, e)
+ }
+ }
+ }
+}
+
+// AddWarnings adds warnings to this validation result (if not already reported).
+func (r *Result) AddWarnings(warnings ...error) {
+ for _, e := range warnings {
+ found := false
+ if e != nil {
+ for _, isReported := range r.Warnings {
+ if e.Error() == isReported.Error() {
+ found = true
+ break
+ }
+ }
+ if !found {
+ r.Warnings = append(r.Warnings, e)
+ }
+ }
+ }
+}
+
+// IsValid returns true when this result is valid.
+//
+// Returns true on a nil *Result.
+func (r *Result) IsValid() bool {
+ if r == nil {
+ return true
+ }
+ return len(r.Errors) == 0
+}
+
+// HasErrors returns true when this result is invalid.
+//
+// Returns false on a nil *Result.
+func (r *Result) HasErrors() bool {
+ if r == nil {
+ return false
+ }
+ return !r.IsValid()
+}
+
+// HasWarnings returns true when this result contains warnings.
+//
+// Returns false on a nil *Result.
+func (r *Result) HasWarnings() bool {
+ if r == nil {
+ return false
+ }
+ return len(r.Warnings) > 0
+}
+
+// HasErrorsOrWarnings returns true when this result contains
+// either errors or warnings.
+//
+// Returns false on a nil *Result.
+func (r *Result) HasErrorsOrWarnings() bool {
+ if r == nil {
+ return false
+ }
+ return len(r.Errors) > 0 || len(r.Warnings) > 0
+}
+
+// Inc increments the match count
+func (r *Result) Inc() {
+ r.MatchCount++
+}
+
+// AsError renders this result as an error interface
+//
+// TODO: reporting / pretty print with path ordered and indented
+func (r *Result) AsError() error {
+ if r.IsValid() {
+ return nil
+ }
+ return errors.CompositeValidationError(r.Errors...)
+}
+
+func (r *Result) resetCaches() {
+ r.cachedFieldSchemata = nil
+ r.cachedItemSchemata = nil
+}
+
+// mergeForField merges other into r, assigning other's root schemata to the given Object and field name.
+//
+//nolint:unparam
+func (r *Result) mergeForField(obj map[string]any, field string, other *Result) *Result {
+ if other == nil {
+ return r
+ }
+ r.mergeWithoutRootSchemata(other)
+
+ if other.rootObjectSchemata.Len() > 0 {
+ if r.fieldSchemata == nil {
+ r.fieldSchemata = make([]fieldSchemata, len(obj))
+ }
+ // clone other schemata, as other is about to be redeemed to the pool
+ r.fieldSchemata = append(r.fieldSchemata, fieldSchemata{
+ obj: obj,
+ field: field,
+ schemata: other.rootObjectSchemata.Clone(),
+ })
+ }
+ if other.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(other)
+ }
+
+ return r
+}
+
+// mergeForSlice merges other into r, assigning other's root schemata to the given slice and index.
+//
+//nolint:unparam
+func (r *Result) mergeForSlice(slice reflect.Value, i int, other *Result) *Result {
+ if other == nil {
+ return r
+ }
+ r.mergeWithoutRootSchemata(other)
+
+ if other.rootObjectSchemata.Len() > 0 {
+ if r.itemSchemata == nil {
+ r.itemSchemata = make([]itemSchemata, slice.Len())
+ }
+ // clone other schemata, as other is about to be redeemed to the pool
+ r.itemSchemata = append(r.itemSchemata, itemSchemata{
+ slice: slice,
+ index: i,
+ schemata: other.rootObjectSchemata.Clone(),
+ })
+ }
+
+ if other.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(other)
+ }
+
+ return r
+}
+
+// addRootObjectSchemata adds the given schemata for the root object of the result.
+//
+// Since the slice schemata might be reused, it is shallow-cloned before saving it into the result.
+func (r *Result) addRootObjectSchemata(s *spec.Schema) {
+ clone := *s
+ r.rootObjectSchemata.Append(schemata{one: &clone})
+}
+
+// addPropertySchemata adds the given schemata for the object and field.
+//
+// Since the slice schemata might be reused, it is shallow-cloned before saving it into the result.
+func (r *Result) addPropertySchemata(obj map[string]any, fld string, schema *spec.Schema) {
+ if r.fieldSchemata == nil {
+ r.fieldSchemata = make([]fieldSchemata, 0, len(obj))
+ }
+ clone := *schema
+ r.fieldSchemata = append(r.fieldSchemata, fieldSchemata{obj: obj, field: fld, schemata: schemata{one: &clone}})
+}
+
+/*
+// addSliceSchemata adds the given schemata for the slice and index.
+// The slice schemata might be reused. I.e. do not modify it after being added to a result.
+func (r *Result) addSliceSchemata(slice reflect.Value, i int, schema *spec.Schema) {
+ if r.itemSchemata == nil {
+ r.itemSchemata = make([]itemSchemata, 0, slice.Len())
+ }
+ r.itemSchemata = append(r.itemSchemata, itemSchemata{slice: slice, index: i, schemata: schemata{one: schema}})
+}
+*/
+
+// mergeWithoutRootSchemata merges other into r, ignoring the rootObject schemata.
+func (r *Result) mergeWithoutRootSchemata(other *Result) {
+ r.resetCaches()
+ r.AddErrors(other.Errors...)
+ r.AddWarnings(other.Warnings...)
+ r.MatchCount += other.MatchCount
+
+ if other.fieldSchemata != nil {
+ if r.fieldSchemata == nil {
+ r.fieldSchemata = make([]fieldSchemata, 0, len(other.fieldSchemata))
+ }
+ for _, field := range other.fieldSchemata {
+ field.schemata = field.schemata.Clone()
+ r.fieldSchemata = append(r.fieldSchemata, field)
+ }
+ }
+
+ if other.itemSchemata != nil {
+ if r.itemSchemata == nil {
+ r.itemSchemata = make([]itemSchemata, 0, len(other.itemSchemata))
+ }
+ for _, field := range other.itemSchemata {
+ field.schemata = field.schemata.Clone()
+ r.itemSchemata = append(r.itemSchemata, field)
+ }
+ }
+}
+
+func isImportant(err error) bool {
+ return strings.HasPrefix(err.Error(), "IMPORTANT!")
+}
+
+func stripImportantTag(err error) error {
+ return stderrors.New(strings.TrimPrefix(err.Error(), "IMPORTANT!")) //nolint:err113
+}
+
+func (r *Result) keepRelevantErrors() *Result {
+ // TODO: this one is going to disapear...
+ // keepRelevantErrors strips a result from standard errors and keeps
+ // the ones which are supposedly more accurate.
+ //
+ // The original result remains unaffected (creates a new instance of Result).
+ // This method is used to work around the "matchCount" filter which would otherwise
+ // strip our result from some accurate error reporting from lower level validators.
+ //
+ // NOTE: this implementation with a placeholder (IMPORTANT!) is neither clean nor
+ // very efficient. On the other hand, relying on go-openapi/errors to manipulate
+ // codes would require to change a lot here. So, for the moment, let's go with
+ // placeholders.
+ strippedErrors := []error{}
+ for _, e := range r.Errors {
+ if isImportant(e) {
+ strippedErrors = append(strippedErrors, stripImportantTag(e))
+ }
+ }
+ strippedWarnings := []error{}
+ for _, e := range r.Warnings {
+ if isImportant(e) {
+ strippedWarnings = append(strippedWarnings, stripImportantTag(e))
+ }
+ }
+ var strippedResult *Result
+ if r.wantsRedeemOnMerge {
+ strippedResult = pools.poolOfResults.BorrowResult()
+ } else {
+ strippedResult = new(Result)
+ }
+ strippedResult.Errors = strippedErrors
+ strippedResult.Warnings = strippedWarnings
+ return strippedResult
+}
+
+func (r *Result) cleared() *Result {
+ // clear the Result to be reusable. Keep allocated capacity.
+ r.Errors = r.Errors[:0]
+ r.Warnings = r.Warnings[:0]
+ r.MatchCount = 0
+ r.data = nil
+ r.rootObjectSchemata.one = nil
+ r.rootObjectSchemata.multiple = r.rootObjectSchemata.multiple[:0]
+ r.fieldSchemata = r.fieldSchemata[:0]
+ r.itemSchemata = r.itemSchemata[:0]
+ for k := range r.cachedFieldSchemata {
+ delete(r.cachedFieldSchemata, k)
+ }
+ for k := range r.cachedItemSchemata {
+ delete(r.cachedItemSchemata, k)
+ }
+ r.wantsRedeemOnMerge = true // mark this result as eligible for redeem when merged into another
+
+ return r
+}
+
+// schemata is an arbitrary number of schemata. It does a distinction between zero,
+// one and many schemata to avoid slice allocations.
+type schemata struct {
+ // one is set if there is exactly one schema. In that case multiple must be nil.
+ one *spec.Schema
+ // multiple is an arbitrary number of schemas. If it is set, one must be nil.
+ multiple []*spec.Schema
+}
+
+func (s *schemata) Len() int {
+ if s.one != nil {
+ return 1
+ }
+ return len(s.multiple)
+}
+
+func (s *schemata) Slice() []*spec.Schema {
+ if s == nil {
+ return nil
+ }
+ if s.one != nil {
+ return []*spec.Schema{s.one}
+ }
+ return s.multiple
+}
+
+// Append appends the schemata in other to s. It mutates s in-place.
+func (s *schemata) Append(other schemata) {
+ if other.one == nil && len(other.multiple) == 0 {
+ return
+ }
+ if s.one == nil && len(s.multiple) == 0 {
+ *s = other
+ return
+ }
+
+ if s.one != nil {
+ if other.one != nil {
+ s.multiple = []*spec.Schema{s.one, other.one}
+ } else {
+ t := make([]*spec.Schema, 0, 1+len(other.multiple))
+ s.multiple = append(append(t, s.one), other.multiple...)
+ }
+ s.one = nil
+ } else {
+ if other.one != nil {
+ s.multiple = append(s.multiple, other.one)
+ } else {
+ if cap(s.multiple) >= len(s.multiple)+len(other.multiple) {
+ s.multiple = append(s.multiple, other.multiple...)
+ } else {
+ t := make([]*spec.Schema, 0, len(s.multiple)+len(other.multiple))
+ s.multiple = append(append(t, s.multiple...), other.multiple...)
+ }
+ }
+ }
+}
+
+func (s schemata) Clone() schemata {
+ var clone schemata
+
+ if s.one != nil {
+ clone.one = new(spec.Schema)
+ *clone.one = *s.one
+ }
+
+ if len(s.multiple) > 0 {
+ clone.multiple = make([]*spec.Schema, len(s.multiple))
+ for idx := range len(s.multiple) {
+ sp := new(spec.Schema)
+ *sp = *s.multiple[idx]
+ clone.multiple[idx] = sp
+ }
+ }
+
+ return clone
+}
diff --git a/vendor/github.com/go-openapi/validate/rexp.go b/vendor/github.com/go-openapi/validate/rexp.go
new file mode 100644
index 000000000000..795f148d0cfc
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/rexp.go
@@ -0,0 +1,59 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "maps"
+ re "regexp"
+ "sync"
+ "sync/atomic"
+)
+
+// Cache for compiled regular expressions
+var (
+ cacheMutex = &sync.Mutex{}
+ reDict = atomic.Value{} // map[string]*re.Regexp
+)
+
+func compileRegexp(pattern string) (*re.Regexp, error) {
+ if cache, ok := reDict.Load().(map[string]*re.Regexp); ok {
+ if r := cache[pattern]; r != nil {
+ return r, nil
+ }
+ }
+
+ r, err := re.Compile(pattern)
+ if err != nil {
+ return nil, err
+ }
+ cacheRegexp(r)
+ return r, nil
+}
+
+func mustCompileRegexp(pattern string) *re.Regexp {
+ if cache, ok := reDict.Load().(map[string]*re.Regexp); ok {
+ if r := cache[pattern]; r != nil {
+ return r
+ }
+ }
+
+ r := re.MustCompile(pattern)
+ cacheRegexp(r)
+ return r
+}
+
+func cacheRegexp(r *re.Regexp) {
+ cacheMutex.Lock()
+ defer cacheMutex.Unlock()
+
+ if cache, ok := reDict.Load().(map[string]*re.Regexp); !ok || cache[r.String()] == nil {
+ newCache := map[string]*re.Regexp{
+ r.String(): r,
+ }
+
+ maps.Copy(newCache, cache)
+
+ reDict.Store(newCache)
+ }
+}
diff --git a/vendor/github.com/go-openapi/validate/schema.go b/vendor/github.com/go-openapi/validate/schema.go
new file mode 100644
index 000000000000..375a98765d75
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/schema.go
@@ -0,0 +1,351 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "encoding/json"
+ "reflect"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// SchemaValidator validates data against a JSON schema
+type SchemaValidator struct {
+ Path string
+ in string
+ Schema *spec.Schema
+ validators [8]valueValidator
+ Root any
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+// AgainstSchema validates the specified data against the provided schema, using a registry of supported formats.
+//
+// When no pre-parsed *spec.Schema structure is provided, it uses a JSON schema as default. See example.
+func AgainstSchema(schema *spec.Schema, data any, formats strfmt.Registry, options ...Option) error {
+ res := NewSchemaValidator(schema, nil, "", formats,
+ append(options, WithRecycleValidators(true), withRecycleResults(true))...,
+ ).Validate(data)
+ defer func() {
+ pools.poolOfResults.RedeemResult(res)
+ }()
+
+ if res.HasErrors() {
+ return errors.CompositeValidationError(res.Errors...)
+ }
+
+ return nil
+}
+
+// NewSchemaValidator creates a new schema validator.
+//
+// Panics if the provided schema is invalid.
+func NewSchemaValidator(schema *spec.Schema, rootSchema any, root string, formats strfmt.Registry, options ...Option) *SchemaValidator {
+ opts := new(SchemaValidatorOptions)
+ for _, o := range options {
+ o(opts)
+ }
+
+ return newSchemaValidator(schema, rootSchema, root, formats, opts)
+}
+
+func newSchemaValidator(schema *spec.Schema, rootSchema any, root string, formats strfmt.Registry, opts *SchemaValidatorOptions) *SchemaValidator {
+ if schema == nil {
+ return nil
+ }
+
+ if rootSchema == nil {
+ rootSchema = schema
+ }
+
+ if schema.ID != "" || schema.Ref.String() != "" || schema.Ref.IsRoot() {
+ err := spec.ExpandSchema(schema, rootSchema, nil)
+ if err != nil {
+ msg := invalidSchemaProvidedMsg(err).Error()
+ panic(msg)
+ }
+ }
+
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var s *SchemaValidator
+ if opts.recycleValidators {
+ s = pools.poolOfSchemaValidators.BorrowValidator()
+ } else {
+ s = new(SchemaValidator)
+ }
+
+ s.Path = root
+ s.in = "body"
+ s.Schema = schema
+ s.Root = rootSchema
+ s.Options = opts
+ s.KnownFormats = formats
+
+ s.validators = [8]valueValidator{
+ s.typeValidator(),
+ s.schemaPropsValidator(),
+ s.stringValidator(),
+ s.formatValidator(),
+ s.numberValidator(),
+ s.sliceValidator(),
+ s.commonValidator(),
+ s.objectValidator(),
+ }
+
+ return s
+}
+
+// SetPath sets the path for this schema valdiator
+func (s *SchemaValidator) SetPath(path string) {
+ s.Path = path
+}
+
+// Applies returns true when this schema validator applies
+func (s *SchemaValidator) Applies(source any, _ reflect.Kind) bool {
+ _, ok := source.(*spec.Schema)
+ return ok
+}
+
+// Validate validates the data against the schema
+func (s *SchemaValidator) Validate(data any) *Result {
+ if s == nil {
+ return emptyResult
+ }
+
+ if s.Options.recycleValidators {
+ defer func() {
+ s.redeemChildren()
+ s.redeem() // one-time use validator
+ }()
+ }
+
+ var result *Result
+ if s.Options.recycleResult {
+ result = pools.poolOfResults.BorrowResult()
+ result.data = data
+ } else {
+ result = &Result{data: data}
+ }
+
+ if s.Schema != nil && !s.Options.skipSchemataResult {
+ result.addRootObjectSchemata(s.Schema)
+ }
+
+ if data == nil {
+ // early exit with minimal validation
+ result.Merge(s.validators[0].Validate(data)) // type validator
+ result.Merge(s.validators[6].Validate(data)) // common validator
+
+ if s.Options.recycleValidators {
+ s.validators[0] = nil
+ s.validators[6] = nil
+ }
+
+ return result
+ }
+
+ tpe := reflect.TypeOf(data)
+ kind := tpe.Kind()
+ for kind == reflect.Ptr {
+ tpe = tpe.Elem()
+ kind = tpe.Kind()
+ }
+ d := data
+
+ if kind == reflect.Struct {
+ // NOTE: since reflect retrieves the true nature of types
+ // this means that all strfmt types passed here (e.g. strfmt.Datetime, etc..)
+ // are converted here to strings, and structs are systematically converted
+ // to map[string]interface{}.
+ var dd any
+ if err := jsonutils.FromDynamicJSON(data, &dd); err != nil {
+ result.AddErrors(err)
+ result.Inc()
+
+ return result
+ }
+
+ d = dd
+ }
+
+ // TODO: this part should be handed over to type validator
+ // Handle special case of json.Number data (number marshalled as string)
+ isnumber := s.Schema != nil && (s.Schema.Type.Contains(numberType) || s.Schema.Type.Contains(integerType))
+ if num, ok := data.(json.Number); ok && isnumber {
+ if s.Schema.Type.Contains(integerType) { // avoid lossy conversion
+ in, erri := num.Int64()
+ if erri != nil {
+ result.AddErrors(invalidTypeConversionMsg(s.Path, erri))
+ result.Inc()
+
+ return result
+ }
+ d = in
+ } else {
+ nf, errf := num.Float64()
+ if errf != nil {
+ result.AddErrors(invalidTypeConversionMsg(s.Path, errf))
+ result.Inc()
+
+ return result
+ }
+ d = nf
+ }
+
+ tpe = reflect.TypeOf(d)
+ kind = tpe.Kind()
+ }
+
+ for idx, v := range s.validators {
+ if !v.Applies(s.Schema, kind) {
+ if s.Options.recycleValidators {
+ // Validate won't be called, so relinquish this validator
+ if redeemableChildren, ok := v.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := v.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ s.validators[idx] = nil // prevents further (unsafe) usage
+ }
+
+ continue
+ }
+
+ result.Merge(v.Validate(d))
+ if s.Options.recycleValidators {
+ s.validators[idx] = nil // prevents further (unsafe) usage
+ }
+ result.Inc()
+ }
+ result.Inc()
+
+ return result
+}
+
+func (s *SchemaValidator) typeValidator() valueValidator {
+ return newTypeValidator(
+ s.Path,
+ s.in,
+ s.Schema.Type,
+ s.Schema.Nullable,
+ s.Schema.Format,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) commonValidator() valueValidator {
+ return newBasicCommonValidator(
+ s.Path,
+ s.in,
+ s.Schema.Default,
+ s.Schema.Enum,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) sliceValidator() valueValidator {
+ return newSliceValidator(
+ s.Path,
+ s.in,
+ s.Schema.MaxItems,
+ s.Schema.MinItems,
+ s.Schema.UniqueItems,
+ s.Schema.AdditionalItems,
+ s.Schema.Items,
+ s.Root,
+ s.KnownFormats,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) numberValidator() valueValidator {
+ return newNumberValidator(
+ s.Path,
+ s.in,
+ s.Schema.Default,
+ s.Schema.MultipleOf,
+ s.Schema.Maximum,
+ s.Schema.ExclusiveMaximum,
+ s.Schema.Minimum,
+ s.Schema.ExclusiveMinimum,
+ "",
+ "",
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) stringValidator() valueValidator {
+ return newStringValidator(
+ s.Path,
+ s.in,
+ nil,
+ false,
+ false,
+ s.Schema.MaxLength,
+ s.Schema.MinLength,
+ s.Schema.Pattern,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) formatValidator() valueValidator {
+ return newFormatValidator(
+ s.Path,
+ s.in,
+ s.Schema.Format,
+ s.KnownFormats,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) schemaPropsValidator() valueValidator {
+ sch := s.Schema
+ return newSchemaPropsValidator(
+ s.Path, s.in, sch.AllOf, sch.OneOf, sch.AnyOf, sch.Not, sch.Dependencies, s.Root, s.KnownFormats,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) objectValidator() valueValidator {
+ return newObjectValidator(
+ s.Path,
+ s.in,
+ s.Schema.MaxProperties,
+ s.Schema.MinProperties,
+ s.Schema.Required,
+ s.Schema.Properties,
+ s.Schema.AdditionalProperties,
+ s.Schema.PatternProperties,
+ s.Root,
+ s.KnownFormats,
+ s.Options,
+ )
+}
+
+func (s *SchemaValidator) redeem() {
+ pools.poolOfSchemaValidators.RedeemValidator(s)
+}
+
+func (s *SchemaValidator) redeemChildren() {
+ for i, validator := range s.validators {
+ if validator == nil {
+ continue
+ }
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ s.validators[i] = nil // free up allocated children if not in pool
+ }
+}
diff --git a/vendor/github.com/go-openapi/validate/schema_messages.go b/vendor/github.com/go-openapi/validate/schema_messages.go
new file mode 100644
index 000000000000..e8c7c48ad7f1
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/schema_messages.go
@@ -0,0 +1,67 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "github.com/go-openapi/errors"
+)
+
+// Error messages related to schema validation and returned as results.
+const (
+ // ArrayDoesNotAllowAdditionalItemsError when an additionalItems construct is not verified by the array values provided.
+ //
+ // TODO: should move to package go-openapi/errors
+ ArrayDoesNotAllowAdditionalItemsError = "array doesn't allow for additional items"
+
+ // HasDependencyError indicates that a dependencies construct was not verified
+ HasDependencyError = "%q has a dependency on %s"
+
+ // InvalidSchemaProvidedError indicates that the schema provided to validate a value cannot be properly compiled
+ InvalidSchemaProvidedError = "Invalid schema provided to SchemaValidator: %v"
+
+ // InvalidTypeConversionError indicates that a numerical conversion for the given type could not be carried on
+ InvalidTypeConversionError = "invalid type conversion in %s: %v "
+
+ // MustValidateAtLeastOneSchemaError indicates that in a AnyOf construct, none of the schema constraints specified were verified
+ MustValidateAtLeastOneSchemaError = "%q must validate at least one schema (anyOf)"
+
+ // MustValidateOnlyOneSchemaError indicates that in a OneOf construct, either none of the schema constraints specified were verified, or several were
+ MustValidateOnlyOneSchemaError = "%q must validate one and only one schema (oneOf). %s"
+
+ // MustValidateAllSchemasError indicates that in a AllOf construct, at least one of the schema constraints specified were not verified
+ //
+ // TODO: punctuation in message
+ MustValidateAllSchemasError = "%q must validate all the schemas (allOf)%s"
+
+ // MustNotValidateSchemaError indicates that in a Not construct, the schema constraint specified was verified
+ MustNotValidateSchemaError = "%q must not validate the schema (not)"
+)
+
+// Warning messages related to schema validation and returned as results
+const ()
+
+func invalidSchemaProvidedMsg(err error) errors.Error {
+ return errors.New(InternalErrorCode, InvalidSchemaProvidedError, err)
+}
+func invalidTypeConversionMsg(path string, err error) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidTypeConversionError, path, err)
+}
+func mustValidateOnlyOneSchemaMsg(path, additionalMsg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, MustValidateOnlyOneSchemaError, path, additionalMsg)
+}
+func mustValidateAtLeastOneSchemaMsg(path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, MustValidateAtLeastOneSchemaError, path)
+}
+func mustValidateAllSchemasMsg(path, additionalMsg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, MustValidateAllSchemasError, path, additionalMsg)
+}
+func mustNotValidatechemaMsg(path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, MustNotValidateSchemaError, path)
+}
+func hasADependencyMsg(path, depkey string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, HasDependencyError, path, depkey)
+}
+func arrayDoesNotAllowAdditionalItemsMsg() errors.Error {
+ return errors.New(errors.CompositeErrorCode, ArrayDoesNotAllowAdditionalItemsError)
+}
diff --git a/vendor/github.com/go-openapi/validate/schema_option.go b/vendor/github.com/go-openapi/validate/schema_option.go
new file mode 100644
index 000000000000..d9fd21a75a12
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/schema_option.go
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+// SchemaValidatorOptions defines optional rules for schema validation
+type SchemaValidatorOptions struct {
+ EnableObjectArrayTypeCheck bool
+ EnableArrayMustHaveItemsCheck bool
+ recycleValidators bool
+ recycleResult bool
+ skipSchemataResult bool
+}
+
+// Option sets optional rules for schema validation
+type Option func(*SchemaValidatorOptions)
+
+// EnableObjectArrayTypeCheck activates the swagger rule: an items must be in type: array
+func EnableObjectArrayTypeCheck(enable bool) Option {
+ return func(svo *SchemaValidatorOptions) {
+ svo.EnableObjectArrayTypeCheck = enable
+ }
+}
+
+// EnableArrayMustHaveItemsCheck activates the swagger rule: an array must have items defined
+func EnableArrayMustHaveItemsCheck(enable bool) Option {
+ return func(svo *SchemaValidatorOptions) {
+ svo.EnableArrayMustHaveItemsCheck = enable
+ }
+}
+
+// SwaggerSchema activates swagger schema validation rules
+func SwaggerSchema(enable bool) Option {
+ return func(svo *SchemaValidatorOptions) {
+ svo.EnableObjectArrayTypeCheck = enable
+ svo.EnableArrayMustHaveItemsCheck = enable
+ }
+}
+
+// WithRecycleValidators saves memory allocations and makes validators
+// available for a single use of Validate() only.
+//
+// When a validator is recycled, called MUST not call the Validate() method twice.
+func WithRecycleValidators(enable bool) Option {
+ return func(svo *SchemaValidatorOptions) {
+ svo.recycleValidators = enable
+ }
+}
+
+func withRecycleResults(enable bool) Option {
+ return func(svo *SchemaValidatorOptions) {
+ svo.recycleResult = enable
+ }
+}
+
+// WithSkipSchemataResult skips the deep audit payload stored in validation Result
+func WithSkipSchemataResult(enable bool) Option {
+ return func(svo *SchemaValidatorOptions) {
+ svo.skipSchemataResult = enable
+ }
+}
+
+// Options returns the current set of options
+func (svo SchemaValidatorOptions) Options() []Option {
+ return []Option{
+ EnableObjectArrayTypeCheck(svo.EnableObjectArrayTypeCheck),
+ EnableArrayMustHaveItemsCheck(svo.EnableArrayMustHaveItemsCheck),
+ WithRecycleValidators(svo.recycleValidators),
+ withRecycleResults(svo.recycleResult),
+ WithSkipSchemataResult(svo.skipSchemataResult),
+ }
+}
diff --git a/vendor/github.com/go-openapi/validate/schema_props.go b/vendor/github.com/go-openapi/validate/schema_props.go
new file mode 100644
index 000000000000..485f536adc3a
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/schema_props.go
@@ -0,0 +1,345 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+type schemaPropsValidator struct {
+ Path string
+ In string
+ AllOf []spec.Schema
+ OneOf []spec.Schema
+ AnyOf []spec.Schema
+ Not *spec.Schema
+ Dependencies spec.Dependencies
+ anyOfValidators []*SchemaValidator
+ allOfValidators []*SchemaValidator
+ oneOfValidators []*SchemaValidator
+ notValidator *SchemaValidator
+ Root any
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+func (s *schemaPropsValidator) SetPath(path string) {
+ s.Path = path
+}
+
+func newSchemaPropsValidator(
+ path string, in string, allOf, oneOf, anyOf []spec.Schema, not *spec.Schema, deps spec.Dependencies, root any, formats strfmt.Registry,
+ opts *SchemaValidatorOptions) *schemaPropsValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ anyValidators := make([]*SchemaValidator, 0, len(anyOf))
+ for i := range anyOf {
+ anyValidators = append(anyValidators, newSchemaValidator(&anyOf[i], root, path, formats, opts))
+ }
+ allValidators := make([]*SchemaValidator, 0, len(allOf))
+ for i := range allOf {
+ allValidators = append(allValidators, newSchemaValidator(&allOf[i], root, path, formats, opts))
+ }
+ oneValidators := make([]*SchemaValidator, 0, len(oneOf))
+ for i := range oneOf {
+ oneValidators = append(oneValidators, newSchemaValidator(&oneOf[i], root, path, formats, opts))
+ }
+
+ var notValidator *SchemaValidator
+ if not != nil {
+ notValidator = newSchemaValidator(not, root, path, formats, opts)
+ }
+
+ var s *schemaPropsValidator
+ if opts.recycleValidators {
+ s = pools.poolOfSchemaPropsValidators.BorrowValidator()
+ } else {
+ s = new(schemaPropsValidator)
+ }
+
+ s.Path = path
+ s.In = in
+ s.AllOf = allOf
+ s.OneOf = oneOf
+ s.AnyOf = anyOf
+ s.Not = not
+ s.Dependencies = deps
+ s.anyOfValidators = anyValidators
+ s.allOfValidators = allValidators
+ s.oneOfValidators = oneValidators
+ s.notValidator = notValidator
+ s.Root = root
+ s.KnownFormats = formats
+ s.Options = opts
+
+ return s
+}
+
+func (s *schemaPropsValidator) Applies(source any, _ reflect.Kind) bool {
+ _, isSchema := source.(*spec.Schema)
+ return isSchema
+}
+
+func (s *schemaPropsValidator) Validate(data any) *Result {
+ var mainResult *Result
+ if s.Options.recycleResult {
+ mainResult = pools.poolOfResults.BorrowResult()
+ } else {
+ mainResult = new(Result)
+ }
+
+ // Intermediary error results
+
+ // IMPORTANT! messages from underlying validators
+ var keepResultAnyOf, keepResultOneOf, keepResultAllOf *Result
+
+ if s.Options.recycleValidators {
+ defer func() {
+ s.redeemChildren()
+ s.redeem()
+
+ // results are redeemed when merged
+ }()
+ }
+
+ if len(s.anyOfValidators) > 0 {
+ keepResultAnyOf = pools.poolOfResults.BorrowResult()
+ s.validateAnyOf(data, mainResult, keepResultAnyOf)
+ }
+
+ if len(s.oneOfValidators) > 0 {
+ keepResultOneOf = pools.poolOfResults.BorrowResult()
+ s.validateOneOf(data, mainResult, keepResultOneOf)
+ }
+
+ if len(s.allOfValidators) > 0 {
+ keepResultAllOf = pools.poolOfResults.BorrowResult()
+ s.validateAllOf(data, mainResult, keepResultAllOf)
+ }
+
+ if s.notValidator != nil {
+ s.validateNot(data, mainResult)
+ }
+
+ if len(s.Dependencies) > 0 && reflect.TypeOf(data).Kind() == reflect.Map {
+ s.validateDependencies(data, mainResult)
+ }
+
+ mainResult.Inc()
+
+ // In the end we retain best failures for schema validation
+ // plus, if any, composite errors which may explain special cases (tagged as IMPORTANT!).
+ return mainResult.Merge(keepResultAllOf, keepResultOneOf, keepResultAnyOf)
+}
+
+func (s *schemaPropsValidator) validateAnyOf(data any, mainResult, keepResultAnyOf *Result) {
+ // Validates at least one in anyOf schemas
+ var bestFailures *Result
+
+ for i, anyOfSchema := range s.anyOfValidators {
+ result := anyOfSchema.Validate(data)
+ if s.Options.recycleValidators {
+ s.anyOfValidators[i] = nil
+ }
+ // We keep inner IMPORTANT! errors no matter what MatchCount tells us
+ keepResultAnyOf.Merge(result.keepRelevantErrors()) // merges (and redeems) a new instance of Result
+
+ if result.IsValid() {
+ if bestFailures != nil && bestFailures.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(bestFailures)
+ }
+
+ _ = keepResultAnyOf.cleared()
+ mainResult.Merge(result)
+
+ return
+ }
+
+ // MatchCount is used to select errors from the schema with most positive checks
+ if bestFailures == nil || result.MatchCount > bestFailures.MatchCount {
+ if bestFailures != nil && bestFailures.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(bestFailures)
+ }
+ bestFailures = result
+
+ continue
+ }
+
+ if result.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(result) // this result is ditched
+ }
+ }
+
+ mainResult.AddErrors(mustValidateAtLeastOneSchemaMsg(s.Path))
+ mainResult.Merge(bestFailures)
+}
+
+func (s *schemaPropsValidator) validateOneOf(data any, mainResult, keepResultOneOf *Result) {
+ // Validates exactly one in oneOf schemas
+ var (
+ firstSuccess, bestFailures *Result
+ validated int
+ )
+
+ for i, oneOfSchema := range s.oneOfValidators {
+ result := oneOfSchema.Validate(data)
+ if s.Options.recycleValidators {
+ s.oneOfValidators[i] = nil
+ }
+
+ // We keep inner IMPORTANT! errors no matter what MatchCount tells us
+ keepResultOneOf.Merge(result.keepRelevantErrors()) // merges (and redeems) a new instance of Result
+
+ if result.IsValid() {
+ validated++
+ _ = keepResultOneOf.cleared()
+
+ if firstSuccess == nil {
+ firstSuccess = result
+ } else if result.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(result) // this result is ditched
+ }
+
+ continue
+ }
+
+ // MatchCount is used to select errors from the schema with most positive checks
+ if validated == 0 && (bestFailures == nil || result.MatchCount > bestFailures.MatchCount) {
+ if bestFailures != nil && bestFailures.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(bestFailures)
+ }
+ bestFailures = result
+ } else if result.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(result) // this result is ditched
+ }
+ }
+
+ switch validated {
+ case 0:
+ mainResult.AddErrors(mustValidateOnlyOneSchemaMsg(s.Path, "Found none valid"))
+ mainResult.Merge(bestFailures)
+ // firstSucess necessarily nil
+ case 1:
+ mainResult.Merge(firstSuccess)
+ if bestFailures != nil && bestFailures.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(bestFailures)
+ }
+ default:
+ mainResult.AddErrors(mustValidateOnlyOneSchemaMsg(s.Path, fmt.Sprintf("Found %d valid alternatives", validated)))
+ mainResult.Merge(bestFailures)
+ if firstSuccess != nil && firstSuccess.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(firstSuccess)
+ }
+ }
+}
+
+func (s *schemaPropsValidator) validateAllOf(data any, mainResult, keepResultAllOf *Result) {
+ // Validates all of allOf schemas
+ var validated int
+
+ for i, allOfSchema := range s.allOfValidators {
+ result := allOfSchema.Validate(data)
+ if s.Options.recycleValidators {
+ s.allOfValidators[i] = nil
+ }
+ // We keep inner IMPORTANT! errors no matter what MatchCount tells us
+ keepResultAllOf.Merge(result.keepRelevantErrors())
+ if result.IsValid() {
+ validated++
+ }
+ mainResult.Merge(result)
+ }
+
+ switch validated {
+ case 0:
+ mainResult.AddErrors(mustValidateAllSchemasMsg(s.Path, ". None validated"))
+ case len(s.allOfValidators):
+ default:
+ mainResult.AddErrors(mustValidateAllSchemasMsg(s.Path, ""))
+ }
+}
+
+func (s *schemaPropsValidator) validateNot(data any, mainResult *Result) {
+ result := s.notValidator.Validate(data)
+ if s.Options.recycleValidators {
+ s.notValidator = nil
+ }
+ // We keep inner IMPORTANT! errors no matter what MatchCount tells us
+ if result.IsValid() {
+ mainResult.AddErrors(mustNotValidatechemaMsg(s.Path))
+ }
+ if result.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(result) // this result is ditched
+ }
+}
+
+func (s *schemaPropsValidator) validateDependencies(data any, mainResult *Result) {
+ val := data.(map[string]any)
+ for key := range val {
+ dep, ok := s.Dependencies[key]
+ if !ok {
+ continue
+ }
+
+ if dep.Schema != nil {
+ mainResult.Merge(
+ newSchemaValidator(dep.Schema, s.Root, s.Path+"."+key, s.KnownFormats, s.Options).Validate(data),
+ )
+ continue
+ }
+
+ if len(dep.Property) > 0 {
+ for _, depKey := range dep.Property {
+ if _, ok := val[depKey]; !ok {
+ mainResult.AddErrors(hasADependencyMsg(s.Path, depKey))
+ }
+ }
+ }
+ }
+}
+
+func (s *schemaPropsValidator) redeem() {
+ pools.poolOfSchemaPropsValidators.RedeemValidator(s)
+}
+
+func (s *schemaPropsValidator) redeemChildren() {
+ for _, v := range s.anyOfValidators {
+ if v == nil {
+ continue
+ }
+ v.redeemChildren()
+ v.redeem()
+ }
+ s.anyOfValidators = nil
+
+ for _, v := range s.allOfValidators {
+ if v == nil {
+ continue
+ }
+ v.redeemChildren()
+ v.redeem()
+ }
+ s.allOfValidators = nil
+
+ for _, v := range s.oneOfValidators {
+ if v == nil {
+ continue
+ }
+ v.redeemChildren()
+ v.redeem()
+ }
+ s.oneOfValidators = nil
+
+ if s.notValidator != nil {
+ s.notValidator.redeemChildren()
+ s.notValidator.redeem()
+ s.notValidator = nil
+ }
+}
diff --git a/vendor/github.com/go-openapi/validate/slice_validator.go b/vendor/github.com/go-openapi/validate/slice_validator.go
new file mode 100644
index 000000000000..4a5a20896870
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/slice_validator.go
@@ -0,0 +1,139 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+type schemaSliceValidator struct {
+ Path string
+ In string
+ MaxItems *int64
+ MinItems *int64
+ UniqueItems bool
+ AdditionalItems *spec.SchemaOrBool
+ Items *spec.SchemaOrArray
+ Root any
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+func newSliceValidator(path, in string,
+ maxItems, minItems *int64, uniqueItems bool,
+ additionalItems *spec.SchemaOrBool, items *spec.SchemaOrArray,
+ root any, formats strfmt.Registry, opts *SchemaValidatorOptions) *schemaSliceValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var v *schemaSliceValidator
+ if opts.recycleValidators {
+ v = pools.poolOfSliceValidators.BorrowValidator()
+ } else {
+ v = new(schemaSliceValidator)
+ }
+
+ v.Path = path
+ v.In = in
+ v.MaxItems = maxItems
+ v.MinItems = minItems
+ v.UniqueItems = uniqueItems
+ v.AdditionalItems = additionalItems
+ v.Items = items
+ v.Root = root
+ v.KnownFormats = formats
+ v.Options = opts
+
+ return v
+}
+
+func (s *schemaSliceValidator) SetPath(path string) {
+ s.Path = path
+}
+
+func (s *schemaSliceValidator) Applies(source any, kind reflect.Kind) bool {
+ _, ok := source.(*spec.Schema)
+ r := ok && kind == reflect.Slice
+ return r
+}
+
+func (s *schemaSliceValidator) Validate(data any) *Result {
+ if s.Options.recycleValidators {
+ defer func() {
+ s.redeem()
+ }()
+ }
+
+ var result *Result
+ if s.Options.recycleResult {
+ result = pools.poolOfResults.BorrowResult()
+ } else {
+ result = new(Result)
+ }
+ if data == nil {
+ return result
+ }
+ val := reflect.ValueOf(data)
+ size := val.Len()
+
+ if s.Items != nil && s.Items.Schema != nil {
+ for i := range size {
+ validator := newSchemaValidator(s.Items.Schema, s.Root, s.Path, s.KnownFormats, s.Options)
+ validator.SetPath(fmt.Sprintf("%s.%d", s.Path, i))
+ value := val.Index(i)
+ result.mergeForSlice(val, i, validator.Validate(value.Interface()))
+ }
+ }
+
+ itemsSize := 0
+ if s.Items != nil && len(s.Items.Schemas) > 0 {
+ itemsSize = len(s.Items.Schemas)
+ for i := range itemsSize {
+ if size <= i {
+ break
+ }
+
+ validator := newSchemaValidator(&s.Items.Schemas[i], s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options)
+ result.mergeForSlice(val, i, validator.Validate(val.Index(i).Interface()))
+ }
+ }
+ if s.AdditionalItems != nil && itemsSize < size {
+ if s.Items != nil && len(s.Items.Schemas) > 0 && !s.AdditionalItems.Allows {
+ result.AddErrors(arrayDoesNotAllowAdditionalItemsMsg())
+ }
+ if s.AdditionalItems.Schema != nil {
+ for i := itemsSize; i < size-itemsSize+1; i++ {
+ validator := newSchemaValidator(s.AdditionalItems.Schema, s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options)
+ result.mergeForSlice(val, i, validator.Validate(val.Index(i).Interface()))
+ }
+ }
+ }
+
+ if s.MinItems != nil {
+ if err := MinItems(s.Path, s.In, int64(size), *s.MinItems); err != nil {
+ result.AddErrors(err)
+ }
+ }
+ if s.MaxItems != nil {
+ if err := MaxItems(s.Path, s.In, int64(size), *s.MaxItems); err != nil {
+ result.AddErrors(err)
+ }
+ }
+ if s.UniqueItems {
+ if err := UniqueItems(s.Path, s.In, val.Interface()); err != nil {
+ result.AddErrors(err)
+ }
+ }
+ result.Inc()
+ return result
+}
+
+func (s *schemaSliceValidator) redeem() {
+ pools.poolOfSliceValidators.RedeemValidator(s)
+}
diff --git a/vendor/github.com/go-openapi/validate/spec.go b/vendor/github.com/go-openapi/validate/spec.go
new file mode 100644
index 000000000000..8616a861f28c
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/spec.go
@@ -0,0 +1,845 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/json"
+ "fmt"
+ "slices"
+ "sort"
+ "strings"
+
+ "github.com/go-openapi/analysis"
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/jsonpointer"
+ "github.com/go-openapi/loads"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/jsonutils"
+)
+
+// Spec validates an OpenAPI 2.0 specification document.
+//
+// Returns an error flattening in a single standard error, all validation messages.
+//
+// - TODO: $ref should not have siblings
+// - TODO: make sure documentation reflects all checks and warnings
+// - TODO: check on discriminators
+// - TODO: explicit message on unsupported keywords (better than "forbidden property"...)
+// - TODO: full list of unresolved refs
+// - TODO: validate numeric constraints (issue#581): this should be handled like defaults and examples
+// - TODO: option to determine if we validate for go-swagger or in a more general context
+// - TODO: check on required properties to support anyOf, allOf, oneOf
+//
+// NOTE: SecurityScopes are maps: no need to check uniqueness
+func Spec(doc *loads.Document, formats strfmt.Registry) error {
+ errs, _ /*warns*/ := NewSpecValidator(doc.Schema(), formats).Validate(doc)
+ if errs.HasErrors() {
+ return errors.CompositeValidationError(errs.Errors...)
+ }
+ return nil
+}
+
+// SpecValidator validates a swagger 2.0 spec
+type SpecValidator struct {
+ schema *spec.Schema // swagger 2.0 schema
+ spec *loads.Document
+ analyzer *analysis.Spec
+ expanded *loads.Document
+ KnownFormats strfmt.Registry
+ Options Opts // validation options
+ schemaOptions *SchemaValidatorOptions
+}
+
+// NewSpecValidator creates a new swagger spec validator instance
+func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry) *SpecValidator {
+ // schema options that apply to all called validators
+ schemaOptions := new(SchemaValidatorOptions)
+ for _, o := range []Option{
+ SwaggerSchema(true),
+ WithRecycleValidators(true),
+ // withRecycleResults(true),
+ } {
+ o(schemaOptions)
+ }
+
+ return &SpecValidator{
+ schema: schema,
+ KnownFormats: formats,
+ Options: defaultOpts,
+ schemaOptions: schemaOptions,
+ }
+}
+
+// Validate validates the swagger spec
+func (s *SpecValidator) Validate(data any) (*Result, *Result) {
+ s.schemaOptions.skipSchemataResult = s.Options.SkipSchemataResult
+ var sd *loads.Document
+ errs, warnings := new(Result), new(Result)
+
+ if v, ok := data.(*loads.Document); ok {
+ sd = v
+ }
+ if sd == nil {
+ errs.AddErrors(invalidDocumentMsg())
+ return errs, warnings // no point in continuing
+ }
+ s.spec = sd
+ s.analyzer = analysis.New(sd.Spec())
+
+ // Raw spec unmarshalling errors
+ var obj any
+ if err := json.Unmarshal(sd.Raw(), &obj); err != nil {
+ // NOTE: under normal conditions, the *load.Document has been already unmarshalled
+ // So this one is just a paranoid check on the behavior of the spec package
+ panic(InvalidDocumentError)
+ }
+
+ defer func() {
+ // errs holds all errors and warnings,
+ // warnings only warnings
+ errs.MergeAsWarnings(warnings)
+ warnings.AddErrors(errs.Warnings...)
+ }()
+
+ // Swagger schema validator
+ schv := newSchemaValidator(s.schema, nil, "", s.KnownFormats, s.schemaOptions)
+ errs.Merge(schv.Validate(obj)) // error -
+ // There may be a point in continuing to try and determine more accurate errors
+ if !s.Options.ContinueOnErrors && errs.HasErrors() {
+ return errs, warnings // no point in continuing
+ }
+
+ errs.Merge(s.validateReferencesValid()) // error -
+ // There may be a point in continuing to try and determine more accurate errors
+ if !s.Options.ContinueOnErrors && errs.HasErrors() {
+ return errs, warnings // no point in continuing
+ }
+
+ errs.Merge(s.validateDuplicateOperationIDs())
+ errs.Merge(s.validateDuplicatePropertyNames()) // error -
+ errs.Merge(s.validateParameters()) // error -
+ errs.Merge(s.validateItems()) // error -
+
+ // Properties in required definition MUST validate their schema
+ // Properties SHOULD NOT be declared as both required and readOnly (warning)
+ errs.Merge(s.validateRequiredDefinitions()) // error and warning
+
+ // There may be a point in continuing to try and determine more accurate errors
+ if !s.Options.ContinueOnErrors && errs.HasErrors() {
+ return errs, warnings // no point in continuing
+ }
+
+ // Values provided as default MUST validate their schema
+ df := &defaultValidator{SpecValidator: s, schemaOptions: s.schemaOptions}
+ errs.Merge(df.Validate())
+
+ // Values provided as examples MUST validate their schema
+ // Value provided as examples in a response without schema generate a warning
+ // Known limitations: examples in responses for mime type not application/json are ignored (warning)
+ ex := &exampleValidator{SpecValidator: s, schemaOptions: s.schemaOptions}
+ errs.Merge(ex.Validate())
+
+ errs.Merge(s.validateNonEmptyPathParamNames())
+
+ // errs.Merge(s.validateRefNoSibling()) // warning only
+ errs.Merge(s.validateReferenced()) // warning only
+
+ return errs, warnings
+}
+
+// SetContinueOnErrors sets the ContinueOnErrors option for this validator.
+func (s *SpecValidator) SetContinueOnErrors(c bool) {
+ s.Options.ContinueOnErrors = c
+}
+
+func (s *SpecValidator) validateNonEmptyPathParamNames() *Result {
+ res := pools.poolOfResults.BorrowResult()
+ if s.spec.Spec().Paths == nil {
+ // There is no Paths object: error
+ res.AddErrors(noValidPathMsg())
+
+ return res
+ }
+
+ if s.spec.Spec().Paths.Paths == nil {
+ // Paths may be empty: warning
+ res.AddWarnings(noValidPathMsg())
+
+ return res
+ }
+
+ for k := range s.spec.Spec().Paths.Paths {
+ if strings.Contains(k, "{}") {
+ res.AddErrors(emptyPathParameterMsg(k))
+ }
+ }
+
+ return res
+}
+
+func (s *SpecValidator) validateDuplicateOperationIDs() *Result {
+ // OperationID, if specified, must be unique across the board
+ var analyzer *analysis.Spec
+ if s.expanded != nil {
+ // $ref are valid: we can analyze operations on an expanded spec
+ analyzer = analysis.New(s.expanded.Spec())
+ } else {
+ // fallback on possible incomplete picture because of previous errors
+ analyzer = s.analyzer
+ }
+ res := pools.poolOfResults.BorrowResult()
+ known := make(map[string]int)
+ for _, v := range analyzer.OperationIDs() {
+ if v != "" {
+ known[v]++
+ }
+ }
+ for k, v := range known {
+ if v > 1 {
+ res.AddErrors(nonUniqueOperationIDMsg(k, v))
+ }
+ }
+ return res
+}
+
+type dupProp struct {
+ Name string
+ Definition string
+}
+
+func (s *SpecValidator) validateDuplicatePropertyNames() *Result {
+ // definition can't declare a property that's already defined by one of its ancestors
+ res := pools.poolOfResults.BorrowResult()
+ for k, sch := range s.spec.Spec().Definitions {
+ if len(sch.AllOf) == 0 {
+ continue
+ }
+
+ knownanc := map[string]struct{}{
+ "#/definitions/" + k: {},
+ }
+
+ ancs, rec := s.validateCircularAncestry(k, sch, knownanc)
+ if rec != nil && (rec.HasErrors() || !rec.HasWarnings()) {
+ res.Merge(rec)
+ }
+ if len(ancs) > 0 {
+ res.AddErrors(circularAncestryDefinitionMsg(k, ancs))
+ return res
+ }
+
+ knowns := make(map[string]struct{})
+ dups, rep := s.validateSchemaPropertyNames(k, sch, knowns)
+ if rep != nil && (rep.HasErrors() || rep.HasWarnings()) {
+ res.Merge(rep)
+ }
+ if len(dups) > 0 {
+ var pns []string
+ for _, v := range dups {
+ pns = append(pns, v.Definition+"."+v.Name)
+ }
+ res.AddErrors(duplicatePropertiesMsg(k, pns))
+ }
+
+ }
+ return res
+}
+
+func (s *SpecValidator) resolveRef(ref *spec.Ref) (*spec.Schema, error) {
+ if s.spec.SpecFilePath() != "" {
+ return spec.ResolveRefWithBase(s.spec.Spec(), ref, &spec.ExpandOptions{RelativeBase: s.spec.SpecFilePath()})
+ }
+ // NOTE: it looks like with the new spec resolver, this code is now unrecheable
+ return spec.ResolveRef(s.spec.Spec(), ref)
+}
+
+func (s *SpecValidator) validateSchemaPropertyNames(nm string, sch spec.Schema, knowns map[string]struct{}) ([]dupProp, *Result) {
+ var dups []dupProp
+
+ schn := nm
+ schc := &sch
+ res := pools.poolOfResults.BorrowResult()
+
+ for schc.Ref.String() != "" {
+ // gather property names
+ reso, err := s.resolveRef(&schc.Ref)
+ if err != nil {
+ errorHelp.addPointerError(res, err, schc.Ref.String(), nm)
+ return dups, res
+ }
+ schc = reso
+ schn = sch.Ref.String()
+ }
+
+ if len(schc.AllOf) > 0 {
+ for _, chld := range schc.AllOf {
+ dup, rep := s.validateSchemaPropertyNames(schn, chld, knowns)
+ if rep != nil && (rep.HasErrors() || rep.HasWarnings()) {
+ res.Merge(rep)
+ }
+ dups = append(dups, dup...)
+ }
+ return dups, res
+ }
+
+ for k := range schc.Properties {
+ _, ok := knowns[k]
+ if ok {
+ dups = append(dups, dupProp{Name: k, Definition: schn})
+ } else {
+ knowns[k] = struct{}{}
+ }
+ }
+
+ return dups, res
+}
+
+func (s *SpecValidator) validateCircularAncestry(nm string, sch spec.Schema, knowns map[string]struct{}) ([]string, *Result) {
+ res := pools.poolOfResults.BorrowResult()
+
+ if sch.Ref.String() == "" && len(sch.AllOf) == 0 { // Safeguard. We should not be able to actually get there
+ return nil, res
+ }
+ var ancs []string
+
+ schn := nm
+ schc := &sch
+
+ for schc.Ref.String() != "" {
+ reso, err := s.resolveRef(&schc.Ref)
+ if err != nil {
+ errorHelp.addPointerError(res, err, schc.Ref.String(), nm)
+ return ancs, res
+ }
+ schc = reso
+ schn = sch.Ref.String()
+ }
+
+ if schn != nm && schn != "" {
+ if _, ok := knowns[schn]; ok {
+ ancs = append(ancs, schn)
+ }
+ knowns[schn] = struct{}{}
+
+ if len(ancs) > 0 {
+ return ancs, res
+ }
+ }
+
+ if len(schc.AllOf) > 0 {
+ for _, chld := range schc.AllOf {
+ if chld.Ref.String() != "" || len(chld.AllOf) > 0 {
+ anc, rec := s.validateCircularAncestry(schn, chld, knowns)
+ if rec != nil && (rec.HasErrors() || !rec.HasWarnings()) {
+ res.Merge(rec)
+ }
+ ancs = append(ancs, anc...)
+ if len(ancs) > 0 {
+ return ancs, res
+ }
+ }
+ }
+ }
+ return ancs, res
+}
+
+func (s *SpecValidator) validateItems() *Result {
+ // validate parameter, items, schema and response objects for presence of item if type is array
+ res := pools.poolOfResults.BorrowResult()
+
+ for method, pi := range s.analyzer.Operations() {
+ for path, op := range pi {
+ for _, param := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+
+ if param.TypeName() == arrayType && param.ItemsTypeName() == "" {
+ res.AddErrors(arrayInParamRequiresItemsMsg(param.Name, op.ID))
+ continue
+ }
+ if param.In != swaggerBody {
+ if param.Items != nil {
+ items := param.Items
+ for items.TypeName() == arrayType {
+ if items.ItemsTypeName() == "" {
+ res.AddErrors(arrayInParamRequiresItemsMsg(param.Name, op.ID))
+ break
+ }
+ items = items.Items
+ }
+ }
+ } else {
+ // In: body
+ if param.Schema != nil {
+ res.Merge(s.validateSchemaItems(*param.Schema, fmt.Sprintf("body param %q", param.Name), op.ID))
+ }
+ }
+ }
+
+ var responses []spec.Response
+ if op.Responses != nil {
+ if op.Responses.Default != nil {
+ responses = append(responses, *op.Responses.Default)
+ }
+ if op.Responses.StatusCodeResponses != nil {
+ for _, v := range op.Responses.StatusCodeResponses {
+ responses = append(responses, v)
+ }
+ }
+ }
+
+ for _, resp := range responses {
+ // Response headers with array
+ for hn, hv := range resp.Headers {
+ if hv.TypeName() == arrayType && hv.ItemsTypeName() == "" {
+ res.AddErrors(arrayInHeaderRequiresItemsMsg(hn, op.ID))
+ }
+ }
+ if resp.Schema != nil {
+ res.Merge(s.validateSchemaItems(*resp.Schema, "response body", op.ID))
+ }
+ }
+ }
+ }
+ return res
+}
+
+// Verifies constraints on array type
+func (s *SpecValidator) validateSchemaItems(schema spec.Schema, prefix, opID string) *Result {
+ res := pools.poolOfResults.BorrowResult()
+ if !schema.Type.Contains(arrayType) {
+ return res
+ }
+
+ if schema.Items == nil || schema.Items.Len() == 0 {
+ res.AddErrors(arrayRequiresItemsMsg(prefix, opID))
+ return res
+ }
+
+ if schema.Items.Schema != nil {
+ schema = *schema.Items.Schema
+ if _, err := compileRegexp(schema.Pattern); err != nil {
+ res.AddErrors(invalidItemsPatternMsg(prefix, opID, schema.Pattern))
+ }
+
+ res.Merge(s.validateSchemaItems(schema, prefix, opID))
+ }
+ return res
+}
+
+func (s *SpecValidator) validatePathParamPresence(path string, fromPath, fromOperation []string) *Result {
+ // Each defined operation path parameters must correspond to a named element in the API's path pattern.
+ // (For example, you cannot have a path parameter named id for the following path /pets/{petId} but you must have a path parameter named petId.)
+ res := pools.poolOfResults.BorrowResult()
+ for _, l := range fromPath {
+ var matched bool
+ for _, r := range fromOperation {
+ if l == "{"+r+"}" {
+ matched = true
+ break
+ }
+ }
+ if !matched {
+ res.AddErrors(noParameterInPathMsg(l))
+ }
+ }
+
+ for _, p := range fromOperation {
+ var matched bool
+ if slices.Contains(fromPath, "{"+p+"}") {
+ matched = true
+ }
+ if !matched {
+ res.AddErrors(pathParamNotInPathMsg(path, p))
+ }
+ }
+
+ return res
+}
+
+func (s *SpecValidator) validateReferenced() *Result {
+ var res Result
+ res.MergeAsWarnings(s.validateReferencedParameters())
+ res.MergeAsWarnings(s.validateReferencedResponses())
+ res.MergeAsWarnings(s.validateReferencedDefinitions())
+ return &res
+}
+
+func (s *SpecValidator) validateReferencedParameters() *Result {
+ // Each referenceable definition should have references.
+ params := s.spec.Spec().Parameters
+ if len(params) == 0 {
+ return nil
+ }
+
+ expected := make(map[string]struct{})
+ for k := range params {
+ expected["#/parameters/"+jsonpointer.Escape(k)] = struct{}{}
+ }
+ for _, k := range s.analyzer.AllParameterReferences() {
+ delete(expected, k)
+ }
+
+ if len(expected) == 0 {
+ return nil
+ }
+ result := pools.poolOfResults.BorrowResult()
+ for k := range expected {
+ result.AddWarnings(unusedParamMsg(k))
+ }
+ return result
+}
+
+func (s *SpecValidator) validateReferencedResponses() *Result {
+ // Each referenceable definition should have references.
+ responses := s.spec.Spec().Responses
+ if len(responses) == 0 {
+ return nil
+ }
+
+ expected := make(map[string]struct{})
+ for k := range responses {
+ expected["#/responses/"+jsonpointer.Escape(k)] = struct{}{}
+ }
+ for _, k := range s.analyzer.AllResponseReferences() {
+ delete(expected, k)
+ }
+
+ if len(expected) == 0 {
+ return nil
+ }
+ result := pools.poolOfResults.BorrowResult()
+ for k := range expected {
+ result.AddWarnings(unusedResponseMsg(k))
+ }
+ return result
+}
+
+func (s *SpecValidator) validateReferencedDefinitions() *Result {
+ // Each referenceable definition must have references.
+ defs := s.spec.Spec().Definitions
+ if len(defs) == 0 {
+ return nil
+ }
+
+ expected := make(map[string]struct{})
+ for k := range defs {
+ expected["#/definitions/"+jsonpointer.Escape(k)] = struct{}{}
+ }
+ for _, k := range s.analyzer.AllDefinitionReferences() {
+ delete(expected, k)
+ }
+
+ if len(expected) == 0 {
+ return nil
+ }
+
+ result := new(Result)
+ for k := range expected {
+ result.AddWarnings(unusedDefinitionMsg(k))
+ }
+ return result
+}
+
+func (s *SpecValidator) validateRequiredDefinitions() *Result {
+ // Each property listed in the required array must be defined in the properties of the model
+ res := pools.poolOfResults.BorrowResult()
+
+DEFINITIONS:
+ for d, schema := range s.spec.Spec().Definitions {
+ if schema.Required != nil { // Safeguard
+ for _, pn := range schema.Required {
+ red := s.validateRequiredProperties(pn, d, &schema) //#nosec
+ res.Merge(red)
+ if !red.IsValid() && !s.Options.ContinueOnErrors {
+ break DEFINITIONS // there is an error, let's stop that bleeding
+ }
+ }
+ }
+ }
+ return res
+}
+
+func (s *SpecValidator) validateRequiredProperties(path, in string, v *spec.Schema) *Result {
+ // Takes care of recursive property definitions, which may be nested in additionalProperties schemas
+ res := pools.poolOfResults.BorrowResult()
+ propertyMatch := false
+ patternMatch := false
+ additionalPropertiesMatch := false
+ isReadOnly := false
+
+ // Regular properties
+ if _, ok := v.Properties[path]; ok {
+ propertyMatch = true
+ isReadOnly = v.Properties[path].ReadOnly
+ }
+
+ // NOTE: patternProperties are not supported in swagger. Even though, we continue validation here
+ // We check all defined patterns: if one regexp is invalid, croaks an error
+ for pp, pv := range v.PatternProperties {
+ re, err := compileRegexp(pp)
+ if err != nil {
+ res.AddErrors(invalidPatternMsg(pp, in))
+ } else if re.MatchString(path) {
+ patternMatch = true
+ if !propertyMatch {
+ isReadOnly = pv.ReadOnly
+ }
+ }
+ }
+
+ if !propertyMatch && !patternMatch {
+ if v.AdditionalProperties != nil {
+ if v.AdditionalProperties.Allows && v.AdditionalProperties.Schema == nil {
+ additionalPropertiesMatch = true
+ } else if v.AdditionalProperties.Schema != nil {
+ // additionalProperties as schema are upported in swagger
+ // recursively validates additionalProperties schema
+ // TODO : anyOf, allOf, oneOf like in schemaPropsValidator
+ red := s.validateRequiredProperties(path, in, v.AdditionalProperties.Schema)
+ if red.IsValid() {
+ additionalPropertiesMatch = true
+ if !propertyMatch && !patternMatch {
+ isReadOnly = v.AdditionalProperties.Schema.ReadOnly
+ }
+ }
+ res.Merge(red)
+ }
+ }
+ }
+
+ if !propertyMatch && !patternMatch && !additionalPropertiesMatch {
+ res.AddErrors(requiredButNotDefinedMsg(path, in))
+ }
+
+ if isReadOnly {
+ res.AddWarnings(readOnlyAndRequiredMsg(in, path))
+ }
+ return res
+}
+
+func (s *SpecValidator) validateParameters() *Result {
+ // - for each method, path is unique, regardless of path parameters
+ // e.g. GET:/petstore/{id}, GET:/petstore/{pet}, GET:/petstore are
+ // considered duplicate paths, if StrictPathParamUniqueness is enabled.
+ // - each parameter should have a unique `name` and `type` combination
+ // - each operation should have only 1 parameter of type body
+ // - there must be at most 1 parameter in body
+ // - parameters with pattern property must specify valid patterns
+ // - $ref in parameters must resolve
+ // - path param must be required
+ res := pools.poolOfResults.BorrowResult()
+ rexGarbledPathSegment := mustCompileRegexp(`.*[{}\s]+.*`)
+ for method, pi := range s.expandedAnalyzer().Operations() {
+ methodPaths := make(map[string]map[string]string)
+ for path, op := range pi {
+ if s.Options.StrictPathParamUniqueness {
+ pathToAdd := pathHelp.stripParametersInPath(path)
+
+ // Warn on garbled path afer param stripping
+ if rexGarbledPathSegment.MatchString(pathToAdd) {
+ res.AddWarnings(pathStrippedParamGarbledMsg(pathToAdd))
+ }
+
+ // Check uniqueness of stripped paths
+ if _, found := methodPaths[method][pathToAdd]; found {
+
+ // Sort names for stable, testable output
+ if strings.Compare(path, methodPaths[method][pathToAdd]) < 0 {
+ res.AddErrors(pathOverlapMsg(path, methodPaths[method][pathToAdd]))
+ } else {
+ res.AddErrors(pathOverlapMsg(methodPaths[method][pathToAdd], path))
+ }
+ } else {
+ if _, found := methodPaths[method]; !found {
+ methodPaths[method] = map[string]string{}
+ }
+ methodPaths[method][pathToAdd] = path // Original non stripped path
+
+ }
+ }
+
+ var bodyParams []string
+ var paramNames []string
+ var hasForm, hasBody bool
+
+ // Check parameters names uniqueness for operation
+ // TODO: should be done after param expansion
+ res.Merge(s.checkUniqueParams(path, method, op))
+
+ // pick the root schema from the swagger specification which describes a parameter
+ origSchema, ok := s.schema.Definitions["parameter"]
+ if !ok {
+ panic("unexpected swagger schema: missing #/definitions/parameter")
+ }
+ // clone it once to avoid expanding a global schema (e.g. swagger spec)
+ paramSchema, err := deepCloneSchema(origSchema)
+ if err != nil {
+ panic(fmt.Errorf("can't clone schema: %w", err))
+ }
+
+ for _, pr := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+ // An expanded parameter must validate the Parameter schema (an unexpanded $ref always passes high-level schema validation)
+ schv := newSchemaValidator(¶mSchema, s.schema, fmt.Sprintf("%s.%s.parameters.%s", path, method, pr.Name), s.KnownFormats, s.schemaOptions)
+ var obj any
+ if err := jsonutils.FromDynamicJSON(pr, &obj); err != nil {
+ res.AddErrors(err)
+
+ return res
+ }
+
+ res.Merge(schv.Validate(obj))
+
+ // Validate pattern regexp for parameters with a Pattern property
+ if _, err := compileRegexp(pr.Pattern); err != nil {
+ res.AddErrors(invalidPatternInParamMsg(op.ID, pr.Name, pr.Pattern))
+ }
+
+ // There must be at most one parameter in body: list them all
+ if pr.In == swaggerBody {
+ bodyParams = append(bodyParams, fmt.Sprintf("%q", pr.Name))
+ hasBody = true
+ }
+
+ if pr.In == "path" {
+ paramNames = append(paramNames, pr.Name)
+ // Path declared in path must have the required: true property
+ if !pr.Required {
+ res.AddErrors(pathParamRequiredMsg(op.ID, pr.Name))
+ }
+ }
+
+ if pr.In == "formData" {
+ hasForm = true
+ }
+
+ if pr.Type != numberType && pr.Type != integerType &&
+ (pr.Maximum != nil || pr.Minimum != nil || pr.MultipleOf != nil) {
+ // A non-numeric parameter has validation keywords for numeric instances (number and integer)
+ res.AddWarnings(parameterValidationTypeMismatchMsg(pr.Name, path, pr.Type))
+ }
+
+ if pr.Type != stringType &&
+ // A non-string parameter has validation keywords for strings
+ (pr.MaxLength != nil || pr.MinLength != nil || pr.Pattern != "") {
+ res.AddWarnings(parameterValidationTypeMismatchMsg(pr.Name, path, pr.Type))
+ }
+
+ if pr.Type != arrayType &&
+ // A non-array parameter has validation keywords for arrays
+ (pr.MaxItems != nil || pr.MinItems != nil || pr.UniqueItems) {
+ res.AddWarnings(parameterValidationTypeMismatchMsg(pr.Name, path, pr.Type))
+ }
+ }
+
+ // In:formData and In:body are mutually exclusive
+ if hasBody && hasForm {
+ res.AddErrors(bothFormDataAndBodyMsg(op.ID))
+ }
+ // There must be at most one body param
+ // Accurately report situations when more than 1 body param is declared (possibly unnamed)
+ if len(bodyParams) > 1 {
+ sort.Strings(bodyParams)
+ res.AddErrors(multipleBodyParamMsg(op.ID, bodyParams))
+ }
+
+ // Check uniqueness of parameters in path
+ paramsInPath := pathHelp.extractPathParams(path)
+ for i, p := range paramsInPath {
+ for j, q := range paramsInPath {
+ if p == q && i > j {
+ res.AddErrors(pathParamNotUniqueMsg(path, p, q))
+ break
+ }
+ }
+ }
+
+ // Warns about possible malformed params in path
+ rexGarbledParam := mustCompileRegexp(`{.*[{}\s]+.*}`)
+ for _, p := range paramsInPath {
+ if rexGarbledParam.MatchString(p) {
+ res.AddWarnings(pathParamGarbledMsg(path, p))
+ }
+ }
+
+ // Match params from path vs params from params section
+ res.Merge(s.validatePathParamPresence(path, paramsInPath, paramNames))
+ }
+ }
+ return res
+}
+
+func (s *SpecValidator) validateReferencesValid() *Result {
+ // each reference must point to a valid object
+ res := pools.poolOfResults.BorrowResult()
+ for _, r := range s.analyzer.AllRefs() {
+ if !r.IsValidURI(s.spec.SpecFilePath()) { // Safeguard - spec should always yield a valid URI
+ res.AddErrors(invalidRefMsg(r.String()))
+ }
+ }
+ if !res.HasErrors() {
+ // NOTE: with default settings, loads.Document.Expanded()
+ // stops on first error. Anyhow, the expand option to continue
+ // on errors fails to report errors at all.
+ exp, err := s.spec.Expanded()
+ if err != nil {
+ res.AddErrors(unresolvedReferencesMsg(err))
+ }
+ s.expanded = exp
+ }
+ return res
+}
+
+func (s *SpecValidator) checkUniqueParams(path, method string, op *spec.Operation) *Result {
+ // Check for duplicate parameters declaration in param section.
+ // Each parameter should have a unique `name` and `type` combination
+ // NOTE: this could be factorized in analysis (when constructing the params map)
+ // However, there are some issues with such a factorization:
+ // - analysis does not seem to fully expand params
+ // - param keys may be altered by x-go-name
+ res := pools.poolOfResults.BorrowResult()
+ pnames := make(map[string]struct{})
+
+ if op.Parameters != nil { // Safeguard
+ for _, ppr := range op.Parameters {
+ var ok bool
+ pr, red := paramHelp.resolveParam(path, method, op.ID, &ppr, s) //#nosec
+ res.Merge(red)
+
+ if pr != nil && pr.Name != "" { // params with empty name does no participate the check
+ key := fmt.Sprintf("%s#%s", pr.In, pr.Name)
+
+ if _, ok = pnames[key]; ok {
+ res.AddErrors(duplicateParamNameMsg(pr.In, pr.Name, op.ID))
+ }
+ pnames[key] = struct{}{}
+ }
+ }
+ }
+ return res
+}
+
+// expandedAnalyzer returns expanded.Analyzer when it is available.
+// otherwise just analyzer.
+func (s *SpecValidator) expandedAnalyzer() *analysis.Spec {
+ if s.expanded != nil && s.expanded.Analyzer != nil {
+ return s.expanded.Analyzer
+ }
+ return s.analyzer
+}
+
+func deepCloneSchema(src spec.Schema) (spec.Schema, error) {
+ var b bytes.Buffer
+ if err := gob.NewEncoder(&b).Encode(src); err != nil {
+ return spec.Schema{}, err
+ }
+
+ var dst spec.Schema
+ if err := gob.NewDecoder(&b).Decode(&dst); err != nil {
+ return spec.Schema{}, err
+ }
+
+ return dst, nil
+}
diff --git a/vendor/github.com/go-openapi/validate/spec_messages.go b/vendor/github.com/go-openapi/validate/spec_messages.go
new file mode 100644
index 000000000000..9b079af647a7
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/spec_messages.go
@@ -0,0 +1,355 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+)
+
+// Error messages related to spec validation and returned as results.
+const (
+ // ArrayRequiresItemsError ...
+ ArrayRequiresItemsError = "%s for %q is a collection without an element type (array requires items definition)"
+
+ // ArrayInParamRequiresItemsError ...
+ ArrayInParamRequiresItemsError = "param %q for %q is a collection without an element type (array requires item definition)"
+
+ // ArrayInHeaderRequiresItemsError ...
+ ArrayInHeaderRequiresItemsError = "header %q for %q is a collection without an element type (array requires items definition)"
+
+ // BothFormDataAndBodyError indicates that an operation specifies both a body and a formData parameter, which is forbidden
+ BothFormDataAndBodyError = "operation %q has both formData and body parameters. Only one such In: type may be used for a given operation"
+
+ // CannotResolveReferenceError when a $ref could not be resolved
+ CannotResolveReferenceError = "could not resolve reference in %s to $ref %s: %v"
+
+ // CircularAncestryDefinitionError ...
+ CircularAncestryDefinitionError = "definition %q has circular ancestry: %v"
+
+ // DefaultValueDoesNotValidateError results from an invalid default value provided
+ DefaultValueDoesNotValidateError = "default value for %s in %s does not validate its schema"
+
+ // DefaultValueItemsDoesNotValidateError results from an invalid default value provided for Items
+ DefaultValueItemsDoesNotValidateError = "default value for %s.items in %s does not validate its schema"
+
+ // DefaultValueHeaderDoesNotValidateError results from an invalid default value provided in header
+ DefaultValueHeaderDoesNotValidateError = "in operation %q, default value in header %s for %s does not validate its schema"
+
+ // DefaultValueHeaderItemsDoesNotValidateError results from an invalid default value provided in header.items
+ DefaultValueHeaderItemsDoesNotValidateError = "in operation %q, default value in header.items %s for %s does not validate its schema"
+
+ // DefaultValueInDoesNotValidateError ...
+ DefaultValueInDoesNotValidateError = "in operation %q, default value in %s does not validate its schema"
+
+ // DuplicateParamNameError ...
+ DuplicateParamNameError = "duplicate parameter name %q for %q in operation %q"
+
+ // DuplicatePropertiesError ...
+ DuplicatePropertiesError = "definition %q contains duplicate properties: %v"
+
+ // ExampleValueDoesNotValidateError results from an invalid example value provided
+ ExampleValueDoesNotValidateError = "example value for %s in %s does not validate its schema"
+
+ // ExampleValueItemsDoesNotValidateError results from an invalid example value provided for Items
+ ExampleValueItemsDoesNotValidateError = "example value for %s.items in %s does not validate its schema"
+
+ // ExampleValueHeaderDoesNotValidateError results from an invalid example value provided in header
+ ExampleValueHeaderDoesNotValidateError = "in operation %q, example value in header %s for %s does not validate its schema"
+
+ // ExampleValueHeaderItemsDoesNotValidateError results from an invalid example value provided in header.items
+ ExampleValueHeaderItemsDoesNotValidateError = "in operation %q, example value in header.items %s for %s does not validate its schema"
+
+ // ExampleValueInDoesNotValidateError ...
+ ExampleValueInDoesNotValidateError = "in operation %q, example value in %s does not validate its schema"
+
+ // EmptyPathParameterError means that a path parameter was found empty (e.g. "{}")
+ EmptyPathParameterError = "%q contains an empty path parameter"
+
+ // InvalidDocumentError states that spec validation only processes spec.Document objects
+ InvalidDocumentError = "spec validator can only validate spec.Document objects"
+
+ // InvalidItemsPatternError indicates an Items definition with invalid pattern
+ InvalidItemsPatternError = "%s for %q has invalid items pattern: %q"
+
+ // InvalidParameterDefinitionError indicates an error detected on a parameter definition
+ InvalidParameterDefinitionError = "invalid definition for parameter %s in %s in operation %q"
+
+ // InvalidParameterDefinitionAsSchemaError indicates an error detected on a parameter definition, which was mistaken with a schema definition.
+ // Most likely, this situation is encountered whenever a $ref has been added as a sibling of the parameter definition.
+ InvalidParameterDefinitionAsSchemaError = "invalid definition as Schema for parameter %s in %s in operation %q"
+
+ // InvalidPatternError ...
+ InvalidPatternError = "pattern %q is invalid in %s"
+
+ // InvalidPatternInError indicates an invalid pattern in a schema or items definition
+ InvalidPatternInError = "%s in %s has invalid pattern: %q"
+
+ // InvalidPatternInHeaderError indicates a header definition with an invalid pattern
+ InvalidPatternInHeaderError = "in operation %q, header %s for %s has invalid pattern %q: %v"
+
+ // InvalidPatternInParamError ...
+ InvalidPatternInParamError = "operation %q has invalid pattern in param %q: %q"
+
+ // InvalidReferenceError indicates that a $ref property could not be resolved
+ InvalidReferenceError = "invalid ref %q"
+
+ // InvalidResponseDefinitionAsSchemaError indicates an error detected on a response definition, which was mistaken with a schema definition.
+ // Most likely, this situation is encountered whenever a $ref has been added as a sibling of the response definition.
+ InvalidResponseDefinitionAsSchemaError = "invalid definition as Schema for response %s in %s"
+
+ // MultipleBodyParamError indicates that an operation specifies multiple parameter with in: body
+ MultipleBodyParamError = "operation %q has more than 1 body param: %v"
+
+ // NonUniqueOperationIDError indicates that the same operationId has been specified several times
+ NonUniqueOperationIDError = "%q is defined %d times"
+
+ // NoParameterInPathError indicates that a path was found without any parameter
+ NoParameterInPathError = "path param %q has no parameter definition"
+
+ // NoValidPathErrorOrWarning indicates that no single path could be validated. If Paths is empty, this message is only a warning.
+ NoValidPathErrorOrWarning = "spec has no valid path defined"
+
+ // NoValidResponseError indicates that no valid response description could be found for an operation
+ NoValidResponseError = "operation %q has no valid response"
+
+ // PathOverlapError ...
+ PathOverlapError = "path %s overlaps with %s"
+
+ // PathParamNotInPathError indicates that a parameter specified with in: path was not found in the path specification
+ PathParamNotInPathError = "path param %q is not present in path %q"
+
+ // PathParamNotUniqueError ...
+ PathParamNotUniqueError = "params in path %q must be unique: %q conflicts with %q"
+
+ // PathParamRequiredError ...
+ PathParamRequiredError = "in operation %q,path param %q must be declared as required"
+
+ // RefNotAllowedInHeaderError indicates a $ref was found in a header definition, which is not allowed by Swagger
+ RefNotAllowedInHeaderError = "IMPORTANT!in %q: $ref are not allowed in headers. In context for header %q%s"
+
+ // RequiredButNotDefinedError ...
+ RequiredButNotDefinedError = "%q is present in required but not defined as property in definition %q"
+
+ // SomeParametersBrokenError indicates that some parameters could not be resolved, which might result in partial checks to be carried on
+ SomeParametersBrokenError = "some parameters definitions are broken in %q.%s. Cannot carry on full checks on parameters for operation %s"
+
+ // UnresolvedReferencesError indicates that at least one $ref could not be resolved
+ UnresolvedReferencesError = "some references could not be resolved in spec. First found: %v"
+)
+
+// Warning messages related to spec validation and returned as results
+const (
+ // ExamplesWithoutSchemaWarning indicates that examples are provided for a response,but not schema to validate the example against
+ ExamplesWithoutSchemaWarning = "Examples provided without schema in operation %q, %s"
+
+ // ExamplesMimeNotSupportedWarning indicates that examples are provided with a mime type different than application/json, which
+ // the validator dos not support yetl
+ ExamplesMimeNotSupportedWarning = "No validation attempt for examples for media types other than application/json, in operation %q, %s"
+
+ // PathParamGarbledWarning ...
+ PathParamGarbledWarning = "in path %q, param %q contains {,} or white space. Albeit not stricly illegal, this is probably no what you want"
+
+ // ParamValidationTypeMismatch indicates that parameter has validation which does not match its type
+ ParamValidationTypeMismatch = "validation keywords of parameter %q in path %q don't match its type %s"
+
+ // PathStrippedParamGarbledWarning ...
+ PathStrippedParamGarbledWarning = "path stripped from path parameters %s contains {,} or white space. This is probably no what you want."
+
+ // ReadOnlyAndRequiredWarning ...
+ ReadOnlyAndRequiredWarning = "Required property %s in %q should not be marked as both required and readOnly"
+
+ // RefShouldNotHaveSiblingsWarning indicates that a $ref was found with a sibling definition. This results in the $ref taking over its siblings,
+ // which is most likely not wanted.
+ RefShouldNotHaveSiblingsWarning = "$ref property should have no sibling in %q.%s"
+
+ // RequiredHasDefaultWarning indicates that a required parameter property should not have a default
+ RequiredHasDefaultWarning = "%s in %s has a default value and is required as parameter"
+
+ // UnusedDefinitionWarning ...
+ UnusedDefinitionWarning = "definition %q is not used anywhere"
+
+ // UnusedParamWarning ...
+ UnusedParamWarning = "parameter %q is not used anywhere"
+
+ // UnusedResponseWarning ...
+ UnusedResponseWarning = "response %q is not used anywhere"
+
+ InvalidObject = "expected an object in %q.%s"
+)
+
+// Additional error codes
+const (
+ // InternalErrorCode reports an internal technical error
+ InternalErrorCode = http.StatusInternalServerError
+ // NotFoundErrorCode indicates that a resource (e.g. a $ref) could not be found
+ NotFoundErrorCode = http.StatusNotFound
+)
+
+func invalidDocumentMsg() errors.Error {
+ return errors.New(InternalErrorCode, InvalidDocumentError)
+}
+func invalidRefMsg(path string) errors.Error {
+ return errors.New(NotFoundErrorCode, InvalidReferenceError, path)
+}
+func unresolvedReferencesMsg(err error) errors.Error {
+ return errors.New(errors.CompositeErrorCode, UnresolvedReferencesError, err)
+}
+func noValidPathMsg() errors.Error {
+ return errors.New(errors.CompositeErrorCode, NoValidPathErrorOrWarning)
+}
+func emptyPathParameterMsg(path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, EmptyPathParameterError, path)
+}
+func nonUniqueOperationIDMsg(path string, i int) errors.Error {
+ return errors.New(errors.CompositeErrorCode, NonUniqueOperationIDError, path, i)
+}
+func circularAncestryDefinitionMsg(path string, args any) errors.Error {
+ return errors.New(errors.CompositeErrorCode, CircularAncestryDefinitionError, path, args)
+}
+func duplicatePropertiesMsg(path string, args any) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DuplicatePropertiesError, path, args)
+}
+func pathParamNotInPathMsg(path, param string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, PathParamNotInPathError, param, path)
+}
+func arrayRequiresItemsMsg(path, operation string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ArrayRequiresItemsError, path, operation)
+}
+func arrayInParamRequiresItemsMsg(path, operation string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ArrayInParamRequiresItemsError, path, operation)
+}
+func arrayInHeaderRequiresItemsMsg(path, operation string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ArrayInHeaderRequiresItemsError, path, operation)
+}
+func invalidItemsPatternMsg(path, operation, pattern string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidItemsPatternError, path, operation, pattern)
+}
+func invalidPatternMsg(pattern, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidPatternError, pattern, path)
+}
+func requiredButNotDefinedMsg(path, definition string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, RequiredButNotDefinedError, path, definition)
+}
+func pathParamGarbledMsg(path, param string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, PathParamGarbledWarning, path, param)
+}
+func pathStrippedParamGarbledMsg(path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, PathStrippedParamGarbledWarning, path)
+}
+func pathOverlapMsg(path, arg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, PathOverlapError, path, arg)
+}
+func invalidPatternInParamMsg(operation, param, pattern string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidPatternInParamError, operation, param, pattern)
+}
+func pathParamRequiredMsg(operation, param string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, PathParamRequiredError, operation, param)
+}
+func bothFormDataAndBodyMsg(operation string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, BothFormDataAndBodyError, operation)
+}
+func multipleBodyParamMsg(operation string, args any) errors.Error {
+ return errors.New(errors.CompositeErrorCode, MultipleBodyParamError, operation, args)
+}
+func pathParamNotUniqueMsg(path, param, arg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, PathParamNotUniqueError, path, param, arg)
+}
+func duplicateParamNameMsg(path, param, operation string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DuplicateParamNameError, param, path, operation)
+}
+func unusedParamMsg(arg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, UnusedParamWarning, arg)
+}
+func unusedDefinitionMsg(arg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, UnusedDefinitionWarning, arg)
+}
+func unusedResponseMsg(arg string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, UnusedResponseWarning, arg)
+}
+func readOnlyAndRequiredMsg(path, param string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ReadOnlyAndRequiredWarning, param, path)
+}
+func noParameterInPathMsg(param string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, NoParameterInPathError, param)
+}
+func requiredHasDefaultMsg(param, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, RequiredHasDefaultWarning, param, path)
+}
+func defaultValueDoesNotValidateMsg(param, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DefaultValueDoesNotValidateError, param, path)
+}
+func defaultValueItemsDoesNotValidateMsg(param, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DefaultValueItemsDoesNotValidateError, param, path)
+}
+func noValidResponseMsg(operation string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, NoValidResponseError, operation)
+}
+func defaultValueHeaderDoesNotValidateMsg(operation, header, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DefaultValueHeaderDoesNotValidateError, operation, header, path)
+}
+func defaultValueHeaderItemsDoesNotValidateMsg(operation, header, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DefaultValueHeaderItemsDoesNotValidateError, operation, header, path)
+}
+func invalidPatternInHeaderMsg(operation, header, path, pattern string, args any) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidPatternInHeaderError, operation, header, path, pattern, args)
+}
+func invalidPatternInMsg(path, in, pattern string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidPatternInError, path, in, pattern)
+}
+func defaultValueInDoesNotValidateMsg(operation, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, DefaultValueInDoesNotValidateError, operation, path)
+}
+func exampleValueDoesNotValidateMsg(param, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExampleValueDoesNotValidateError, param, path)
+}
+func exampleValueItemsDoesNotValidateMsg(param, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExampleValueItemsDoesNotValidateError, param, path)
+}
+func exampleValueHeaderDoesNotValidateMsg(operation, header, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExampleValueHeaderDoesNotValidateError, operation, header, path)
+}
+func exampleValueHeaderItemsDoesNotValidateMsg(operation, header, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExampleValueHeaderItemsDoesNotValidateError, operation, header, path)
+}
+func exampleValueInDoesNotValidateMsg(operation, path string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExampleValueInDoesNotValidateError, operation, path)
+}
+func examplesWithoutSchemaMsg(operation, response string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExamplesWithoutSchemaWarning, operation, response)
+}
+func examplesMimeNotSupportedMsg(operation, response string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ExamplesMimeNotSupportedWarning, operation, response)
+}
+func refNotAllowedInHeaderMsg(path, header, ref string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, RefNotAllowedInHeaderError, path, header, ref)
+}
+func cannotResolveRefMsg(path, ref string, err error) errors.Error {
+ return errors.New(errors.CompositeErrorCode, CannotResolveReferenceError, path, ref, err)
+}
+func invalidParameterDefinitionMsg(path, method, operationID string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidParameterDefinitionError, path, method, operationID)
+}
+func invalidParameterDefinitionAsSchemaMsg(path, method, operationID string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidParameterDefinitionAsSchemaError, path, method, operationID)
+}
+func parameterValidationTypeMismatchMsg(param, path, typ string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, ParamValidationTypeMismatch, param, path, typ)
+}
+func invalidObjectMsg(path, in string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, InvalidObject, path, in)
+}
+
+// disabled
+//
+// func invalidResponseDefinitionAsSchemaMsg(path, method string) errors.Error {
+// return errors.New(errors.CompositeErrorCode, InvalidResponseDefinitionAsSchemaError, path, method)
+// }
+func someParametersBrokenMsg(path, method, operationID string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, SomeParametersBrokenError, path, method, operationID)
+}
+func refShouldNotHaveSiblingsMsg(path, operationID string) errors.Error {
+ return errors.New(errors.CompositeErrorCode, RefShouldNotHaveSiblingsWarning, operationID, path)
+}
diff --git a/vendor/github.com/go-openapi/validate/type.go b/vendor/github.com/go-openapi/validate/type.go
new file mode 100644
index 000000000000..9b9ab8d917dd
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/type.go
@@ -0,0 +1,203 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "reflect"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/conv"
+ "github.com/go-openapi/swag/fileutils"
+)
+
+type typeValidator struct {
+ Path string
+ In string
+ Type spec.StringOrArray
+ Nullable bool
+ Format string
+ Options *SchemaValidatorOptions
+}
+
+func newTypeValidator(path, in string, typ spec.StringOrArray, nullable bool, format string, opts *SchemaValidatorOptions) *typeValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var t *typeValidator
+ if opts.recycleValidators {
+ t = pools.poolOfTypeValidators.BorrowValidator()
+ } else {
+ t = new(typeValidator)
+ }
+
+ t.Path = path
+ t.In = in
+ t.Type = typ
+ t.Nullable = nullable
+ t.Format = format
+ t.Options = opts
+
+ return t
+}
+
+func (t *typeValidator) SetPath(path string) {
+ t.Path = path
+}
+
+func (t *typeValidator) Applies(source any, _ reflect.Kind) bool {
+ // typeValidator applies to Schema, Parameter and Header objects
+ switch source.(type) {
+ case *spec.Schema:
+ case *spec.Parameter:
+ case *spec.Header:
+ default:
+ return false
+ }
+
+ return (len(t.Type) > 0 || t.Format != "")
+}
+
+func (t *typeValidator) Validate(data any) *Result {
+ if t.Options.recycleValidators {
+ defer func() {
+ t.redeem()
+ }()
+ }
+
+ if data == nil {
+ // nil or zero value for the passed structure require Type: null
+ if len(t.Type) > 0 && !t.Type.Contains(nullType) && !t.Nullable { // TODO: if a property is not required it also passes this
+ return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), nullType), t.Options.recycleResult)
+ }
+
+ return emptyResult
+ }
+
+ // check if the type matches, should be used in every validator chain as first item
+ val := reflect.Indirect(reflect.ValueOf(data))
+ kind := val.Kind()
+
+ // infer schema type (JSON) and format from passed data type
+ schType, format := t.schemaInfoForType(data)
+
+ // check numerical types
+ // TODO: check unsigned ints
+ // TODO: check json.Number (see schema.go)
+ isLowerInt := t.Format == integerFormatInt64 && format == integerFormatInt32
+ isLowerFloat := t.Format == numberFormatFloat64 && format == numberFormatFloat32
+ isFloatInt := schType == numberType && conv.IsFloat64AJSONInteger(val.Float()) && t.Type.Contains(integerType)
+ isIntFloat := schType == integerType && t.Type.Contains(numberType)
+
+ if kind != reflect.String && kind != reflect.Slice && t.Format != "" && !t.Type.Contains(schType) && format != t.Format && !isFloatInt && !isIntFloat && !isLowerInt && !isLowerFloat {
+ // TODO: test case
+ return errorHelp.sErr(errors.InvalidType(t.Path, t.In, t.Format, format), t.Options.recycleResult)
+ }
+
+ if !t.Type.Contains(numberType) && !t.Type.Contains(integerType) && t.Format != "" && (kind == reflect.String || kind == reflect.Slice) {
+ return emptyResult
+ }
+
+ if !t.Type.Contains(schType) && !isFloatInt && !isIntFloat {
+ return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), schType), t.Options.recycleResult)
+ }
+
+ return emptyResult
+}
+
+func (t *typeValidator) schemaInfoForType(data any) (string, string) {
+ // internal type to JSON type with swagger 2.0 format (with go-openapi/strfmt extensions),
+ // see https://github.com/go-openapi/strfmt/blob/master/README.md
+ // TODO: this switch really is some sort of reverse lookup for formats. It should be provided by strfmt.
+ switch data.(type) {
+ case []byte, strfmt.Base64, *strfmt.Base64:
+ return stringType, stringFormatByte
+ case strfmt.CreditCard, *strfmt.CreditCard:
+ return stringType, stringFormatCreditCard
+ case strfmt.Date, *strfmt.Date:
+ return stringType, stringFormatDate
+ case strfmt.DateTime, *strfmt.DateTime:
+ return stringType, stringFormatDateTime
+ case strfmt.Duration, *strfmt.Duration:
+ return stringType, stringFormatDuration
+ case fileutils.File, *fileutils.File:
+ return fileType, ""
+ case strfmt.Email, *strfmt.Email:
+ return stringType, stringFormatEmail
+ case strfmt.HexColor, *strfmt.HexColor:
+ return stringType, stringFormatHexColor
+ case strfmt.Hostname, *strfmt.Hostname:
+ return stringType, stringFormatHostname
+ case strfmt.IPv4, *strfmt.IPv4:
+ return stringType, stringFormatIPv4
+ case strfmt.IPv6, *strfmt.IPv6:
+ return stringType, stringFormatIPv6
+ case strfmt.ISBN, *strfmt.ISBN:
+ return stringType, stringFormatISBN
+ case strfmt.ISBN10, *strfmt.ISBN10:
+ return stringType, stringFormatISBN10
+ case strfmt.ISBN13, *strfmt.ISBN13:
+ return stringType, stringFormatISBN13
+ case strfmt.MAC, *strfmt.MAC:
+ return stringType, stringFormatMAC
+ case strfmt.ObjectId, *strfmt.ObjectId:
+ return stringType, stringFormatBSONObjectID
+ case strfmt.Password, *strfmt.Password:
+ return stringType, stringFormatPassword
+ case strfmt.RGBColor, *strfmt.RGBColor:
+ return stringType, stringFormatRGBColor
+ case strfmt.SSN, *strfmt.SSN:
+ return stringType, stringFormatSSN
+ case strfmt.URI, *strfmt.URI:
+ return stringType, stringFormatURI
+ case strfmt.UUID, *strfmt.UUID:
+ return stringType, stringFormatUUID
+ case strfmt.UUID3, *strfmt.UUID3:
+ return stringType, stringFormatUUID3
+ case strfmt.UUID4, *strfmt.UUID4:
+ return stringType, stringFormatUUID4
+ case strfmt.UUID5, *strfmt.UUID5:
+ return stringType, stringFormatUUID5
+ // TODO: missing binary (io.ReadCloser)
+ // TODO: missing json.Number
+ default:
+ val := reflect.ValueOf(data)
+ tpe := val.Type()
+ switch tpe.Kind() { //nolint:exhaustive
+ case reflect.Bool:
+ return booleanType, ""
+ case reflect.String:
+ return stringType, ""
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
+ // NOTE: that is the spec. With go-openapi, is that not uint32 for unsigned integers?
+ return integerType, integerFormatInt32
+ case reflect.Int, reflect.Int64, reflect.Uint, reflect.Uint64:
+ return integerType, integerFormatInt64
+ case reflect.Float32:
+ // NOTE: is that not numberFormatFloat?
+ return numberType, numberFormatFloat32
+ case reflect.Float64:
+ // NOTE: is that not "double"?
+ return numberType, numberFormatFloat64
+ // NOTE: go arrays (reflect.Array) are not supported (fixed length)
+ case reflect.Slice:
+ return arrayType, ""
+ case reflect.Map, reflect.Struct:
+ return objectType, ""
+ case reflect.Interface:
+ // What to do here?
+ panic("dunno what to do here")
+ case reflect.Ptr:
+ return t.schemaInfoForType(reflect.Indirect(val).Interface())
+ }
+ }
+ return "", ""
+}
+
+func (t *typeValidator) redeem() {
+ pools.poolOfTypeValidators.RedeemValidator(t)
+}
diff --git a/vendor/github.com/go-openapi/validate/update-fixtures.sh b/vendor/github.com/go-openapi/validate/update-fixtures.sh
new file mode 100644
index 000000000000..21b06e2b09a1
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/update-fixtures.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -eu -o pipefail
+dir=$(git rev-parse --show-toplevel)
+scratch=$(mktemp -d -t tmp.XXXXXXXXXX)
+
+function finish {
+ rm -rf "$scratch"
+}
+trap finish EXIT SIGHUP SIGINT SIGTERM
+
+cd "$scratch"
+git clone https://github.com/json-schema-org/JSON-Schema-Test-Suite Suite
+cp -r Suite/tests/draft4/* "$dir/fixtures/jsonschema_suite"
+cp -a Suite/remotes "$dir/fixtures/jsonschema_suite"
diff --git a/vendor/github.com/go-openapi/validate/validator.go b/vendor/github.com/go-openapi/validate/validator.go
new file mode 100644
index 000000000000..289a847fc7b0
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/validator.go
@@ -0,0 +1,1040 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+// An EntityValidator is an interface for things that can validate entities
+type EntityValidator interface {
+ Validate(any) *Result
+}
+
+type valueValidator interface {
+ SetPath(path string)
+ Applies(any, reflect.Kind) bool
+ Validate(any) *Result
+}
+
+type itemsValidator struct {
+ items *spec.Items
+ root any
+ path string
+ in string
+ validators [6]valueValidator
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+func newItemsValidator(path, in string, items *spec.Items, root any, formats strfmt.Registry, opts *SchemaValidatorOptions) *itemsValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var iv *itemsValidator
+ if opts.recycleValidators {
+ iv = pools.poolOfItemsValidators.BorrowValidator()
+ } else {
+ iv = new(itemsValidator)
+ }
+
+ iv.path = path
+ iv.in = in
+ iv.items = items
+ iv.root = root
+ iv.KnownFormats = formats
+ iv.Options = opts
+ iv.validators = [6]valueValidator{
+ iv.typeValidator(),
+ iv.stringValidator(),
+ iv.formatValidator(),
+ iv.numberValidator(),
+ iv.sliceValidator(),
+ iv.commonValidator(),
+ }
+ return iv
+}
+
+func (i *itemsValidator) Validate(index int, data any) *Result {
+ if i.Options.recycleValidators {
+ defer func() {
+ i.redeemChildren()
+ i.redeem()
+ }()
+ }
+
+ tpe := reflect.TypeOf(data)
+ kind := tpe.Kind()
+ var result *Result
+ if i.Options.recycleResult {
+ result = pools.poolOfResults.BorrowResult()
+ } else {
+ result = new(Result)
+ }
+
+ path := fmt.Sprintf("%s.%d", i.path, index)
+
+ for idx, validator := range i.validators {
+ if !validator.Applies(i.root, kind) {
+ if i.Options.recycleValidators {
+ // Validate won't be called, so relinquish this validator
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ i.validators[idx] = nil // prevents further (unsafe) usage
+ }
+
+ continue
+ }
+
+ validator.SetPath(path)
+ err := validator.Validate(data)
+ if i.Options.recycleValidators {
+ i.validators[idx] = nil // prevents further (unsafe) usage
+ }
+ if err != nil {
+ result.Inc()
+ if err.HasErrors() {
+ result.Merge(err)
+
+ break
+ }
+
+ result.Merge(err)
+ }
+ }
+
+ return result
+}
+
+func (i *itemsValidator) typeValidator() valueValidator {
+ return newTypeValidator(
+ i.path,
+ i.in,
+ spec.StringOrArray([]string{i.items.Type}),
+ i.items.Nullable,
+ i.items.Format,
+ i.Options,
+ )
+}
+
+func (i *itemsValidator) commonValidator() valueValidator {
+ return newBasicCommonValidator(
+ "",
+ i.in,
+ i.items.Default,
+ i.items.Enum,
+ i.Options,
+ )
+}
+
+func (i *itemsValidator) sliceValidator() valueValidator {
+ return newBasicSliceValidator(
+ "",
+ i.in,
+ i.items.Default,
+ i.items.MaxItems,
+ i.items.MinItems,
+ i.items.UniqueItems,
+ i.items.Items,
+ i.root,
+ i.KnownFormats,
+ i.Options,
+ )
+}
+
+func (i *itemsValidator) numberValidator() valueValidator {
+ return newNumberValidator(
+ "",
+ i.in,
+ i.items.Default,
+ i.items.MultipleOf,
+ i.items.Maximum,
+ i.items.ExclusiveMaximum,
+ i.items.Minimum,
+ i.items.ExclusiveMinimum,
+ i.items.Type,
+ i.items.Format,
+ i.Options,
+ )
+}
+
+func (i *itemsValidator) stringValidator() valueValidator {
+ return newStringValidator(
+ "",
+ i.in,
+ i.items.Default,
+ false, // Required
+ false, // AllowEmpty
+ i.items.MaxLength,
+ i.items.MinLength,
+ i.items.Pattern,
+ i.Options,
+ )
+}
+
+func (i *itemsValidator) formatValidator() valueValidator {
+ return newFormatValidator(
+ "",
+ i.in,
+ i.items.Format,
+ i.KnownFormats,
+ i.Options,
+ )
+}
+
+func (i *itemsValidator) redeem() {
+ pools.poolOfItemsValidators.RedeemValidator(i)
+}
+
+func (i *itemsValidator) redeemChildren() {
+ for idx, validator := range i.validators {
+ if validator == nil {
+ continue
+ }
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ i.validators[idx] = nil // free up allocated children if not in pool
+ }
+}
+
+type basicCommonValidator struct {
+ Path string
+ In string
+ Default any
+ Enum []any
+ Options *SchemaValidatorOptions
+}
+
+func newBasicCommonValidator(path, in string, def any, enum []any, opts *SchemaValidatorOptions) *basicCommonValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var b *basicCommonValidator
+ if opts.recycleValidators {
+ b = pools.poolOfBasicCommonValidators.BorrowValidator()
+ } else {
+ b = new(basicCommonValidator)
+ }
+
+ b.Path = path
+ b.In = in
+ b.Default = def
+ b.Enum = enum
+ b.Options = opts
+
+ return b
+}
+
+func (b *basicCommonValidator) SetPath(path string) {
+ b.Path = path
+}
+
+func (b *basicCommonValidator) Applies(source any, _ reflect.Kind) bool {
+ switch source.(type) {
+ case *spec.Parameter, *spec.Schema, *spec.Header:
+ return true
+ default:
+ return false
+ }
+}
+
+func (b *basicCommonValidator) Validate(data any) (res *Result) {
+ if b.Options.recycleValidators {
+ defer func() {
+ b.redeem()
+ }()
+ }
+
+ if len(b.Enum) == 0 {
+ return nil
+ }
+
+ for _, enumValue := range b.Enum {
+ actualType := reflect.TypeOf(enumValue)
+ if actualType == nil { // Safeguard
+ continue
+ }
+
+ expectedValue := reflect.ValueOf(data)
+ if expectedValue.IsValid() &&
+ expectedValue.Type().ConvertibleTo(actualType) &&
+ reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
+ return nil
+ }
+ }
+
+ return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum), b.Options.recycleResult)
+}
+
+func (b *basicCommonValidator) redeem() {
+ pools.poolOfBasicCommonValidators.RedeemValidator(b)
+}
+
+// A HeaderValidator has very limited subset of validations to apply
+type HeaderValidator struct {
+ name string
+ header *spec.Header
+ validators [6]valueValidator
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+// NewHeaderValidator creates a new header validator object
+func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry, options ...Option) *HeaderValidator {
+ opts := new(SchemaValidatorOptions)
+ for _, o := range options {
+ o(opts)
+ }
+
+ return newHeaderValidator(name, header, formats, opts)
+}
+
+func newHeaderValidator(name string, header *spec.Header, formats strfmt.Registry, opts *SchemaValidatorOptions) *HeaderValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var p *HeaderValidator
+ if opts.recycleValidators {
+ p = pools.poolOfHeaderValidators.BorrowValidator()
+ } else {
+ p = new(HeaderValidator)
+ }
+
+ p.name = name
+ p.header = header
+ p.KnownFormats = formats
+ p.Options = opts
+ p.validators = [6]valueValidator{
+ newTypeValidator(
+ name,
+ "header",
+ spec.StringOrArray([]string{header.Type}),
+ header.Nullable,
+ header.Format,
+ p.Options,
+ ),
+ p.stringValidator(),
+ p.formatValidator(),
+ p.numberValidator(),
+ p.sliceValidator(),
+ p.commonValidator(),
+ }
+
+ return p
+}
+
+// Validate the value of the header against its schema
+func (p *HeaderValidator) Validate(data any) *Result {
+ if p.Options.recycleValidators {
+ defer func() {
+ p.redeemChildren()
+ p.redeem()
+ }()
+ }
+
+ if data == nil {
+ return nil
+ }
+
+ var result *Result
+ if p.Options.recycleResult {
+ result = pools.poolOfResults.BorrowResult()
+ } else {
+ result = new(Result)
+ }
+
+ tpe := reflect.TypeOf(data)
+ kind := tpe.Kind()
+
+ for idx, validator := range p.validators {
+ if !validator.Applies(p.header, kind) {
+ if p.Options.recycleValidators {
+ // Validate won't be called, so relinquish this validator
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ p.validators[idx] = nil // prevents further (unsafe) usage
+ }
+
+ continue
+ }
+
+ err := validator.Validate(data)
+ if p.Options.recycleValidators {
+ p.validators[idx] = nil // prevents further (unsafe) usage
+ }
+ if err != nil {
+ if err.HasErrors() {
+ result.Merge(err)
+ break
+ }
+ result.Merge(err)
+ }
+ }
+
+ return result
+}
+
+func (p *HeaderValidator) commonValidator() valueValidator {
+ return newBasicCommonValidator(
+ p.name,
+ "response",
+ p.header.Default,
+ p.header.Enum,
+ p.Options,
+ )
+}
+
+func (p *HeaderValidator) sliceValidator() valueValidator {
+ return newBasicSliceValidator(
+ p.name,
+ "response",
+ p.header.Default,
+ p.header.MaxItems,
+ p.header.MinItems,
+ p.header.UniqueItems,
+ p.header.Items,
+ p.header,
+ p.KnownFormats,
+ p.Options,
+ )
+}
+
+func (p *HeaderValidator) numberValidator() valueValidator {
+ return newNumberValidator(
+ p.name,
+ "response",
+ p.header.Default,
+ p.header.MultipleOf,
+ p.header.Maximum,
+ p.header.ExclusiveMaximum,
+ p.header.Minimum,
+ p.header.ExclusiveMinimum,
+ p.header.Type,
+ p.header.Format,
+ p.Options,
+ )
+}
+
+func (p *HeaderValidator) stringValidator() valueValidator {
+ return newStringValidator(
+ p.name,
+ "response",
+ p.header.Default,
+ true,
+ false,
+ p.header.MaxLength,
+ p.header.MinLength,
+ p.header.Pattern,
+ p.Options,
+ )
+}
+
+func (p *HeaderValidator) formatValidator() valueValidator {
+ return newFormatValidator(
+ p.name,
+ "response",
+ p.header.Format,
+ p.KnownFormats,
+ p.Options,
+ )
+}
+
+func (p *HeaderValidator) redeem() {
+ pools.poolOfHeaderValidators.RedeemValidator(p)
+}
+
+func (p *HeaderValidator) redeemChildren() {
+ for idx, validator := range p.validators {
+ if validator == nil {
+ continue
+ }
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ p.validators[idx] = nil // free up allocated children if not in pool
+ }
+}
+
+// A ParamValidator has very limited subset of validations to apply
+type ParamValidator struct {
+ param *spec.Parameter
+ validators [6]valueValidator
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+// NewParamValidator creates a new param validator object
+func NewParamValidator(param *spec.Parameter, formats strfmt.Registry, options ...Option) *ParamValidator {
+ opts := new(SchemaValidatorOptions)
+ for _, o := range options {
+ o(opts)
+ }
+
+ return newParamValidator(param, formats, opts)
+}
+
+func newParamValidator(param *spec.Parameter, formats strfmt.Registry, opts *SchemaValidatorOptions) *ParamValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var p *ParamValidator
+ if opts.recycleValidators {
+ p = pools.poolOfParamValidators.BorrowValidator()
+ } else {
+ p = new(ParamValidator)
+ }
+
+ p.param = param
+ p.KnownFormats = formats
+ p.Options = opts
+ p.validators = [6]valueValidator{
+ newTypeValidator(
+ param.Name,
+ param.In,
+ spec.StringOrArray([]string{param.Type}),
+ param.Nullable,
+ param.Format,
+ p.Options,
+ ),
+ p.stringValidator(),
+ p.formatValidator(),
+ p.numberValidator(),
+ p.sliceValidator(),
+ p.commonValidator(),
+ }
+
+ return p
+}
+
+// Validate the data against the description of the parameter
+func (p *ParamValidator) Validate(data any) *Result {
+ if data == nil {
+ return nil
+ }
+
+ var result *Result
+ if p.Options.recycleResult {
+ result = pools.poolOfResults.BorrowResult()
+ } else {
+ result = new(Result)
+ }
+
+ tpe := reflect.TypeOf(data)
+ kind := tpe.Kind()
+
+ if p.Options.recycleValidators {
+ defer func() {
+ p.redeemChildren()
+ p.redeem()
+ }()
+ }
+
+ // TODO: validate type
+ for idx, validator := range p.validators {
+ if !validator.Applies(p.param, kind) {
+ if p.Options.recycleValidators {
+ // Validate won't be called, so relinquish this validator
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ p.validators[idx] = nil // prevents further (unsafe) usage
+ }
+
+ continue
+ }
+
+ err := validator.Validate(data)
+ if p.Options.recycleValidators {
+ p.validators[idx] = nil // prevents further (unsafe) usage
+ }
+ if err != nil {
+ if err.HasErrors() {
+ result.Merge(err)
+ break
+ }
+ result.Merge(err)
+ }
+ }
+
+ return result
+}
+
+func (p *ParamValidator) commonValidator() valueValidator {
+ return newBasicCommonValidator(
+ p.param.Name,
+ p.param.In,
+ p.param.Default,
+ p.param.Enum,
+ p.Options,
+ )
+}
+
+func (p *ParamValidator) sliceValidator() valueValidator {
+ return newBasicSliceValidator(
+ p.param.Name,
+ p.param.In,
+ p.param.Default,
+ p.param.MaxItems,
+ p.param.MinItems,
+ p.param.UniqueItems,
+ p.param.Items,
+ p.param,
+ p.KnownFormats,
+ p.Options,
+ )
+}
+
+func (p *ParamValidator) numberValidator() valueValidator {
+ return newNumberValidator(
+ p.param.Name,
+ p.param.In,
+ p.param.Default,
+ p.param.MultipleOf,
+ p.param.Maximum,
+ p.param.ExclusiveMaximum,
+ p.param.Minimum,
+ p.param.ExclusiveMinimum,
+ p.param.Type,
+ p.param.Format,
+ p.Options,
+ )
+}
+
+func (p *ParamValidator) stringValidator() valueValidator {
+ return newStringValidator(
+ p.param.Name,
+ p.param.In,
+ p.param.Default,
+ p.param.Required,
+ p.param.AllowEmptyValue,
+ p.param.MaxLength,
+ p.param.MinLength,
+ p.param.Pattern,
+ p.Options,
+ )
+}
+
+func (p *ParamValidator) formatValidator() valueValidator {
+ return newFormatValidator(
+ p.param.Name,
+ p.param.In,
+ p.param.Format,
+ p.KnownFormats,
+ p.Options,
+ )
+}
+
+func (p *ParamValidator) redeem() {
+ pools.poolOfParamValidators.RedeemValidator(p)
+}
+
+func (p *ParamValidator) redeemChildren() {
+ for idx, validator := range p.validators {
+ if validator == nil {
+ continue
+ }
+ if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
+ redeemableChildren.redeemChildren()
+ }
+ if redeemable, ok := validator.(interface{ redeem() }); ok {
+ redeemable.redeem()
+ }
+ p.validators[idx] = nil // free up allocated children if not in pool
+ }
+}
+
+type basicSliceValidator struct {
+ Path string
+ In string
+ Default any
+ MaxItems *int64
+ MinItems *int64
+ UniqueItems bool
+ Items *spec.Items
+ Source any
+ KnownFormats strfmt.Registry
+ Options *SchemaValidatorOptions
+}
+
+func newBasicSliceValidator(
+ path, in string,
+ def any, maxItems, minItems *int64, uniqueItems bool, items *spec.Items,
+ source any, formats strfmt.Registry,
+ opts *SchemaValidatorOptions) *basicSliceValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var s *basicSliceValidator
+ if opts.recycleValidators {
+ s = pools.poolOfBasicSliceValidators.BorrowValidator()
+ } else {
+ s = new(basicSliceValidator)
+ }
+
+ s.Path = path
+ s.In = in
+ s.Default = def
+ s.MaxItems = maxItems
+ s.MinItems = minItems
+ s.UniqueItems = uniqueItems
+ s.Items = items
+ s.Source = source
+ s.KnownFormats = formats
+ s.Options = opts
+
+ return s
+}
+
+func (s *basicSliceValidator) SetPath(path string) {
+ s.Path = path
+}
+
+func (s *basicSliceValidator) Applies(source any, kind reflect.Kind) bool {
+ switch source.(type) {
+ case *spec.Parameter, *spec.Items, *spec.Header:
+ return kind == reflect.Slice
+ default:
+ return false
+ }
+}
+
+func (s *basicSliceValidator) Validate(data any) *Result {
+ if s.Options.recycleValidators {
+ defer func() {
+ s.redeem()
+ }()
+ }
+ val := reflect.ValueOf(data)
+
+ size := int64(val.Len())
+ if s.MinItems != nil {
+ if err := MinItems(s.Path, s.In, size, *s.MinItems); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+
+ if s.MaxItems != nil {
+ if err := MaxItems(s.Path, s.In, size, *s.MaxItems); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+
+ if s.UniqueItems {
+ if err := UniqueItems(s.Path, s.In, data); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+
+ if s.Items == nil {
+ return nil
+ }
+
+ for i := range int(size) {
+ itemsValidator := newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats, s.Options)
+ ele := val.Index(i)
+ if err := itemsValidator.Validate(i, ele.Interface()); err != nil {
+ if err.HasErrors() {
+ return err
+ }
+ if err.wantsRedeemOnMerge {
+ pools.poolOfResults.RedeemResult(err)
+ }
+ }
+ }
+
+ return nil
+}
+
+func (s *basicSliceValidator) redeem() {
+ pools.poolOfBasicSliceValidators.RedeemValidator(s)
+}
+
+type numberValidator struct {
+ Path string
+ In string
+ Default any
+ MultipleOf *float64
+ Maximum *float64
+ ExclusiveMaximum bool
+ Minimum *float64
+ ExclusiveMinimum bool
+ // Allows for more accurate behavior regarding integers
+ Type string
+ Format string
+ Options *SchemaValidatorOptions
+}
+
+func newNumberValidator(
+ path, in string, def any,
+ multipleOf, maximum *float64, exclusiveMaximum bool, minimum *float64, exclusiveMinimum bool,
+ typ, format string,
+ opts *SchemaValidatorOptions) *numberValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var n *numberValidator
+ if opts.recycleValidators {
+ n = pools.poolOfNumberValidators.BorrowValidator()
+ } else {
+ n = new(numberValidator)
+ }
+
+ n.Path = path
+ n.In = in
+ n.Default = def
+ n.MultipleOf = multipleOf
+ n.Maximum = maximum
+ n.ExclusiveMaximum = exclusiveMaximum
+ n.Minimum = minimum
+ n.ExclusiveMinimum = exclusiveMinimum
+ n.Type = typ
+ n.Format = format
+ n.Options = opts
+
+ return n
+}
+
+func (n *numberValidator) SetPath(path string) {
+ n.Path = path
+}
+
+func (n *numberValidator) Applies(source any, kind reflect.Kind) bool {
+ switch source.(type) {
+ case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
+ isInt := kind >= reflect.Int && kind <= reflect.Uint64
+ isFloat := kind == reflect.Float32 || kind == reflect.Float64
+ return isInt || isFloat
+ default:
+ return false
+ }
+}
+
+// Validate provides a validator for generic JSON numbers,
+//
+// By default, numbers are internally represented as float64.
+// Formats float, or float32 may alter this behavior by mapping to float32.
+// A special validation process is followed for integers, with optional "format":
+// this is an attempt to provide a validation with native types.
+//
+// NOTE: since the constraint specified (boundary, multipleOf) is unmarshalled
+// as float64, loss of information remains possible (e.g. on very large integers).
+//
+// Since this value directly comes from the unmarshalling, it is not possible
+// at this stage of processing to check further and guarantee the correctness of such values.
+//
+// Normally, the JSON Number.MAX_SAFE_INTEGER (resp. Number.MIN_SAFE_INTEGER)
+// would check we do not get such a loss.
+//
+// If this is the case, replace AddErrors() by AddWarnings() and IsValid() by !HasWarnings().
+//
+// TODO: consider replacing boundary check errors by simple warnings.
+//
+// TODO: default boundaries with MAX_SAFE_INTEGER are not checked (specific to json.Number?)
+func (n *numberValidator) Validate(val any) *Result {
+ if n.Options.recycleValidators {
+ defer func() {
+ n.redeem()
+ }()
+ }
+
+ var res, resMultiple, resMinimum, resMaximum *Result
+ if n.Options.recycleResult {
+ res = pools.poolOfResults.BorrowResult()
+ } else {
+ res = new(Result)
+ }
+
+ // Used only to attempt to validate constraint on value,
+ // even though value or constraint specified do not match type and format
+ data := valueHelp.asFloat64(val)
+
+ // Is the provided value within the range of the specified numeric type and format?
+ res.AddErrors(IsValueValidAgainstRange(val, n.Type, n.Format, "Checked", n.Path))
+
+ if n.MultipleOf != nil {
+ resMultiple = pools.poolOfResults.BorrowResult()
+
+ // Is the constraint specifier within the range of the specific numeric type and format?
+ resMultiple.AddErrors(IsValueValidAgainstRange(*n.MultipleOf, n.Type, n.Format, "MultipleOf", n.Path))
+ if resMultiple.IsValid() {
+ // Constraint validated with compatible types
+ if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil {
+ resMultiple.Merge(errorHelp.sErr(err, n.Options.recycleResult))
+ }
+ } else {
+ // Constraint nevertheless validated, converted as general number
+ if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil {
+ resMultiple.Merge(errorHelp.sErr(err, n.Options.recycleResult))
+ }
+ }
+ }
+
+ if n.Maximum != nil {
+ resMaximum = pools.poolOfResults.BorrowResult()
+
+ // Is the constraint specifier within the range of the specific numeric type and format?
+ resMaximum.AddErrors(IsValueValidAgainstRange(*n.Maximum, n.Type, n.Format, "Maximum boundary", n.Path))
+ if resMaximum.IsValid() {
+ // Constraint validated with compatible types
+ if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil {
+ resMaximum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
+ }
+ } else {
+ // Constraint nevertheless validated, converted as general number
+ if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil {
+ resMaximum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
+ }
+ }
+ }
+
+ if n.Minimum != nil {
+ resMinimum = pools.poolOfResults.BorrowResult()
+
+ // Is the constraint specifier within the range of the specific numeric type and format?
+ resMinimum.AddErrors(IsValueValidAgainstRange(*n.Minimum, n.Type, n.Format, "Minimum boundary", n.Path))
+ if resMinimum.IsValid() {
+ // Constraint validated with compatible types
+ if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil {
+ resMinimum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
+ }
+ } else {
+ // Constraint nevertheless validated, converted as general number
+ if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil {
+ resMinimum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
+ }
+ }
+ }
+ res.Merge(resMultiple, resMinimum, resMaximum)
+ res.Inc()
+
+ return res
+}
+
+func (n *numberValidator) redeem() {
+ pools.poolOfNumberValidators.RedeemValidator(n)
+}
+
+type stringValidator struct {
+ Path string
+ In string
+ Default any
+ Required bool
+ AllowEmptyValue bool
+ MaxLength *int64
+ MinLength *int64
+ Pattern string
+ Options *SchemaValidatorOptions
+}
+
+func newStringValidator(
+ path, in string,
+ def any, required, allowEmpty bool, maxLength, minLength *int64, pattern string,
+ opts *SchemaValidatorOptions) *stringValidator {
+ if opts == nil {
+ opts = new(SchemaValidatorOptions)
+ }
+
+ var s *stringValidator
+ if opts.recycleValidators {
+ s = pools.poolOfStringValidators.BorrowValidator()
+ } else {
+ s = new(stringValidator)
+ }
+
+ s.Path = path
+ s.In = in
+ s.Default = def
+ s.Required = required
+ s.AllowEmptyValue = allowEmpty
+ s.MaxLength = maxLength
+ s.MinLength = minLength
+ s.Pattern = pattern
+ s.Options = opts
+
+ return s
+}
+
+func (s *stringValidator) SetPath(path string) {
+ s.Path = path
+}
+
+func (s *stringValidator) Applies(source any, kind reflect.Kind) bool {
+ switch source.(type) {
+ case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
+ return kind == reflect.String
+ default:
+ return false
+ }
+}
+
+func (s *stringValidator) Validate(val any) *Result {
+ if s.Options.recycleValidators {
+ defer func() {
+ s.redeem()
+ }()
+ }
+
+ data, ok := val.(string)
+ if !ok {
+ return errorHelp.sErr(errors.InvalidType(s.Path, s.In, stringType, val), s.Options.recycleResult)
+ }
+
+ if s.Required && !s.AllowEmptyValue && (s.Default == nil || s.Default == "") {
+ if err := RequiredString(s.Path, s.In, data); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+
+ if s.MaxLength != nil {
+ if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+
+ if s.MinLength != nil {
+ if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+
+ if s.Pattern != "" {
+ if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil {
+ return errorHelp.sErr(err, s.Options.recycleResult)
+ }
+ }
+ return nil
+}
+
+func (s *stringValidator) redeem() {
+ pools.poolOfStringValidators.RedeemValidator(s)
+}
diff --git a/vendor/github.com/go-openapi/validate/values.go b/vendor/github.com/go-openapi/validate/values.go
new file mode 100644
index 000000000000..e7dd5c8d3ab5
--- /dev/null
+++ b/vendor/github.com/go-openapi/validate/values.go
@@ -0,0 +1,448 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package validate
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/conv"
+)
+
+type valueError string
+
+func (e valueError) Error() string {
+ return string(e)
+}
+
+// ErrValue indicates that a value validation occurred
+const ErrValue valueError = "value validation error"
+
+// Enum validates if the data is a member of the enum
+func Enum(path, in string, data any, enum any) *errors.Validation {
+ return EnumCase(path, in, data, enum, true)
+}
+
+// EnumCase validates if the data is a member of the enum and may respect case-sensitivity for strings
+func EnumCase(path, in string, data any, enum any, caseSensitive bool) *errors.Validation {
+ val := reflect.ValueOf(enum)
+ if val.Kind() != reflect.Slice {
+ return nil
+ }
+
+ dataString := convertEnumCaseStringKind(data, caseSensitive)
+ values := make([]any, 0, val.Len())
+ for i := range val.Len() {
+ ele := val.Index(i)
+ enumValue := ele.Interface()
+ if data != nil {
+ if reflect.DeepEqual(data, enumValue) {
+ return nil
+ }
+ enumString := convertEnumCaseStringKind(enumValue, caseSensitive)
+ if dataString != nil && enumString != nil && strings.EqualFold(*dataString, *enumString) {
+ return nil
+ }
+ actualType := reflect.TypeOf(enumValue)
+ if actualType == nil { // Safeguard. Frankly, I don't know how we may get a nil
+ continue
+ }
+ expectedValue := reflect.ValueOf(data)
+ if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+ // Attempt comparison after type conversion
+ if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
+ return nil
+ }
+ }
+ }
+ values = append(values, enumValue)
+ }
+ return errors.EnumFail(path, in, data, values)
+}
+
+// convertEnumCaseStringKind converts interface if it is kind of string and case insensitivity is set
+func convertEnumCaseStringKind(value any, caseSensitive bool) *string {
+ if caseSensitive {
+ return nil
+ }
+
+ val := reflect.ValueOf(value)
+ if val.Kind() != reflect.String {
+ return nil
+ }
+
+ str := fmt.Sprintf("%v", value)
+ return &str
+}
+
+// MinItems validates that there are at least n items in a slice
+func MinItems(path, in string, size, minimum int64) *errors.Validation {
+ if size < minimum {
+ return errors.TooFewItems(path, in, minimum, size)
+ }
+ return nil
+}
+
+// MaxItems validates that there are at most n items in a slice
+func MaxItems(path, in string, size, maximum int64) *errors.Validation {
+ if size > maximum {
+ return errors.TooManyItems(path, in, maximum, size)
+ }
+ return nil
+}
+
+// UniqueItems validates that the provided slice has unique elements
+func UniqueItems(path, in string, data any) *errors.Validation {
+ val := reflect.ValueOf(data)
+ if val.Kind() != reflect.Slice {
+ return nil
+ }
+ unique := make([]any, 0, val.Len())
+ for i := range val.Len() {
+ v := val.Index(i).Interface()
+ for _, u := range unique {
+ if reflect.DeepEqual(v, u) {
+ return errors.DuplicateItems(path, in)
+ }
+ }
+ unique = append(unique, v)
+ }
+ return nil
+}
+
+// MinLength validates a string for minimum length
+func MinLength(path, in, data string, minLength int64) *errors.Validation {
+ strLen := int64(utf8.RuneCountInString(data))
+ if strLen < minLength {
+ return errors.TooShort(path, in, minLength, data)
+ }
+ return nil
+}
+
+// MaxLength validates a string for maximum length
+func MaxLength(path, in, data string, maxLength int64) *errors.Validation {
+ strLen := int64(utf8.RuneCountInString(data))
+ if strLen > maxLength {
+ return errors.TooLong(path, in, maxLength, data)
+ }
+ return nil
+}
+
+// ReadOnly validates an interface for readonly
+func ReadOnly(ctx context.Context, path, in string, data any) *errors.Validation {
+
+ // read only is only validated when operationType is request
+ if op := extractOperationType(ctx); op != request {
+ return nil
+ }
+
+ // data must be of zero value of its type
+ val := reflect.ValueOf(data)
+ if val.IsValid() {
+ if reflect.DeepEqual(reflect.Zero(val.Type()).Interface(), val.Interface()) {
+ return nil
+ }
+ } else {
+ return nil
+ }
+
+ return errors.ReadOnly(path, in, data)
+}
+
+// Required validates an interface for requiredness
+func Required(path, in string, data any) *errors.Validation {
+ val := reflect.ValueOf(data)
+ if val.IsValid() {
+ if reflect.DeepEqual(reflect.Zero(val.Type()).Interface(), val.Interface()) {
+ return errors.Required(path, in, data)
+ }
+ return nil
+ }
+ return errors.Required(path, in, data)
+}
+
+// RequiredString validates a string for requiredness
+func RequiredString(path, in, data string) *errors.Validation {
+ if data == "" {
+ return errors.Required(path, in, data)
+ }
+ return nil
+}
+
+// RequiredNumber validates a number for requiredness
+func RequiredNumber(path, in string, data float64) *errors.Validation {
+ if data == 0 {
+ return errors.Required(path, in, data)
+ }
+ return nil
+}
+
+// Pattern validates a string against a regular expression
+func Pattern(path, in, data, pattern string) *errors.Validation {
+ re, err := compileRegexp(pattern)
+ if err != nil {
+ return errors.FailedPattern(path, in, fmt.Sprintf("%s, but pattern is invalid: %s", pattern, err.Error()), data)
+ }
+ if !re.MatchString(data) {
+ return errors.FailedPattern(path, in, pattern, data)
+ }
+ return nil
+}
+
+// MaximumInt validates if a number is smaller than a given maximum
+func MaximumInt(path, in string, data, maximum int64, exclusive bool) *errors.Validation {
+ if (!exclusive && data > maximum) || (exclusive && data >= maximum) {
+ return errors.ExceedsMaximumInt(path, in, maximum, exclusive, data)
+ }
+ return nil
+}
+
+// MaximumUint validates if a number is smaller than a given maximum
+func MaximumUint(path, in string, data, maximum uint64, exclusive bool) *errors.Validation {
+ if (!exclusive && data > maximum) || (exclusive && data >= maximum) {
+ return errors.ExceedsMaximumUint(path, in, maximum, exclusive, data)
+ }
+ return nil
+}
+
+// Maximum validates if a number is smaller than a given maximum
+func Maximum(path, in string, data, maximum float64, exclusive bool) *errors.Validation {
+ if (!exclusive && data > maximum) || (exclusive && data >= maximum) {
+ return errors.ExceedsMaximum(path, in, maximum, exclusive, data)
+ }
+ return nil
+}
+
+// Minimum validates if a number is smaller than a given minimum
+func Minimum(path, in string, data, minimum float64, exclusive bool) *errors.Validation {
+ if (!exclusive && data < minimum) || (exclusive && data <= minimum) {
+ return errors.ExceedsMinimum(path, in, minimum, exclusive, data)
+ }
+ return nil
+}
+
+// MinimumInt validates if a number is smaller than a given minimum
+func MinimumInt(path, in string, data, minimum int64, exclusive bool) *errors.Validation {
+ if (!exclusive && data < minimum) || (exclusive && data <= minimum) {
+ return errors.ExceedsMinimumInt(path, in, minimum, exclusive, data)
+ }
+ return nil
+}
+
+// MinimumUint validates if a number is smaller than a given minimum
+func MinimumUint(path, in string, data, minimum uint64, exclusive bool) *errors.Validation {
+ if (!exclusive && data < minimum) || (exclusive && data <= minimum) {
+ return errors.ExceedsMinimumUint(path, in, minimum, exclusive, data)
+ }
+ return nil
+}
+
+// MultipleOf validates if the provided number is a multiple of the factor
+func MultipleOf(path, in string, data, factor float64) *errors.Validation {
+ // multipleOf factor must be positive
+ if factor <= 0 {
+ return errors.MultipleOfMustBePositive(path, in, factor)
+ }
+ var mult float64
+ if factor < 1 {
+ mult = 1 / factor * data
+ } else {
+ mult = data / factor
+ }
+ if !conv.IsFloat64AJSONInteger(mult) {
+ return errors.NotMultipleOf(path, in, factor, data)
+ }
+ return nil
+}
+
+// MultipleOfInt validates if the provided integer is a multiple of the factor
+func MultipleOfInt(path, in string, data int64, factor int64) *errors.Validation {
+ // multipleOf factor must be positive
+ if factor <= 0 {
+ return errors.MultipleOfMustBePositive(path, in, factor)
+ }
+ mult := data / factor
+ if mult*factor != data {
+ return errors.NotMultipleOf(path, in, factor, data)
+ }
+ return nil
+}
+
+// MultipleOfUint validates if the provided unsigned integer is a multiple of the factor
+func MultipleOfUint(path, in string, data, factor uint64) *errors.Validation {
+ // multipleOf factor must be positive
+ if factor == 0 {
+ return errors.MultipleOfMustBePositive(path, in, factor)
+ }
+ mult := data / factor
+ if mult*factor != data {
+ return errors.NotMultipleOf(path, in, factor, data)
+ }
+ return nil
+}
+
+// FormatOf validates if a string matches a format in the format registry
+func FormatOf(path, in, format, data string, registry strfmt.Registry) *errors.Validation {
+ if registry == nil {
+ registry = strfmt.Default
+ }
+ if ok := registry.ContainsName(format); !ok {
+ return errors.InvalidTypeName(format)
+ }
+ if ok := registry.Validates(format, data); !ok {
+ return errors.InvalidType(path, in, format, data)
+ }
+ return nil
+}
+
+// MaximumNativeType provides native type constraint validation as a facade
+// to various numeric types versions of Maximum constraint check.
+//
+// Assumes that any possible loss conversion during conversion has been
+// checked beforehand.
+//
+// NOTE: currently, the max value is marshalled as a float64, no matter what,
+// which means there may be a loss during conversions (e.g. for very large integers)
+//
+// TODO: Normally, a JSON MAX_SAFE_INTEGER check would ensure conversion remains loss-free
+func MaximumNativeType(path, in string, val any, maximum float64, exclusive bool) *errors.Validation {
+ kind := reflect.ValueOf(val).Type().Kind()
+ switch kind { //nolint:exhaustive
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ value := valueHelp.asInt64(val)
+ return MaximumInt(path, in, value, int64(maximum), exclusive)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ value := valueHelp.asUint64(val)
+ if maximum < 0 {
+ return errors.ExceedsMaximum(path, in, maximum, exclusive, val)
+ }
+ return MaximumUint(path, in, value, uint64(maximum), exclusive)
+ case reflect.Float32, reflect.Float64:
+ fallthrough
+ default:
+ value := valueHelp.asFloat64(val)
+ return Maximum(path, in, value, maximum, exclusive)
+ }
+}
+
+// MinimumNativeType provides native type constraint validation as a facade
+// to various numeric types versions of Minimum constraint check.
+//
+// Assumes that any possible loss conversion during conversion has been
+// checked beforehand.
+//
+// NOTE: currently, the min value is marshalled as a float64, no matter what,
+// which means there may be a loss during conversions (e.g. for very large integers)
+//
+// TODO: Normally, a JSON MAX_SAFE_INTEGER check would ensure conversion remains loss-free
+func MinimumNativeType(path, in string, val any, minimum float64, exclusive bool) *errors.Validation {
+ kind := reflect.ValueOf(val).Type().Kind()
+ switch kind { //nolint:exhaustive
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ value := valueHelp.asInt64(val)
+ return MinimumInt(path, in, value, int64(minimum), exclusive)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ value := valueHelp.asUint64(val)
+ if minimum < 0 {
+ return nil
+ }
+ return MinimumUint(path, in, value, uint64(minimum), exclusive)
+ case reflect.Float32, reflect.Float64:
+ fallthrough
+ default:
+ value := valueHelp.asFloat64(val)
+ return Minimum(path, in, value, minimum, exclusive)
+ }
+}
+
+// MultipleOfNativeType provides native type constraint validation as a facade
+// to various numeric types version of MultipleOf constraint check.
+//
+// Assumes that any possible loss conversion during conversion has been
+// checked beforehand.
+//
+// NOTE: currently, the multipleOf factor is marshalled as a float64, no matter what,
+// which means there may be a loss during conversions (e.g. for very large integers)
+//
+// TODO: Normally, a JSON MAX_SAFE_INTEGER check would ensure conversion remains loss-free
+func MultipleOfNativeType(path, in string, val any, multipleOf float64) *errors.Validation {
+ kind := reflect.ValueOf(val).Type().Kind()
+ switch kind { //nolint:exhaustive
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ value := valueHelp.asInt64(val)
+ return MultipleOfInt(path, in, value, int64(multipleOf))
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ value := valueHelp.asUint64(val)
+ return MultipleOfUint(path, in, value, uint64(multipleOf))
+ case reflect.Float32, reflect.Float64:
+ fallthrough
+ default:
+ value := valueHelp.asFloat64(val)
+ return MultipleOf(path, in, value, multipleOf)
+ }
+}
+
+// IsValueValidAgainstRange checks that a numeric value is compatible with
+// the range defined by Type and Format, that is, may be converted without loss.
+//
+// NOTE: this check is about type capacity and not formal verification such as: 1.0 != 1L
+func IsValueValidAgainstRange(val any, typeName, format, prefix, path string) error {
+ kind := reflect.ValueOf(val).Type().Kind()
+
+ // What is the string representation of val
+ var stringRep string
+ switch kind { //nolint:exhaustive
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ stringRep = conv.FormatUinteger(valueHelp.asUint64(val))
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ stringRep = conv.FormatInteger(valueHelp.asInt64(val))
+ case reflect.Float32, reflect.Float64:
+ stringRep = conv.FormatFloat(valueHelp.asFloat64(val))
+ default:
+ return fmt.Errorf("%s value number range checking called with invalid (non numeric) val type in %s: %w", prefix, path, ErrValue)
+ }
+
+ var errVal error
+
+ switch typeName {
+ case integerType:
+ switch format {
+ case integerFormatInt32:
+ _, errVal = conv.ConvertInt32(stringRep)
+ case integerFormatUInt32:
+ _, errVal = conv.ConvertUint32(stringRep)
+ case integerFormatUInt64:
+ _, errVal = conv.ConvertUint64(stringRep)
+ case integerFormatInt64:
+ fallthrough
+ default:
+ _, errVal = conv.ConvertInt64(stringRep)
+ }
+ case numberType:
+ fallthrough
+ default:
+ switch format {
+ case numberFormatFloat, numberFormatFloat32:
+ _, errVal = conv.ConvertFloat32(stringRep)
+ case numberFormatDouble, numberFormatFloat64:
+ fallthrough
+ default:
+ // No check can be performed here since
+ // no number beyond float64 is supported
+ }
+ }
+ if errVal != nil { // We don't report the actual errVal from strconv
+ if format != "" {
+ errVal = fmt.Errorf("%s value must be of type %s with format %s in %s: %w", prefix, typeName, format, path, ErrValue)
+ } else {
+ errVal = fmt.Errorf("%s value must be of type %s (default format) in %s: %w", prefix, typeName, path, ErrValue)
+ }
+ }
+ return errVal
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
new file mode 100644
index 000000000000..faef0c91e7e6
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
@@ -0,0 +1,21 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.go]
+indent_style = tab
+
+[{Makefile,*.mk}]
+indent_style = tab
+
+[*.nix]
+indent_size = 2
+
+[.golangci.yaml]
+indent_size = 2
diff --git a/vendor/github.com/go-viper/mapstructure/v2/.envrc b/vendor/github.com/go-viper/mapstructure/v2/.envrc
new file mode 100644
index 000000000000..2e0f9f5f7119
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/.envrc
@@ -0,0 +1,4 @@
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+ source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
+fi
+use flake . --impure
diff --git a/vendor/github.com/go-viper/mapstructure/v2/.gitignore b/vendor/github.com/go-viper/mapstructure/v2/.gitignore
new file mode 100644
index 000000000000..470e7ca2bd2b
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/.gitignore
@@ -0,0 +1,6 @@
+/.devenv/
+/.direnv/
+/.pre-commit-config.yaml
+/bin/
+/build/
+/var/
diff --git a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
new file mode 100644
index 000000000000..bda962566837
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
@@ -0,0 +1,48 @@
+version: "2"
+
+run:
+ timeout: 10m
+
+linters:
+ enable:
+ - govet
+ - ineffassign
+ # - misspell
+ - nolintlint
+ # - revive
+
+ disable:
+ - errcheck
+ - staticcheck
+ - unused
+
+ settings:
+ misspell:
+ locale: US
+ nolintlint:
+ allow-unused: false # report any unused nolint directives
+ require-specific: false # don't require nolint directives to be specific about which linter is being skipped
+
+formatters:
+ enable:
+ - gci
+ - gofmt
+ - gofumpt
+ - goimports
+ # - golines
+
+ settings:
+ gci:
+ sections:
+ - standard
+ - default
+ - localmodule
+ gofmt:
+ simplify: true
+ rewrite-rules:
+ - pattern: interface{}
+ replacement: any
+
+ exclusions:
+ paths:
+ - internal/
diff --git a/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md b/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md
new file mode 100644
index 000000000000..afd44e5f5fc3
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md
@@ -0,0 +1,104 @@
+> [!WARNING]
+> As of v2 of this library, change log can be found in GitHub releases.
+
+## 1.5.1
+
+* Wrap errors so they're compatible with `errors.Is` and `errors.As` [GH-282]
+* Fix map of slices not decoding properly in certain cases. [GH-266]
+
+## 1.5.0
+
+* New option `IgnoreUntaggedFields` to ignore decoding to any fields
+ without `mapstructure` (or the configured tag name) set [GH-277]
+* New option `ErrorUnset` which makes it an error if any fields
+ in a target struct are not set by the decoding process. [GH-225]
+* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240]
+* Decoding to slice from array no longer crashes [GH-265]
+* Decode nested struct pointers to map [GH-271]
+* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280]
+* Fix issue where fields with `,omitempty` would sometimes decode
+ into a map with an empty string key [GH-281]
+
+## 1.4.3
+
+* Fix cases where `json.Number` didn't decode properly [GH-261]
+
+## 1.4.2
+
+* Custom name matchers to support any sort of casing, formatting, etc. for
+ field names. [GH-250]
+* Fix possible panic in ComposeDecodeHookFunc [GH-251]
+
+## 1.4.1
+
+* Fix regression where `*time.Time` value would be set to empty and not be sent
+ to decode hooks properly [GH-232]
+
+## 1.4.0
+
+* A new decode hook type `DecodeHookFuncValue` has been added that has
+ access to the full values. [GH-183]
+* Squash is now supported with embedded fields that are struct pointers [GH-205]
+* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206]
+
+## 1.3.3
+
+* Decoding maps from maps creates a settable value for decode hooks [GH-203]
+
+## 1.3.2
+
+* Decode into interface type with a struct value is supported [GH-187]
+
+## 1.3.1
+
+* Squash should only squash embedded structs. [GH-194]
+
+## 1.3.0
+
+* Added `",omitempty"` support. This will ignore zero values in the source
+ structure when encoding. [GH-145]
+
+## 1.2.3
+
+* Fix duplicate entries in Keys list with pointer values. [GH-185]
+
+## 1.2.2
+
+* Do not add unsettable (unexported) values to the unused metadata key
+ or "remain" value. [GH-150]
+
+## 1.2.1
+
+* Go modules checksum mismatch fix
+
+## 1.2.0
+
+* Added support to capture unused values in a field using the `",remain"` value
+ in the mapstructure tag. There is an example to showcase usage.
+* Added `DecoderConfig` option to always squash embedded structs
+* `json.Number` can decode into `uint` types
+* Empty slices are preserved and not replaced with nil slices
+* Fix panic that can occur in when decoding a map into a nil slice of structs
+* Improved package documentation for godoc
+
+## 1.1.2
+
+* Fix error when decode hook decodes interface implementation into interface
+ type. [GH-140]
+
+## 1.1.1
+
+* Fix panic that can happen in `decodePtr`
+
+## 1.1.0
+
+* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133]
+* Support struct to struct decoding [GH-137]
+* If source map value is nil, then destination map value is nil (instead of empty)
+* If source slice value is nil, then destination slice value is nil (instead of empty)
+* If source pointer is nil, then destination pointer is set to nil (instead of
+ allocated zero value of type)
+
+## 1.0.0
+
+* Initial tagged stable release.
diff --git a/vendor/github.com/go-viper/mapstructure/v2/LICENSE b/vendor/github.com/go-viper/mapstructure/v2/LICENSE
new file mode 100644
index 000000000000..f9c841a51e0d
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Mitchell Hashimoto
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/go-viper/mapstructure/v2/README.md b/vendor/github.com/go-viper/mapstructure/v2/README.md
new file mode 100644
index 000000000000..45db719755af
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/README.md
@@ -0,0 +1,81 @@
+# mapstructure
+
+[](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml)
+[](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
+
+[](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2)
+
+mapstructure is a Go library for decoding generic map values to structures
+and vice versa, while providing helpful error handling.
+
+This library is most useful when decoding values from some data stream (JSON,
+Gob, etc.) where you don't _quite_ know the structure of the underlying data
+until you read a part of it. You can therefore read a `map[string]interface{}`
+and use this library to decode it into the proper underlying native Go
+structure.
+
+## Installation
+
+```shell
+go get github.com/go-viper/mapstructure/v2
+```
+
+## Migrating from `github.com/mitchellh/mapstructure`
+
+[@mitchehllh](https://github.com/mitchellh) announced his intent to archive some of his unmaintained projects (see [here](https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc) and [here](https://github.com/mitchellh/mapstructure/issues/349)). This is a repository achieved the "blessed fork" status.
+
+You can migrate to this package by changing your import paths in your Go files to `github.com/go-viper/mapstructure/v2`.
+The API is the same, so you don't need to change anything else.
+
+Here is a script that can help you with the migration:
+
+```shell
+sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go')
+```
+
+If you need more time to migrate your code, that is absolutely fine.
+
+Some of the latest fixes are backported to the v1 release branch of this package, so you can use the Go modules `replace` feature until you are ready to migrate:
+
+```shell
+replace github.com/mitchellh/mapstructure => github.com/go-viper/mapstructure v1.6.0
+```
+
+## Usage & Example
+
+For usage and examples see the [documentation](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2).
+
+The `Decode` function has examples associated with it there.
+
+## But Why?!
+
+Go offers fantastic standard libraries for decoding formats such as JSON.
+The standard method is to have a struct pre-created, and populate that struct
+from the bytes of the encoded format. This is great, but the problem is if
+you have configuration or an encoding that changes slightly depending on
+specific fields. For example, consider this JSON:
+
+```json
+{
+ "type": "person",
+ "name": "Mitchell"
+}
+```
+
+Perhaps we can't populate a specific structure without first reading
+the "type" field from the JSON. We could always do two passes over the
+decoding of the JSON (reading the "type" first, and the rest later).
+However, it is much simpler to just decode this into a `map[string]interface{}`
+structure, read the "type" key, then use something like this library
+to decode it into the proper structure.
+
+## Credits
+
+Mapstructure was originally created by [@mitchellh](https://github.com/mitchellh).
+This is a maintained fork of the original library.
+
+Read more about the reasons for the fork [here](https://github.com/mitchellh/mapstructure/issues/349).
+
+## License
+
+The project is licensed under the [MIT License](LICENSE).
diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
new file mode 100644
index 000000000000..a852a0a04c82
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
@@ -0,0 +1,714 @@
+package mapstructure
+
+import (
+ "encoding"
+ "errors"
+ "fmt"
+ "net"
+ "net/netip"
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns
+// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
+func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
+ // Create variables here so we can reference them with the reflect pkg
+ var f1 DecodeHookFuncType
+ var f2 DecodeHookFuncKind
+ var f3 DecodeHookFuncValue
+
+ // Fill in the variables into this interface and the rest is done
+ // automatically using the reflect package.
+ potential := []any{f1, f2, f3}
+
+ v := reflect.ValueOf(h)
+ vt := v.Type()
+ for _, raw := range potential {
+ pt := reflect.ValueOf(raw).Type()
+ if vt.ConvertibleTo(pt) {
+ return v.Convert(pt).Interface()
+ }
+ }
+
+ return nil
+}
+
+// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns
+// it into a closure to be used directly
+// if the type fails to convert we return a closure always erroring to keep the previous behaviour
+func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) {
+ switch f := typedDecodeHook(raw).(type) {
+ case DecodeHookFuncType:
+ return func(from reflect.Value, to reflect.Value) (any, error) {
+ return f(from.Type(), to.Type(), from.Interface())
+ }
+ case DecodeHookFuncKind:
+ return func(from reflect.Value, to reflect.Value) (any, error) {
+ return f(from.Kind(), to.Kind(), from.Interface())
+ }
+ case DecodeHookFuncValue:
+ return func(from reflect.Value, to reflect.Value) (any, error) {
+ return f(from, to)
+ }
+ default:
+ return func(from reflect.Value, to reflect.Value) (any, error) {
+ return nil, errors.New("invalid decode hook signature")
+ }
+ }
+}
+
+// DecodeHookExec executes the given decode hook. This should be used
+// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
+// that took reflect.Kind instead of reflect.Type.
+func DecodeHookExec(
+ raw DecodeHookFunc,
+ from reflect.Value, to reflect.Value,
+) (any, error) {
+ switch f := typedDecodeHook(raw).(type) {
+ case DecodeHookFuncType:
+ return f(from.Type(), to.Type(), from.Interface())
+ case DecodeHookFuncKind:
+ return f(from.Kind(), to.Kind(), from.Interface())
+ case DecodeHookFuncValue:
+ return f(from, to)
+ default:
+ return nil, errors.New("invalid decode hook signature")
+ }
+}
+
+// ComposeDecodeHookFunc creates a single DecodeHookFunc that
+// automatically composes multiple DecodeHookFuncs.
+//
+// The composed funcs are called in order, with the result of the
+// previous transformation.
+func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
+ cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs))
+ for _, f := range fs {
+ cached = append(cached, cachedDecodeHook(f))
+ }
+ return func(f reflect.Value, t reflect.Value) (any, error) {
+ var err error
+ data := f.Interface()
+
+ newFrom := f
+ for _, c := range cached {
+ data, err = c(newFrom, t)
+ if err != nil {
+ return nil, err
+ }
+ if v, ok := data.(reflect.Value); ok {
+ newFrom = v
+ } else {
+ newFrom = reflect.ValueOf(data)
+ }
+ }
+
+ return data, nil
+ }
+}
+
+// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
+// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
+func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
+ cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff))
+ for _, f := range ff {
+ cached = append(cached, cachedDecodeHook(f))
+ }
+ return func(a, b reflect.Value) (any, error) {
+ var allErrs string
+ var out any
+ var err error
+
+ for _, c := range cached {
+ out, err = c(a, b)
+ if err != nil {
+ allErrs += err.Error() + "\n"
+ continue
+ }
+
+ return out, nil
+ }
+
+ return nil, errors.New(allErrs)
+ }
+}
+
+// StringToSliceHookFunc returns a DecodeHookFunc that converts
+// string to []string by splitting on the given sep.
+func StringToSliceHookFunc(sep string) DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.SliceOf(f) {
+ return data, nil
+ }
+
+ raw := data.(string)
+ if raw == "" {
+ return []string{}, nil
+ }
+
+ return strings.Split(raw, sep), nil
+ }
+}
+
+// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc].
+//
+// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice.
+// This function removes that check.
+func StringToWeakSliceHookFunc(sep string) DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+ return data, nil
+ }
+
+ raw := data.(string)
+ if raw == "" {
+ return []string{}, nil
+ }
+
+ return strings.Split(raw, sep), nil
+ }
+}
+
+// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
+// strings to time.Duration.
+func StringToTimeDurationHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(time.Duration(5)) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ d, err := time.ParseDuration(data.(string))
+
+ return d, wrapTimeParseDurationError(err)
+ }
+}
+
+// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts
+// strings to *time.Location.
+func StringToTimeLocationHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(time.Local) {
+ return data, nil
+ }
+ d, err := time.LoadLocation(data.(string))
+
+ return d, wrapTimeParseLocationError(err)
+ }
+}
+
+// StringToURLHookFunc returns a DecodeHookFunc that converts
+// strings to *url.URL.
+func StringToURLHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(&url.URL{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ u, err := url.Parse(data.(string))
+
+ return u, wrapUrlError(err)
+ }
+}
+
+// StringToIPHookFunc returns a DecodeHookFunc that converts
+// strings to net.IP
+func StringToIPHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(net.IP{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ ip := net.ParseIP(data.(string))
+ if ip == nil {
+ return net.IP{}, fmt.Errorf("failed parsing ip")
+ }
+
+ return ip, nil
+ }
+}
+
+// StringToIPNetHookFunc returns a DecodeHookFunc that converts
+// strings to net.IPNet
+func StringToIPNetHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(net.IPNet{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ _, net, err := net.ParseCIDR(data.(string))
+ return net, wrapNetParseError(err)
+ }
+}
+
+// StringToTimeHookFunc returns a DecodeHookFunc that converts
+// strings to time.Time.
+func StringToTimeHookFunc(layout string) DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(time.Time{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ ti, err := time.Parse(layout, data.(string))
+
+ return ti, wrapTimeParseError(err)
+ }
+}
+
+// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
+// the decoder.
+//
+// Note that this is significantly different from the WeaklyTypedInput option
+// of the DecoderConfig.
+func WeaklyTypedHook(
+ f reflect.Kind,
+ t reflect.Kind,
+ data any,
+) (any, error) {
+ dataVal := reflect.ValueOf(data)
+ switch t {
+ case reflect.String:
+ switch f {
+ case reflect.Bool:
+ if dataVal.Bool() {
+ return "1", nil
+ }
+ return "0", nil
+ case reflect.Float32:
+ return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
+ case reflect.Int:
+ return strconv.FormatInt(dataVal.Int(), 10), nil
+ case reflect.Slice:
+ dataType := dataVal.Type()
+ elemKind := dataType.Elem().Kind()
+ if elemKind == reflect.Uint8 {
+ return string(dataVal.Interface().([]uint8)), nil
+ }
+ case reflect.Uint:
+ return strconv.FormatUint(dataVal.Uint(), 10), nil
+ }
+ }
+
+ return data, nil
+}
+
+func RecursiveStructToMapHookFunc() DecodeHookFunc {
+ return func(f reflect.Value, t reflect.Value) (any, error) {
+ if f.Kind() != reflect.Struct {
+ return f.Interface(), nil
+ }
+
+ var i any = struct{}{}
+ if t.Type() != reflect.TypeOf(&i).Elem() {
+ return f.Interface(), nil
+ }
+
+ m := make(map[string]any)
+ t.Set(reflect.ValueOf(m))
+
+ return f.Interface(), nil
+ }
+}
+
+// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies
+// strings to the UnmarshalText function, when the target type
+// implements the encoding.TextUnmarshaler interface
+func TextUnmarshallerHookFunc() DecodeHookFuncType {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ result := reflect.New(t).Interface()
+ unmarshaller, ok := result.(encoding.TextUnmarshaler)
+ if !ok {
+ return data, nil
+ }
+ str, ok := data.(string)
+ if !ok {
+ str = reflect.Indirect(reflect.ValueOf(&data)).Elem().String()
+ }
+ if err := unmarshaller.UnmarshalText([]byte(str)); err != nil {
+ return nil, err
+ }
+ return result, nil
+ }
+}
+
+// StringToNetIPAddrHookFunc returns a DecodeHookFunc that converts
+// strings to netip.Addr.
+func StringToNetIPAddrHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(netip.Addr{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ addr, err := netip.ParseAddr(data.(string))
+
+ return addr, wrapNetIPParseAddrError(err)
+ }
+}
+
+// StringToNetIPAddrPortHookFunc returns a DecodeHookFunc that converts
+// strings to netip.AddrPort.
+func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(netip.AddrPort{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ addrPort, err := netip.ParseAddrPort(data.(string))
+
+ return addrPort, wrapNetIPParseAddrPortError(err)
+ }
+}
+
+// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts
+// strings to netip.Prefix.
+func StringToNetIPPrefixHookFunc() DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data any,
+ ) (any, error) {
+ if f.Kind() != reflect.String {
+ return data, nil
+ }
+ if t != reflect.TypeOf(netip.Prefix{}) {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ prefix, err := netip.ParsePrefix(data.(string))
+
+ return prefix, wrapNetIPParsePrefixError(err)
+ }
+}
+
+// StringToBasicTypeHookFunc returns a DecodeHookFunc that converts
+// strings to basic types.
+// int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint, float32, float64, bool, byte, rune, complex64, complex128
+func StringToBasicTypeHookFunc() DecodeHookFunc {
+ return ComposeDecodeHookFunc(
+ StringToInt8HookFunc(),
+ StringToUint8HookFunc(),
+ StringToInt16HookFunc(),
+ StringToUint16HookFunc(),
+ StringToInt32HookFunc(),
+ StringToUint32HookFunc(),
+ StringToInt64HookFunc(),
+ StringToUint64HookFunc(),
+ StringToIntHookFunc(),
+ StringToUintHookFunc(),
+ StringToFloat32HookFunc(),
+ StringToFloat64HookFunc(),
+ StringToBoolHookFunc(),
+ // byte and rune are aliases for uint8 and int32 respectively
+ // StringToByteHookFunc(),
+ // StringToRuneHookFunc(),
+ StringToComplex64HookFunc(),
+ StringToComplex128HookFunc(),
+ )
+}
+
+// StringToInt8HookFunc returns a DecodeHookFunc that converts
+// strings to int8.
+func StringToInt8HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ i64, err := strconv.ParseInt(data.(string), 0, 8)
+ return int8(i64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToUint8HookFunc returns a DecodeHookFunc that converts
+// strings to uint8.
+func StringToUint8HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ u64, err := strconv.ParseUint(data.(string), 0, 8)
+ return uint8(u64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToInt16HookFunc returns a DecodeHookFunc that converts
+// strings to int16.
+func StringToInt16HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ i64, err := strconv.ParseInt(data.(string), 0, 16)
+ return int16(i64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToUint16HookFunc returns a DecodeHookFunc that converts
+// strings to uint16.
+func StringToUint16HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ u64, err := strconv.ParseUint(data.(string), 0, 16)
+ return uint16(u64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToInt32HookFunc returns a DecodeHookFunc that converts
+// strings to int32.
+func StringToInt32HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ i64, err := strconv.ParseInt(data.(string), 0, 32)
+ return int32(i64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToUint32HookFunc returns a DecodeHookFunc that converts
+// strings to uint32.
+func StringToUint32HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ u64, err := strconv.ParseUint(data.(string), 0, 32)
+ return uint32(u64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToInt64HookFunc returns a DecodeHookFunc that converts
+// strings to int64.
+func StringToInt64HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ i64, err := strconv.ParseInt(data.(string), 0, 64)
+ return int64(i64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToUint64HookFunc returns a DecodeHookFunc that converts
+// strings to uint64.
+func StringToUint64HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ u64, err := strconv.ParseUint(data.(string), 0, 64)
+ return uint64(u64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToIntHookFunc returns a DecodeHookFunc that converts
+// strings to int.
+func StringToIntHookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Int {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ i64, err := strconv.ParseInt(data.(string), 0, 0)
+ return int(i64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToUintHookFunc returns a DecodeHookFunc that converts
+// strings to uint.
+func StringToUintHookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ u64, err := strconv.ParseUint(data.(string), 0, 0)
+ return uint(u64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToFloat32HookFunc returns a DecodeHookFunc that converts
+// strings to float32.
+func StringToFloat32HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ f64, err := strconv.ParseFloat(data.(string), 32)
+ return float32(f64), wrapStrconvNumError(err)
+ }
+}
+
+// StringToFloat64HookFunc returns a DecodeHookFunc that converts
+// strings to float64.
+func StringToFloat64HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ f64, err := strconv.ParseFloat(data.(string), 64)
+ return f64, wrapStrconvNumError(err)
+ }
+}
+
+// StringToBoolHookFunc returns a DecodeHookFunc that converts
+// strings to bool.
+func StringToBoolHookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ b, err := strconv.ParseBool(data.(string))
+ return b, wrapStrconvNumError(err)
+ }
+}
+
+// StringToByteHookFunc returns a DecodeHookFunc that converts
+// strings to byte.
+func StringToByteHookFunc() DecodeHookFunc {
+ return StringToUint8HookFunc()
+}
+
+// StringToRuneHookFunc returns a DecodeHookFunc that converts
+// strings to rune.
+func StringToRuneHookFunc() DecodeHookFunc {
+ return StringToInt32HookFunc()
+}
+
+// StringToComplex64HookFunc returns a DecodeHookFunc that converts
+// strings to complex64.
+func StringToComplex64HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ c128, err := strconv.ParseComplex(data.(string), 64)
+ return complex64(c128), wrapStrconvNumError(err)
+ }
+}
+
+// StringToComplex128HookFunc returns a DecodeHookFunc that converts
+// strings to complex128.
+func StringToComplex128HookFunc() DecodeHookFunc {
+ return func(f reflect.Type, t reflect.Type, data any) (any, error) {
+ if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
+ return data, nil
+ }
+
+ // Convert it by parsing
+ c128, err := strconv.ParseComplex(data.(string), 128)
+ return c128, wrapStrconvNumError(err)
+ }
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/errors.go b/vendor/github.com/go-viper/mapstructure/v2/errors.go
new file mode 100644
index 000000000000..07d31c22aad2
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/errors.go
@@ -0,0 +1,244 @@
+package mapstructure
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Error interface is implemented by all errors emitted by mapstructure.
+//
+// Use [errors.As] to check if an error implements this interface.
+type Error interface {
+ error
+
+ mapstructure()
+}
+
+// DecodeError is a generic error type that holds information about
+// a decoding error together with the name of the field that caused the error.
+type DecodeError struct {
+ name string
+ err error
+}
+
+func newDecodeError(name string, err error) *DecodeError {
+ return &DecodeError{
+ name: name,
+ err: err,
+ }
+}
+
+func (e *DecodeError) Name() string {
+ return e.name
+}
+
+func (e *DecodeError) Unwrap() error {
+ return e.err
+}
+
+func (e *DecodeError) Error() string {
+ return fmt.Sprintf("'%s' %s", e.name, e.err)
+}
+
+func (*DecodeError) mapstructure() {}
+
+// ParseError is an error type that indicates a value could not be parsed
+// into the expected type.
+type ParseError struct {
+ Expected reflect.Value
+ Value any
+ Err error
+}
+
+func (e *ParseError) Error() string {
+ return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err)
+}
+
+func (*ParseError) mapstructure() {}
+
+// UnconvertibleTypeError is an error type that indicates a value could not be
+// converted to the expected type.
+type UnconvertibleTypeError struct {
+ Expected reflect.Value
+ Value any
+}
+
+func (e *UnconvertibleTypeError) Error() string {
+ return fmt.Sprintf(
+ "expected type '%s', got unconvertible type '%s'",
+ e.Expected.Type(),
+ reflect.TypeOf(e.Value),
+ )
+}
+
+func (*UnconvertibleTypeError) mapstructure() {}
+
+func wrapStrconvNumError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ if err, ok := err.(*strconv.NumError); ok {
+ return &strconvNumError{Err: err}
+ }
+
+ return err
+}
+
+type strconvNumError struct {
+ Err *strconv.NumError
+}
+
+func (e *strconvNumError) Error() string {
+ return "strconv." + e.Err.Func + ": " + e.Err.Err.Error()
+}
+
+func (e *strconvNumError) Unwrap() error { return e.Err }
+
+func wrapUrlError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ if err, ok := err.(*url.Error); ok {
+ return &urlError{Err: err}
+ }
+
+ return err
+}
+
+type urlError struct {
+ Err *url.Error
+}
+
+func (e *urlError) Error() string {
+ return fmt.Sprintf("%s", e.Err.Err)
+}
+
+func (e *urlError) Unwrap() error { return e.Err }
+
+func wrapNetParseError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ if err, ok := err.(*net.ParseError); ok {
+ return &netParseError{Err: err}
+ }
+
+ return err
+}
+
+type netParseError struct {
+ Err *net.ParseError
+}
+
+func (e *netParseError) Error() string {
+ return "invalid " + e.Err.Type
+}
+
+func (e *netParseError) Unwrap() error { return e.Err }
+
+func wrapTimeParseError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ if err, ok := err.(*time.ParseError); ok {
+ return &timeParseError{Err: err}
+ }
+
+ return err
+}
+
+type timeParseError struct {
+ Err *time.ParseError
+}
+
+func (e *timeParseError) Error() string {
+ if e.Err.Message == "" {
+ return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem)
+ }
+
+ return "parsing time " + e.Err.Message
+}
+
+func (e *timeParseError) Unwrap() error { return e.Err }
+
+func wrapNetIPParseAddrError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") {
+ errPieces := strings.Split(errMsg, ": ")
+
+ return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1])
+ }
+
+ return err
+}
+
+func wrapNetIPParseAddrPortError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ errMsg := err.Error()
+ if strings.HasPrefix(errMsg, "invalid port ") {
+ return errors.New("invalid port")
+ } else if strings.HasPrefix(errMsg, "invalid ip:port ") {
+ return errors.New("invalid ip:port")
+ }
+
+ return err
+}
+
+func wrapNetIPParsePrefixError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") {
+ errPieces := strings.Split(errMsg, ": ")
+
+ return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1])
+ }
+
+ return err
+}
+
+func wrapTimeParseDurationError(err error) error {
+ if err == nil {
+ return nil
+ }
+
+ errMsg := err.Error()
+ if strings.HasPrefix(errMsg, "time: unknown unit ") {
+ return errors.New("time: unknown unit")
+ } else if strings.HasPrefix(errMsg, "time: ") {
+ idx := strings.LastIndex(errMsg, " ")
+
+ return errors.New(errMsg[:idx])
+ }
+
+ return err
+}
+
+func wrapTimeParseLocationError(err error) error {
+ if err == nil {
+ return nil
+ }
+ errMsg := err.Error()
+ if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") {
+ return fmt.Errorf("invalid time zone format: %w", err)
+ }
+
+ return err
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/vendor/github.com/go-viper/mapstructure/v2/flake.lock
new file mode 100644
index 000000000000..5e67bdd6b42e
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/flake.lock
@@ -0,0 +1,294 @@
+{
+ "nodes": {
+ "cachix": {
+ "inputs": {
+ "devenv": [
+ "devenv"
+ ],
+ "flake-compat": [
+ "devenv"
+ ],
+ "git-hooks": [
+ "devenv"
+ ],
+ "nixpkgs": "nixpkgs"
+ },
+ "locked": {
+ "lastModified": 1742042642,
+ "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
+ "owner": "cachix",
+ "repo": "cachix",
+ "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "ref": "latest",
+ "repo": "cachix",
+ "type": "github"
+ }
+ },
+ "devenv": {
+ "inputs": {
+ "cachix": "cachix",
+ "flake-compat": "flake-compat",
+ "git-hooks": "git-hooks",
+ "nix": "nix",
+ "nixpkgs": "nixpkgs_3"
+ },
+ "locked": {
+ "lastModified": 1744876578,
+ "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=",
+ "owner": "cachix",
+ "repo": "devenv",
+ "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "repo": "devenv",
+ "type": "github"
+ }
+ },
+ "flake-compat": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1733328505,
+ "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
+ "type": "github"
+ },
+ "original": {
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "type": "github"
+ }
+ },
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "devenv",
+ "nix",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1712014858,
+ "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "flake-parts_2": {
+ "inputs": {
+ "nixpkgs-lib": "nixpkgs-lib"
+ },
+ "locked": {
+ "lastModified": 1743550720,
+ "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "c621e8422220273271f52058f618c94e405bb0f5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "git-hooks": {
+ "inputs": {
+ "flake-compat": [
+ "devenv"
+ ],
+ "gitignore": "gitignore",
+ "nixpkgs": [
+ "devenv",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1742649964,
+ "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
+ "owner": "cachix",
+ "repo": "git-hooks.nix",
+ "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "repo": "git-hooks.nix",
+ "type": "github"
+ }
+ },
+ "gitignore": {
+ "inputs": {
+ "nixpkgs": [
+ "devenv",
+ "git-hooks",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1709087332,
+ "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "type": "github"
+ }
+ },
+ "libgit2": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1697646580,
+ "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
+ "owner": "libgit2",
+ "repo": "libgit2",
+ "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "libgit2",
+ "repo": "libgit2",
+ "type": "github"
+ }
+ },
+ "nix": {
+ "inputs": {
+ "flake-compat": [
+ "devenv"
+ ],
+ "flake-parts": "flake-parts",
+ "libgit2": "libgit2",
+ "nixpkgs": "nixpkgs_2",
+ "nixpkgs-23-11": [
+ "devenv"
+ ],
+ "nixpkgs-regression": [
+ "devenv"
+ ],
+ "pre-commit-hooks": [
+ "devenv"
+ ]
+ },
+ "locked": {
+ "lastModified": 1741798497,
+ "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
+ "owner": "domenkozar",
+ "repo": "nix",
+ "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
+ "type": "github"
+ },
+ "original": {
+ "owner": "domenkozar",
+ "ref": "devenv-2.24",
+ "repo": "nix",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1733212471,
+ "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs-lib": {
+ "locked": {
+ "lastModified": 1743296961,
+ "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "type": "github"
+ }
+ },
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1717432640,
+ "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "release-24.05",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_3": {
+ "locked": {
+ "lastModified": 1733477122,
+ "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
+ "owner": "cachix",
+ "repo": "devenv-nixpkgs",
+ "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "ref": "rolling",
+ "repo": "devenv-nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_4": {
+ "locked": {
+ "lastModified": 1744536153,
+ "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "devenv": "devenv",
+ "flake-parts": "flake-parts_2",
+ "nixpkgs": "nixpkgs_4"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/vendor/github.com/go-viper/mapstructure/v2/flake.nix
new file mode 100644
index 000000000000..3b116f426d46
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/flake.nix
@@ -0,0 +1,46 @@
+{
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ flake-parts.url = "github:hercules-ci/flake-parts";
+ devenv.url = "github:cachix/devenv";
+ };
+
+ outputs =
+ inputs@{ flake-parts, ... }:
+ flake-parts.lib.mkFlake { inherit inputs; } {
+ imports = [
+ inputs.devenv.flakeModule
+ ];
+
+ systems = [
+ "x86_64-linux"
+ "x86_64-darwin"
+ "aarch64-darwin"
+ ];
+
+ perSystem =
+ { pkgs, ... }:
+ rec {
+ devenv.shells = {
+ default = {
+ languages = {
+ go.enable = true;
+ };
+
+ pre-commit.hooks = {
+ nixpkgs-fmt.enable = true;
+ };
+
+ packages = with pkgs; [
+ golangci-lint
+ ];
+
+ # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
+ containers = pkgs.lib.mkForce { };
+ };
+
+ ci = devenv.shells.default;
+ };
+ };
+ };
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go
new file mode 100644
index 000000000000..d1c15e474f44
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go
@@ -0,0 +1,11 @@
+package errors
+
+import "errors"
+
+func New(text string) error {
+ return errors.New(text)
+}
+
+func As(err error, target interface{}) bool {
+ return errors.As(err, target)
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go
new file mode 100644
index 000000000000..d74e3a0b5a43
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go
@@ -0,0 +1,9 @@
+//go:build go1.20
+
+package errors
+
+import "errors"
+
+func Join(errs ...error) error {
+ return errors.Join(errs...)
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go
new file mode 100644
index 000000000000..700b40229cbe
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go
@@ -0,0 +1,61 @@
+//go:build !go1.20
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package errors
+
+// Join returns an error that wraps the given errors.
+// Any nil error values are discarded.
+// Join returns nil if every value in errs is nil.
+// The error formats as the concatenation of the strings obtained
+// by calling the Error method of each element of errs, with a newline
+// between each string.
+//
+// A non-nil error returned by Join implements the Unwrap() []error method.
+func Join(errs ...error) error {
+ n := 0
+ for _, err := range errs {
+ if err != nil {
+ n++
+ }
+ }
+ if n == 0 {
+ return nil
+ }
+ e := &joinError{
+ errs: make([]error, 0, n),
+ }
+ for _, err := range errs {
+ if err != nil {
+ e.errs = append(e.errs, err)
+ }
+ }
+ return e
+}
+
+type joinError struct {
+ errs []error
+}
+
+func (e *joinError) Error() string {
+ // Since Join returns nil if every value in errs is nil,
+ // e.errs cannot be empty.
+ if len(e.errs) == 1 {
+ return e.errs[0].Error()
+ }
+
+ b := []byte(e.errs[0].Error())
+ for _, err := range e.errs[1:] {
+ b = append(b, '\n')
+ b = append(b, err.Error()...)
+ }
+ // At this point, b has at least one byte '\n'.
+ // return unsafe.String(&b[0], len(b))
+ return string(b)
+}
+
+func (e *joinError) Unwrap() []error {
+ return e.errs
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
new file mode 100644
index 000000000000..7c35bce02026
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
@@ -0,0 +1,1712 @@
+// Package mapstructure exposes functionality to convert one arbitrary
+// Go type into another, typically to convert a map[string]any
+// into a native Go structure.
+//
+// The Go structure can be arbitrarily complex, containing slices,
+// other structs, etc. and the decoder will properly decode nested
+// maps and so on into the proper structures in the native Go struct.
+// See the examples to see what the decoder is capable of.
+//
+// The simplest function to start with is Decode.
+//
+// # Field Tags
+//
+// When decoding to a struct, mapstructure will use the field name by
+// default to perform the mapping. For example, if a struct has a field
+// "Username" then mapstructure will look for a key in the source value
+// of "username" (case insensitive).
+//
+// type User struct {
+// Username string
+// }
+//
+// You can change the behavior of mapstructure by using struct tags.
+// The default struct tag that mapstructure looks for is "mapstructure"
+// but you can customize it using DecoderConfig.
+//
+// # Renaming Fields
+//
+// To rename the key that mapstructure looks for, use the "mapstructure"
+// tag and set a value directly. For example, to change the "username" example
+// above to "user":
+//
+// type User struct {
+// Username string `mapstructure:"user"`
+// }
+//
+// # Embedded Structs and Squashing
+//
+// Embedded structs are treated as if they're another field with that name.
+// By default, the two structs below are equivalent when decoding with
+// mapstructure:
+//
+// type Person struct {
+// Name string
+// }
+//
+// type Friend struct {
+// Person
+// }
+//
+// type Friend struct {
+// Person Person
+// }
+//
+// This would require an input that looks like below:
+//
+// map[string]any{
+// "person": map[string]any{"name": "alice"},
+// }
+//
+// If your "person" value is NOT nested, then you can append ",squash" to
+// your tag value and mapstructure will treat it as if the embedded struct
+// were part of the struct directly. Example:
+//
+// type Friend struct {
+// Person `mapstructure:",squash"`
+// }
+//
+// Now the following input would be accepted:
+//
+// map[string]any{
+// "name": "alice",
+// }
+//
+// When decoding from a struct to a map, the squash tag squashes the struct
+// fields into a single map. Using the example structs from above:
+//
+// Friend{Person: Person{Name: "alice"}}
+//
+// Will be decoded into a map:
+//
+// map[string]any{
+// "name": "alice",
+// }
+//
+// DecoderConfig has a field that changes the behavior of mapstructure
+// to always squash embedded structs.
+//
+// # Remainder Values
+//
+// If there are any unmapped keys in the source value, mapstructure by
+// default will silently ignore them. You can error by setting ErrorUnused
+// in DecoderConfig. If you're using Metadata you can also maintain a slice
+// of the unused keys.
+//
+// You can also use the ",remain" suffix on your tag to collect all unused
+// values in a map. The field with this tag MUST be a map type and should
+// probably be a "map[string]any" or "map[any]any".
+// See example below:
+//
+// type Friend struct {
+// Name string
+// Other map[string]any `mapstructure:",remain"`
+// }
+//
+// Given the input below, Other would be populated with the other
+// values that weren't used (everything but "name"):
+//
+// map[string]any{
+// "name": "bob",
+// "address": "123 Maple St.",
+// }
+//
+// # Omit Empty Values
+//
+// When decoding from a struct to any other value, you may use the
+// ",omitempty" suffix on your tag to omit that value if it equates to
+// the zero value, or a zero-length element. The zero value of all types is
+// specified in the Go specification.
+//
+// For example, the zero type of a numeric type is zero ("0"). If the struct
+// field value is zero and a numeric type, the field is empty, and it won't
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil or empty, it won't be encoded into the destination type.
+//
+// type Source struct {
+// Age int `mapstructure:",omitempty"`
+// URLs []string `mapstructure:",omitempty"`
+// }
+//
+// # Omit Zero Values
+//
+// When decoding from a struct to any other value, you may use the
+// ",omitzero" suffix on your tag to omit that value if it equates to the zero
+// value. The zero value of all types is specified in the Go specification.
+//
+// For example, the zero type of a numeric type is zero ("0"). If the struct
+// field value is zero and a numeric type, the field is empty, and it won't
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil, it won't be encoded into the destination type.
+//
+// Note that if the field is a slice, and it is empty but not nil, it will
+// still be encoded into the destination type.
+//
+// type Source struct {
+// Age int `mapstructure:",omitzero"`
+// URLs []string `mapstructure:",omitzero"`
+// }
+//
+// # Unexported fields
+//
+// Since unexported (private) struct fields cannot be set outside the package
+// where they are defined, the decoder will simply skip them.
+//
+// For this output type definition:
+//
+// type Exported struct {
+// private string // this unexported field will be skipped
+// Public string
+// }
+//
+// Using this map as input:
+//
+// map[string]any{
+// "private": "I will be ignored",
+// "Public": "I made it through!",
+// }
+//
+// The following struct will be decoded:
+//
+// type Exported struct {
+// private: "" // field is left with an empty string (zero value)
+// Public: "I made it through!"
+// }
+//
+// # Other Configuration
+//
+// mapstructure is highly configurable. See the DecoderConfig struct
+// for other features and options that are supported.
+package mapstructure
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/go-viper/mapstructure/v2/internal/errors"
+)
+
+// DecodeHookFunc is the callback function that can be used for
+// data transformations. See "DecodeHook" in the DecoderConfig
+// struct.
+//
+// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or
+// DecodeHookFuncValue.
+// Values are a superset of Types (Values can return types), and Types are a
+// superset of Kinds (Types can return Kinds) and are generally a richer thing
+// to use, but Kinds are simpler if you only need those.
+//
+// The reason DecodeHookFunc is multi-typed is for backwards compatibility:
+// we started with Kinds and then realized Types were the better solution,
+// but have a promise to not break backwards compat so we now support
+// both.
+type DecodeHookFunc any
+
+// DecodeHookFuncType is a DecodeHookFunc which has complete information about
+// the source and target types.
+type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error)
+
+// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
+// source and target types.
+type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error)
+
+// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
+// values.
+type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error)
+
+// DecoderConfig is the configuration that is used to create a new decoder
+// and allows customization of various aspects of decoding.
+type DecoderConfig struct {
+ // DecodeHook, if set, will be called before any decoding and any
+ // type conversion (if WeaklyTypedInput is on). This lets you modify
+ // the values before they're set down onto the resulting struct. The
+ // DecodeHook is called for every map and value in the input. This means
+ // that if a struct has embedded fields with squash tags the decode hook
+ // is called only once with all of the input data, not once for each
+ // embedded struct.
+ //
+ // If an error is returned, the entire decode will fail with that error.
+ DecodeHook DecodeHookFunc
+
+ // If ErrorUnused is true, then it is an error for there to exist
+ // keys in the original map that were unused in the decoding process
+ // (extra keys).
+ ErrorUnused bool
+
+ // If ErrorUnset is true, then it is an error for there to exist
+ // fields in the result that were not set in the decoding process
+ // (extra fields). This only applies to decoding to a struct. This
+ // will affect all nested structs as well.
+ ErrorUnset bool
+
+ // AllowUnsetPointer, if set to true, will prevent fields with pointer types
+ // from being reported as unset, even if ErrorUnset is true and the field was
+ // not present in the input data. This allows pointer fields to be optional
+ // without triggering an error when they are missing.
+ AllowUnsetPointer bool
+
+ // ZeroFields, if set to true, will zero fields before writing them.
+ // For example, a map will be emptied before decoded values are put in
+ // it. If this is false, a map will be merged.
+ ZeroFields bool
+
+ // If WeaklyTypedInput is true, the decoder will make the following
+ // "weak" conversions:
+ //
+ // - bools to string (true = "1", false = "0")
+ // - numbers to string (base 10)
+ // - bools to int/uint (true = 1, false = 0)
+ // - strings to int/uint (base implied by prefix)
+ // - int to bool (true if value != 0)
+ // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
+ // FALSE, false, False. Anything else is an error)
+ // - empty array = empty map and vice versa
+ // - negative numbers to overflowed uint values (base 10)
+ // - slice of maps to a merged map
+ // - single values are converted to slices if required. Each
+ // element is weakly decoded. For example: "4" can become []int{4}
+ // if the target type is an int slice.
+ //
+ WeaklyTypedInput bool
+
+ // Squash will squash embedded structs. A squash tag may also be
+ // added to an individual struct field using a tag. For example:
+ //
+ // type Parent struct {
+ // Child `mapstructure:",squash"`
+ // }
+ Squash bool
+
+ // Metadata is the struct that will contain extra metadata about
+ // the decoding. If this is nil, then no metadata will be tracked.
+ Metadata *Metadata
+
+ // Result is a pointer to the struct that will contain the decoded
+ // value.
+ Result any
+
+ // The tag name that mapstructure reads for field names. This
+ // defaults to "mapstructure"
+ TagName string
+
+ // The option of the value in the tag that indicates a field should
+ // be squashed. This defaults to "squash".
+ SquashTagOption string
+
+ // IgnoreUntaggedFields ignores all struct fields without explicit
+ // TagName, comparable to `mapstructure:"-"` as default behaviour.
+ IgnoreUntaggedFields bool
+
+ // MatchName is the function used to match the map key to the struct
+ // field name or tag. Defaults to `strings.EqualFold`. This can be used
+ // to implement case-sensitive tag values, support snake casing, etc.
+ MatchName func(mapKey, fieldName string) bool
+
+ // DecodeNil, if set to true, will cause the DecodeHook (if present) to run
+ // even if the input is nil. This can be used to provide default values.
+ DecodeNil bool
+}
+
+// A Decoder takes a raw interface value and turns it into structured
+// data, keeping track of rich error information along the way in case
+// anything goes wrong. Unlike the basic top-level Decode method, you can
+// more finely control how the Decoder behaves using the DecoderConfig
+// structure. The top-level Decode method is just a convenience that sets
+// up the most basic Decoder.
+type Decoder struct {
+ config *DecoderConfig
+ cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error)
+}
+
+// Metadata contains information about decoding a structure that
+// is tedious or difficult to get otherwise.
+type Metadata struct {
+ // Keys are the keys of the structure which were successfully decoded
+ Keys []string
+
+ // Unused is a slice of keys that were found in the raw value but
+ // weren't decoded since there was no matching field in the result interface
+ Unused []string
+
+ // Unset is a slice of field names that were found in the result interface
+ // but weren't set in the decoding process since there was no matching value
+ // in the input
+ Unset []string
+}
+
+// Decode takes an input structure and uses reflection to translate it to
+// the output structure. output must be a pointer to a map or struct.
+func Decode(input any, output any) error {
+ config := &DecoderConfig{
+ Metadata: nil,
+ Result: output,
+ }
+
+ decoder, err := NewDecoder(config)
+ if err != nil {
+ return err
+ }
+
+ return decoder.Decode(input)
+}
+
+// WeakDecode is the same as Decode but is shorthand to enable
+// WeaklyTypedInput. See DecoderConfig for more info.
+func WeakDecode(input, output any) error {
+ config := &DecoderConfig{
+ Metadata: nil,
+ Result: output,
+ WeaklyTypedInput: true,
+ }
+
+ decoder, err := NewDecoder(config)
+ if err != nil {
+ return err
+ }
+
+ return decoder.Decode(input)
+}
+
+// DecodeMetadata is the same as Decode, but is shorthand to
+// enable metadata collection. See DecoderConfig for more info.
+func DecodeMetadata(input any, output any, metadata *Metadata) error {
+ config := &DecoderConfig{
+ Metadata: metadata,
+ Result: output,
+ }
+
+ decoder, err := NewDecoder(config)
+ if err != nil {
+ return err
+ }
+
+ return decoder.Decode(input)
+}
+
+// WeakDecodeMetadata is the same as Decode, but is shorthand to
+// enable both WeaklyTypedInput and metadata collection. See
+// DecoderConfig for more info.
+func WeakDecodeMetadata(input any, output any, metadata *Metadata) error {
+ config := &DecoderConfig{
+ Metadata: metadata,
+ Result: output,
+ WeaklyTypedInput: true,
+ }
+
+ decoder, err := NewDecoder(config)
+ if err != nil {
+ return err
+ }
+
+ return decoder.Decode(input)
+}
+
+// NewDecoder returns a new decoder for the given configuration. Once
+// a decoder has been returned, the same configuration must not be used
+// again.
+func NewDecoder(config *DecoderConfig) (*Decoder, error) {
+ val := reflect.ValueOf(config.Result)
+ if val.Kind() != reflect.Ptr {
+ return nil, errors.New("result must be a pointer")
+ }
+
+ val = val.Elem()
+ if !val.CanAddr() {
+ return nil, errors.New("result must be addressable (a pointer)")
+ }
+
+ if config.Metadata != nil {
+ if config.Metadata.Keys == nil {
+ config.Metadata.Keys = make([]string, 0)
+ }
+
+ if config.Metadata.Unused == nil {
+ config.Metadata.Unused = make([]string, 0)
+ }
+
+ if config.Metadata.Unset == nil {
+ config.Metadata.Unset = make([]string, 0)
+ }
+ }
+
+ if config.TagName == "" {
+ config.TagName = "mapstructure"
+ }
+
+ if config.SquashTagOption == "" {
+ config.SquashTagOption = "squash"
+ }
+
+ if config.MatchName == nil {
+ config.MatchName = strings.EqualFold
+ }
+
+ result := &Decoder{
+ config: config,
+ }
+ if config.DecodeHook != nil {
+ result.cachedDecodeHook = cachedDecodeHook(config.DecodeHook)
+ }
+
+ return result, nil
+}
+
+// Decode decodes the given raw interface to the target pointer specified
+// by the configuration.
+func (d *Decoder) Decode(input any) error {
+ err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
+
+ // Retain some of the original behavior when multiple errors ocurr
+ var joinedErr interface{ Unwrap() []error }
+ if errors.As(err, &joinedErr) {
+ return fmt.Errorf("decoding failed due to the following error(s):\n\n%w", err)
+ }
+
+ return err
+}
+
+// isNil returns true if the input is nil or a typed nil pointer.
+func isNil(input any) bool {
+ if input == nil {
+ return true
+ }
+ val := reflect.ValueOf(input)
+ return val.Kind() == reflect.Ptr && val.IsNil()
+}
+
+// Decodes an unknown data type into a specific reflection value.
+func (d *Decoder) decode(name string, input any, outVal reflect.Value) error {
+ var (
+ inputVal = reflect.ValueOf(input)
+ outputKind = getKind(outVal)
+ decodeNil = d.config.DecodeNil && d.cachedDecodeHook != nil
+ )
+ if isNil(input) {
+ // Typed nils won't match the "input == nil" below, so reset input.
+ input = nil
+ }
+ if input == nil {
+ // If the data is nil, then we don't set anything, unless ZeroFields is set
+ // to true.
+ if d.config.ZeroFields {
+ outVal.Set(reflect.Zero(outVal.Type()))
+
+ if d.config.Metadata != nil && name != "" {
+ d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
+ }
+ }
+ if !decodeNil {
+ return nil
+ }
+ }
+ if !inputVal.IsValid() {
+ if !decodeNil {
+ // If the input value is invalid, then we just set the value
+ // to be the zero value.
+ outVal.Set(reflect.Zero(outVal.Type()))
+ if d.config.Metadata != nil && name != "" {
+ d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
+ }
+ return nil
+ }
+ // Hooks need a valid inputVal, so reset it to zero value of outVal type.
+ switch outputKind {
+ case reflect.Struct, reflect.Map:
+ var mapVal map[string]any
+ inputVal = reflect.ValueOf(mapVal) // create nil map pointer
+ case reflect.Slice, reflect.Array:
+ var sliceVal []any
+ inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
+ default:
+ inputVal = reflect.Zero(outVal.Type())
+ }
+ }
+
+ if d.cachedDecodeHook != nil {
+ // We have a DecodeHook, so let's pre-process the input.
+ var err error
+ input, err = d.cachedDecodeHook(inputVal, outVal)
+ if err != nil {
+ return newDecodeError(name, err)
+ }
+ }
+ if isNil(input) {
+ return nil
+ }
+
+ var err error
+ addMetaKey := true
+ switch outputKind {
+ case reflect.Bool:
+ err = d.decodeBool(name, input, outVal)
+ case reflect.Interface:
+ err = d.decodeBasic(name, input, outVal)
+ case reflect.String:
+ err = d.decodeString(name, input, outVal)
+ case reflect.Int:
+ err = d.decodeInt(name, input, outVal)
+ case reflect.Uint:
+ err = d.decodeUint(name, input, outVal)
+ case reflect.Float32:
+ err = d.decodeFloat(name, input, outVal)
+ case reflect.Complex64:
+ err = d.decodeComplex(name, input, outVal)
+ case reflect.Struct:
+ err = d.decodeStruct(name, input, outVal)
+ case reflect.Map:
+ err = d.decodeMap(name, input, outVal)
+ case reflect.Ptr:
+ addMetaKey, err = d.decodePtr(name, input, outVal)
+ case reflect.Slice:
+ err = d.decodeSlice(name, input, outVal)
+ case reflect.Array:
+ err = d.decodeArray(name, input, outVal)
+ case reflect.Func:
+ err = d.decodeFunc(name, input, outVal)
+ default:
+ // If we reached this point then we weren't able to decode it
+ return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind))
+ }
+
+ // If we reached here, then we successfully decoded SOMETHING, so
+ // mark the key as used if we're tracking metainput.
+ if addMetaKey && d.config.Metadata != nil && name != "" {
+ d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
+ }
+
+ return err
+}
+
+// This decodes a basic type (bool, int, string, etc.) and sets the
+// value to "data" of that type.
+func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error {
+ if val.IsValid() && val.Elem().IsValid() {
+ elem := val.Elem()
+
+ // If we can't address this element, then its not writable. Instead,
+ // we make a copy of the value (which is a pointer and therefore
+ // writable), decode into that, and replace the whole value.
+ copied := false
+ if !elem.CanAddr() {
+ copied = true
+
+ // Make *T
+ copy := reflect.New(elem.Type())
+
+ // *T = elem
+ copy.Elem().Set(elem)
+
+ // Set elem so we decode into it
+ elem = copy
+ }
+
+ // Decode. If we have an error then return. We also return right
+ // away if we're not a copy because that means we decoded directly.
+ if err := d.decode(name, data, elem); err != nil || !copied {
+ return err
+ }
+
+ // If we're a copy, we need to set te final result
+ val.Set(elem.Elem())
+ return nil
+ }
+
+ dataVal := reflect.ValueOf(data)
+
+ // If the input data is a pointer, and the assigned type is the dereference
+ // of that exact pointer, then indirect it so that we can assign it.
+ // Example: *string to string
+ if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() {
+ dataVal = reflect.Indirect(dataVal)
+ }
+
+ if !dataVal.IsValid() {
+ dataVal = reflect.Zero(val.Type())
+ }
+
+ dataValType := dataVal.Type()
+ if !dataValType.AssignableTo(val.Type()) {
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ val.Set(dataVal)
+ return nil
+}
+
+func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataKind := getKind(dataVal)
+
+ converted := true
+ switch {
+ case dataKind == reflect.String:
+ val.SetString(dataVal.String())
+ case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+ if dataVal.Bool() {
+ val.SetString("1")
+ } else {
+ val.SetString("0")
+ }
+ case dataKind == reflect.Int && d.config.WeaklyTypedInput:
+ val.SetString(strconv.FormatInt(dataVal.Int(), 10))
+ case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
+ val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
+ case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
+ val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
+ case dataKind == reflect.Slice && d.config.WeaklyTypedInput,
+ dataKind == reflect.Array && d.config.WeaklyTypedInput:
+ dataType := dataVal.Type()
+ elemKind := dataType.Elem().Kind()
+ switch elemKind {
+ case reflect.Uint8:
+ var uints []uint8
+ if dataKind == reflect.Array {
+ uints = make([]uint8, dataVal.Len(), dataVal.Len())
+ for i := range uints {
+ uints[i] = dataVal.Index(i).Interface().(uint8)
+ }
+ } else {
+ uints = dataVal.Interface().([]uint8)
+ }
+ val.SetString(string(uints))
+ default:
+ converted = false
+ }
+ default:
+ converted = false
+ }
+
+ if !converted {
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataKind := getKind(dataVal)
+ dataType := dataVal.Type()
+
+ switch {
+ case dataKind == reflect.Int:
+ val.SetInt(dataVal.Int())
+ case dataKind == reflect.Uint:
+ val.SetInt(int64(dataVal.Uint()))
+ case dataKind == reflect.Float32:
+ val.SetInt(int64(dataVal.Float()))
+ case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+ if dataVal.Bool() {
+ val.SetInt(1)
+ } else {
+ val.SetInt(0)
+ }
+ case dataKind == reflect.String && d.config.WeaklyTypedInput:
+ str := dataVal.String()
+ if str == "" {
+ str = "0"
+ }
+
+ i, err := strconv.ParseInt(str, 0, val.Type().Bits())
+ if err == nil {
+ val.SetInt(i)
+ } else {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: wrapStrconvNumError(err),
+ })
+ }
+ case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
+ jn := data.(json.Number)
+ i, err := jn.Int64()
+ if err != nil {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: err,
+ })
+ }
+ val.SetInt(i)
+ default:
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataKind := getKind(dataVal)
+ dataType := dataVal.Type()
+
+ switch {
+ case dataKind == reflect.Int:
+ i := dataVal.Int()
+ if i < 0 && !d.config.WeaklyTypedInput {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: fmt.Errorf("%d overflows uint", i),
+ })
+ }
+ val.SetUint(uint64(i))
+ case dataKind == reflect.Uint:
+ val.SetUint(dataVal.Uint())
+ case dataKind == reflect.Float32:
+ f := dataVal.Float()
+ if f < 0 && !d.config.WeaklyTypedInput {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: fmt.Errorf("%f overflows uint", f),
+ })
+ }
+ val.SetUint(uint64(f))
+ case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+ if dataVal.Bool() {
+ val.SetUint(1)
+ } else {
+ val.SetUint(0)
+ }
+ case dataKind == reflect.String && d.config.WeaklyTypedInput:
+ str := dataVal.String()
+ if str == "" {
+ str = "0"
+ }
+
+ i, err := strconv.ParseUint(str, 0, val.Type().Bits())
+ if err == nil {
+ val.SetUint(i)
+ } else {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: wrapStrconvNumError(err),
+ })
+ }
+ case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
+ jn := data.(json.Number)
+ i, err := strconv.ParseUint(string(jn), 0, 64)
+ if err != nil {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: wrapStrconvNumError(err),
+ })
+ }
+ val.SetUint(i)
+ default:
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataKind := getKind(dataVal)
+
+ switch {
+ case dataKind == reflect.Bool:
+ val.SetBool(dataVal.Bool())
+ case dataKind == reflect.Int && d.config.WeaklyTypedInput:
+ val.SetBool(dataVal.Int() != 0)
+ case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
+ val.SetBool(dataVal.Uint() != 0)
+ case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
+ val.SetBool(dataVal.Float() != 0)
+ case dataKind == reflect.String && d.config.WeaklyTypedInput:
+ b, err := strconv.ParseBool(dataVal.String())
+ if err == nil {
+ val.SetBool(b)
+ } else if dataVal.String() == "" {
+ val.SetBool(false)
+ } else {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: wrapStrconvNumError(err),
+ })
+ }
+ default:
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataKind := getKind(dataVal)
+ dataType := dataVal.Type()
+
+ switch {
+ case dataKind == reflect.Int:
+ val.SetFloat(float64(dataVal.Int()))
+ case dataKind == reflect.Uint:
+ val.SetFloat(float64(dataVal.Uint()))
+ case dataKind == reflect.Float32:
+ val.SetFloat(dataVal.Float())
+ case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+ if dataVal.Bool() {
+ val.SetFloat(1)
+ } else {
+ val.SetFloat(0)
+ }
+ case dataKind == reflect.String && d.config.WeaklyTypedInput:
+ str := dataVal.String()
+ if str == "" {
+ str = "0"
+ }
+
+ f, err := strconv.ParseFloat(str, val.Type().Bits())
+ if err == nil {
+ val.SetFloat(f)
+ } else {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: wrapStrconvNumError(err),
+ })
+ }
+ case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
+ jn := data.(json.Number)
+ i, err := jn.Float64()
+ if err != nil {
+ return newDecodeError(name, &ParseError{
+ Expected: val,
+ Value: data,
+ Err: err,
+ })
+ }
+ val.SetFloat(i)
+ default:
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataKind := getKind(dataVal)
+
+ switch {
+ case dataKind == reflect.Complex64:
+ val.SetComplex(dataVal.Complex())
+ default:
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
+ valType := val.Type()
+ valKeyType := valType.Key()
+ valElemType := valType.Elem()
+
+ // By default we overwrite keys in the current map
+ valMap := val
+
+ // If the map is nil or we're purposely zeroing fields, make a new map
+ if valMap.IsNil() || d.config.ZeroFields {
+ // Make a new map to hold our result
+ mapType := reflect.MapOf(valKeyType, valElemType)
+ valMap = reflect.MakeMap(mapType)
+ }
+
+ dataVal := reflect.ValueOf(data)
+
+ // Resolve any levels of indirection
+ for dataVal.Kind() == reflect.Pointer {
+ dataVal = reflect.Indirect(dataVal)
+ }
+
+ // Check input type and based on the input type jump to the proper func
+ switch dataVal.Kind() {
+ case reflect.Map:
+ return d.decodeMapFromMap(name, dataVal, val, valMap)
+
+ case reflect.Struct:
+ return d.decodeMapFromStruct(name, dataVal, val, valMap)
+
+ case reflect.Array, reflect.Slice:
+ if d.config.WeaklyTypedInput {
+ return d.decodeMapFromSlice(name, dataVal, val, valMap)
+ }
+
+ fallthrough
+
+ default:
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+}
+
+func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
+ // Special case for BC reasons (covered by tests)
+ if dataVal.Len() == 0 {
+ val.Set(valMap)
+ return nil
+ }
+
+ for i := 0; i < dataVal.Len(); i++ {
+ err := d.decode(
+ name+"["+strconv.Itoa(i)+"]",
+ dataVal.Index(i).Interface(), val)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
+ valType := val.Type()
+ valKeyType := valType.Key()
+ valElemType := valType.Elem()
+
+ // Accumulate errors
+ var errs []error
+
+ // If the input data is empty, then we just match what the input data is.
+ if dataVal.Len() == 0 {
+ if dataVal.IsNil() {
+ if !val.IsNil() {
+ val.Set(dataVal)
+ }
+ } else {
+ // Set to empty allocated value
+ val.Set(valMap)
+ }
+
+ return nil
+ }
+
+ for _, k := range dataVal.MapKeys() {
+ fieldName := name + "[" + k.String() + "]"
+
+ // First decode the key into the proper type
+ currentKey := reflect.Indirect(reflect.New(valKeyType))
+ if err := d.decode(fieldName, k.Interface(), currentKey); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+
+ // Next decode the data into the proper type
+ v := dataVal.MapIndex(k).Interface()
+ currentVal := reflect.Indirect(reflect.New(valElemType))
+ if err := d.decode(fieldName, v, currentVal); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+
+ valMap.SetMapIndex(currentKey, currentVal)
+ }
+
+ // Set the built up map to the value
+ val.Set(valMap)
+
+ return errors.Join(errs...)
+}
+
+func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
+ typ := dataVal.Type()
+ for i := 0; i < typ.NumField(); i++ {
+ // Get the StructField first since this is a cheap operation. If the
+ // field is unexported, then ignore it.
+ f := typ.Field(i)
+ if f.PkgPath != "" {
+ continue
+ }
+
+ // Next get the actual value of this field and verify it is assignable
+ // to the map value.
+ v := dataVal.Field(i)
+ if !v.Type().AssignableTo(valMap.Type().Elem()) {
+ return newDecodeError(
+ name+"."+f.Name,
+ fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()),
+ )
+ }
+
+ tagValue := f.Tag.Get(d.config.TagName)
+ keyName := f.Name
+
+ if tagValue == "" && d.config.IgnoreUntaggedFields {
+ continue
+ }
+
+ // If Squash is set in the config, we squash the field down.
+ squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
+
+ v = dereferencePtrToStructIfNeeded(v, d.config.TagName)
+
+ // Determine the name of the key in the map
+ if index := strings.Index(tagValue, ","); index != -1 {
+ if tagValue[:index] == "-" {
+ continue
+ }
+ // If "omitempty" is specified in the tag, it ignores empty values.
+ if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) {
+ continue
+ }
+
+ // If "omitzero" is specified in the tag, it ignores zero values.
+ if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() {
+ continue
+ }
+
+ // If "squash" is specified in the tag, we squash the field down.
+ squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
+ if squash {
+ // When squashing, the embedded type can be a pointer to a struct.
+ if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
+ v = v.Elem()
+ }
+
+ // The final type must be a struct
+ if v.Kind() != reflect.Struct {
+ return newDecodeError(
+ name+"."+f.Name,
+ fmt.Errorf("cannot squash non-struct type %q", v.Type()),
+ )
+ }
+ } else {
+ if strings.Index(tagValue[index+1:], "remain") != -1 {
+ if v.Kind() != reflect.Map {
+ return newDecodeError(
+ name+"."+f.Name,
+ fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()),
+ )
+ }
+
+ ptr := v.MapRange()
+ for ptr.Next() {
+ valMap.SetMapIndex(ptr.Key(), ptr.Value())
+ }
+ continue
+ }
+ }
+ if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" {
+ keyName = keyNameTagValue
+ }
+ } else if len(tagValue) > 0 {
+ if tagValue == "-" {
+ continue
+ }
+ keyName = tagValue
+ }
+
+ switch v.Kind() {
+ // this is an embedded struct, so handle it differently
+ case reflect.Struct:
+ x := reflect.New(v.Type())
+ x.Elem().Set(v)
+
+ vType := valMap.Type()
+ vKeyType := vType.Key()
+ vElemType := vType.Elem()
+ mType := reflect.MapOf(vKeyType, vElemType)
+ vMap := reflect.MakeMap(mType)
+
+ // Creating a pointer to a map so that other methods can completely
+ // overwrite the map if need be (looking at you decodeMapFromMap). The
+ // indirection allows the underlying map to be settable (CanSet() == true)
+ // where as reflect.MakeMap returns an unsettable map.
+ addrVal := reflect.New(vMap.Type())
+ reflect.Indirect(addrVal).Set(vMap)
+
+ err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal))
+ if err != nil {
+ return err
+ }
+
+ // the underlying map may have been completely overwritten so pull
+ // it indirectly out of the enclosing value.
+ vMap = reflect.Indirect(addrVal)
+
+ if squash {
+ for _, k := range vMap.MapKeys() {
+ valMap.SetMapIndex(k, vMap.MapIndex(k))
+ }
+ } else {
+ valMap.SetMapIndex(reflect.ValueOf(keyName), vMap)
+ }
+
+ default:
+ valMap.SetMapIndex(reflect.ValueOf(keyName), v)
+ }
+ }
+
+ if val.CanAddr() {
+ val.Set(valMap)
+ }
+
+ return nil
+}
+
+func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) {
+ // If the input data is nil, then we want to just set the output
+ // pointer to be nil as well.
+ isNil := data == nil
+ if !isNil {
+ switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() {
+ case reflect.Chan,
+ reflect.Func,
+ reflect.Interface,
+ reflect.Map,
+ reflect.Ptr,
+ reflect.Slice:
+ isNil = v.IsNil()
+ }
+ }
+ if isNil {
+ if !val.IsNil() && val.CanSet() {
+ nilValue := reflect.New(val.Type()).Elem()
+ val.Set(nilValue)
+ }
+
+ return true, nil
+ }
+
+ // Create an element of the concrete (non pointer) type and decode
+ // into that. Then set the value of the pointer to this type.
+ valType := val.Type()
+ valElemType := valType.Elem()
+ if val.CanSet() {
+ realVal := val
+ if realVal.IsNil() || d.config.ZeroFields {
+ realVal = reflect.New(valElemType)
+ }
+
+ if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
+ return false, err
+ }
+
+ val.Set(realVal)
+ } else {
+ if err := d.decode(name, data, reflect.Indirect(val)); err != nil {
+ return false, err
+ }
+ }
+ return false, nil
+}
+
+func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error {
+ // Create an element of the concrete (non pointer) type and decode
+ // into that. Then set the value of the pointer to this type.
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ if val.Type() != dataVal.Type() {
+ return newDecodeError(name, &UnconvertibleTypeError{
+ Expected: val,
+ Value: data,
+ })
+ }
+ val.Set(dataVal)
+ return nil
+}
+
+func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataValKind := dataVal.Kind()
+ valType := val.Type()
+ valElemType := valType.Elem()
+ sliceType := reflect.SliceOf(valElemType)
+
+ // If we have a non array/slice type then we first attempt to convert.
+ if dataValKind != reflect.Array && dataValKind != reflect.Slice {
+ if d.config.WeaklyTypedInput {
+ switch {
+ // Slice and array we use the normal logic
+ case dataValKind == reflect.Slice, dataValKind == reflect.Array:
+ break
+
+ // Empty maps turn into empty slices
+ case dataValKind == reflect.Map:
+ if dataVal.Len() == 0 {
+ val.Set(reflect.MakeSlice(sliceType, 0, 0))
+ return nil
+ }
+ // Create slice of maps of other sizes
+ return d.decodeSlice(name, []any{data}, val)
+
+ case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
+ return d.decodeSlice(name, []byte(dataVal.String()), val)
+
+ // All other types we try to convert to the slice type
+ // and "lift" it into it. i.e. a string becomes a string slice.
+ default:
+ // Just re-try this function with data as a slice.
+ return d.decodeSlice(name, []any{data}, val)
+ }
+ }
+
+ return newDecodeError(name,
+ fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
+ }
+
+ // If the input value is nil, then don't allocate since empty != nil
+ if dataValKind != reflect.Array && dataVal.IsNil() {
+ return nil
+ }
+
+ valSlice := val
+ if valSlice.IsNil() || d.config.ZeroFields {
+ // Make a new slice to hold our result, same size as the original data.
+ valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
+ } else if valSlice.Len() > dataVal.Len() {
+ valSlice = valSlice.Slice(0, dataVal.Len())
+ }
+
+ // Accumulate any errors
+ var errs []error
+
+ for i := 0; i < dataVal.Len(); i++ {
+ currentData := dataVal.Index(i).Interface()
+ for valSlice.Len() <= i {
+ valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
+ }
+ currentField := valSlice.Index(i)
+
+ fieldName := name + "[" + strconv.Itoa(i) + "]"
+ if err := d.decode(fieldName, currentData, currentField); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ // Finally, set the value to the slice we built up
+ val.Set(valSlice)
+
+ return errors.Join(errs...)
+}
+
+func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+ dataValKind := dataVal.Kind()
+ valType := val.Type()
+ valElemType := valType.Elem()
+ arrayType := reflect.ArrayOf(valType.Len(), valElemType)
+
+ valArray := val
+
+ if isComparable(valArray) && valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields {
+ // Check input type
+ if dataValKind != reflect.Array && dataValKind != reflect.Slice {
+ if d.config.WeaklyTypedInput {
+ switch {
+ // Empty maps turn into empty arrays
+ case dataValKind == reflect.Map:
+ if dataVal.Len() == 0 {
+ val.Set(reflect.Zero(arrayType))
+ return nil
+ }
+
+ // All other types we try to convert to the array type
+ // and "lift" it into it. i.e. a string becomes a string array.
+ default:
+ // Just re-try this function with data as a slice.
+ return d.decodeArray(name, []any{data}, val)
+ }
+ }
+
+ return newDecodeError(name,
+ fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
+
+ }
+ if dataVal.Len() > arrayType.Len() {
+ return newDecodeError(name,
+ fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len()))
+ }
+
+ // Make a new array to hold our result, same size as the original data.
+ valArray = reflect.New(arrayType).Elem()
+ }
+
+ // Accumulate any errors
+ var errs []error
+
+ for i := 0; i < dataVal.Len(); i++ {
+ currentData := dataVal.Index(i).Interface()
+ currentField := valArray.Index(i)
+
+ fieldName := name + "[" + strconv.Itoa(i) + "]"
+ if err := d.decode(fieldName, currentData, currentField); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ // Finally, set the value to the array we built up
+ val.Set(valArray)
+
+ return errors.Join(errs...)
+}
+
+func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
+ dataVal := reflect.Indirect(reflect.ValueOf(data))
+
+ // If the type of the value to write to and the data match directly,
+ // then we just set it directly instead of recursing into the structure.
+ if dataVal.Type() == val.Type() {
+ val.Set(dataVal)
+ return nil
+ }
+
+ dataValKind := dataVal.Kind()
+ switch dataValKind {
+ case reflect.Map:
+ return d.decodeStructFromMap(name, dataVal, val)
+
+ case reflect.Struct:
+ // Not the most efficient way to do this but we can optimize later if
+ // we want to. To convert from struct to struct we go to map first
+ // as an intermediary.
+
+ // Make a new map to hold our result
+ mapType := reflect.TypeOf((map[string]any)(nil))
+ mval := reflect.MakeMap(mapType)
+
+ // Creating a pointer to a map so that other methods can completely
+ // overwrite the map if need be (looking at you decodeMapFromMap). The
+ // indirection allows the underlying map to be settable (CanSet() == true)
+ // where as reflect.MakeMap returns an unsettable map.
+ addrVal := reflect.New(mval.Type())
+
+ reflect.Indirect(addrVal).Set(mval)
+ if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil {
+ return err
+ }
+
+ result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val)
+ return result
+
+ default:
+ return newDecodeError(name,
+ fmt.Errorf("expected a map or struct, got %q", dataValKind))
+ }
+}
+
+func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
+ dataValType := dataVal.Type()
+ if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
+ return newDecodeError(name,
+ fmt.Errorf("needs a map with string keys, has %q keys", kind))
+ }
+
+ dataValKeys := make(map[reflect.Value]struct{})
+ dataValKeysUnused := make(map[any]struct{})
+ for _, dataValKey := range dataVal.MapKeys() {
+ dataValKeys[dataValKey] = struct{}{}
+ dataValKeysUnused[dataValKey.Interface()] = struct{}{}
+ }
+
+ targetValKeysUnused := make(map[any]struct{})
+
+ var errs []error
+
+ // This slice will keep track of all the structs we'll be decoding.
+ // There can be more than one struct if there are embedded structs
+ // that are squashed.
+ structs := make([]reflect.Value, 1, 5)
+ structs[0] = val
+
+ // Compile the list of all the fields that we're going to be decoding
+ // from all the structs.
+ type field struct {
+ field reflect.StructField
+ val reflect.Value
+ }
+
+ // remainField is set to a valid field set with the "remain" tag if
+ // we are keeping track of remaining values.
+ var remainField *field
+
+ fields := []field{}
+ for len(structs) > 0 {
+ structVal := structs[0]
+ structs = structs[1:]
+
+ structType := structVal.Type()
+
+ for i := 0; i < structType.NumField(); i++ {
+ fieldType := structType.Field(i)
+ fieldVal := structVal.Field(i)
+ if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct {
+ // Handle embedded struct pointers as embedded structs.
+ fieldVal = fieldVal.Elem()
+ }
+
+ // If "squash" is specified in the tag, we squash the field down.
+ squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous
+ remain := false
+
+ // We always parse the tags cause we're looking for other tags too
+ tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
+ for _, tag := range tagParts[1:] {
+ if tag == d.config.SquashTagOption {
+ squash = true
+ break
+ }
+
+ if tag == "remain" {
+ remain = true
+ break
+ }
+ }
+
+ if squash {
+ switch fieldVal.Kind() {
+ case reflect.Struct:
+ structs = append(structs, fieldVal)
+ case reflect.Interface:
+ if !fieldVal.IsNil() {
+ structs = append(structs, fieldVal.Elem().Elem())
+ }
+ default:
+ errs = append(errs, newDecodeError(
+ name+"."+fieldType.Name,
+ fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()),
+ ))
+ }
+ continue
+ }
+
+ // Build our field
+ if remain {
+ remainField = &field{fieldType, fieldVal}
+ } else {
+ // Normal struct field, store it away
+ fields = append(fields, field{fieldType, fieldVal})
+ }
+ }
+ }
+
+ // for fieldType, field := range fields {
+ for _, f := range fields {
+ field, fieldValue := f.field, f.val
+ fieldName := field.Name
+
+ tagValue := field.Tag.Get(d.config.TagName)
+ if tagValue == "" && d.config.IgnoreUntaggedFields {
+ continue
+ }
+ tagValue = strings.SplitN(tagValue, ",", 2)[0]
+ if tagValue != "" {
+ fieldName = tagValue
+ }
+
+ rawMapKey := reflect.ValueOf(fieldName)
+ rawMapVal := dataVal.MapIndex(rawMapKey)
+ if !rawMapVal.IsValid() {
+ // Do a slower search by iterating over each key and
+ // doing case-insensitive search.
+ for dataValKey := range dataValKeys {
+ mK, ok := dataValKey.Interface().(string)
+ if !ok {
+ // Not a string key
+ continue
+ }
+
+ if d.config.MatchName(mK, fieldName) {
+ rawMapKey = dataValKey
+ rawMapVal = dataVal.MapIndex(dataValKey)
+ break
+ }
+ }
+
+ if !rawMapVal.IsValid() {
+ // There was no matching key in the map for the value in
+ // the struct. Remember it for potential errors and metadata.
+ if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) {
+ targetValKeysUnused[fieldName] = struct{}{}
+ }
+ continue
+ }
+ }
+
+ if !fieldValue.IsValid() {
+ // This should never happen
+ panic("field is not valid")
+ }
+
+ // If we can't set the field, then it is unexported or something,
+ // and we just continue onwards.
+ if !fieldValue.CanSet() {
+ continue
+ }
+
+ // Delete the key we're using from the unused map so we stop tracking
+ delete(dataValKeysUnused, rawMapKey.Interface())
+
+ // If the name is empty string, then we're at the root, and we
+ // don't dot-join the fields.
+ if name != "" {
+ fieldName = name + "." + fieldName
+ }
+
+ if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ // If we have a "remain"-tagged field and we have unused keys then
+ // we put the unused keys directly into the remain field.
+ if remainField != nil && len(dataValKeysUnused) > 0 {
+ // Build a map of only the unused values
+ remain := map[any]any{}
+ for key := range dataValKeysUnused {
+ remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
+ }
+
+ // Decode it as-if we were just decoding this map onto our map.
+ if err := d.decodeMap(name, remain, remainField.val); err != nil {
+ errs = append(errs, err)
+ }
+
+ // Set the map to nil so we have none so that the next check will
+ // not error (ErrorUnused)
+ dataValKeysUnused = nil
+ }
+
+ if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
+ keys := make([]string, 0, len(dataValKeysUnused))
+ for rawKey := range dataValKeysUnused {
+ keys = append(keys, rawKey.(string))
+ }
+ sort.Strings(keys)
+
+ errs = append(errs, newDecodeError(
+ name,
+ fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")),
+ ))
+ }
+
+ if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
+ keys := make([]string, 0, len(targetValKeysUnused))
+ for rawKey := range targetValKeysUnused {
+ keys = append(keys, rawKey.(string))
+ }
+ sort.Strings(keys)
+
+ errs = append(errs, newDecodeError(
+ name,
+ fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")),
+ ))
+ }
+
+ if err := errors.Join(errs...); err != nil {
+ return err
+ }
+
+ // Add the unused keys to the list of unused keys if we're tracking metadata
+ if d.config.Metadata != nil {
+ for rawKey := range dataValKeysUnused {
+ key := rawKey.(string)
+ if name != "" {
+ key = name + "." + key
+ }
+
+ d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
+ }
+ for rawKey := range targetValKeysUnused {
+ key := rawKey.(string)
+ if name != "" {
+ key = name + "." + key
+ }
+
+ d.config.Metadata.Unset = append(d.config.Metadata.Unset, key)
+ }
+ }
+
+ return nil
+}
+
+func isEmptyValue(v reflect.Value) bool {
+ switch getKind(v) {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ }
+ return false
+}
+
+func getKind(val reflect.Value) reflect.Kind {
+ kind := val.Kind()
+
+ switch {
+ case kind >= reflect.Int && kind <= reflect.Int64:
+ return reflect.Int
+ case kind >= reflect.Uint && kind <= reflect.Uint64:
+ return reflect.Uint
+ case kind >= reflect.Float32 && kind <= reflect.Float64:
+ return reflect.Float32
+ case kind >= reflect.Complex64 && kind <= reflect.Complex128:
+ return reflect.Complex64
+ default:
+ return kind
+ }
+}
+
+func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool {
+ for i := 0; i < typ.NumField(); i++ {
+ f := typ.Field(i)
+ if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields
+ return true
+ }
+ if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside
+ return true
+ }
+ }
+ return false
+}
+
+func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value {
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
+ return v
+ }
+ deref := v.Elem()
+ derefT := deref.Type()
+ if isStructTypeConvertibleToMap(derefT, true, tagName) {
+ return deref
+ }
+ return v
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go
new file mode 100644
index 000000000000..d0913fff6c7d
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go
@@ -0,0 +1,44 @@
+//go:build !go1.20
+
+package mapstructure
+
+import "reflect"
+
+func isComparable(v reflect.Value) bool {
+ k := v.Kind()
+ switch k {
+ case reflect.Invalid:
+ return false
+
+ case reflect.Array:
+ switch v.Type().Elem().Kind() {
+ case reflect.Interface, reflect.Array, reflect.Struct:
+ for i := 0; i < v.Type().Len(); i++ {
+ // if !v.Index(i).Comparable() {
+ if !isComparable(v.Index(i)) {
+ return false
+ }
+ }
+ return true
+ }
+ return v.Type().Comparable()
+
+ case reflect.Interface:
+ // return v.Elem().Comparable()
+ return isComparable(v.Elem())
+
+ case reflect.Struct:
+ for i := 0; i < v.NumField(); i++ {
+ return false
+
+ // if !v.Field(i).Comparable() {
+ if !isComparable(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+
+ default:
+ return v.Type().Comparable()
+ }
+}
diff --git a/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go
new file mode 100644
index 000000000000..f8255a1b174b
--- /dev/null
+++ b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go
@@ -0,0 +1,10 @@
+//go:build go1.20
+
+package mapstructure
+
+import "reflect"
+
+// TODO: remove once we drop support for Go <1.20
+func isComparable(v reflect.Value) bool {
+ return v.Comparable()
+}
diff --git a/vendor/github.com/google/certificate-transparency-go/.gitignore b/vendor/github.com/google/certificate-transparency-go/.gitignore
new file mode 100644
index 000000000000..8c13cd1c9d3d
--- /dev/null
+++ b/vendor/github.com/google/certificate-transparency-go/.gitignore
@@ -0,0 +1,28 @@
+*.iml
+*.swo
+*.swp
+*.tfstate
+*.tfstate.backup
+*~
+/.idea
+/certcheck
+/chainfix
+/coverage.txt
+/createtree
+/crlcheck
+/ctclient
+/ct_server
+/ct_hammer
+/data
+/dumpscts
+/findlog
+/goshawk
+/gosmin
+/gossip_server
+/preloader
+/scanlog
+/sctcheck
+/sctscan
+/trillian_log_server
+/trillian_log_signer
+/trillian.json
diff --git a/vendor/github.com/google/certificate-transparency-go/.golangci.yaml b/vendor/github.com/google/certificate-transparency-go/.golangci.yaml
new file mode 100644
index 000000000000..e9b683b2bd18
--- /dev/null
+++ b/vendor/github.com/google/certificate-transparency-go/.golangci.yaml
@@ -0,0 +1,39 @@
+version: "2"
+linters:
+ settings:
+ depguard:
+ rules:
+ main:
+ deny:
+ - pkg: ^golang.org/x/net/context$
+ - pkg: github.com/gogo/protobuf/proto
+ - pkg: encoding/asn1
+ - pkg: crypto/x509
+ gocyclo:
+ min-complexity: 25
+ exclusions:
+ generated: lax
+ rules:
+ - linters:
+ - staticcheck
+ text: 'SA1019: grpc.Dial is deprecated: use NewClient instead'
+ - linters:
+ - staticcheck
+ text: 'SA1019: grpc.DialContext is deprecated: use NewClient instead'
+ - linters:
+ - staticcheck
+ text: 'SA1019: grpc.WithBlock is deprecated: this DialOption is not supported by NewClient'
+ paths:
+ - (^|/)x509($|/)
+ - (^|/)x509util($|/)
+ - (^|/)asn1($|/)
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
diff --git a/vendor/github.com/google/certificate-transparency-go/AUTHORS b/vendor/github.com/google/certificate-transparency-go/AUTHORS
new file mode 100644
index 000000000000..ad514665ef63
--- /dev/null
+++ b/vendor/github.com/google/certificate-transparency-go/AUTHORS
@@ -0,0 +1,29 @@
+# This is the official list of benchmark authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+#
+# Names should be added to this file as:
+# Name or Organization
+# The email address is not required for organizations.
+#
+# Please keep the list sorted.
+
+Alex Cohn
+Ed Maste
+Elisha Silas
+Fiaz Hossain
+Google LLC
+Internet Security Research Group
+Jeff Trawick
+Katriel Cohn-Gordon
+Laël Cellier
+Mark Schloesser
+NORDUnet A/S
+Nicholas Galbreath
+Oliver Weidner
+PrimeKey Solutions AB
+Ruslan Kovalov
+Sectigo Limited
+Venafi, Inc.
+Vladimir Rutsky
+Ximin Luo
diff --git a/vendor/github.com/google/certificate-transparency-go/CHANGELOG.md b/vendor/github.com/google/certificate-transparency-go/CHANGELOG.md
new file mode 100644
index 000000000000..0206cfe12482
--- /dev/null
+++ b/vendor/github.com/google/certificate-transparency-go/CHANGELOG.md
@@ -0,0 +1,1311 @@
+# CERTIFICATE-TRANSPARENCY-GO Changelog
+
+## HEAD
+
+## v1.3.2
+
+### Misc
+
+* [migrillian] remove etcd support in #1699
+* Bump golangci-lint from 1.55.1 to 1.61.0 (developers should update to this version).
+* Update ctclient tool to support SCT extensions field by @liweitianux in https://github.com/google/certificate-transparency-go/pull/1645
+* Bump go to 1.23
+* [ct_hammer] support HTTPS and Bearer token for Authentication.
+* [preloader] support Bearer token Authentication for non temporal logs.
+* [preloader] support end indexes
+* [CTFE] Short cache max-age when get-entries returns fewer entries than requested by @robstradling in https://github.com/google/certificate-transparency-go/pull/1707
+* [CTFE] Disalllow mismatching signature algorithm identifiers in #702.
+* [jsonclient] surface HTTP Do and Read errors #1695 by @FiloSottile
+
+### CTFE Storage Saving: Extra Data Issuance Chain Deduplication
+
+* Suppress unnecessary duplicate key errors in the IssuanceChainStorage PostgreSQL implementation by @robstradling in https://github.com/google/certificate-transparency-go/pull/1678
+* Only store IssuanceChain if not cached by @robstradling in https://github.com/google/certificate-transparency-go/pull/1679
+
+### CTFE Rate Limiting Of Non-Fresh Submissions
+
+To protect a log from being flooded with requests for "old" certificates, optional rate limiting for "non-fresh submissions" can be configured by providing the following flags:
+
+- `non_fresh_submission_age`
+- `non_fresh_submission_burst`
+- `non_fresh_submission_limit`
+
+This can help to ensure that the log maintains its ability to (1) accept "fresh" submissions and (2) distribute all log entries to monitors.
+
+* [CTFE] Configurable mechanism to rate-limit non-fresh submissions by @robstradling in https://github.com/google/certificate-transparency-go/pull/1698
+
+### Dependency updates
+
+* Bump the docker-deps group across 5 directories with 3 updates (#1705)
+* Bump google.golang.org/grpc from 1.72.1 to 1.72.2 in the all-deps group (#1704)
+* Bump github.com/go-jose/go-jose/v4 in the go_modules group (#1700)
+* Bump the all-deps group with 7 updates (#1701)
+* Bump the all-deps group with 7 updates (#1693)
+* Bump the docker-deps group across 4 directories with 1 update (#1694)
+* Bump github/codeql-action from 3.28.13 to 3.28.16 in the all-deps group (#1692)
+* Bump the all-deps group across 1 directory with 7 updates (#1688)
+* Bump distroless/base-debian12 (#1686)
+* Bump golangci/golangci-lint-action from 6.5.1 to 7.0.0 in the all-deps group (#1685)
+* Bump the all-deps group with 4 updates (#1681)
+* Bump the all-deps group with 6 updates (#1683)
+* Bump the docker-deps group across 4 directories with 2 updates (#1682)
+* Bump github.com/golang-jwt/jwt/v4 in the go_modules group (#1680)
+* Bump golangci/golangci-lint-action in the all-deps group (#1676)
+* Bump the all-deps group with 2 updates (#1677)
+* Bump github/codeql-action from 3.28.10 to 3.28.11 in the all-deps group (#1670)
+* Bump the all-deps group with 8 updates (#1672)
+* Bump the docker-deps group across 4 directories with 1 update (#1671)
+* Bump the docker-deps group across 4 directories with 1 update (#1668)
+* Bump the all-deps group with 4 updates (#1666)
+* Bump golangci-lint from 1.55.1 to 1.61.0 (#1667)
+* Bump the all-deps group with 3 updates (#1665)
+* Bump github.com/spf13/cobra from 1.8.1 to 1.9.1 in the all-deps group (#1660)
+* Bump the docker-deps group across 5 directories with 2 updates (#1661)
+* Bump golangci/golangci-lint-action in the all-deps group (#1662)
+* Bump the docker-deps group across 4 directories with 1 update (#1656)
+* Bump the all-deps group with 2 updates (#1654)
+* Bump the all-deps group with 4 updates (#1657)
+* Bump github/codeql-action from 3.28.5 to 3.28.8 in the all-deps group (#1652)
+* Bump github.com/spf13/pflag from 1.0.5 to 1.0.6 in the all-deps group (#1651)
+* Bump the all-deps group with 2 updates (#1649)
+* Bump the all-deps group with 5 updates (#1650)
+* Bump the docker-deps group across 5 directories with 3 updates (#1648)
+* Bump google.golang.org/protobuf in the all-deps group (#1647)
+* Bump golangci/golangci-lint-action in the all-deps group (#1646)
+
+## v1.3.1
+
+* Add AllLogListSignatureURL by @AlexLaroche in https://github.com/google/certificate-transparency-go/pull/1634
+* Add TiledLogs to log list JSON by @mcpherrinm in https://github.com/google/certificate-transparency-go/pull/1635
+* chore: relax go directive to permit 1.22.x by @dnwe in https://github.com/google/certificate-transparency-go/pull/1640
+
+### Dependency Update
+
+* Bump github.com/fullstorydev/grpcurl from 1.9.1 to 1.9.2 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1627
+* Bump the all-deps group with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1628
+* Bump the docker-deps group across 5 directories with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1630
+* Bump github/codeql-action from 3.27.5 to 3.27.6 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1629
+* Bump golang.org/x/crypto from 0.30.0 to 0.31.0 in the go_modules group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1631
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1633
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1632
+* Bump the docker-deps group across 4 directories with 1 update by @dependabot in https://github.com/google/certificate-transparency-go/pull/1638
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1637
+* Bump the all-deps group across 1 directory with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1641
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1643
+* Bump google.golang.org/grpc from 1.69.2 to 1.69.4 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1642
+
+## v1.3.0
+
+### CTFE Storage Saving: Extra Data Issuance Chain Deduplication
+
+This feature now supports PostgreSQL, in addition to the support for MySQL/MariaDB that was added in [v1.2.0](#v1.2.0).
+
+Log operators can choose to enable this feature for new PostgreSQL-based CT logs by adding new CTFE configs in the [LogMultiConfig](trillian/ctfe/configpb/config.proto) and importing the [database schema](trillian/ctfe/storage/postgresql/schema.sql). The other available options are documented in the [v1.2.0](#v1.2.0) changelog entry.
+
+This change is tested in Cloud Build tests using the `postgres:17` Docker image as of the time of writing.
+
+* Add IssuanceChainStorage PostgreSQL implementation by @robstradling in https://github.com/google/certificate-transparency-go/pull/1618
+
+### Misc
+
+* [Dependabot] Update all docker images in one PR by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1614
+* Explicitly include version tag by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1617
+* Add empty cloudbuild_postgresql.yaml by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1623
+
+### Dependency update
+
+* Bump the all-deps group with 4 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1609
+* Bump golang from 1.23.2-bookworm to 1.23.3-bookworm in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1611
+* Bump github/codeql-action from 3.27.0 to 3.27.1 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1610
+* Bump golang from 1.23.2-bookworm to 1.23.3-bookworm in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1612
+* Bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 in the go_modules group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1613
+* Bump the docker-deps group across 3 directories with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1616
+* Bump github/codeql-action from 3.27.1 to 3.27.2 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1615
+* Bump the docker-deps group across 4 directories with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1622
+* Bump github/codeql-action from 3.27.2 to 3.27.4 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1620
+* Bump the all-deps group with 4 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1621
+* Bump github.com/google/trillian from 1.6.1 to 1.7.0 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1624
+* Bump github/codeql-action from 3.27.4 to 3.27.5 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1625
+
+## v1.2.2
+
+* Recommended Go version for development: 1.22
+ * Using a different version can lead to presubmits failing due to unexpected diffs.
+
+### Add TLS Support
+
+Add TLS support for Trillian: By using `--trillian_tls_ca_cert_file` flag, users can provide a CA certificate, that is used to establish a secure communication with Trillian log server.
+
+Add TLS support for ct_server: By using `--tls_certificate` and `--tls_key` flags, users can provide a service certificate and key, that enables the server to handle HTTPS requests.
+
+* Add TLS support for CTLog server by @fghanmi in https://github.com/google/certificate-transparency-go/pull/1523
+* Add TLS support for migrillian by @fghanmi in https://github.com/google/certificate-transparency-go/pull/1525
+* fix TLS configuration for ct_server by @fghanmi in https://github.com/google/certificate-transparency-go/pull/1542
+* Add Trillian TLS support for ct_server by @fghanmi in https://github.com/google/certificate-transparency-go/pull/1551
+
+### HTTP Idle Connection Timeout Flag
+
+A new flag `http_idle_timeout` is added to set the HTTP server's idle timeout value in the ct_server binary. This controls the maximum amount of time to wait for the next request when keep-alives are enabled.
+
+* add flag for HTTP idle connection timeout value by @bobcallaway in https://github.com/google/certificate-transparency-go/pull/1597
+
+### Misc
+
+* Refactor issuance chain service by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1512
+* Use the version in the go.mod file for vuln checks by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1528
+
+### Fixes
+
+* Fix failed tests on 32-bit OS by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1540
+
+### Dependency update
+
+* Bump go.etcd.io/etcd/v3 from 3.5.13 to 3.5.14 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1500
+* Bump github/codeql-action from 3.25.6 to 3.25.7 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1501
+* Bump golang.org/x/net from 0.25.0 to 0.26.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1503
+* Group dependabot updates as much as possible by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1506
+* Bump golang from 1.22.3-bookworm to 1.22.4-bookworm in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1507
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1511
+* Bump golang from 1.22.3-bookworm to 1.22.4-bookworm in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1510
+* Bump golang from 1.22.3-bookworm to 1.22.4-bookworm in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1509
+* Bump golang from 1.22.3-bookworm to 1.22.4-bookworm in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1508
+* Bump the all-deps group with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1516
+* Bump golang from `aec4784` to `9678844` in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1518
+* Bump alpine from 3.19 to 3.20 in /trillian/examples/deployment/docker/envsubst by @dependabot in https://github.com/google/certificate-transparency-go/pull/1492
+* Bump golang from `aec4784` to `9678844` in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1517
+* Bump golang from `aec4784` to `9678844` in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1513
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1515
+* Bump golang from `aec4784` to `9678844` in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1514
+* Bump alpine from `77726ef` to `b89d9c9` in /trillian/examples/deployment/docker/envsubst in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1519
+* Bump k8s.io/klog/v2 from 2.130.0 to 2.130.1 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1521
+* Bump alpine from `77726ef` to `b89d9c9` in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1520
+* Bump github/codeql-action from 3.25.10 to 3.25.11 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1526
+* Bump version of go used by the vuln checker by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1527
+* Bump the all-deps group with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1530
+* Bump golang from 1.22.4-bookworm to 1.22.5-bookworm in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1531
+* Bump golang from 1.22.4-bookworm to 1.22.5-bookworm in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1532
+* Bump the all-deps group in /trillian/examples/deployment/docker/ctfe with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1533
+* Bump actions/upload-artifact from 4.3.3 to 4.3.4 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1534
+* Bump golang from 1.22.4-bookworm to 1.22.5-bookworm in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1535
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1536
+* Bump github/codeql-action from 3.25.12 to 3.25.13 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1538
+* Bump the all-deps group with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1537
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1543
+* Bump golang from `6c27802` to `af9b40f` in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1544
+* Bump golang from `6c27802` to `af9b40f` in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1548
+* Bump golang from `6c27802` to `af9b40f` in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1547
+* Bump alpine from `b89d9c9` to `0a4eaa0` in /trillian/examples/deployment/docker/envsubst in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1546
+* Bump the all-deps group in /internal/witness/cmd/feeder with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1545
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1549
+* Bump golang.org/x/time from 0.5.0 to 0.6.0 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1550
+* Bump golang from 1.22.5-bookworm to 1.22.6-bookworm in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1552
+* Bump golang from 1.22.5-bookworm to 1.22.6-bookworm in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1553
+* Bump golang from 1.22.5-bookworm to 1.22.6-bookworm in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1554
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1555
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1556
+* Bump golang from 1.22.5-bookworm to 1.22.6-bookworm in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1557
+* Bump github.com/prometheus/client_golang from 1.19.1 to 1.20.0 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1559
+* Bump github/codeql-action from 3.26.0 to 3.26.3 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1561
+* Bump golang from 1.22.6-bookworm to 1.23.0-bookworm in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1558
+* Bump golang from 1.22.6-bookworm to 1.23.0-bookworm in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1563
+* Bump golang from 1.22.6-bookworm to 1.23.0-bookworm in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1560
+* Bump golang from 1.22.6-bookworm to 1.23.0-bookworm in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1562
+* Bump go version to 1.22.6 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1564
+* Bump github.com/prometheus/client_golang from 1.20.0 to 1.20.2 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1565
+* Bump github/codeql-action from 3.26.3 to 3.26.5 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1566
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1568
+* Bump the all-deps group with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1569
+* Bump go from 1.22.6 to 1.22.7 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1574
+* Bump alpine from `0a4eaa0` to `beefdbd` in /trillian/examples/deployment/docker/envsubst in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1571
+* Bump the all-deps group across 1 directory with 5 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1577
+* Bump golang from 1.23.0-bookworm to 1.23.1-bookworm in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1575
+* Bump golang from 1.23.0-bookworm to 1.23.1-bookworm in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1576
+* Bump the all-deps group in /trillian/examples/deployment/docker/ctfe with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1572
+* Bump the all-deps group in /internal/witness/cmd/feeder with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1573
+* Bump the all-deps group with 4 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1578
+* Bump github/codeql-action from 3.26.6 to 3.26.7 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1579
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1580
+* Bump github/codeql-action from 3.26.7 to 3.26.8 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1581
+* Bump distroless/base-debian12 from `c925d12` to `88e0a2a` in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1582
+* Bump the all-deps group in /trillian/examples/deployment/docker/ctfe with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1585
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1583
+* Bump golang from `1a5326b` to `dba79eb` in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1584
+* Bump golang from `1a5326b` to `dba79eb` in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1587
+* Bump golang from `1a5326b` to `dba79eb` in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1586
+* Bump the all-deps group with 5 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1588
+* Bump the all-deps group with 6 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1589
+* Bump golang from 1.23.1-bookworm to 1.23.2-bookworm in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1593
+* Bump golang from 1.23.1-bookworm to 1.23.2-bookworm in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1592
+* Bump golang from 1.23.1-bookworm to 1.23.2-bookworm in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1591
+* Bump golang from 1.23.1-bookworm to 1.23.2-bookworm in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1590
+* Bump the all-deps group with 2 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1595
+* Bump github.com/prometheus/client_golang from 1.20.4 to 1.20.5 in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1598
+* Bump golang from `18d2f94` to `2341ddf` in /integration in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1602
+* Bump golang from `18d2f94` to `2341ddf` in /internal/witness/cmd/witness in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1599
+* Bump golang from `18d2f94` to `2341ddf` in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1600
+* Bump golang from `18d2f94` to `2341ddf` in /internal/witness/cmd/feeder in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1601
+* Bump the all-deps group with 3 updates by @dependabot in https://github.com/google/certificate-transparency-go/pull/1603
+* Bump distroless/base-debian12 from `6ae5fe6` to `8fe31fb` in /trillian/examples/deployment/docker/ctfe in the all-deps group by @dependabot in https://github.com/google/certificate-transparency-go/pull/1604
+
+## v1.2.1
+
+### Fixes
+
+* Fix Go potential bugs and maintainability by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1496
+
+### Dependency update
+
+* Bump google.golang.org/grpc from 1.63.2 to 1.64.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1482
+
+## v1.2.0
+
+### CTFE Storage Saving: Extra Data Issuance Chain Deduplication
+
+To reduce CT/Trillian database storage by deduplication of the entire issuance chain (intermediate certificate(s) and root certificate) that is currently stored in the Trillian merkle tree leaf ExtraData field. Storage cost should be reduced by at least 33% for new CT logs with this feature enabled. Currently only MySQL/MariaDB is supported to store the issuance chain in the CTFE database.
+
+Existing logs are not affected by this change.
+
+Log operators can choose to opt-in this change for new CT logs by adding new CTFE configs in the [LogMultiConfig](trillian/ctfe/configpb/config.proto) and importing the [database schema](trillian/ctfe/storage/mysql/schema.sql). See [example](trillian/examples/deployment/docker/ctfe/ct_server.cfg).
+
+- `ctfe_storage_connection_string`
+- `extra_data_issuance_chain_storage_backend`
+
+An optional LRU cache can be enabled by providing the following flags.
+
+- `cache_type`
+- `cache_size`
+- `cache_ttl`
+
+This change is tested in Cloud Build tests using the `mysql:8.4` Docker image as of the time of writing.
+
+* Add issuance chain storage interface by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1430
+* Add issuance chain cache interface by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1431
+* Add CTFE extra data storage saving configs to config.proto by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1432
+* Add new types `PrecertChainEntryHash` and `CertificateChainHash` for TLS marshal/unmarshal in storage saving by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1435
+* Add IssuanceChainCache LRU implementation by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1454
+* Add issuance chain service by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1452
+* Add CTFE extra data storage saving configs validation by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1456
+* Add IssuanceChainStorage MySQL implementation by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1462
+* Fix errcheck lint in mysql test by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1464
+* CTFE Extra Data Issuance Chain Deduplication by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1477
+* Fix incorrect deployment doc and server config by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1494
+
+### Submission proxy: Root compatibility checking
+
+* Adds the ability for a CT client to disable root compatibile checking by @aaomidi in https://github.com/google/certificate-transparency-go/pull/1258
+
+### Fixes
+
+* Return 429 Too Many Requests for gRPC error code `ResourceExhausted` from Trillian by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1401
+* Safeguard against redirects on PUT request by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1418
+* Fix CT client upload to be safe against no-op POSTs by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1424
+
+### Misc
+
+* Prefix errors.New variables with the word "Err" by @aaomidi in https://github.com/google/certificate-transparency-go/pull/1399
+* Remove lint exceptions and fix remaining issues by @silaselisha in https://github.com/google/certificate-transparency-go/pull/1438
+* Fix invalid Go toolchain version by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1471
+* Regenerate proto files by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1489
+
+### Dependency update
+
+* Bump distroless/base-debian12 from `5eae9ef` to `28a7f1f` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1388
+* Bump github/codeql-action from 3.24.6 to 3.24.7 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1389
+* Bump actions/checkout from 4.1.1 to 4.1.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1390
+* Bump golang from `6699d28` to `7f9c058` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1391
+* Bump golang from `6699d28` to `7f9c058` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1392
+* Bump golang from `6699d28` to `7a392a2` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1393
+* Bump golang from `6699d28` to `7a392a2` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1394
+* Bump golang from `7a392a2` to `d996c64` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1395
+* Bump golang from `7f9c058` to `d996c64` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1396
+* Bump golang from `7a392a2` to `d996c64` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1397
+* Bump golang from `7f9c058` to `d996c64` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1398
+* Bump github/codeql-action from 3.24.7 to 3.24.8 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1400
+* Bump github/codeql-action from 3.24.8 to 3.24.9 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1402
+* Bump go.etcd.io/etcd/v3 from 3.5.12 to 3.5.13 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1405
+* Bump distroless/base-debian12 from `28a7f1f` to `611d30d` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1406
+* Bump golang from 1.22.1-bookworm to 1.22.2-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1407
+* Bump golang.org/x/net from 0.22.0 to 0.23.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1408
+* update govulncheck go version from 1.21.8 to 1.21.9 by @phbnf in https://github.com/google/certificate-transparency-go/pull/1412
+* Bump golang from 1.22.1-bookworm to 1.22.2-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1409
+* Bump golang from 1.22.1-bookworm to 1.22.2-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1410
+* Bump golang.org/x/crypto from 0.21.0 to 0.22.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1414
+* Bump golang from 1.22.1-bookworm to 1.22.2-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1411
+* Bump github/codeql-action from 3.24.9 to 3.24.10 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1415
+* Bump golang.org/x/net from 0.23.0 to 0.24.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1416
+* Bump google.golang.org/grpc from 1.62.1 to 1.63.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1417
+* Bump github.com/fullstorydev/grpcurl from 1.8.9 to 1.9.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1419
+* Bump golang from `48b942a` to `3451eec` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1421
+* Bump golang from `48b942a` to `3451eec` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1423
+* Bump golang from `48b942a` to `3451eec` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1420
+* Bump golang from `3451eec` to `b03f3ba` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1426
+* Bump golang from `3451eec` to `b03f3ba` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1425
+* Bump golang from `48b942a` to `3451eec` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1422
+* Bump golang from `3451eec` to `b03f3ba` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1427
+* Bump golang from `3451eec` to `b03f3ba` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1428
+* Bump github/codeql-action from 3.24.10 to 3.25.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1433
+* Bump github/codeql-action from 3.25.0 to 3.25.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1434
+* Bump actions/upload-artifact from 4.3.1 to 4.3.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1436
+* Bump actions/checkout from 4.1.2 to 4.1.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1437
+* Bump actions/upload-artifact from 4.3.2 to 4.3.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1440
+* Bump github/codeql-action from 3.25.1 to 3.25.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1441
+* Bump golang from `b03f3ba` to `d0902ba` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1444
+* Bump golang from `b03f3ba` to `d0902ba` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1443
+* Bump github.com/rs/cors from 1.10.1 to 1.11.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1442
+* Bump golang from `b03f3ba` to `d0902ba` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1447
+* Bump actions/checkout from 4.1.3 to 4.1.4 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1446
+* Bump github/codeql-action from 3.25.2 to 3.25.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1449
+* Bump golangci/golangci-lint-action from 4.0.0 to 5.0.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1448
+* Bump golang from `b03f3ba` to `d0902ba` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1445
+* Bump golangci/golangci-lint-action from 5.0.0 to 5.1.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1451
+* Bump distroless/base-debian12 from `611d30d` to `d8d01e2` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1450
+* Bump google.golang.org/protobuf from 1.33.1-0.20240408130810-98873a205002 to 1.34.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1453
+* Bump actions/setup-go from 5.0.0 to 5.0.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1455
+* Bump golang.org/x/net from 0.24.0 to 0.25.0 and golang.org/x/crypto from v0.22.0 to v0.23.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1457
+* Bump google.golang.org/protobuf from 1.34.0 to 1.34.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1458
+* Bump distroless/base-debian12 from `d8d01e2` to `786007f` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1461
+* Bump golangci/golangci-lint-action from 5.1.0 to 5.3.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1460
+* Bump `go-version-input` to 1.21.10 in govulncheck.yml by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1472
+* Bump golangci/golangci-lint-action from 5.3.0 to 6.0.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1473
+* Bump actions/checkout from 4.1.4 to 4.1.5 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1469
+* Bump github.com/go-sql-driver/mysql from 1.7.1 to 1.8.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1465
+* Bump golang from 1.22.2-bookworm to 1.22.3-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1466
+* Bump golang from 1.22.2-bookworm to 1.22.3-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1463
+* Bump golang from 1.22.2-bookworm to 1.22.3-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1470
+* Bump golang from 1.22.2-bookworm to 1.22.3-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1467
+* Bump github/codeql-action from 3.25.3 to 3.25.4 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1474
+* Bump github.com/prometheus/client_golang from 1.19.0 to 1.19.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1475
+* Bump ossf/scorecard-action from 2.3.1 to 2.3.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1476
+* Bump github/codeql-action from 3.25.4 to 3.25.5 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1478
+* Bump golang from `6d71b7c` to `ef27a3c` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1480
+* Bump golang from `6d71b7c` to `ef27a3c` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1481
+* Bump golang from `6d71b7c` to `ef27a3c` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1479
+* Bump golang from `6d71b7c` to `ef27a3c` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1483
+* Bump golang from `ef27a3c` to `5c56bd4` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1484
+* Bump golang from `ef27a3c` to `5c56bd4` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1485
+* Bump golang from `ef27a3c` to `5c56bd4` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1486
+* Bump actions/checkout from 4.1.5 to 4.1.6 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1487
+* Bump golang from `ef27a3c` to `5c56bd4` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1488
+* Bump github/codeql-action from 3.25.5 to 3.25.6 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1490
+* Bump alpine from `c5b1261` to `58d02b4` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1491
+* Bump alpine from `58d02b4` to `77726ef` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1493
+
+## v1.1.8
+
+* Recommended Go version for development: 1.21
+ * Using a different version can lead to presubmits failing due to unexpected diffs.
+
+### Add support for AIX
+
+* crypto/x509: add AIX operating system by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1277
+
+### Monitoring
+
+* Distribution metric to monitor the start of get-entries requests by @phbnf in https://github.com/google/certificate-transparency-go/pull/1364
+
+### Fixes
+
+* Use the appropriate HTTP response code for backend timeouts by @robstradling in https://github.com/google/certificate-transparency-go/pull/1313
+
+### Misc
+
+* Move golangci-lint from Cloud Build to GitHub Action by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1230
+* Set golangci-lint GH action timeout to 5m by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1231
+* Added Slack channel details by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1246
+* Improve fuzzing by @AdamKorcz in https://github.com/google/certificate-transparency-go/pull/1345
+
+### Dependency update
+
+* Bump golang from `20f9ab5` to `5ee1296` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1216
+* Bump golang from `20f9ab5` to `5ee1296` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1217
+* Bump golang from `20f9ab5` to `5ee1296` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1218
+* Bump k8s.io/klog/v2 from 2.100.1 to 2.110.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1219
+* Bump golang from `20f9ab5` to `5ee1296` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1220
+* Bump golang from `5ee1296` to `5bafbbb` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1221
+* Bump golang from `5ee1296` to `5bafbbb` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1222
+* Bump golang from `5ee1296` to `5bafbbb` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1223
+* Bump golang from `5ee1296` to `5bafbbb` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1224
+* Update the minimal image to gcr.io/distroless/base-debian12 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1148
+* Bump jq from 1.6 to 1.7 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1225
+* Bump github.com/spf13/cobra from 1.7.0 to 1.8.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1226
+* Bump golang.org/x/time from 0.3.0 to 0.4.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1227
+* Bump github.com/mattn/go-sqlite3 from 1.14.17 to 1.14.18 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1228
+* Bump github.com/gorilla/mux from 1.8.0 to 1.8.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1229
+* Bump golang from 1.21.3-bookworm to 1.21.4-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1232
+* Bump golang from 1.21.3-bookworm to 1.21.4-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1233
+* Bump golang from 1.21.3-bookworm to 1.21.4-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1234
+* Bump golang from 1.21.3-bookworm to 1.21.4-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1235
+* Bump go-version-input from 1.20.10 to 1.20.11 in govulncheck.yml by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1238
+* Bump golang.org/x/net from 0.17.0 to 0.18.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1236
+* Bump github/codeql-action from 2.22.5 to 2.22.6 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1240
+* Bump github/codeql-action from 2.22.6 to 2.22.7 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1241
+* Bump golang from `85aacbe` to `dadce81` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1243
+* Bump golang from `85aacbe` to `dadce81` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1242
+* Bump golang from `85aacbe` to `dadce81` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1244
+* Bump golang from `85aacbe` to `dadce81` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1245
+* Bump golang from `dadce81` to `52362e2` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1247
+* Bump golang from `dadce81` to `52362e2` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1248
+* Bump golang from `dadce81` to `52362e2` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1249
+* Bump golang from `dadce81` to `52362e2` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1250
+* Bump github/codeql-action from 2.22.7 to 2.22.8 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1251
+* Bump golang.org/x/net from 0.18.0 to 0.19.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1252
+* Bump golang.org/x/time from 0.4.0 to 0.5.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1254
+* Bump alpine from `eece025` to `34871e7` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1256
+* Bump alpine from `eece025` to `34871e7` in /trillian/examples/deployment/docker/envsubst by @dependabot in https://github.com/google/certificate-transparency-go/pull/1257
+* Bump go-version-input from 1.20.11 to 1.20.12 in govulncheck.yml by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1264
+* Bump actions/setup-go from 4.1.0 to 5.0.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1261
+* Bump golang from 1.21.4-bookworm to 1.21.5-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1259
+* Bump golang from 1.21.4-bookworm to 1.21.5-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1263
+* Bump golang from 1.21.4-bookworm to 1.21.5-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1262
+* Bump golang from 1.21.4-bookworm to 1.21.5-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1260
+* Bump go.etcd.io/etcd/v3 from 3.5.10 to 3.5.11 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1266
+* Bump github/codeql-action from 2.22.8 to 2.22.9 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1269
+* Bump alpine from `34871e7` to `51b6726` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1270
+* Bump alpine from 3.18 to 3.19 in /trillian/examples/deployment/docker/envsubst by @dependabot in https://github.com/google/certificate-transparency-go/pull/1271
+* Bump golang from `a6b787c` to `2d3b13c` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1272
+* Bump golang from `a6b787c` to `2d3b13c` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1273
+* Bump golang from `a6b787c` to `2d3b13c` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1274
+* Bump golang from `a6b787c` to `2d3b13c` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1275
+* Bump github/codeql-action from 2.22.9 to 2.22.10 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1278
+* Bump google.golang.org/grpc from 1.59.0 to 1.60.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1279
+* Bump github/codeql-action from 2.22.10 to 3.22.11 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1280
+* Bump distroless/base-debian12 from `1dfdb5e` to `8a0bb63` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1281
+* Bump github.com/google/trillian from 1.5.3 to 1.5.4-0.20240110091238-00ca9abe023d by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1297
+* Bump actions/upload-artifact from 3.1.3 to 4.0.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1282
+* Bump github/codeql-action from 3.22.11 to 3.23.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1295
+* Bump github.com/mattn/go-sqlite3 from 1.14.18 to 1.14.19 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1283
+* Bump golang from 1.21.5-bookworm to 1.21.6-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1300
+* Bump distroless/base-debian12 from `8a0bb63` to `0a93daa` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1284
+* Bump golang from 1.21.5-bookworm to 1.21.6-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1299
+* Bump golang from 1.21.5-bookworm to 1.21.6-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1298
+* Bump golang from 1.21.5-bookworm to 1.21.6-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1301
+* Bump golang from `688ad7f` to `1e8ea75` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1306
+* Bump golang from `688ad7f` to `1e8ea75` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1305
+* Use trillian release instead of pinned commit by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1304
+* Bump actions/upload-artifact from 4.0.0 to 4.1.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1310
+* Bump golang from `1e8ea75` to `cbee5d2` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1312
+* Bump golang from `688ad7f` to `cbee5d2` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1308
+* Bump golang from `1e8ea75` to `cbee5d2` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1311
+* Bump golang.org/x/net from 0.19.0 to 0.20.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1302
+* Bump golang from `b651ed8` to `cbee5d2` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1309
+* Bump golang from `cbee5d2` to `c4b696f` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1314
+* Bump golang from `cbee5d2` to `c4b696f` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1315
+* Bump github/codeql-action from 3.23.0 to 3.23.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1317
+* Bump golang from `cbee5d2` to `c4b696f` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1316
+* Bump golang from `cbee5d2` to `c4b696f` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1318
+* Bump k8s.io/klog/v2 from 2.120.0 to 2.120.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1319
+* Bump actions/upload-artifact from 4.1.0 to 4.2.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1320
+* Bump actions/upload-artifact from 4.2.0 to 4.3.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1321
+* Bump golang from `c4b696f` to `d8c365d` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1326
+* Bump golang from `c4b696f` to `d8c365d` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1323
+* Bump google.golang.org/grpc from 1.60.1 to 1.61.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1324
+* Bump golang from `c4b696f` to `d8c365d` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1322
+* Bump golang from `c4b696f` to `d8c365d` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1325
+* Bump github.com/mattn/go-sqlite3 from 1.14.19 to 1.14.20 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1327
+* Bump github/codeql-action from 3.23.1 to 3.23.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1328
+* Bump alpine from `51b6726` to `c5b1261` in /trillian/examples/deployment/docker/envsubst by @dependabot in https://github.com/google/certificate-transparency-go/pull/1330
+* Bump alpine from `51b6726` to `c5b1261` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1329
+* Bump go.etcd.io/etcd/v3 from 3.5.11 to 3.5.12 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1332
+* Bump github.com/mattn/go-sqlite3 from 1.14.20 to 1.14.21 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1333
+* Bump golang from `d8c365d` to `69bfed3` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1335
+* Bump golang from `d8c365d` to `69bfed3` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1338
+* Bump golang from `d8c365d` to `69bfed3` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1337
+* Bump golang from `d8c365d` to `69bfed3` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1336
+* Bump golang from `69bfed3` to `3efef61` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1339
+* Bump github.com/mattn/go-sqlite3 from 1.14.21 to 1.14.22 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1344
+* Bump golang from `69bfed3` to `3efef61` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1341
+* Bump golang from `69bfed3` to `3efef61` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1343
+* Bump distroless/base-debian12 from `0a93daa` to `f47fa3d` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1340
+* Bump golang from `69bfed3` to `3efef61` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1342
+* Bump github/codeql-action from 3.23.2 to 3.24.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1346
+* Bump actions/upload-artifact from 4.3.0 to 4.3.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1347
+* Bump golang from 1.21.6-bookworm to 1.22.0-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1350
+* Bump golang from 1.21.6-bookworm to 1.22.0-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1348
+* Bump golang from 1.21.6-bookworm to 1.22.0-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1349
+* Bump golang from 1.21.6-bookworm to 1.22.0-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1351
+* Bump golang.org/x/crypto from 0.18.0 to 0.19.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1353
+* Bump golangci/golangci-lint-action from 3.7.0 to 4.0.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1354
+* Bump golang.org/x/net from 0.20.0 to 0.21.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1352
+* Bump distroless/base-debian12 from `f47fa3d` to `2102ce1` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1355
+* Bump github/codeql-action from 3.24.0 to 3.24.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1357
+* Bump golang from `874c267` to `5a3e169` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1356
+* Bump golang from `874c267` to `5a3e169` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1358
+* Bump golang from `874c267` to `5a3e169` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1359
+* Bump golang from `874c267` to `5a3e169` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1360
+* Bump github/codeql-action from 3.24.1 to 3.24.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1366
+* Bump golang from `5a3e169` to `925fe3f` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1363
+* Bump google.golang.org/grpc from 1.61.0 to 1.61.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1362
+* Bump golang from `5a3e169` to `925fe3f` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1365
+* Bump golang from `5a3e169` to `925fe3f` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1361
+* Bump golang from `5a3e169` to `925fe3f` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1367
+* Bump golang/govulncheck-action from 1.0.1 to 1.0.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1368
+* Bump github/codeql-action from 3.24.3 to 3.24.5 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1371
+* Bump google.golang.org/grpc from 1.61.1 to 1.62.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1369
+* Bump distroless/base-debian12 from `2102ce1` to `5eae9ef` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1372
+* Bump distroless/base-debian12 from `5eae9ef` to `f9b0e86` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1375
+* Bump golang.org/x/crypto from 0.19.0 to 0.20.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1374
+* Bump github.com/prometheus/client_golang from 1.18.0 to 1.19.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1373
+* Bump github/codeql-action from 3.24.5 to 3.24.6 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1377
+* Bump distroless/base-debian12 from `f9b0e86` to `5eae9ef` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1376
+* Bump golang.org/x/net from 0.21.0 to 0.22.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1378
+* Bump Go from 1.20 to 1.21 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1386
+* Bump google.golang.org/grpc from 1.62.0 to 1.62.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1380
+* Bump golang from 1.22.0-bookworm to 1.22.1-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1382
+* Bump golang from 1.22.0-bookworm to 1.22.1-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1385
+* Bump golang from 1.22.0-bookworm to 1.22.1-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1384
+* Bump golang from 1.22.0-bookworm to 1.22.1-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1383
+
+## v1.1.7
+
+* Recommended Go version for development: 1.20
+ * This is the version used by the Cloud Build presubmits. Using a different version can lead to presubmits failing due to unexpected diffs.
+
+* Bump golangci-lint from 1.51.1 to 1.55.1 (developers should update to this version).
+
+### Add support for WASI port
+
+* Add build tags for wasip1 GOOS by @flavio in https://github.com/google/certificate-transparency-go/pull/1089
+
+### Add support for IBM Z operating system z/OS
+
+* Add build tags for zOS by @onlywork1984 in https://github.com/google/certificate-transparency-go/pull/1088
+
+### Log List
+
+* Add support for "is_all_logs" field in loglist3 by @phbnf in https://github.com/google/certificate-transparency-go/pull/1095
+
+### Documentation
+
+* Improve Dockerized Test Deployment documentation by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1179
+
+### Misc
+
+* Escape forward slashes in certificate Subject names when used as user quota id strings by @robstradling in https://github.com/google/certificate-transparency-go/pull/1059
+* Search whole chain looking for issuer match by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1112
+* Use proper check per @AGWA instead of buggy check introduced in #1112 by @mhutchinson in https://github.com/google/certificate-transparency-go/pull/1114
+* Build the ctfe/ct_server binary without depending on glibc by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1119
+* Migrate CTFE Ingress manifest to support GKE version 1.23 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1086
+* Remove Dependabot ignore configuration by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1097
+* Add "github-actions" and "docker" Dependabot config by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1101
+* Add top level permission in CodeQL workflow by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1102
+* Pin Docker image dependencies by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1110
+* Remove GO111MODULE from Dockerfile and Cloud Build yaml files by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1113
+* Add docker Dependabot config by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1126
+* Export is_mirror = 0.0 for non mirror instead of nothing by @phbnf in https://github.com/google/certificate-transparency-go/pull/1133
+* Add govulncheck GitHub action by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1145
+* Spelling by @jsoref in https://github.com/google/certificate-transparency-go/pull/1144
+
+### Dependency update
+
+* Bump Go from 1.19 to 1.20 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1146
+* Bump golangci-lint from 1.51.1 to 1.55.1 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1214
+* Bump go.etcd.io/etcd/v3 from 3.5.8 to 3.5.9 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1083
+* Bump golang.org/x/crypto from 0.8.0 to 0.9.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/108
+* Bump github.com/mattn/go-sqlite3 from 1.14.16 to 1.14.17 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1092
+* Bump golang.org/x/net from 0.10.0 to 0.11.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1094
+* Bump github.com/prometheus/client_golang from 1.15.1 to 1.16.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1098
+* Bump google.golang.org/protobuf from 1.30.0 to 1.31.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1099
+* Bump golang.org/x/net from 0.11.0 to 0.12.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1108
+* Bump actions/checkout from 3.1.0 to 3.5.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1103
+* Bump github/codeql-action from 2.1.27 to 2.20.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1104
+* Bump ossf/scorecard-action from 2.0.6 to 2.2.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1105
+* Bump actions/upload-artifact from 3.1.0 to 3.1.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1106
+* Bump github/codeql-action from 2.20.3 to 2.20.4 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1115
+* Bump github/codeql-action from 2.20.4 to 2.21.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1117
+* Bump golang.org/x/net from 0.12.0 to 0.14.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1124
+* Bump github/codeql-action from 2.21.0 to 2.21.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1121
+* Bump github/codeql-action from 2.21.2 to 2.21.4 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1125
+* Bump golang from `fd9306e` to `eb3f9ac` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1127
+* Bump alpine from 3.8 to 3.18 in /trillian/examples/deployment/docker/envsubst by @dependabot in https://github.com/google/certificate-transparency-go/pull/1129
+* Bump golang from `fd9306e` to `eb3f9ac` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1128
+* Bump alpine from `82d1e9d` to `7144f7b` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1130
+* Bump golang from `fd9306e` to `eb3f9ac` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1131
+* Bump golang from 1.19-alpine to 1.21-alpine in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1132
+* Bump actions/checkout from 3.5.3 to 3.6.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1134
+* Bump github/codeql-action from 2.21.4 to 2.21.5 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1135
+* Bump distroless/base from `73deaaf` to `46c5b9b` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1136
+* Bump actions/checkout from 3.6.0 to 4.0.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1137
+* Bump golang.org/x/net from 0.14.0 to 0.15.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1139
+* Bump github.com/rs/cors from 1.9.0 to 1.10.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1140
+* Bump actions/upload-artifact from 3.1.2 to 3.1.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1141
+* Bump golang from `445f340` to `96634e5` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1142
+* Bump github/codeql-action from 2.21.5 to 2.21.6 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1149
+* Bump Docker golang base images to 1.21.1 by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1147
+* Bump github/codeql-action from 2.21.6 to 2.21.7 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1150
+* Bump github/codeql-action from 2.21.7 to 2.21.8 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1152
+* Bump golang from `d3114db` to `a0b3bc4` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1155
+* Bump golang from `d3114db` to `a0b3bc4` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1157
+* Bump golang from `d3114db` to `a0b3bc4` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1156
+* Bump golang from `d3114db` to `a0b3bc4` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1158
+* Bump golang from `e06b3a4` to `114b9cc` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1159
+* Bump golang from `a0b3bc4` to `114b9cc` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1160
+* Bump golang from `a0b3bc4` to `114b9cc` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1161
+* Bump actions/checkout from 4.0.0 to 4.1.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1162
+* Bump golang from `114b9cc` to `9c7ea4a` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1163
+* Bump golang from `114b9cc` to `9c7ea4a` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1166
+* Bump golang from `114b9cc` to `9c7ea4a` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1165
+* Bump golang from `114b9cc` to `9c7ea4a` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1164
+* Bump github/codeql-action from 2.21.8 to 2.21.9 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1169
+* Bump golang from `9c7ea4a` to `61f84bc` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1168
+* Bump github.com/prometheus/client_golang from 1.16.0 to 1.17.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1172
+* Bump golang from `9c7ea4a` to `61f84bc` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1170
+* Bump github.com/rs/cors from 1.10.0 to 1.10.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1176
+* Bump alpine from `7144f7b` to `eece025` in /trillian/examples/deployment/docker/envsubst by @dependabot in https://github.com/google/certificate-transparency-go/pull/1174
+* Bump alpine from `7144f7b` to `eece025` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1175
+* Bump golang from `9c7ea4a` to `61f84bc` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1171
+* Bump golang from `9c7ea4a` to `61f84bc` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1173
+* Bump distroless/base from `46c5b9b` to `a35b652` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1177
+* Bump golang.org/x/crypto from 0.13.0 to 0.14.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1178
+* Bump github/codeql-action from 2.21.9 to 2.22.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1180
+* Bump golang from 1.21.1-bookworm to 1.21.2-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1181
+* Bump golang.org/x/net from 0.15.0 to 0.16.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1184
+* Bump golang from 1.21.1-bookworm to 1.21.2-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1182
+* Bump golang from 1.21.1-bookworm to 1.21.2-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1185
+* Bump golang from 1.21.1-bookworm to 1.21.2-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1183
+* Bump github/codeql-action from 2.22.0 to 2.22.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1186
+* Bump distroless/base from `a35b652` to `b31a6e0` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1188
+* Bump ossf/scorecard-action from 2.2.0 to 2.3.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1187
+* Bump github.com/google/go-cmp from 0.5.9 to 0.6.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1189
+* Bump golang.org/x/net from 0.16.0 to 0.17.0 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1190
+* Bump go-version-input from 1.20.8 to 1.20.10 in govulncheck by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1195
+* Bump golang from 1.21.2-bookworm to 1.21.3-bookworm in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1193
+* Bump golang from 1.21.2-bookworm to 1.21.3-bookworm in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1191
+* Bump golang from 1.21.2-bookworm to 1.21.3-bookworm in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1194
+* Bump golang from 1.21.2-bookworm to 1.21.3-bookworm in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1192
+* Bump golang from `a94b089` to `8f9a1ec` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1196
+* Bump github/codeql-action from 2.22.1 to 2.22.2 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1197
+* Bump golang from `a94b089` to `5cc7ddc` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1200
+* Bump golang from `a94b089` to `5cc7ddc` in /internal/witness/cmd/witness by @dependabot in https://github.com/google/certificate-transparency-go/pull/1199
+* Bump github/codeql-action from 2.22.2 to 2.22.3 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1202
+* Bump golang from `5cc7ddc` to `20f9ab5` in /integration by @dependabot in https://github.com/google/certificate-transparency-go/pull/1203
+* Bump golang from `a94b089` to `20f9ab5` in /trillian/examples/deployment/docker/ctfe by @dependabot in https://github.com/google/certificate-transparency-go/pull/1198
+* Bump golang from `8f9a1ec` to `20f9ab5` in /internal/witness/cmd/feeder by @dependabot in https://github.com/google/certificate-transparency-go/pull/1201
+* Bump actions/checkout from 4.1.0 to 4.1.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1204
+* Bump github/codeql-action from 2.22.3 to 2.22.4 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1206
+* Bump ossf/scorecard-action from 2.3.0 to 2.3.1 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1207
+* Bump github/codeql-action from 2.22.4 to 2.22.5 by @dependabot in https://github.com/google/certificate-transparency-go/pull/1209
+* Bump multiple Go module dependencies by @roger2hk in https://github.com/google/certificate-transparency-go/pull/1213
+
+## v1.1.6
+
+### Dependency update
+
+* Bump Trillian to v1.5.2
+* Bump Prometheus to v0.43.1
+
+## v1.1.5
+
+### Public/Private Key Consistency
+
+ * #1044: If a public key has been configured for a log, check that it is consistent with the private key.
+ * #1046: Ensure that no two logs in the CTFE configuration use the same private key.
+
+### Cleanup
+
+ * Remove v2 log list package files.
+
+### Misc
+
+ * Updated golangci-lint to v1.51.1 (developers should update to this version).
+ * Bump Go version from 1.17 to 1.19.
+
+## v1.1.4
+
+[Published 2022-10-21](https://github.com/google/certificate-transparency-go/releases/tag/v1.1.4)
+
+### Cleanup
+
+ * Remove log list v1 package and its dependencies.
+
+### Migrillian
+
+ * #960: Skip consistency check when root is size zero.
+
+### Misc
+
+ * Update Trillian to [0a389c4](https://github.com/google/trillian/commit/0a389c4bb8d97fb3be8f55d7e5b428cf4304986f)
+ * Migrate loglist dependency from v1 to v3 in ctclient cmd.
+ * Migrate loglist dependency from v1 to v3 in ctutil/loginfo.go
+ * Migrate loglist dependency from v1 to v3 in ctutil/sctscan.go
+ * Migrate loglist dependency from v1 to v3 in trillian/integration/ct_hammer/main.go
+ * Downgrade 429 errors to verbosity 2
+
+## v1.1.3
+
+[Published 2022-05-14](https://github.com/google/certificate-transparency-go/releases/tag/v1.1.3)
+
+### Integration
+
+ * Breaking change to API for `integration.HammerCTLog`:
+ * Added `ctx` as first argument, and terminate loop if it becomes cancelled
+
+### JSONClient
+
+ * PostAndParseWithRetry now does backoff-and-retry upon receiving HTTP 429.
+
+### Cleanup
+
+ * `WithBalancerName` is deprecated and removed, using the recommended way.
+ * `ctfe.PEMCertPool` type has been moved to `x509util.PEMCertPool` to reduce
+ dependencies (#903).
+
+### Misc
+
+ * updated golangci-lint to v1.46.1 (developers should update to this version)
+ * update `google.golang.org/grpc` to v1.46.0
+ * `ctclient` tool now uses Cobra for better CLI experience (#901).
+ * #800: Remove dependency from `ratelimit`.
+ * #927: Add read-only mode to CTFE config.
+
+## v1.1.2
+
+[Published 2021-09-21](https://github.com/google/certificate-transparency-go/releases/tag/v1.1.2)
+
+### CTFE
+
+ * Removed the `-by_range` flag.
+
+### Updated dependencies
+
+ * Trillian from v1.3.11 to v1.4.0
+ * protobuf to v2
+
+## v1.1.1
+
+[Published 2020-10-06](https://github.com/google/certificate-transparency-go/releases/tag/v1.1.1)
+
+### Tools
+
+#### CT Hammer
+
+Added a flag (--strict_sth_consistency_size) which when set to true enforces the current behaviour of only request consistency proofs between tree sizes for which the hammer has seen valid STHs.
+When setting this flag to false, if no two usable STHs are available the hammer will attempt to request a consistency proof between the latest STH it's seen and a random smaller (but > 0) tree size.
+
+
+### CTFE
+
+#### Caching
+
+The CTFE now includes a Cache-Control header in responses containing purely
+immutable data, e.g. those for get-entries and get-proof-by-hash. This allows
+clients and proxies to cache these responses for up to 24 hours.
+
+#### EKU Filtering
+
+> :warning: **It is not yet recommended to enable this option in a production CT Log!**
+
+CTFE now supports filtering logging submissions by leaf certificate EKU.
+This is enabled by adding an extKeyUsage list to a log's stanza in the
+config file.
+
+The format is a list of strings corresponding to the supported golang x509 EKUs:
+ |Config string | Extended Key Usage |
+ |----------------------------|----------------------------------------|
+ |`Any` | ExtKeyUsageAny |
+ |`ServerAuth` | ExtKeyUsageServerAuth |
+ |`ClientAuth` | ExtKeyUsageClientAuth |
+ |`CodeSigning` | ExtKeyUsageCodeSigning |
+ |`EmailProtection` | ExtKeyUsageEmailProtection |
+ |`IPSECEndSystem` | ExtKeyUsageIPSECEndSystem |
+ |`IPSECTunnel` | ExtKeyUsageIPSECTunnel |
+ |`IPSECUser` | ExtKeyUsageIPSECUser |
+ |`TimeStamping` | ExtKeyUsageTimeStamping |
+ |`OCSPSigning` | ExtKeyUsageOCSPSigning |
+ |`MicrosoftServerGatedCrypto`| ExtKeyUsageMicrosoftServerGatedCrypto |
+ |`NetscapeServerGatedCrypto` | ExtKeyUsageNetscapeServerGatedCrypto |
+
+When an extKeyUsage list is specified, the CT Log will reject logging
+submissions for leaf certificates that do not contain an EKU present in this
+list.
+
+When enabled, EKU filtering is only performed at the leaf level (i.e. there is
+no 'nested' EKU filtering performed).
+
+If no list is specified, or the list contains an `Any` entry, no EKU
+filtering will be performed.
+
+#### GetEntries
+Calls to `get-entries` which are at (or above) the maximum permitted number of
+entries whose `start` parameter does not fall on a multiple of the maximum
+permitted number of entries, will have their responses truncated such that
+subsequent requests will align with this boundary.
+This is intended to coerce callers of `get-entries` into all using the same
+`start` and `end` parameters and thereby increase the cacheability of
+these requests.
+
+e.g.:
+
+