Repository: spf13/viper
Pull request #1628 (2023-09-12 07:40:59)

Make deps fixes
Diving into viper development environment, I hit some rough edges. Here are some fixes for this.

CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/spf13/viper?pullRequest=1628) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/spf13/viper?pullRequest=1628) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/spf13/viper?pullRequest=1628) it.</sub>
github-actions[bot]: 👋 Thanks for contributing to Viper! You are awesome! 🎉

A maintainer will take a look at your pull request shortly. 👀

In the meantime: We are working on **Viper v2** and we would love to hear your thoughts about what you like or don't like about Viper, so we can improve or fix those issues.

⏰ If you have a couple minutes, please take some time and share your thoughts: https://forms.gle/R6faU74qPRPAzchZ9

📣 If you've already given us your feedback, you can still help by spreading the news,
either by sharing the above link or telling people about this on Twitter:

https://twitter.com/sagikazarmark/status/1306904078967074816

**Thank you!** ❤️


Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index bce54e8..ba9b530 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -21,7 +21,7 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
 
       - name: Set up Go
         uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
@@ -45,10 +45,11 @@ jobs:
       matrix:
         os: [ubuntu-latest, macos-latest, windows-latest]
         go: ['1.19', '1.20', '1.21']
+        tags: ['', 'finder']
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
 
       - name: Set up Go
         uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
@@ -56,11 +57,11 @@ jobs:
           go-version: ${{ matrix.go }}
 
       - name: Test
-        run: go test -race -v ./...
+        run: go test -race -v -tags '${{ matrix.tags }}' ./...
         if: runner.os != 'Windows'
 
       - name: Test (without race detector)
-        run: go test -v ./...
+        run: go test -v -tags '${{ matrix.tags }}' ./...
         if: runner.os == 'Windows'
 
   lint:
@@ -69,7 +70,7 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
 
       - name: Set up Go
         uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
@@ -87,7 +88,7 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
 
       - name: Set up Nix
         uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23
@@ -108,7 +109,7 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
 
       - name: Dependency Review
         uses: actions/dependency-review-action@6c5ccdad469c9f8a2996bfecaec55a631a347034 # v3.1.0
diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml
index da36e23..dad2759 100644
--- a/.github/workflows/codeql-analysis.yaml
+++ b/.github/workflows/codeql-analysis.yaml
@@ -39,11 +39,11 @@ jobs:
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+      uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@00e563ead9f72a8461b24876bee2d0c2e8bd2ee8 # v2.21.5
+      uses: github/codeql-action/init@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
       with:
         languages: ${{ matrix.language }}
         # If you wish to specify custom queries, you can do so here or in a config file.
@@ -54,7 +54,7 @@ jobs:
     # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
     # If this step fails, then you should remove it and run the build manually (see below)
     - name: Autobuild
-      uses: github/codeql-action/autobuild@00e563ead9f72a8461b24876bee2d0c2e8bd2ee8 # v2.21.5
+      uses: github/codeql-action/autobuild@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
 
     # ℹ️ Command-line programs to run using the OS shell.
     # 📚 https://git.io/JvXDl
@@ -68,5 +68,5 @@ jobs:
     #   make release
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@00e563ead9f72a8461b24876bee2d0c2e8bd2ee8 # v2.21.5
+      uses: github/codeql-action/analyze@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
 
diff --git a/Makefile b/Makefile
index a2bb79e..a77b9c8 100644
--- a/Makefile
+++ b/Makefile
@@ -66,9 +66,9 @@ bin/golangci-lint:
 	@mkdir -p bin
 	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- v${GOLANGCI_VERSION}
 
-.PHONY: fmt
+.PHONY: yamllint
 yamllint:
-	pip install --user yamllint
+	pip3 install --user yamllint
 
 # Add custom targets here
 -include custom.mk
diff --git a/README.md b/README.md
index f451881..78102fb 100644
--- a/README.md
+++ b/README.md
@@ -222,6 +222,7 @@ These could be from a command line flag, or from your own application logic.
 ```go
 viper.Set("Verbose", true)
 viper.Set("LogFile", LogFile)
+viper.Set("host.port", 5899)   // set subset
 ```
 
 ### Registering and Using Aliases
@@ -544,19 +545,19 @@ go func(){
 In Viper, there are a few ways to get a value depending on the value’s type.
 The following functions and methods exist:
 
- * `Get(key string) : interface{}`
+ * `Get(key string) : any`
  * `GetBool(key string) : bool`
  * `GetFloat64(key string) : float64`
  * `GetInt(key string) : int`
  * `GetIntSlice(key string) : []int`
  * `GetString(key string) : string`
- * `GetStringMap(key string) : map[string]interface{}`
+ * `GetStringMap(key string) : map[string]any`
  * `GetStringMapString(key string) : map[string]string`
  * `GetStringSlice(key string) : []string`
  * `GetTime(key string) : time.Time`
  * `GetDuration(key string) : time.Duration`
  * `IsSet(key string) : bool`
- * `AllSettings() : map[string]interface{}`
+ * `AllSettings() : map[string]any`
 
 One important thing to recognize is that each Get function will return a zero
 value if it’s not found. To check if a given key exists, the `IsSet()` method
@@ -719,8 +720,8 @@ etc.
 
 There are two methods to do this:
 
- * `Unmarshal(rawVal interface{}) : error`
- * `UnmarshalKey(key string, rawVal interface{}) : error`
+ * `Unmarshal(rawVal any) : error`
+ * `UnmarshalKey(key string, rawVal any) : error`
 
 Example:
 
@@ -745,9 +746,9 @@ you have to change the delimiter:
 ```go
 v := viper.NewWithOptions(viper.KeyDelimiter("::"))
 
-v.SetDefault("chart::values", map[string]interface{}{
-	"ingress": map[string]interface{}{
-		"annotations": map[string]interface{}{
+v.SetDefault("chart::values", map[string]any{
+	"ingress": map[string]any{
+		"annotations": map[string]any{
 			"traefik.frontend.rule.type":                 "PathPrefix",
 			"traefik.ingress.kubernetes.io/ssl-redirect": "true",
 		},
@@ -756,7 +757,7 @@ v.SetDefault("chart::values", map[string]interface{}{
 
 type config struct {
 	Chart struct{
-		Values map[string]interface{}
+		Values map[string]any
 	}
 }
 
diff --git a/experimental_logger.go b/experimental_logger.go
deleted file mode 100644
index 206dad6..0000000
--- a/experimental_logger.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build viper_logger
-// +build viper_logger
-
-package viper
-
-// WithLogger sets a custom logger.
-func WithLogger(l Logger) Option {
-	return optionFunc(func(v *Viper) {
-		v.logger = l
-	})
-}
diff --git a/fs.go b/fs.go
deleted file mode 100644
index ecb1769..0000000
--- a/fs.go
+++ /dev/null
@@ -1,65 +0,0 @@
-//go:build go1.16 && finder
-// +build go1.16,finder
-
-package viper
-
-import (
-	"errors"
-	"io/fs"
-	"path"
-)
-
-type finder struct {
-	paths      []string
-	fileNames  []string
-	extensions []string
-
-	withoutExtension bool
-}
-
-func (f finder) Find(fsys fs.FS) (string, error) {
-	for _, searchPath := range f.paths {
-		for _, fileName := range f.fileNames {
-			for _, extension := range f.extensions {
-				filePath := path.Join(searchPath, fileName+"."+extension)
-
-				ok, err := fileExists(fsys, filePath)
-				if err != nil {
-					return "", err
-				}
-
-				if ok {
-					return filePath, nil
-				}
-			}
-
-			if f.withoutExtension {
-				filePath := path.Join(searchPath, fileName)
-
-				ok, err := fileExists(fsys, filePath)
-				if err != nil {
-					return "", err
-				}
-
-				if ok {
-					return filePath, nil
-				}
-			}
-		}
-	}
-
-	return "", nil
-}
-
-func fileExists(fsys fs.FS, filePath string) (bool, error) {
-	fileInfo, err := fs.Stat(fsys, filePath)
-	if err == nil {
-		return !fileInfo.IsDir(), nil
-	}
-
-	if errors.Is(err, fs.ErrNotExist) {
-		return false, nil
-	}
-
-	return false, err
-}
diff --git a/go.mod b/go.mod
index 5cabc6e..ff4cfdf 100644
--- a/go.mod
+++ b/go.mod
@@ -8,10 +8,11 @@ require (
 	github.com/magiconair/properties v1.8.7
 	github.com/mitchellh/mapstructure v1.5.0
 	github.com/pelletier/go-toml/v2 v2.1.0
-	github.com/sagikazarmark/crypt v0.14.0
-	github.com/spf13/afero v1.9.5
+	github.com/sagikazarmark/crypt v0.15.0
+	github.com/sagikazarmark/locafero v0.3.0
+	github.com/sagikazarmark/slog-shim v0.1.0
+	github.com/spf13/afero v1.10.0
 	github.com/spf13/cast v1.5.1
-	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.8.4
 	github.com/subosito/gotenv v1.6.0
@@ -20,10 +21,10 @@ require (
 )
 
 require (
-	cloud.google.com/go v0.110.6 // indirect
+	cloud.google.com/go v0.110.7 // indirect
 	cloud.google.com/go/compute v1.23.0 // indirect
 	cloud.google.com/go/compute/metadata v0.2.3 // indirect
-	cloud.google.com/go/firestore v1.12.0 // indirect
+	cloud.google.com/go/firestore v1.13.0 // indirect
 	cloud.google.com/go/longrunning v0.5.1 // indirect
 	github.com/armon/go-metrics v0.4.1 // indirect
 	github.com/coreos/go-semver v0.3.0 // indirect
@@ -34,10 +35,10 @@ require (
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/google/go-cmp v0.5.9 // indirect
-	github.com/google/s2a-go v0.1.5 // indirect
-	github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
+	github.com/google/s2a-go v0.1.7 // indirect
+	github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
 	github.com/googleapis/gax-go/v2 v2.12.0 // indirect
-	github.com/hashicorp/consul/api v1.24.0 // indirect
+	github.com/hashicorp/consul/api v1.25.1 // indirect
 	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
 	github.com/hashicorp/go-hclog v1.5.0 // indirect
 	github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
@@ -45,7 +46,7 @@ require (
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/hashicorp/serf v0.10.1 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/compress v1.16.5 // indirect
+	github.com/klauspost/compress v1.17.0 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
 	github.com/mattn/go-isatty v0.0.17 // indirect
 	github.com/minio/highwayhash v1.0.2 // indirect
@@ -53,33 +54,34 @@ require (
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/nats-io/jwt/v2 v2.4.1 // indirect
-	github.com/nats-io/nats.go v1.28.0 // indirect
-	github.com/nats-io/nkeys v0.4.4 // indirect
+	github.com/nats-io/nats.go v1.30.2 // indirect
+	github.com/nats-io/nkeys v0.4.5 // indirect
 	github.com/nats-io/nuid v1.0.1 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+	github.com/sourcegraph/conc v0.3.0 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.9 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
 	go.etcd.io/etcd/client/v2 v2.305.9 // indirect
 	go.etcd.io/etcd/client/v3 v3.5.9 // indirect
 	go.opencensus.io v0.24.0 // indirect
 	go.uber.org/atomic v1.9.0 // indirect
-	go.uber.org/multierr v1.8.0 // indirect
+	go.uber.org/multierr v1.9.0 // indirect
 	go.uber.org/zap v1.21.0 // indirect
 	golang.org/x/crypto v0.13.0 // indirect
-	golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
-	golang.org/x/net v0.14.0 // indirect
-	golang.org/x/oauth2 v0.11.0 // indirect
+	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
+	golang.org/x/net v0.15.0 // indirect
+	golang.org/x/oauth2 v0.12.0 // indirect
 	golang.org/x/sync v0.3.0 // indirect
 	golang.org/x/sys v0.12.0 // indirect
 	golang.org/x/text v0.13.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
-	google.golang.org/api v0.138.0 // indirect
+	google.golang.org/api v0.143.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
-	google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect
-	google.golang.org/grpc v1.58.0 // indirect
+	google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
+	google.golang.org/grpc v1.58.2 // indirect
 	google.golang.org/protobuf v1.31.0 // indirect
 )
diff --git a/go.sum b/go.sum
index f608c28..2de8b34 100644
--- a/go.sum
+++ b/go.sum
@@ -17,8 +17,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
 cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
 cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
 cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
-cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q=
-cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
+cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
+cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
 cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
 cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -31,8 +31,8 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB
 cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/firestore v1.12.0 h1:aeEA/N7DW7+l2u5jtkO8I0qv0D95YwjggD8kUHrTHO4=
-cloud.google.com/go/firestore v1.12.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4=
+cloud.google.com/go/firestore v1.13.0 h1:/3S4RssUV4GO/kvgJZB+tayjhOfyAHs+KcpJgRVu/Qk=
+cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8=
 cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
 cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
 cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@@ -53,7 +53,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
@@ -77,10 +76,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
@@ -94,7 +89,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
@@ -104,7 +98,6 @@ github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8Wlg
 github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -145,7 +138,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -179,19 +171,18 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
 github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg=
-github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
+github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
+github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
-github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
+github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ=
+github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
 github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.24.0 h1:u2XyStA2j0jnCiVUU7Qyrt8idjRn4ORhK6DlvZ3bWhA=
-github.com/hashicorp/consul/api v1.24.0/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg=
+github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
+github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
 github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
@@ -241,8 +232,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
-github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
+github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -291,10 +282,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
 github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4=
 github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
 github.com/nats-io/nats-server/v2 v2.9.20 h1:bt1dW6xsL1hWWwv7Hovm+EJt5L6iplyqlgEFkoEUk0k=
-github.com/nats-io/nats.go v1.28.0 h1:Th4G6zdsz2d0OqXdfzKLClo6bOfoI/b1kInhRtFIy5c=
-github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc=
-github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA=
-github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
+github.com/nats-io/nats.go v1.30.2 h1:aloM0TGpPorZKQhbAkdCzYDj+ZmsJDyeo3Gkbr72NuY=
+github.com/nats-io/nats.go v1.30.2/go.mod h1:dcfhUgmQNN4GJEfIb2f9R7Fow+gzBF4emzDHrVBd5qM=
+github.com/nats-io/nkeys v0.4.5 h1:Zdz2BUlFm4fJlierwvGK+yl20IAKUm7eV6AAZXEhkPk=
+github.com/nats-io/nkeys v0.4.5/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
 github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -324,22 +315,25 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
 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.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
-github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/sagikazarmark/crypt v0.14.0 h1:+QD5vjd6aZd6moHuIRVL+uJO7fkhiRjMz3ldbZQY5go=
-github.com/sagikazarmark/crypt v0.14.0/go.mod h1:JuxBJUNXrVOAywrtQNTZpOeTgcL1Az5qM7jKVDOifig=
+github.com/sagikazarmark/crypt v0.15.0 h1:TQJg76CemcIdJyC9/dmNjU9OUyIFHyvE50Tpq1t1nqY=
+github.com/sagikazarmark/crypt v0.15.0/go.mod h1:5rwNNax6Mlk9sZ40AcyVtiEw24Z4J04cfSioF2COKmc=
+github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
+github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
+github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
+github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
-github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
+github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
+github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
+github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
+github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
 github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
-github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
-github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -366,7 +360,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs=
 go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k=
 go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE=
@@ -383,15 +376,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
 go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
 go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
-go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
-go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
+go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
+go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
 go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
 go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -402,8 +394,6 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
@@ -417,8 +407,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
-golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
+golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
+golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -443,7 +433,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 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=
@@ -482,9 +471,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
-golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -494,8 +482,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
-golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
+golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
+golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
 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=
@@ -507,7 +495,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -561,15 +548,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -578,7 +562,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -637,7 +620,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -663,8 +645,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
 google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
 google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0=
-google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY=
+google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA=
+google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk=
 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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -696,7 +678,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
 google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
@@ -710,12 +691,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g=
-google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
-google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44=
-google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
+google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA=
+google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
+google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI=
+google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -729,14 +710,11 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
 google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o=
-google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
+google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
+google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -761,7 +739,6 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/internal/encoding/decoder.go b/internal/encoding/decoder.go
index f472e9f..8a7b1db 100644
--- a/internal/encoding/decoder.go
+++ b/internal/encoding/decoder.go
@@ -5,9 +5,9 @@ import (
 )
 
 // Decoder decodes the contents of b into v.
-// It's primarily used for decoding contents of a file into a map[string]interface{}.
+// It's primarily used for decoding contents of a file into a map[string]any.
 type Decoder interface {
-	Decode(b []byte, v map[string]interface{}) error
+	Decode(b []byte, v map[string]any) error
 }
 
 const (
@@ -48,7 +48,7 @@ func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
 }
 
 // Decode calls the underlying Decoder based on the format.
-func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]interface{}) error {
+func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
 	e.mu.RLock()
 	decoder, ok := e.decoders[format]
 	e.mu.RUnlock()
diff --git a/internal/encoding/dotenv/codec.go b/internal/encoding/dotenv/codec.go
index 4485063..3ebc76f 100644
--- a/internal/encoding/dotenv/codec.go
+++ b/internal/encoding/dotenv/codec.go
@@ -15,8 +15,8 @@ const keyDelimiter = "_"
 // (commonly called as dotenv format).
 type Codec struct{}
 
-func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
-	flattened := map[string]interface{}{}
+func (Codec) Encode(v map[string]any) ([]byte, error) {
+	flattened := map[string]any{}
 
 	flattened = flattenAndMergeMap(flattened, v, "", keyDelimiter)
 
@@ -40,7 +40,7 @@ func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
 	return buf.Bytes(), nil
 }
 
-func (Codec) Decode(b []byte, v map[string]interface{}) error {
+func (Codec) Decode(b []byte, v map[string]any) error {
 	var buf bytes.Buffer
 
 	_, err := buf.Write(b)
diff --git a/internal/encoding/dotenv/map_utils.go b/internal/encoding/dotenv/map_utils.go
index aeb6b87..1340c73 100644
--- a/internal/encoding/dotenv/map_utils.go
+++ b/internal/encoding/dotenv/map_utils.go
@@ -9,25 +9,25 @@ import (
 // flattenAndMergeMap recursively flattens the given map into a new map
 // Code is based on the function with the same name in the main package.
 // TODO: move it to a common place
-func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} {
+func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
 	if shadow != nil && prefix != "" && shadow[prefix] != nil {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
 	}
 	if shadow == nil {
-		shadow = make(map[string]interface{})
+		shadow = make(map[string]any)
 	}
 
-	var m2 map[string]interface{}
+	var m2 map[string]any
 	if prefix != "" {
 		prefix += delimiter
 	}
 	for k, val := range m {
 		fullKey := prefix + k
 		switch val := val.(type) {
-		case map[string]interface{}:
+		case map[string]any:
 			m2 = val
-		case map[interface{}]interface{}:
+		case map[any]any:
 			m2 = cast.ToStringMap(val)
 		default:
 			// immediate value
diff --git a/internal/encoding/encoder.go b/internal/encoding/encoder.go
index 2341bf2..6595859 100644
--- a/internal/encoding/encoder.go
+++ b/internal/encoding/encoder.go
@@ -5,9 +5,9 @@ import (
 )
 
 // Encoder encodes the contents of v into a byte representation.
-// It's primarily used for encoding a map[string]interface{} into a file format.
+// It's primarily used for encoding a map[string]any into a file format.
 type Encoder interface {
-	Encode(v map[string]interface{}) ([]byte, error)
+	Encode(v map[string]any) ([]byte, error)
 }
 
 const (
@@ -47,7 +47,7 @@ func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
 	return nil
 }
 
-func (e *EncoderRegistry) Encode(format string, v map[string]interface{}) ([]byte, error) {
+func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) {
 	e.mu.RLock()
 	encoder, ok := e.encoders[format]
 	e.mu.RUnlock()
diff --git a/internal/encoding/hcl/codec.go b/internal/encoding/hcl/codec.go
index 7fde8e4..d7fa8a1 100644
--- a/internal/encoding/hcl/codec.go
+++ b/internal/encoding/hcl/codec.go
@@ -12,7 +12,7 @@ import (
 // TODO: add printer config to the codec?
 type Codec struct{}
 
-func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
+func (Codec) Encode(v map[string]any) ([]byte, error) {
 	b, err := json.Marshal(v)
 	if err != nil {
 		return nil, err
@@ -35,6 +35,6 @@ func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
 	return buf.Bytes(), nil
 }
 
-func (Codec) Decode(b []byte, v map[string]interface{}) error {
+func (Codec) Decode(b []byte, v map[string]any) error {
 	return hcl.Unmarshal(b, &v)
 }
diff --git a/internal/encoding/ini/codec.go b/internal/encoding/ini/codec.go
index 9acd87f..d91cf59 100644
--- a/internal/encoding/ini/codec.go
+++ b/internal/encoding/ini/codec.go
@@ -19,11 +19,11 @@ type Codec struct {
 	LoadOptions  LoadOptions
 }
 
-func (c Codec) Encode(v map[string]interface{}) ([]byte, error) {
+func (c Codec) Encode(v map[string]any) ([]byte, error) {
 	cfg := ini.Empty()
 	ini.PrettyFormat = false
 
-	flattened := map[string]interface{}{}
+	flattened := map[string]any{}
 
 	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
 
@@ -62,7 +62,7 @@ func (c Codec) Encode(v map[string]interface{}) ([]byte, error) {
 	return buf.Bytes(), nil
 }
 
-func (c Codec) Decode(b []byte, v map[string]interface{}) error {
+func (c Codec) Decode(b []byte, v map[string]any) error {
 	cfg := ini.Empty(c.LoadOptions)
 
 	err := cfg.Append(b)
diff --git a/internal/encoding/ini/map_utils.go b/internal/encoding/ini/map_utils.go
index 4fb9eb1..c1919a3 100644
--- a/internal/encoding/ini/map_utils.go
+++ b/internal/encoding/ini/map_utils.go
@@ -15,22 +15,22 @@ import (
 // In case intermediate keys do not exist, or map to a non-map value,
 // a new map is created and inserted, and the search continues from there:
 // the initial map "m" may be modified!
-func deepSearch(m map[string]interface{}, path []string) map[string]interface{} {
+func deepSearch(m map[string]any, path []string) map[string]any {
 	for _, k := range path {
 		m2, ok := m[k]
 		if !ok {
 			// intermediate key does not exist
 			// => create it and continue from there
-			m3 := make(map[string]interface{})
+			m3 := make(map[string]any)
 			m[k] = m3
 			m = m3
 			continue
 		}
-		m3, ok := m2.(map[string]interface{})
+		m3, ok := m2.(map[string]any)
 		if !ok {
 			// intermediate key is a value
 			// => replace with a new map
-			m3 = make(map[string]interface{})
+			m3 = make(map[string]any)
 			m[k] = m3
 		}
 		// continue search from here
@@ -42,25 +42,25 @@ func deepSearch(m map[string]interface{}, path []string) map[string]interface{}
 // flattenAndMergeMap recursively flattens the given map into a new map
 // Code is based on the function with the same name in the main package.
 // TODO: move it to a common place
-func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} {
+func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
 	if shadow != nil && prefix != "" && shadow[prefix] != nil {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
 	}
 	if shadow == nil {
-		shadow = make(map[string]interface{})
+		shadow = make(map[string]any)
 	}
 
-	var m2 map[string]interface{}
+	var m2 map[string]any
 	if prefix != "" {
 		prefix += delimiter
 	}
 	for k, val := range m {
 		fullKey := prefix + k
 		switch val := val.(type) {
-		case map[string]interface{}:
+		case map[string]any:
 			m2 = val
-		case map[interface{}]interface{}:
+		case map[any]any:
 			m2 = cast.ToStringMap(val)
 		default:
 			// immediate value
diff --git a/internal/encoding/javaproperties/codec.go b/internal/encoding/javaproperties/codec.go
index b8a2251..e92e517 100644
--- a/internal/encoding/javaproperties/codec.go
+++ b/internal/encoding/javaproperties/codec.go
@@ -20,12 +20,12 @@ type Codec struct {
 	Properties *properties.Properties
 }
 
-func (c *Codec) Encode(v map[string]interface{}) ([]byte, error) {
+func (c *Codec) Encode(v map[string]any) ([]byte, error) {
 	if c.Properties == nil {
 		c.Properties = properties.NewProperties()
 	}
 
-	flattened := map[string]interface{}{}
+	flattened := map[string]any{}
 
 	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
 
@@ -54,7 +54,7 @@ func (c *Codec) Encode(v map[string]interface{}) ([]byte, error) {
 	return buf.Bytes(), nil
 }
 
-func (c *Codec) Decode(b []byte, v map[string]interface{}) error {
+func (c *Codec) Decode(b []byte, v map[string]any) error {
 	var err error
 	c.Properties, err = properties.Load(b, properties.UTF8)
 	if err != nil {
diff --git a/internal/encoding/javaproperties/map_utils.go b/internal/encoding/javaproperties/map_utils.go
index eb53790..8386920 100644
--- a/internal/encoding/javaproperties/map_utils.go
+++ b/internal/encoding/javaproperties/map_utils.go
@@ -15,22 +15,22 @@ import (
 // In case intermediate keys do not exist, or map to a non-map value,
 // a new map is created and inserted, and the search continues from there:
 // the initial map "m" may be modified!
-func deepSearch(m map[string]interface{}, path []string) map[string]interface{} {
+func deepSearch(m map[string]any, path []string) map[string]any {
 	for _, k := range path {
 		m2, ok := m[k]
 		if !ok {
 			// intermediate key does not exist
 			// => create it and continue from there
-			m3 := make(map[string]interface{})
+			m3 := make(map[string]any)
 			m[k] = m3
 			m = m3
 			continue
 		}
-		m3, ok := m2.(map[string]interface{})
+		m3, ok := m2.(map[string]any)
 		if !ok {
 			// intermediate key is a value
 			// => replace with a new map
-			m3 = make(map[string]interface{})
+			m3 = make(map[string]any)
 			m[k] = m3
 		}
 		// continue search from here
@@ -42,25 +42,25 @@ func deepSearch(m map[string]interface{}, path []string) map[string]interface{}
 // flattenAndMergeMap recursively flattens the given map into a new map
 // Code is based on the function with the same name in the main package.
 // TODO: move it to a common place
-func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} {
+func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
 	if shadow != nil && prefix != "" && shadow[prefix] != nil {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
 	}
 	if shadow == nil {
-		shadow = make(map[string]interface{})
+		shadow = make(map[string]any)
 	}
 
-	var m2 map[string]interface{}
+	var m2 map[string]any
 	if prefix != "" {
 		prefix += delimiter
 	}
 	for k, val := range m {
 		fullKey := prefix + k
 		switch val := val.(type) {
-		case map[string]interface{}:
+		case map[string]any:
 			m2 = val
-		case map[interface{}]interface{}:
+		case map[any]any:
 			m2 = cast.ToStringMap(val)
 		default:
 			// immediate value
diff --git a/internal/encoding/json/codec.go b/internal/encoding/json/codec.go
index 1b7caac..da7546b 100644
--- a/internal/encoding/json/codec.go
+++ b/internal/encoding/json/codec.go
@@ -7,11 +7,11 @@ import (
 // Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding.
 type Codec struct{}
 
-func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
+func (Codec) Encode(v map[string]any) ([]byte, error) {
 	// TODO: expose prefix and indent in the Codec as setting?
 	return json.MarshalIndent(v, "", "  ")
 }
 
-func (Codec) Decode(b []byte, v map[string]interface{}) error {
+func (Codec) Decode(b []byte, v map[string]any) error {
 	return json.Unmarshal(b, &v)
 }
diff --git a/internal/encoding/toml/codec.go b/internal/encoding/toml/codec.go
index a993c59..c70aa8d 100644
--- a/internal/encoding/toml/codec.go
+++ b/internal/encoding/toml/codec.go
@@ -7,10 +7,10 @@ import (
 // Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
 type Codec struct{}
 
-func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
+func (Codec) Encode(v map[string]any) ([]byte, error) {
 	return toml.Marshal(v)
 }
 
-func (Codec) Decode(b []byte, v map[string]interface{}) error {
+func (Codec) Decode(b []byte, v map[string]any) error {
 	return toml.Unmarshal(b, &v)
 }
diff --git a/internal/encoding/yaml/codec.go b/internal/encoding/yaml/codec.go
index 82dc136..0368792 100644
--- a/internal/encoding/yaml/codec.go
+++ b/internal/encoding/yaml/codec.go
@@ -5,10 +5,10 @@ import "gopkg.in/yaml.v3"
 // Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
 type Codec struct{}
 
-func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
+func (Codec) Encode(v map[string]any) ([]byte, error) {
 	return yaml.Marshal(v)
 }
 
-func (Codec) Decode(b []byte, v map[string]interface{}) error {
+func (Codec) Decode(b []byte, v map[string]any) error {
 	return yaml.Unmarshal(b, &v)
 }
diff --git a/logger.go b/logger.go
index 3f69e98..8938053 100644
--- a/logger.go
+++ b/logger.go
@@ -1,77 +1,68 @@
 package viper
 
 import (
-	"fmt"
+	"context"
 
-	jww "github.com/spf13/jwalterweatherman"
+	slog "github.com/sagikazarmark/slog-shim"
 )
 
 // Logger is a unified interface for various logging use cases and practices, including:
 //   - leveled logging
 //   - structured logging
+//
+// Deprecated: use `log/slog` instead.
 type Logger interface {
 	// Trace logs a Trace event.
 	//
 	// Even more fine-grained information than Debug events.
 	// Loggers not supporting this level should fall back to Debug.
-	Trace(msg string, keyvals ...interface{})
+	Trace(msg string, keyvals ...any)
 
 	// Debug logs a Debug event.
 	//
 	// A verbose series of information events.
 	// They are useful when debugging the system.
-	Debug(msg string, keyvals ...interface{})
+	Debug(msg string, keyvals ...any)
 
 	// Info logs an Info event.
 	//
 	// General information about what's happening inside the system.
-	Info(msg string, keyvals ...interface{})
+	Info(msg string, keyvals ...any)
 
 	// Warn logs a Warn(ing) event.
 	//
 	// Non-critical events that should be looked at.
-	Warn(msg string, keyvals ...interface{})
+	Warn(msg string, keyvals ...any)
 
 	// Error logs an Error event.
 	//
 	// Critical events that require immediate attention.
 	// Loggers commonly provide Fatal and Panic levels above Error level,
 	// but exiting and panicking is out of scope for a logging library.
-	Error(msg string, keyvals ...interface{})
+	Error(msg string, keyvals ...any)
 }
 
-type jwwLogger struct{}
-
-func (jwwLogger) Trace(msg string, keyvals ...interface{}) {
-	jww.TRACE.Printf(jwwLogMessage(msg, keyvals...))
+// WithLogger sets a custom logger.
+func WithLogger(l *slog.Logger) Option {
+	return optionFunc(func(v *Viper) {
+		v.logger = l
+	})
 }
 
-func (jwwLogger) Debug(msg string, keyvals ...interface{}) {
-	jww.DEBUG.Printf(jwwLogMessage(msg, keyvals...))
-}
+type discardHandler struct{}
 
-func (jwwLogger) Info(msg string, keyvals ...interface{}) {
-	jww.INFO.Printf(jwwLogMessage(msg, keyvals...))
+func (n *discardHandler) Enabled(_ context.Context, _ slog.Level) bool {
+	return false
 }
 
-func (jwwLogger) Warn(msg string, keyvals ...interface{}) {
-	jww.WARN.Printf(jwwLogMessage(msg, keyvals...))
+func (n *discardHandler) Handle(_ context.Context, _ slog.Record) error {
+	return nil
 }
 
-func (jwwLogger) Error(msg string, keyvals ...interface{}) {
-	jww.ERROR.Printf(jwwLogMessage(msg, keyvals...))
+func (n *discardHandler) WithAttrs(_ []slog.Attr) slog.Handler {
+	return n
 }
 
-func jwwLogMessage(msg string, keyvals ...interface{}) string {
-	out := msg
-
-	if len(keyvals) > 0 && len(keyvals)%2 == 1 {
-		keyvals = append(keyvals, nil)
-	}
-
-	for i := 0; i <= len(keyvals)-2; i += 2 {
-		out = fmt.Sprintf("%s %v=%v", out, keyvals[i], keyvals[i+1])
-	}
-
-	return out
+func (n *discardHandler) WithGroup(_ string) slog.Handler {
+	return n
 }
diff --git a/util.go b/util.go
index 8236d3a..52116ac 100644
--- a/util.go
+++ b/util.go
@@ -18,6 +18,7 @@ import (
 	"strings"
 	"unicode"
 
+	slog "github.com/sagikazarmark/slog-shim"
 	"github.com/spf13/cast"
 )
 
@@ -38,11 +39,11 @@ func (pe ConfigParseError) Unwrap() error {
 
 // toCaseInsensitiveValue checks if the value is a  map;
 // if so, create a copy and lower-case the keys recursively.
-func toCaseInsensitiveValue(value interface{}) interface{} {
+func toCaseInsensitiveValue(value any) any {
 	switch v := value.(type) {
-	case map[interface{}]interface{}:
+	case map[any]any:
 		value = copyAndInsensitiviseMap(cast.ToStringMap(v))
-	case map[string]interface{}:
+	case map[string]any:
 		value = copyAndInsensitiviseMap(v)
 	}
 
@@ -51,15 +52,15 @@ func toCaseInsensitiveValue(value interface{}) interface{} {
 
 // copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of
 // any map it makes case insensitive.
-func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
-	nm := make(map[string]interface{})
+func copyAndInsensitiviseMap(m map[string]any) map[string]any {
+	nm := make(map[string]any)
 
 	for key, val := range m {
 		lkey := strings.ToLower(key)
 		switch v := val.(type) {
-		case map[interface{}]interface{}:
+		case map[any]any:
 			nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v))
-		case map[string]interface{}:
+		case map[string]any:
 			nm[lkey] = copyAndInsensitiviseMap(v)
 		default:
 			nm[lkey] = v
@@ -69,23 +70,23 @@ func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
 	return nm
 }
 
-func insensitiviseVal(val interface{}) interface{} {
+func insensitiviseVal(val any) any {
 	switch v := val.(type) {
-	case map[interface{}]interface{}:
+	case map[any]any:
 		// nested map: cast and recursively insensitivise
 		val = cast.ToStringMap(val)
-		insensitiviseMap(val.(map[string]interface{}))
-	case map[string]interface{}:
+		insensitiviseMap(val.(map[string]any))
+	case map[string]any:
 		// nested map: recursively insensitivise
 		insensitiviseMap(v)
-	case []interface{}:
+	case []any:
 		// nested array: recursively insensitivise
 		insensitiveArray(v)
 	}
 	return val
 }
 
-func insensitiviseMap(m map[string]interface{}) {
+func insensitiviseMap(m map[string]any) {
 	for key, val := range m {
 		val = insensitiviseVal(val)
 		lower := strings.ToLower(key)
@@ -98,13 +99,13 @@ func insensitiviseMap(m map[string]interface{}) {
 	}
 }
 
-func insensitiveArray(a []interface{}) {
+func insensitiveArray(a []any) {
 	for i, val := range a {
 		a[i] = insensitiviseVal(val)
 	}
 }
 
-func absPathify(logger Logger, inPath string) string {
+func absPathify(logger *slog.Logger, inPath string) string {
 	logger.Info("trying to resolve absolute path", "path", inPath)
 
 	if inPath == "$HOME" || strings.HasPrefix(inPath, "$HOME"+string(os.PathSeparator)) {
@@ -197,22 +198,22 @@ func parseSizeInBytes(sizeStr string) uint {
 // In case intermediate keys do not exist, or map to a non-map value,
 // a new map is created and inserted, and the search continues from there:
 // the initial map "m" may be modified!
-func deepSearch(m map[string]interface{}, path []string) map[string]interface{} {
+func deepSearch(m map[string]any, path []string) map[string]any {
 	for _, k := range path {
 		m2, ok := m[k]
 		if !ok {
 			// intermediate key does not exist
 			// => create it and continue from there
-			m3 := make(map[string]interface{})
+			m3 := make(map[string]any)
 			m[k] = m3
 			m = m3
 			continue
 		}
-		m3, ok := m2.(map[string]interface{})
+		m3, ok := m2.(map[string]any)
 		if !ok {
 			// intermediate key is a value
 			// => replace with a new map
-			m3 = make(map[string]interface{})
+			m3 = make(map[string]any)
 			m[k] = m3
 		}
 		// continue search from here
diff --git a/viper.go b/viper.go
index 6c9f0e0..ffc5f70 100644
--- a/viper.go
+++ b/viper.go
@@ -35,6 +35,7 @@ import (
 
 	"github.com/fsnotify/fsnotify"
 	"github.com/mitchellh/mapstructure"
+	slog "github.com/sagikazarmark/slog-shim"
 	"github.com/spf13/afero"
 	"github.com/spf13/cast"
 	"github.com/spf13/pflag"
@@ -206,10 +207,10 @@ type Viper struct {
 	allowEmptyEnv       bool
 
 	parents        []string
-	config         map[string]interface{}
-	override       map[string]interface{}
-	defaults       map[string]interface{}
-	kvstore        map[string]interface{}
+	config         map[string]any
+	override       map[string]any
+	defaults       map[string]any
+	kvstore        map[string]any
 	pflags         map[string]FlagValue
 	env            map[string][]string
 	aliases        map[string]string
@@ -217,7 +218,7 @@ type Viper struct {
 
 	onConfigChange func(fsnotify.Event)
 
-	logger Logger
+	logger *slog.Logger
 
 	// TODO: should probably be protected with a mutex
 	encoderRegistry *encoding.EncoderRegistry
@@ -231,16 +232,16 @@ func New() *Viper {
 	v.configName = "config"
 	v.configPermissions = os.FileMode(0o644)
 	v.fs = afero.NewOsFs()
-	v.config = make(map[string]interface{})
+	v.config = make(map[string]any)
 	v.parents = []string{}
-	v.override = make(map[string]interface{})
-	v.defaults = make(map[string]interface{})
-	v.kvstore = make(map[string]interface{})
+	v.override = make(map[string]any)
+	v.defaults = make(map[string]any)
+	v.kvstore = make(map[string]any)
 	v.pflags = make(map[string]FlagValue)
 	v.env = make(map[string][]string)
 	v.aliases = make(map[string]string)
 	v.typeByDefValue = false
-	v.logger = jwwLogger{}
+	v.logger = slog.New(&discardHandler{})
 
 	v.resetEncoding()
 
@@ -659,7 +660,7 @@ func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
 // searchMap recursively searches for a value for path in source map.
 // Returns nil if not found.
 // Note: This assumes that the path entries and map keys are lower cased.
-func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {
+func (v *Viper) searchMap(source map[string]any, path []string) any {
 	if len(path) == 0 {
 		return source
 	}
@@ -673,9 +674,9 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac
 
 		// Nested case
 		switch next := next.(type) {
-		case map[interface{}]interface{}:
+		case map[any]any:
 			return v.searchMap(cast.ToStringMap(next), path[1:])
-		case map[string]interface{}:
+		case map[string]any:
 			// Type assertion is safe here since it is only reached
 			// if the type of `next` is the same as the type being asserted
 			return v.searchMap(next, path[1:])
@@ -698,7 +699,7 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac
 // in their keys).
 //
 // Note: This assumes that the path entries and map keys are lower cased.
-func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []string) interface{} {
+func (v *Viper) searchIndexableWithPathPrefixes(source any, path []string) any {
 	if len(path) == 0 {
 		return source
 	}
@@ -707,11 +708,11 @@ func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []strin
 	for i := len(path); i > 0; i-- {
 		prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim))
 
-		var val interface{}
+		var val any
 		switch sourceIndexable := source.(type) {
-		case []interface{}:
+		case []any:
 			val = v.searchSliceWithPathPrefixes(sourceIndexable, prefixKey, i, path)
-		case map[string]interface{}:
+		case map[string]any:
 			val = v.searchMapWithPathPrefixes(sourceIndexable, prefixKey, i, path)
 		}
 		if val != nil {
@@ -728,11 +729,11 @@ func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []strin
 // This function is part of the searchIndexableWithPathPrefixes recurring search and
 // should not be called directly from functions other than searchIndexableWithPathPrefixes.
 func (v *Viper) searchSliceWithPathPrefixes(
-	sourceSlice []interface{},
+	sourceSlice []any,
 	prefixKey string,
 	pathIndex int,
 	path []string,
-) interface{} {
+) any {
 	// if the prefixKey is not a number or it is out of bounds of the slice
 	index, err := strconv.Atoi(prefixKey)
 	if err != nil || len(sourceSlice) <= index {
@@ -747,9 +748,9 @@ func (v *Viper) searchSliceWithPathPrefixes(
 	}
 
 	switch n := next.(type) {
-	case map[interface{}]interface{}:
+	case map[any]any:
 		return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:])
-	case map[string]interface{}, []interface{}:
+	case map[string]any, []any:
 		return v.searchIndexableWithPathPrefixes(n, path[pathIndex:])
 	default:
 		// got a value but nested key expected, do nothing and look for next prefix
@@ -764,11 +765,11 @@ func (v *Viper) searchSliceWithPathPrefixes(
 // This function is part of the searchIndexableWithPathPrefixes recurring search and
 // should not be called directly from functions other than searchIndexableWithPathPrefixes.
 func (v *Viper) searchMapWithPathPrefixes(
-	sourceMap map[string]interface{},
+	sourceMap map[string]any,
 	prefixKey string,
 	pathIndex int,
 	path []string,
-) interface{} {
+) any {
 	next, ok := sourceMap[prefixKey]
 	if !ok {
 		return nil
@@ -781,9 +782,9 @@ func (v *Viper) searchMapWithPathPrefixes(
 
 	// Nested case
 	switch n := next.(type) {
-	case map[interface{}]interface{}:
+	case map[any]any:
 		return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:])
-	case map[string]interface{}, []interface{}:
+	case map[string]any, []any:
 		return v.searchIndexableWithPathPrefixes(n, path[pathIndex:])
 	default:
 		// got a value but nested key expected, do nothing and look for next prefix
@@ -798,8 +799,8 @@ func (v *Viper) searchMapWithPathPrefixes(
 // e.g., if "foo.bar" has a value in the given map, it “shadows”
 //
 //	"foo.bar.baz" in a lower-priority map
-func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string {
-	var parentVal interface{}
+func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string {
+	var parentVal any
 	for i := 1; i < len(path); i++ {
 		parentVal = v.searchMap(m, path[0:i])
 		if parentVal == nil {
@@ -807,9 +808,9 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{})
 			return ""
 		}
 		switch parentVal.(type) {
-		case map[interface{}]interface{}:
+		case map[any]any:
 			continue
-		case map[string]interface{}:
+		case map[string]any:
 			continue
 		default:
 			// parentVal is a regular value which shadows "path"
@@ -824,9 +825,9 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{})
 // e.g., if "foo.bar" has a value in the given map, it “shadows”
 //
 //	"foo.bar.baz" in a lower-priority map
-func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string {
+func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
 	// unify input map
-	var m map[string]interface{}
+	var m map[string]any
 	switch mi.(type) {
 	case map[string]string, map[string]FlagValue:
 		m = cast.ToStringMap(mi)
@@ -893,9 +894,9 @@ func GetViper() *Viper {
 // override, flag, env, config file, key/value store, default
 //
 // Get returns an interface. For a specific value use one of the Get____ methods.
-func Get(key string) interface{} { return v.Get(key) }
+func Get(key string) any { return v.Get(key) }
 
-func (v *Viper) Get(key string) interface{} {
+func (v *Viper) Get(key string) any {
 	lcaseKey := strings.ToLower(key)
 	val := v.find(lcaseKey, true)
 	if val == nil {
@@ -1065,9 +1066,9 @@ func (v *Viper) GetStringSlice(key string) []string {
 }
 
 // GetStringMap returns the value associated with the key as a map of interfaces.
-func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) }
+func GetStringMap(key string) map[string]any { return v.GetStringMap(key) }
 
-func (v *Viper) GetStringMap(key string) map[string]interface{} {
+func (v *Viper) GetStringMap(key string) map[string]any {
 	return cast.ToStringMap(v.Get(key))
 }
 
@@ -1095,27 +1096,27 @@ func (v *Viper) GetSizeInBytes(key string) uint {
 }
 
 // UnmarshalKey takes a single key and unmarshals it into a Struct.
-func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error {
+func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
 	return v.UnmarshalKey(key, rawVal, opts...)
 }
 
-func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error {
+func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
 	return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
 }
 
 // Unmarshal unmarshals the config into a Struct. Make sure that the tags
 // on the fields of the structure are properly set.
-func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
+func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
 	return v.Unmarshal(rawVal, opts...)
 }
 
-func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
+func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
 	return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
 }
 
 // defaultDecoderConfig returns default mapstructure.DecoderConfig with support
 // of time.Duration values & string slices
-func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
 	c := &mapstructure.DecoderConfig{
 		Metadata:         nil,
 		Result:           output,
@@ -1132,7 +1133,7 @@ func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *maps
 }
 
 // A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
-func decode(input interface{}, config *mapstructure.DecoderConfig) error {
+func decode(input any, config *mapstructure.DecoderConfig) error {
 	decoder, err := mapstructure.NewDecoder(config)
 	if err != nil {
 		return err
@@ -1142,11 +1143,11 @@ func decode(input interface{}, config *mapstructure.DecoderConfig) error {
 
 // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
 // in the destination struct.
-func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error {
+func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
 	return v.UnmarshalExact(rawVal, opts...)
 }
 
-func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error {
+func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
 	config := defaultDecoderConfig(rawVal, opts...)
 	config.ErrorUnused = true
 
@@ -1243,9 +1244,9 @@ func (v *Viper) MustBindEnv(input ...string) {
 // corresponds to a flag, the flag's default value is returned.
 //
 // Note: this assumes a lower-cased key given.
-func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} {
+func (v *Viper) find(lcaseKey string, flagDefault bool) any {
 	var (
-		val    interface{}
+		val    any
 		exists bool
 		path   = strings.Split(lcaseKey, v.keyDelim)
 		nested = len(path) > 1
@@ -1404,19 +1405,19 @@ func readAsCSV(val string) ([]string, error) {
 }
 
 // mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79
-// alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap
-func stringToStringConv(val string) interface{} {
+// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
+func stringToStringConv(val string) any {
 	val = strings.Trim(val, "[]")
 	// An empty string would cause an empty map
 	if len(val) == 0 {
-		return map[string]interface{}{}
+		return map[string]any{}
 	}
 	r := csv.NewReader(strings.NewReader(val))
 	ss, err := r.Read()
 	if err != nil {
 		return nil
 	}
-	out := make(map[string]interface{}, len(ss))
+	out := make(map[string]any, len(ss))
 	for _, pair := range ss {
 		kv := strings.SplitN(pair, "=", 2)
 		if len(kv) != 2 {
@@ -1428,15 +1429,15 @@ func stringToStringConv(val string) interface{} {
 }
 
 // mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68
-// alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap
-func stringToIntConv(val string) interface{} {
+// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
+func stringToIntConv(val string) any {
 	val = strings.Trim(val, "[]")
 	// An empty string would cause an empty map
 	if len(val) == 0 {
-		return map[string]interface{}{}
+		return map[string]any{}
 	}
 	ss := strings.Split(val, ",")
-	out := make(map[string]interface{}, len(ss))
+	out := make(map[string]any, len(ss))
 	for _, pair := range ss {
 		kv := strings.SplitN(pair, "=", 2)
 		if len(kv) != 2 {
@@ -1544,9 +1545,9 @@ func (v *Viper) InConfig(key string) bool {
 // SetDefault sets the default value for this key.
 // SetDefault is case-insensitive for a key.
 // Default only used when no value is provided by the user via flag, config or ENV.
-func SetDefault(key string, value interface{}) { v.SetDefault(key, value) }
+func SetDefault(key string, value any) { v.SetDefault(key, value) }
 
-func (v *Viper) SetDefault(key string, value interface{}) {
+func (v *Viper) SetDefault(key string, value any) {
 	// If alias passed in, then set the proper default
 	key = v.realKey(strings.ToLower(key))
 	value = toCaseInsensitiveValue(value)
@@ -1563,9 +1564,9 @@ func (v *Viper) SetDefault(key string, value interface{}) {
 // Set is case-insensitive for a key.
 // Will be used instead of values obtained via
 // flags, config file, ENV, default, or key/value store.
-func Set(key string, value interface{}) { v.Set(key, value) }
+func Set(key string, value any) { v.Set(key, value) }
 
-func (v *Viper) Set(key string, value interface{}) {
+func (v *Viper) Set(key string, value any) {
 	// If alias passed in, then set the proper override
 	key = v.realKey(strings.ToLower(key))
 	value = toCaseInsensitiveValue(value)
@@ -1599,7 +1600,7 @@ func (v *Viper) ReadInConfig() error {
 		return err
 	}
 
-	config := make(map[string]interface{})
+	config := make(map[string]any)
 
 	err = v.unmarshalReader(bytes.NewReader(file), config)
 	if err != nil {
@@ -1637,7 +1638,7 @@ func (v *Viper) MergeInConfig() error {
 func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
 
 func (v *Viper) ReadConfig(in io.Reader) error {
-	v.config = make(map[string]interface{})
+	v.config = make(map[string]any)
 	return v.unmarshalReader(in, v.config)
 }
 
@@ -1645,7 +1646,7 @@ func (v *Viper) ReadConfig(in io.Reader) error {
 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
 
 func (v *Viper) MergeConfig(in io.Reader) error {
-	cfg := make(map[string]interface{})
+	cfg := make(map[string]any)
 	if err := v.unmarshalReader(in, cfg); err != nil {
 		return err
 	}
@@ -1654,11 +1655,11 @@ func (v *Viper) MergeConfig(in io.Reader) error {
 
 // MergeConfigMap merges the configuration from the map given with an existing config.
 // Note that the map given may be modified.
-func MergeConfigMap(cfg map[string]interface{}) error { return v.MergeConfigMap(cfg) }
+func MergeConfigMap(cfg map[string]any) error { return v.MergeConfigMap(cfg) }
 
-func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error {
+func (v *Viper) MergeConfigMap(cfg map[string]any) error {
 	if v.config == nil {
-		v.config = make(map[string]interface{})
+		v.config = make(map[string]any)
 	}
 	insensitiviseMap(cfg)
 	mergeMaps(cfg, v.config, nil)
@@ -1723,7 +1724,7 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 		return UnsupportedConfigError(configType)
 	}
 	if v.config == nil {
-		v.config = make(map[string]interface{})
+		v.config = make(map[string]any)
 	}
 	flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY
 	if !force {
@@ -1744,11 +1745,11 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 
 // Unmarshal a Reader into a map.
 // Should probably be an unexported function.
-func unmarshalReader(in io.Reader, c map[string]interface{}) error {
+func unmarshalReader(in io.Reader, c map[string]any) error {
 	return v.unmarshalReader(in, c)
 }
 
-func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
+func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
 	buf := new(bytes.Buffer)
 	buf.ReadFrom(in)
 
@@ -1782,7 +1783,7 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
 	return nil
 }
 
-func keyExists(k string, m map[string]interface{}) string {
+func keyExists(k string, m map[string]any) string {
 	lk := strings.ToLower(k)
 	for mk := range m {
 		lmk := strings.ToLower(mk)
@@ -1794,33 +1795,33 @@ func keyExists(k string, m map[string]interface{}) string {
 }
 
 func castToMapStringInterface(
-	src map[interface{}]interface{},
-) map[string]interface{} {
-	tgt := map[string]interface{}{}
+	src map[any]any,
+) map[string]any {
+	tgt := map[string]any{}
 	for k, v := range src {
 		tgt[fmt.Sprintf("%v", k)] = v
 	}
 	return tgt
 }
 
-func castMapStringSliceToMapInterface(src map[string][]string) map[string]interface{} {
-	tgt := map[string]interface{}{}
+func castMapStringSliceToMapInterface(src map[string][]string) map[string]any {
+	tgt := map[string]any{}
 	for k, v := range src {
 		tgt[k] = v
 	}
 	return tgt
 }
 
-func castMapStringToMapInterface(src map[string]string) map[string]interface{} {
-	tgt := map[string]interface{}{}
+func castMapStringToMapInterface(src map[string]string) map[string]any {
+	tgt := map[string]any{}
 	for k, v := range src {
 		tgt[k] = v
 	}
 	return tgt
 }
 
-func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} {
-	tgt := map[string]interface{}{}
+func castMapFlagToMapInterface(src map[string]FlagValue) map[string]any {
+	tgt := map[string]any{}
 	for k, v := range src {
 		tgt[k] = v
 	}
@@ -1828,17 +1829,15 @@ func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{}
 }
 
 // mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's
-// insistence on parsing nested structures as `map[interface{}]interface{}`
+// insistence on parsing nested structures as `map[any]any`
 // instead of using a `string` as the key for nest structures beyond one level
 // deep. Both map types are supported as there is a go-yaml fork that uses
-// `map[string]interface{}` instead.
-func mergeMaps(
-	src, tgt map[string]interface{}, itgt map[interface{}]interface{},
-) {
+// `map[string]any` instead.
+func mergeMaps(src, tgt map[string]any, itgt map[any]any) {
 	for sk, sv := range src {
 		tk := keyExists(sk, tgt)
 		if tk == "" {
-			v.logger.Trace("", "tk", "\"\"", fmt.Sprintf("tgt[%s]", sk), sv)
+			v.logger.Debug("", "tk", "\"\"", fmt.Sprintf("tgt[%s]", sk), sv)
 			tgt[sk] = sv
 			if itgt != nil {
 				itgt[sk] = sv
@@ -1848,7 +1847,7 @@ func mergeMaps(
 
 		tv, ok := tgt[tk]
 		if !ok {
-			v.logger.Trace("", fmt.Sprintf("ok[%s]", tk), false, fmt.Sprintf("tgt[%s]", sk), sv)
+			v.logger.Debug("", fmt.Sprintf("ok[%s]", tk), false, fmt.Sprintf("tgt[%s]", sk), sv)
 			tgt[sk] = sv
 			if itgt != nil {
 				itgt[sk] = sv
@@ -1859,7 +1858,7 @@ func mergeMaps(
 		svType := reflect.TypeOf(sv)
 		tvType := reflect.TypeOf(tv)
 
-		v.logger.Trace(
+		v.logger.Debug(
 			"processing",
 			"key", sk,
 			"st", svType,
@@ -1869,12 +1868,12 @@ func mergeMaps(
 		)
 
 		switch ttv := tv.(type) {
-		case map[interface{}]interface{}:
-			v.logger.Trace("merging maps (must convert)")
-			tsv, ok := sv.(map[interface{}]interface{})
+		case map[any]any:
+			v.logger.Debug("merging maps (must convert)")
+			tsv, ok := sv.(map[any]any)
 			if !ok {
 				v.logger.Error(
-					"Could not cast sv to map[interface{}]interface{}",
+					"Could not cast sv to map[any]any",
 					"key", sk,
 					"st", svType,
 					"tt", tvType,
@@ -1887,12 +1886,12 @@ func mergeMaps(
 			ssv := castToMapStringInterface(tsv)
 			stv := castToMapStringInterface(ttv)
 			mergeMaps(ssv, stv, ttv)
-		case map[string]interface{}:
-			v.logger.Trace("merging maps")
-			tsv, ok := sv.(map[string]interface{})
+		case map[string]any:
+			v.logger.Debug("merging maps")
+			tsv, ok := sv.(map[string]any)
 			if !ok {
 				v.logger.Error(
-					"Could not cast sv to map[string]interface{}",
+					"Could not cast sv to map[string]any",
 					"key", sk,
 					"st", svType,
 					"tt", tvType,
@@ -1903,7 +1902,7 @@ func mergeMaps(
 			}
 			mergeMaps(tsv, ttv, nil)
 		default:
-			v.logger.Trace("setting value")
+			v.logger.Debug("setting value")
 			tgt[tk] = sv
 			if itgt != nil {
 				itgt[tk] = sv
@@ -1954,7 +1953,7 @@ func (v *Viper) getKeyValueConfig() error {
 	return RemoteConfigError("No Files Found")
 }
 
-func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) {
+func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
 	reader, err := RemoteConfig.Get(provider)
 	if err != nil {
 		return nil, err
@@ -2003,7 +2002,7 @@ func (v *Viper) watchKeyValueConfig() error {
 	return RemoteConfigError("No Files Found")
 }
 
-func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) {
+func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
 	reader, err := RemoteConfig.Watch(provider)
 	if err != nil {
 		return nil, err
@@ -2042,7 +2041,7 @@ func (v *Viper) AllKeys() []string {
 //     it is skipped.
 //
 // The resulting set of paths is merged to the given shadow set at the same time.
-func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool {
+func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]any, prefix string) map[string]bool {
 	if shadow != nil && prefix != "" && shadow[prefix] {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
@@ -2051,16 +2050,16 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac
 		shadow = make(map[string]bool)
 	}
 
-	var m2 map[string]interface{}
+	var m2 map[string]any
 	if prefix != "" {
 		prefix += v.keyDelim
 	}
 	for k, val := range m {
 		fullKey := prefix + k
 		switch val := val.(type) {
-		case map[string]interface{}:
+		case map[string]any:
 			m2 = val
-		case map[interface{}]interface{}:
+		case map[any]any:
 			m2 = cast.ToStringMap(val)
 		default:
 			// immediate value
@@ -2075,7 +2074,7 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac
 
 // mergeFlatMap merges the given maps, excluding values of the second map
 // shadowed by values from the first map.
-func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool {
+func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]any) map[string]bool {
 	// scan keys
 outer:
 	for k := range m {
@@ -2095,11 +2094,11 @@ outer:
 	return shadow
 }
 
-// AllSettings merges all settings and returns them as a map[string]interface{}.
-func AllSettings() map[string]interface{} { return v.AllSettings() }
+// AllSettings merges all settings and returns them as a map[string]any.
+func AllSettings() map[string]any { return v.AllSettings() }
 
-func (v *Viper) AllSettings() map[string]interface{} {
-	m := map[string]interface{}{}
+func (v *Viper) AllSettings() map[string]any {
+	m := map[string]any{}
 	// start from the list of keys, and construct the map one value at a time
 	for _, k := range v.AllKeys() {
 		value := v.Get(k)
diff --git a/viper_go1_15.go b/viper_go1_15.go
index 19a771c..7fc6aff 100644
--- a/viper_go1_15.go
+++ b/viper_go1_15.go
@@ -1,5 +1,4 @@
-//go:build !go1.16 || !finder
-// +build !go1.16 !finder
+//go:build !finder
 
 package viper
 
diff --git a/viper_go1_16.go b/viper_go1_16.go
index e10172f..d96a1bd 100644
--- a/viper_go1_16.go
+++ b/viper_go1_16.go
@@ -1,32 +1,38 @@
-//go:build go1.16 && finder
-// +build go1.16,finder
+//go:build finder
 
 package viper
 
 import (
 	"fmt"
 
-	"github.com/spf13/afero"
+	"github.com/sagikazarmark/locafero"
 )
 
 // Search all configPaths for any config file.
 // Returns the first path that exists (and is a config file).
 func (v *Viper) findConfigFile() (string, error) {
-	finder := finder{
-		paths:            v.configPaths,
-		fileNames:        []string{v.configName},
-		extensions:       SupportedExts,
-		withoutExtension: v.configType != "",
+	var names []string
+
+	if v.configType != "" {
+		names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...)
+	} else {
+		names = locafero.NameWithExtensions(v.configName, SupportedExts...)
+	}
+
+	finder := locafero.Finder{
+		Paths: v.configPaths,
+		Names: names,
+		Type:  locafero.FileTypeFile,
 	}
 
-	file, err := finder.Find(afero.NewIOFS(v.fs))
+	results, err := finder.Find(v.fs)
 	if err != nil {
 		return "", err
 	}
 
-	if file == "" {
+	if len(results) == 0 {
 		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
 	}
 
-	return file, nil
+	return results[0], nil
 }
diff --git a/watch.go b/watch.go
index 1ce84ea..e98fce8 100644
--- a/watch.go
+++ b/watch.go
@@ -1,5 +1,4 @@
 //go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
-// +build darwin dragonfly freebsd openbsd linux netbsd solaris windows
 
 package viper
 
diff --git a/watch_unsupported.go b/watch_unsupported.go
index 7e27153..7076405 100644
--- a/watch_unsupported.go
+++ b/watch_unsupported.go
@@ -1,5 +1,4 @@
 //go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
-// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
 
 package viper
 


Test patch:
diff --git a/flags_test.go b/flags_test.go
index a22e31b..171828d 100644
--- a/flags_test.go
+++ b/flags_test.go
@@ -39,7 +39,7 @@ func TestBindFlagValueSet(t *testing.T) {
 	})
 
 	for name, expected := range mutatedTestValues {
-		assert.Equal(t, Get(name), expected)
+		assert.Equal(t, expected, Get(name))
 	}
 }
 
diff --git a/fs_test.go b/fs_test.go
deleted file mode 100644
index 071e346..0000000
--- a/fs_test.go
+++ /dev/null
@@ -1,100 +0,0 @@
-//go:build go1.16 && finder
-// +build go1.16,finder
-
-package viper
-
-import (
-	"io/fs"
-	"testing"
-	"testing/fstest"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-)
-
-func TestFinder(t *testing.T) {
-	t.Parallel()
-
-	fsys := fstest.MapFS{
-		"home/user/.config":            &fstest.MapFile{},
-		"home/user/config.json":        &fstest.MapFile{},
-		"home/user/config.yaml":        &fstest.MapFile{},
-		"home/user/data.json":          &fstest.MapFile{},
-		"etc/config/.config":           &fstest.MapFile{},
-		"etc/config/a_random_file.txt": &fstest.MapFile{},
-		"etc/config/config.json":       &fstest.MapFile{},
-		"etc/config/config.yaml":       &fstest.MapFile{},
-		"etc/config/config.xml":        &fstest.MapFile{},
-	}
-
-	testCases := []struct {
-		name   string
-		fsys   func() fs.FS
-		finder finder
-		result string
-	}{
-		{
-			name: "find file",
-			fsys: func() fs.FS { return fsys },
-			finder: finder{
-				paths:      []string{"etc/config"},
-				fileNames:  []string{"config"},
-				extensions: []string{"json"},
-			},
-			result: "etc/config/config.json",
-		},
-		{
-			name: "file not found",
-			fsys: func() fs.FS { return fsys },
-			finder: finder{
-				paths:      []string{"var/config"},
-				fileNames:  []string{"config"},
-				extensions: []string{"json"},
-			},
-			result: "",
-		},
-		{
-			name:   "empty search params",
-			fsys:   func() fs.FS { return fsys },
-			finder: finder{},
-			result: "",
-		},
-		{
-			name: "precedence",
-			fsys: func() fs.FS { return fsys },
-			finder: finder{
-				paths:      []string{"var/config", "home/user", "etc/config"},
-				fileNames:  []string{"aconfig", "config"},
-				extensions: []string{"zml", "xml", "json"},
-			},
-			result: "home/user/config.json",
-		},
-		{
-			name: "without extension",
-			fsys: func() fs.FS { return fsys },
-			finder: finder{
-				paths:      []string{"var/config", "home/user", "etc/config"},
-				fileNames:  []string{".config"},
-				extensions: []string{"zml", "xml", "json"},
-
-				withoutExtension: true,
-			},
-			result: "home/user/.config",
-		},
-	}
-
-	for _, testCase := range testCases {
-		testCase := testCase
-
-		t.Run(testCase.name, func(t *testing.T) {
-			t.Parallel()
-
-			fsys := testCase.fsys()
-
-			result, err := testCase.finder.Find(fsys)
-			require.NoError(t, err)
-
-			assert.Equal(t, testCase.result, result)
-		})
-	}
-}
diff --git a/internal/encoding/decoder_test.go b/internal/encoding/decoder_test.go
index 6cb56d0..0cd49fb 100644
--- a/internal/encoding/decoder_test.go
+++ b/internal/encoding/decoder_test.go
@@ -6,10 +6,10 @@ import (
 )
 
 type decoder struct {
-	v map[string]interface{}
+	v map[string]any
 }
 
-func (d decoder) Decode(_ []byte, v map[string]interface{}) error {
+func (d decoder) Decode(_ []byte, v map[string]any) error {
 	for key, value := range d.v {
 		v[key] = value
 	}
@@ -46,7 +46,7 @@ func TestDecoderRegistry_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		registry := NewDecoderRegistry()
 		decoder := decoder{
-			v: map[string]interface{}{
+			v: map[string]any{
 				"key": "value",
 			},
 		}
@@ -56,7 +56,7 @@ func TestDecoderRegistry_Decode(t *testing.T) {
 			t.Fatal(err)
 		}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err = registry.Decode("myformat", []byte("key: value"), v)
 		if err != nil {
@@ -71,7 +71,7 @@ func TestDecoderRegistry_Decode(t *testing.T) {
 	t.Run("DecoderNotFound", func(t *testing.T) {
 		registry := NewDecoderRegistry()
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := registry.Decode("myformat", nil, v)
 		if err != ErrDecoderNotFound {
diff --git a/internal/encoding/dotenv/codec_test.go b/internal/encoding/dotenv/codec_test.go
index d297071..f9a6fb4 100644
--- a/internal/encoding/dotenv/codec_test.go
+++ b/internal/encoding/dotenv/codec_test.go
@@ -15,7 +15,7 @@ const encoded = `KEY=value
 `
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"KEY": "value",
 }
 
@@ -36,7 +36,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
 		if err != nil {
@@ -51,7 +51,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("InvalidData", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
 		if err == nil {
diff --git a/internal/encoding/encoder_test.go b/internal/encoding/encoder_test.go
index adee6d0..795e868 100644
--- a/internal/encoding/encoder_test.go
+++ b/internal/encoding/encoder_test.go
@@ -8,7 +8,7 @@ type encoder struct {
 	b []byte
 }
 
-func (e encoder) Encode(_ map[string]interface{}) ([]byte, error) {
+func (e encoder) Encode(_ map[string]any) ([]byte, error) {
 	return e.b, nil
 }
 
@@ -49,7 +49,7 @@ func TestEncoderRegistry_Decode(t *testing.T) {
 			t.Fatal(err)
 		}
 
-		b, err := registry.Encode("myformat", map[string]interface{}{"key": "value"})
+		b, err := registry.Encode("myformat", map[string]any{"key": "value"})
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -62,7 +62,7 @@ func TestEncoderRegistry_Decode(t *testing.T) {
 	t.Run("EncoderNotFound", func(t *testing.T) {
 		registry := NewEncoderRegistry()
 
-		_, err := registry.Encode("myformat", map[string]interface{}{"key": "value"})
+		_, err := registry.Encode("myformat", map[string]any{"key": "value"})
 		if err != ErrEncoderNotFound {
 			t.Fatalf("expected ErrEncoderNotFound, got: %v", err)
 		}
diff --git a/internal/encoding/hcl/codec_test.go b/internal/encoding/hcl/codec_test.go
index 7e48057..e0b1ebc 100644
--- a/internal/encoding/hcl/codec_test.go
+++ b/internal/encoding/hcl/codec_test.go
@@ -45,24 +45,24 @@ const encoded = `"key" = "value"
 //
 // in case of HCL it's slightly different from Viper's internal representation
 // (eg. map is decoded into a list of maps)
-var decoded = map[string]interface{}{
+var decoded = map[string]any{
 	"key": "value",
-	"list": []interface{}{
+	"list": []any{
 		"item1",
 		"item2",
 		"item3",
 	},
-	"map": []map[string]interface{}{
+	"map": []map[string]any{
 		{
 			"key": "value",
 		},
 	},
-	"nested_map": []map[string]interface{}{
+	"nested_map": []map[string]any{
 		{
-			"map": []map[string]interface{}{
+			"map": []map[string]any{
 				{
 					"key": "value",
-					"list": []interface{}{
+					"list": []any{
 						"item1",
 						"item2",
 						"item3",
@@ -74,20 +74,20 @@ var decoded = map[string]interface{}{
 }
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"key": "value",
-	"list": []interface{}{
+	"list": []any{
 		"item1",
 		"item2",
 		"item3",
 	},
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
-	"nested_map": map[string]interface{}{
-		"map": map[string]interface{}{
+	"nested_map": map[string]any{
+		"map": map[string]any{
 			"key": "value",
-			"list": []interface{}{
+			"list": []any{
 				"item1",
 				"item2",
 				"item3",
@@ -113,7 +113,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
 		if err != nil {
@@ -128,7 +128,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("InvalidData", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
 		if err == nil {
diff --git a/internal/encoding/ini/codec_test.go b/internal/encoding/ini/codec_test.go
index e54812c..0b635d1 100644
--- a/internal/encoding/ini/codec_test.go
+++ b/internal/encoding/ini/codec_test.go
@@ -26,19 +26,19 @@ key=value
 //
 // in case of INI it's slightly different from Viper's internal representation
 // (eg. top level keys land in a section called default)
-var decoded = map[string]interface{}{
-	"DEFAULT": map[string]interface{}{
+var decoded = map[string]any{
+	"DEFAULT": map[string]any{
 		"key": "value",
 	},
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
 }
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"key": "value",
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
 }
@@ -60,11 +60,11 @@ func TestCodec_Encode(t *testing.T) {
 	t.Run("Default", func(t *testing.T) {
 		codec := Codec{}
 
-		data := map[string]interface{}{
-			"default": map[string]interface{}{
+		data := map[string]any{
+			"default": map[string]any{
 				"key": "value",
 			},
-			"map": map[string]interface{}{
+			"map": map[string]any{
 				"key": "value",
 			},
 		}
@@ -84,7 +84,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
 		if err != nil {
@@ -99,7 +99,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("InvalidData", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
 		if err == nil {
diff --git a/internal/encoding/javaproperties/codec_test.go b/internal/encoding/javaproperties/codec_test.go
index 0a33ebf..7c4f898 100644
--- a/internal/encoding/javaproperties/codec_test.go
+++ b/internal/encoding/javaproperties/codec_test.go
@@ -17,9 +17,9 @@ map.key = value
 `
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"key": "value",
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
 }
@@ -41,7 +41,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
 		if err != nil {
@@ -58,7 +58,7 @@ func TestCodec_Decode(t *testing.T) {
 
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		codec.Decode([]byte(``), v)
 
@@ -71,7 +71,7 @@ func TestCodec_Decode(t *testing.T) {
 func TestCodec_DecodeEncode(t *testing.T) {
 	codec := Codec{}
 
-	v := map[string]interface{}{}
+	v := map[string]any{}
 
 	err := codec.Decode([]byte(original), v)
 	if err != nil {
diff --git a/internal/encoding/json/codec_test.go b/internal/encoding/json/codec_test.go
index f4a71df..a1ec360 100644
--- a/internal/encoding/json/codec_test.go
+++ b/internal/encoding/json/codec_test.go
@@ -29,20 +29,20 @@ const encoded = `{
 }`
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"key": "value",
-	"list": []interface{}{
+	"list": []any{
 		"item1",
 		"item2",
 		"item3",
 	},
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
-	"nested_map": map[string]interface{}{
-		"map": map[string]interface{}{
+	"nested_map": map[string]any{
+		"map": map[string]any{
 			"key": "value",
-			"list": []interface{}{
+			"list": []any{
 				"item1",
 				"item2",
 				"item3",
@@ -68,7 +68,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(encoded), v)
 		if err != nil {
@@ -83,7 +83,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("InvalidData", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
 		if err == nil {
diff --git a/internal/encoding/toml/codec_test.go b/internal/encoding/toml/codec_test.go
index acbe905..b52f117 100644
--- a/internal/encoding/toml/codec_test.go
+++ b/internal/encoding/toml/codec_test.go
@@ -39,20 +39,20 @@ list = ['item1', 'item2', 'item3']
 `
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"key": "value",
-	"list": []interface{}{
+	"list": []any{
 		"item1",
 		"item2",
 		"item3",
 	},
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
-	"nested_map": map[string]interface{}{
-		"map": map[string]interface{}{
+	"nested_map": map[string]any{
+		"map": map[string]any{
 			"key": "value",
-			"list": []interface{}{
+			"list": []any{
 				"item1",
 				"item2",
 				"item3",
@@ -78,7 +78,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
 		if err != nil {
@@ -93,7 +93,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("InvalidData", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
 		if err == nil {
diff --git a/internal/encoding/yaml/codec_test.go b/internal/encoding/yaml/codec_test.go
index 9fe3838..1a00a83 100644
--- a/internal/encoding/yaml/codec_test.go
+++ b/internal/encoding/yaml/codec_test.go
@@ -47,20 +47,20 @@ nested_map:
 //
 // in case of YAML it's slightly different from Viper's internal representation
 // (eg. map is decoded into a map with interface key)
-var decoded = map[string]interface{}{
+var decoded = map[string]any{
 	"key": "value",
-	"list": []interface{}{
+	"list": []any{
 		"item1",
 		"item2",
 		"item3",
 	},
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
-	"nested_map": map[string]interface{}{
-		"map": map[string]interface{}{
+	"nested_map": map[string]any{
+		"map": map[string]any{
 			"key": "value",
-			"list": []interface{}{
+			"list": []any{
 				"item1",
 				"item2",
 				"item3",
@@ -70,20 +70,20 @@ var decoded = map[string]interface{}{
 }
 
 // Viper's internal representation
-var data = map[string]interface{}{
+var data = map[string]any{
 	"key": "value",
-	"list": []interface{}{
+	"list": []any{
 		"item1",
 		"item2",
 		"item3",
 	},
-	"map": map[string]interface{}{
+	"map": map[string]any{
 		"key": "value",
 	},
-	"nested_map": map[string]interface{}{
-		"map": map[string]interface{}{
+	"nested_map": map[string]any{
+		"map": map[string]any{
 			"key": "value",
-			"list": []interface{}{
+			"list": []any{
 				"item1",
 				"item2",
 				"item3",
@@ -109,7 +109,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("OK", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
 		if err != nil {
@@ -124,7 +124,7 @@ func TestCodec_Decode(t *testing.T) {
 	t.Run("InvalidData", func(t *testing.T) {
 		codec := Codec{}
 
-		v := map[string]interface{}{}
+		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
 		if err == nil {
diff --git a/overrides_test.go b/overrides_test.go
index 4491ea2..f0de2e9 100644
--- a/overrides_test.go
+++ b/overrides_test.go
@@ -1,7 +1,6 @@
 package viper
 
 import (
-	"fmt"
 	"strings"
 	"testing"
 
@@ -46,11 +45,11 @@ func TestNestedOverrides(t *testing.T) {
 	deepCheckValue(assert, v, overrideLayer, []string{"tom", "size"}, 4)
 
 	// Case 4: key:value overridden by a map
-	v = overrideDefault(assert, "tom.size", 4, "tom", map[string]interface{}{"age": 10}) // "tom.size" is first given "4" as default value, then "tom" is overridden by map{"age":10}
-	assert.Equal(4, v.Get("tom.size"))                                                   // "tom.size" should still be reachable
-	assert.Equal(10, v.Get("tom.age"))                                                   // new value should be there
-	deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10)                 // new value should be there
-	v = override(assert, "tom.size", 4, "tom", map[string]interface{}{"age": 10})
+	v = overrideDefault(assert, "tom.size", 4, "tom", map[string]any{"age": 10}) // "tom.size" is first given "4" as default value, then "tom" is overridden by map{"age":10}
+	assert.Equal(4, v.Get("tom.size"))                                           // "tom.size" should still be reachable
+	assert.Equal(10, v.Get("tom.age"))                                           // new value should be there
+	deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10)         // new value should be there
+	v = override(assert, "tom.size", 4, "tom", map[string]any{"age": 10})
 	assert.Nil(v.Get("tom.size"))
 	assert.Equal(10, v.Get("tom.age"))
 	deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10)
@@ -75,11 +74,11 @@ func TestNestedOverrides(t *testing.T) {
 	}
 }
 
-func overrideDefault(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
+func overrideDefault(assert *assert.Assertions, firstPath string, firstValue any, secondPath string, secondValue any) *Viper {
 	return overrideFromLayer(defaultLayer, assert, firstPath, firstValue, secondPath, secondValue)
 }
 
-func override(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
+func override(assert *assert.Assertions, firstPath string, firstValue any, secondPath string, secondValue any) *Viper {
 	return overrideFromLayer(overrideLayer, assert, firstPath, firstValue, secondPath, secondValue)
 }
 
@@ -94,7 +93,7 @@ func override(assert *assert.Assertions, firstPath string, firstValue interface{
 //
 // After each assignment, the value is checked, retrieved both by its full path
 // and by its key sequence (successive maps).
-func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
+func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, firstValue any, secondPath string, secondValue any) *Viper {
 	v := New()
 	firstKeys := strings.Split(firstPath, v.keyDelim)
 	if assert == nil ||
@@ -128,14 +127,14 @@ func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, fir
 
 // deepCheckValue checks that all given keys correspond to a valid path in the
 // configuration map of the given layer, and that the final value equals the one given
-func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string, value interface{}) {
+func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string, value any) {
 	if assert == nil || v == nil ||
 		len(keys) == 0 || len(keys[0]) == 0 {
 		return
 	}
 
 	// init
-	var val interface{}
+	var val any
 	var ms string
 	switch l {
 	case defaultLayer:
@@ -147,28 +146,25 @@ func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string,
 	}
 
 	// loop through map
-	var m map[string]interface{}
-	err := false
+	var m map[string]any
 	for _, k := range keys {
 		if val == nil {
-			assert.Fail(fmt.Sprintf("%s is not a map[string]interface{}", ms))
+			assert.Failf("%s is not a map[string]any", ms)
 			return
 		}
 
 		// deep scan of the map to get the final value
 		switch val := val.(type) {
-		case map[interface{}]interface{}:
+		case map[any]any:
 			m = cast.ToStringMap(val)
-		case map[string]interface{}:
+		case map[string]any:
 			m = val
 		default:
-			assert.Fail(fmt.Sprintf("%s is not a map[string]interface{}", ms))
+			assert.Failf("%s is not a map[string]any", ms)
 			return
 		}
 		ms = ms + "[\"" + k + "\"]"
 		val = m[k]
 	}
-	if !err {
-		assert.Equal(value, val)
-	}
+	assert.Equal(value, val)
 }
diff --git a/util_test.go b/util_test.go
index 83d5daa..400d02d 100644
--- a/util_test.go
+++ b/util_test.go
@@ -15,20 +15,22 @@ import (
 	"path/filepath"
 	"reflect"
 	"testing"
+
+	slog "github.com/sagikazarmark/slog-shim"
 )
 
 func TestCopyAndInsensitiviseMap(t *testing.T) {
 	var (
-		given = map[string]interface{}{
+		given = map[string]any{
 			"Foo": 32,
-			"Bar": map[interface{}]interface{}{
+			"Bar": map[any]any{
 				"ABc": "A",
 				"cDE": "B",
 			},
 		}
-		expected = map[string]interface{}{
+		expected = map[string]any{
 			"foo": 32,
-			"bar": map[string]interface{}{
+			"bar": map[string]any{
 				"abc": "A",
 				"cde": "B",
 			},
@@ -49,7 +51,7 @@ func TestCopyAndInsensitiviseMap(t *testing.T) {
 		t.Fatal("Input map changed")
 	}
 
-	m := given["Bar"].(map[interface{}]interface{})
+	m := given["Bar"].(map[any]any)
 	if _, ok := m["ABc"]; !ok {
 		t.Fatal("Input map changed")
 	}
@@ -85,7 +87,7 @@ func TestAbsPathify(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		got := absPathify(jwwLogger{}, test.input)
+		got := absPathify(slog.Default(), test.input)
 		if got != test.output {
 			t.Errorf("Got %v\nexpected\n%q", got, test.output)
 		}
diff --git a/viper_test.go b/viper_test.go
index ccc9225..e88b89f 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -10,14 +10,12 @@ import (
 	"encoding/json"
 	"errors"
 	"io"
-	"io/ioutil"
 	"os"
 	"os/exec"
 	"path"
 	"path/filepath"
 	"reflect"
 	"runtime"
-	"sort"
 	"strings"
 	"sync"
 	"testing"
@@ -237,7 +235,7 @@ func initIni() {
 }
 
 // make directories for testing
-func initDirs(t *testing.T) (string, string, func()) {
+func initDirs(t *testing.T) (string, string) {
 	var (
 		testDirs = []string{`a a`, `b`, `C_`}
 		config   = `improbable`
@@ -247,38 +245,21 @@ func initDirs(t *testing.T) (string, string, func()) {
 		testDirs = append(testDirs, `d\d`)
 	}
 
-	root, err := ioutil.TempDir("", "")
-	require.NoError(t, err, "Failed to create temporary directory")
-
-	cleanup := true
-	defer func() {
-		if cleanup {
-			os.Chdir("..")
-			os.RemoveAll(root)
-		}
-	}()
-
-	assert.Nil(t, err)
-
-	err = os.Chdir(root)
-	require.Nil(t, err)
+	root := t.TempDir()
 
 	for _, dir := range testDirs {
-		err = os.Mkdir(dir, 0o750)
-		assert.Nil(t, err)
+		innerDir := filepath.Join(root, dir)
+		err := os.Mkdir(innerDir, 0o750)
+		require.NoError(t, err)
 
-		err = ioutil.WriteFile(
-			path.Join(dir, config+".toml"),
-			[]byte("key = \"value is "+dir+"\"\n"),
+		err = os.WriteFile(
+			filepath.Join(innerDir, config+".toml"),
+			[]byte(`key = "value is `+dir+`"`+"\n"),
 			0o640)
-		assert.Nil(t, err)
+		require.NoError(t, err)
 	}
 
-	cleanup = false
-	return root, config, func() {
-		os.Chdir("..")
-		os.RemoveAll(root)
-	}
+	return root, config
 }
 
 // stubs for PFlag Values
@@ -514,8 +495,8 @@ func TestUnmarshaling(t *testing.T) {
 	assert.False(t, InConfig("state"))
 	assert.False(t, InConfig("clothing.hat"))
 	assert.Equal(t, "steve", Get("name"))
-	assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
-	assert.Equal(t, map[string]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[string]interface{}{"size": "large"}}, Get("clothing"))
+	assert.Equal(t, []any{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
+	assert.Equal(t, map[string]any{"jacket": "leather", "trousers": "denim", "pants": map[string]any{"size": "large"}}, Get("clothing"))
 	assert.Equal(t, 35, Get("age"))
 }
 
@@ -755,7 +736,7 @@ func TestEnvSubConfig(t *testing.T) {
 func TestAllKeys(t *testing.T) {
 	initConfigs()
 
-	ks := sort.StringSlice{
+	ks := []string{
 		"title",
 		"author.bio",
 		"author.e-mail",
@@ -792,14 +773,14 @@ func TestAllKeys(t *testing.T) {
 		"name_dotenv",
 	}
 	dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
-	all := map[string]interface{}{
-		"owner": map[string]interface{}{
+	all := map[string]any{
+		"owner": map[string]any{
 			"organization": "MongoDB",
 			"bio":          "MongoDB Chief Developer Advocate & Hacker at Large",
 			"dob":          dob,
 		},
 		"title": "TOML Example",
-		"author": map[string]interface{}{
+		"author": map[string]any{
 			"e-mail": "fake@localhost",
 			"github": "https://github.com/Unknown",
 			"name":   "Unknown",
@@ -807,28 +788,28 @@ func TestAllKeys(t *testing.T) {
 		},
 		"ppu":  0.55,
 		"eyes": "brown",
-		"clothing": map[string]interface{}{
+		"clothing": map[string]any{
 			"trousers": "denim",
 			"jacket":   "leather",
-			"pants":    map[string]interface{}{"size": "large"},
+			"pants":    map[string]any{"size": "large"},
 		},
-		"default": map[string]interface{}{
+		"default": map[string]any{
 			"import_path": "gopkg.in/ini.v1",
 			"name":        "ini",
 			"version":     "v1",
 		},
 		"id": "0001",
-		"batters": map[string]interface{}{
-			"batter": []interface{}{
-				map[string]interface{}{"type": "Regular"},
-				map[string]interface{}{"type": "Chocolate"},
-				map[string]interface{}{"type": "Blueberry"},
-				map[string]interface{}{"type": "Devil's Food"},
+		"batters": map[string]any{
+			"batter": []any{
+				map[string]any{"type": "Regular"},
+				map[string]any{"type": "Chocolate"},
+				map[string]any{"type": "Blueberry"},
+				map[string]any{"type": "Devil's Food"},
 			},
 		},
 		"hacker": true,
 		"beard":  true,
-		"hobbies": []interface{}{
+		"hobbies": []any{
 			"skateboarding",
 			"snowboarding",
 			"go",
@@ -840,13 +821,13 @@ func TestAllKeys(t *testing.T) {
 		"p_id":   "0001",
 		"p_ppu":  "0.55",
 		"p_name": "Cake",
-		"p_batters": map[string]interface{}{
-			"batter": map[string]interface{}{"type": "Regular"},
+		"p_batters": map[string]any{
+			"batter": map[string]any{"type": "Regular"},
 		},
 		"p_type": "donut",
-		"foos": []map[string]interface{}{
+		"foos": []map[string]any{
 			{
-				"foo": []map[string]interface{}{
+				"foo": []map[string]any{
 					{"key": 1},
 					{"key": 2},
 					{"key": 3},
@@ -859,11 +840,7 @@ func TestAllKeys(t *testing.T) {
 		"name_dotenv":  "Cake",
 	}
 
-	allkeys := sort.StringSlice(AllKeys())
-	allkeys.Sort()
-	ks.Sort()
-
-	assert.Equal(t, ks, allkeys)
+	assert.ElementsMatch(t, ks, AllKeys())
 	assert.Equal(t, all, AllSettings())
 }
 
@@ -878,11 +855,7 @@ func TestAllKeysWithEnv(t *testing.T) {
 	t.Setenv("ID", "13")
 	t.Setenv("FOO_BAR", "baz")
 
-	expectedKeys := sort.StringSlice{"id", "foo.bar"}
-	expectedKeys.Sort()
-	keys := sort.StringSlice(v.AllKeys())
-	keys.Sort()
-	assert.Equal(t, expectedKeys, keys)
+	assert.ElementsMatch(t, []string{"id", "foo.bar"}, v.AllKeys())
 }
 
 func TestAliasesOfAliases(t *testing.T) {
@@ -955,7 +928,7 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) {
 		mapstructure.StringToTimeDurationHookFunc(),
 		mapstructure.StringToSliceHookFunc(","),
 		// Custom Decode Hook Function
-		func(rf reflect.Kind, rt reflect.Kind, data interface{}) (interface{}, error) {
+		func(rf reflect.Kind, rt reflect.Kind, data any) (any, error) {
 			if rf != reflect.String || rt != reflect.Map {
 				return data, nil
 			}
@@ -1346,38 +1319,38 @@ func TestFindsNestedKeys(t *testing.T) {
 	initConfigs()
 	dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
 
-	Set("super", map[string]interface{}{
-		"deep": map[string]interface{}{
+	Set("super", map[string]any{
+		"deep": map[string]any{
 			"nested": "value",
 		},
 	})
 
-	expected := map[string]interface{}{
-		"super": map[string]interface{}{
-			"deep": map[string]interface{}{
+	expected := map[string]any{
+		"super": map[string]any{
+			"deep": map[string]any{
 				"nested": "value",
 			},
 		},
-		"super.deep": map[string]interface{}{
+		"super.deep": map[string]any{
 			"nested": "value",
 		},
 		"super.deep.nested":  "value",
 		"owner.organization": "MongoDB",
-		"batters.batter": []interface{}{
-			map[string]interface{}{
+		"batters.batter": []any{
+			map[string]any{
 				"type": "Regular",
 			},
-			map[string]interface{}{
+			map[string]any{
 				"type": "Chocolate",
 			},
-			map[string]interface{}{
+			map[string]any{
 				"type": "Blueberry",
 			},
-			map[string]interface{}{
+			map[string]any{
 				"type": "Devil's Food",
 			},
 		},
-		"hobbies": []interface{}{
+		"hobbies": []any{
 			"skateboarding", "snowboarding", "go",
 		},
 		"TITLE_DOTENV": "DotEnv Example",
@@ -1385,25 +1358,25 @@ func TestFindsNestedKeys(t *testing.T) {
 		"NAME_DOTENV":  "Cake",
 		"title":        "TOML Example",
 		"newkey":       "remote",
-		"batters": map[string]interface{}{
-			"batter": []interface{}{
-				map[string]interface{}{
+		"batters": map[string]any{
+			"batter": []any{
+				map[string]any{
 					"type": "Regular",
 				},
-				map[string]interface{}{
+				map[string]any{
 					"type": "Chocolate",
 				},
-				map[string]interface{}{
+				map[string]any{
 					"type": "Blueberry",
 				},
-				map[string]interface{}{
+				map[string]any{
 					"type": "Devil's Food",
 				},
 			},
 		},
 		"eyes": "brown",
 		"age":  35,
-		"owner": map[string]interface{}{
+		"owner": map[string]any{
 			"organization": "MongoDB",
 			"bio":          "MongoDB Chief Developer Advocate & Hacker at Large",
 			"dob":          dob,
@@ -1414,10 +1387,10 @@ func TestFindsNestedKeys(t *testing.T) {
 		"name":      "Cake",
 		"hacker":    true,
 		"ppu":       0.55,
-		"clothing": map[string]interface{}{
+		"clothing": map[string]any{
 			"jacket":   "leather",
 			"trousers": "denim",
-			"pants": map[string]interface{}{
+			"pants": map[string]any{
 				"size": "large",
 			},
 		},
@@ -1426,9 +1399,9 @@ func TestFindsNestedKeys(t *testing.T) {
 		"clothing.trousers":   "denim",
 		"owner.dob":           dob,
 		"beard":               true,
-		"foos": []map[string]interface{}{
+		"foos": []map[string]any{
 			{
-				"foo": []map[string]interface{}{
+				"foo": []map[string]any{
 					{
 						"key": 1,
 					},
@@ -1462,8 +1435,8 @@ func TestReadBufConfig(t *testing.T) {
 	assert.False(t, v.InConfig("state"))
 	assert.False(t, v.InConfig("clothing.hat"))
 	assert.Equal(t, "steve", v.Get("name"))
-	assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, v.Get("hobbies"))
-	assert.Equal(t, map[string]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[string]interface{}{"size": "large"}}, v.Get("clothing"))
+	assert.Equal(t, []any{"skateboarding", "snowboarding", "go"}, v.Get("hobbies"))
+	assert.Equal(t, map[string]any{"jacket": "leather", "trousers": "denim", "pants": map[string]any{"size": "large"}}, v.Get("clothing"))
 	assert.Equal(t, 35, v.Get("age"))
 }
 
@@ -1515,30 +1488,28 @@ func TestIsSet(t *testing.T) {
 }
 
 func TestDirsSearch(t *testing.T) {
-	root, config, cleanup := initDirs(t)
-	defer cleanup()
+	root, config := initDirs(t)
 
 	v := New()
 	v.SetConfigName(config)
 	v.SetDefault(`key`, `default`)
 
-	entries, err := ioutil.ReadDir(root)
-	assert.Nil(t, err)
+	entries, err := os.ReadDir(root)
+	require.NoError(t, err)
 	for _, e := range entries {
 		if e.IsDir() {
-			v.AddConfigPath(e.Name())
+			v.AddConfigPath(filepath.Join(root, e.Name()))
 		}
 	}
 
 	err = v.ReadInConfig()
-	assert.Nil(t, err)
+	require.NoError(t, err)
 
 	assert.Equal(t, `value is `+filepath.Base(v.configPaths[0]), v.GetString(`key`))
 }
 
 func TestWrongDirsSearchNotFound(t *testing.T) {
-	_, config, cleanup := initDirs(t)
-	defer cleanup()
+	_, config := initDirs(t)
 
 	v := New()
 	v.SetConfigName(config)
@@ -1548,7 +1519,7 @@ func TestWrongDirsSearchNotFound(t *testing.T) {
 	v.AddConfigPath(`thispathaintthere`)
 
 	err := v.ReadInConfig()
-	assert.Equal(t, reflect.TypeOf(ConfigFileNotFoundError{"", ""}), reflect.TypeOf(err))
+	assert.IsType(t, err, ConfigFileNotFoundError{"", ""})
 
 	// Even though config did not load and the error might have
 	// been ignored by the client, the default still loads
@@ -1556,8 +1527,7 @@ func TestWrongDirsSearchNotFound(t *testing.T) {
 }
 
 func TestWrongDirsSearchNotFoundForMerge(t *testing.T) {
-	_, config, cleanup := initDirs(t)
-	defer cleanup()
+	_, config := initDirs(t)
 
 	v := New()
 	v.SetConfigName(config)
@@ -1604,12 +1574,10 @@ func TestSub(t *testing.T) {
 	assert.Equal(t, (*Viper)(nil), subv)
 
 	subv = v.Sub("clothing")
-	assert.Equal(t, subv.parents[0], "clothing")
+	assert.Equal(t, []string{"clothing"}, subv.parents)
 
 	subv = v.Sub("clothing").Sub("pants")
-	assert.Equal(t, len(subv.parents), 2)
-	assert.Equal(t, subv.parents[0], "clothing")
-	assert.Equal(t, subv.parents[1], "pants")
+	assert.Equal(t, []string{"clothing", "pants"}, subv.parents)
 }
 
 var hclWriteExpected = []byte(`"foos" = {
@@ -2201,11 +2169,11 @@ func TestMergeConfigMap(t *testing.T) {
 
 	assert(37890)
 
-	update := map[string]interface{}{
-		"Hello": map[string]interface{}{
+	update := map[string]any{
+		"Hello": map[string]any{
 			"Pop": 1234,
 		},
-		"World": map[interface{}]interface{}{
+		"World": map[any]any{
 			"Rock": 345,
 		},
 	}
@@ -2276,7 +2244,7 @@ clothing:
 	assert.Nil(t, Get("clothing.jacket.price"))
 	assert.Equal(t, polyester, GetString("clothing.shirt"))
 
-	clothingSettings := AllSettings()["clothing"].(map[string]interface{})
+	clothingSettings := AllSettings()["clothing"].(map[string]any)
 	assert.Equal(t, "leather", clothingSettings["jacket"])
 	assert.Equal(t, polyester, clothingSettings["shirt"])
 }
@@ -2288,7 +2256,7 @@ func TestDotParameter(t *testing.T) {
 	unmarshalReader(r, v.config)
 
 	actual := Get("batters.batter")
-	expected := []interface{}{map[string]interface{}{"type": "Small"}}
+	expected := []any{map[string]any{"type": "Small"}}
 	assert.Equal(t, expected, actual)
 }
 
@@ -2339,17 +2307,17 @@ R = 6
 
 func TestCaseInsensitiveSet(t *testing.T) {
 	Reset()
-	m1 := map[string]interface{}{
+	m1 := map[string]any{
 		"Foo": 32,
-		"Bar": map[interface{}]interface{}{
+		"Bar": map[any]any{
 			"ABc": "A",
 			"cDE": "B",
 		},
 	}
 
-	m2 := map[string]interface{}{
+	m2 := map[string]any{
 		"Foo": 52,
-		"Bar": map[interface{}]interface{}{
+		"Bar": map[any]any{
 			"bCd": "A",
 			"eFG": "B",
 		},
@@ -2420,7 +2388,7 @@ func TestParseNested(t *testing.T) {
 		t.Fatalf("unable to decode into struct, %v", err)
 	}
 
-	assert.Equal(t, 1, len(items))
+	assert.Len(t, items, 1)
 	assert.Equal(t, 100*time.Millisecond, items[0].Delay)
 	assert.Equal(t, 200*time.Millisecond, items[0].Nested.Delay)
 }
@@ -2438,36 +2406,28 @@ func doTestCaseInsensitive(t *testing.T, typ, config string) {
 	assert.Equal(t, 5, cast.ToInt(Get("ef.lm.p.q")))
 }
 
-func newViperWithConfigFile(t *testing.T) (*Viper, string, func()) {
-	watchDir, err := ioutil.TempDir("", "")
-	require.Nil(t, err)
+func newViperWithConfigFile(t *testing.T) (*Viper, string) {
+	watchDir := t.TempDir()
 	configFile := path.Join(watchDir, "config.yaml")
-	err = ioutil.WriteFile(configFile, []byte("foo: bar\n"), 0o640)
-	require.Nil(t, err)
-	cleanup := func() {
-		os.RemoveAll(watchDir)
-	}
+	err := os.WriteFile(configFile, []byte("foo: bar\n"), 0o640)
+	require.NoError(t, err)
 	v := New()
 	v.SetConfigFile(configFile)
 	err = v.ReadInConfig()
-	require.Nil(t, err)
+	require.NoError(t, err)
 	require.Equal(t, "bar", v.Get("foo"))
-	return v, configFile, cleanup
+	return v, configFile
 }
 
-func newViperWithSymlinkedConfigFile(t *testing.T) (*Viper, string, string, func()) {
-	watchDir, err := ioutil.TempDir("", "")
-	require.Nil(t, err)
+func newViperWithSymlinkedConfigFile(t *testing.T) (*Viper, string, string) {
+	watchDir := t.TempDir()
 	dataDir1 := path.Join(watchDir, "data1")
-	err = os.Mkdir(dataDir1, 0o777)
-	require.Nil(t, err)
+	err := os.Mkdir(dataDir1, 0o777)
+	require.NoError(t, err)
 	realConfigFile := path.Join(dataDir1, "config.yaml")
 	t.Logf("Real config file location: %s\n", realConfigFile)
-	err = ioutil.WriteFile(realConfigFile, []byte("foo: bar\n"), 0o640)
-	require.Nil(t, err)
-	cleanup := func() {
-		os.RemoveAll(watchDir)
-	}
+	err = os.WriteFile(realConfigFile, []byte("foo: bar\n"), 0o640)
+	require.NoError(t, err)
 	// now, symlink the tm `data1` dir to `data` in the baseDir
 	os.Symlink(dataDir1, path.Join(watchDir, "data"))
 	// and link the `<watchdir>/datadir1/config.yaml` to `<watchdir>/config.yaml`
@@ -2478,9 +2438,9 @@ func newViperWithSymlinkedConfigFile(t *testing.T) (*Viper, string, string, func
 	v := New()
 	v.SetConfigFile(configFile)
 	err = v.ReadInConfig()
-	require.Nil(t, err)
+	require.NoError(t, err)
 	require.Equal(t, "bar", v.Get("foo"))
-	return v, watchDir, configFile, cleanup
+	return v, watchDir, configFile
 }
 
 func TestWatchFile(t *testing.T) {
@@ -2491,8 +2451,7 @@ func TestWatchFile(t *testing.T) {
 
 	t.Run("file content changed", func(t *testing.T) {
 		// given a `config.yaml` file being watched
-		v, configFile, cleanup := newViperWithConfigFile(t)
-		defer cleanup()
+		v, configFile := newViperWithConfigFile(t)
 		_, err := os.Stat(configFile)
 		require.NoError(t, err)
 		t.Logf("test config file: %s\n", configFile)
@@ -2507,10 +2466,10 @@ func TestWatchFile(t *testing.T) {
 		})
 		v.WatchConfig()
 		// when overwriting the file and waiting for the custom change notification handler to be triggered
-		err = ioutil.WriteFile(configFile, []byte("foo: baz\n"), 0o640)
+		err = os.WriteFile(configFile, []byte("foo: baz\n"), 0o640)
 		wg.Wait()
 		// then the config value should have changed
-		require.Nil(t, err)
+		require.NoError(t, err)
 		assert.Equal(t, "baz", v.Get("foo"))
 	})
 
@@ -2519,8 +2478,7 @@ func TestWatchFile(t *testing.T) {
 		if runtime.GOOS != "linux" {
 			t.Skipf("Skipping test as symlink replacements don't work on non-linux environment...")
 		}
-		v, watchDir, _, _ := newViperWithSymlinkedConfigFile(t)
-		// defer cleanup()
+		v, watchDir, _ := newViperWithSymlinkedConfigFile(t)
 		wg := sync.WaitGroup{}
 		v.WatchConfig()
 		v.OnConfigChange(func(in fsnotify.Event) {
@@ -2531,16 +2489,16 @@ func TestWatchFile(t *testing.T) {
 		// when link to another `config.yaml` file
 		dataDir2 := path.Join(watchDir, "data2")
 		err := os.Mkdir(dataDir2, 0o777)
-		require.Nil(t, err)
+		require.NoError(t, err)
 		configFile2 := path.Join(dataDir2, "config.yaml")
-		err = ioutil.WriteFile(configFile2, []byte("foo: baz\n"), 0o640)
-		require.Nil(t, err)
+		err = os.WriteFile(configFile2, []byte("foo: baz\n"), 0o640)
+		require.NoError(t, err)
 		// change the symlink using the `ln -sfn` command
 		err = exec.Command("ln", "-sfn", dataDir2, path.Join(watchDir, "data")).Run()
-		require.Nil(t, err)
+		require.NoError(t, err)
 		wg.Wait()
 		// then
-		require.Nil(t, err)
+		require.NoError(t, err)
 		assert.Equal(t, "baz", v.Get("foo"))
 	})
 }
@@ -2590,13 +2548,13 @@ func TestKeyDelimiter(t *testing.T) {
 	err := v.unmarshalReader(r, v.config)
 	require.NoError(t, err)
 
-	values := map[string]interface{}{
-		"image": map[string]interface{}{
+	values := map[string]any{
+		"image": map[string]any{
 			"repository": "someImage",
 			"tag":        "1.0.0",
 		},
-		"ingress": map[string]interface{}{
-			"annotations": map[string]interface{}{
+		"ingress": map[string]any{
+			"annotations": map[string]any{
 				"traefik.frontend.rule.type":                 "PathPrefix",
 				"traefik.ingress.kubernetes.io/ssl-redirect": "true",
 			},
@@ -2610,13 +2568,13 @@ func TestKeyDelimiter(t *testing.T) {
 
 	type config struct {
 		Charts struct {
-			Values map[string]interface{}
+			Values map[string]any
 		}
 	}
 
 	expected := config{
 		Charts: struct {
-			Values map[string]interface{}
+			Values map[string]any
 		}{
 			Values: values,
 		},