diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index 754e8ec4..1aab96ef 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -31,3 +31,4 @@ jobs:
         uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v3.7.1
         with:
           skip-cache: true
+          args: --timeout 5m
diff --git a/go.mod b/go.mod
index 5d065d05..92a511e1 100644
--- a/go.mod
+++ b/go.mod
@@ -6,11 +6,89 @@ require (
 	github.com/envoyproxy/go-control-plane v0.12.0
 	github.com/jmespath-community/go-jmespath v1.1.2-0.20240117150817-e430401a2172
 	github.com/kyverno/kyverno-json v0.0.3-alpha.2
+	github.com/spf13/cobra v1.8.0
+	go.uber.org/multierr v1.11.0
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de
 	google.golang.org/grpc v1.63.2
 	k8s.io/apimachinery v0.29.3
 )
 
+require (
+	github.com/NYTimes/gziphandler v1.1.1 // indirect
+	github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
+	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
+	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/coreos/go-semver v0.3.1 // indirect
+	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
+	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+	github.com/emicklei/go-restful/v3 v3.11.2 // indirect
+	github.com/evanphx/json-patch v5.9.0+incompatible // indirect
+	github.com/felixge/httpsnoop v1.0.4 // indirect
+	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-openapi/jsonpointer v0.20.2 // indirect
+	github.com/go-openapi/jsonreference v0.20.4 // indirect
+	github.com/go-openapi/swag v0.22.9 // indirect
+	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+	github.com/google/cel-go v0.17.7 // indirect
+	github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
+	github.com/google/go-cmp v0.6.0 // indirect
+	github.com/google/gofuzz v1.2.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 // indirect
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
+	github.com/imdario/mergo v0.3.16 // indirect
+	github.com/inconshreveable/mousetrap v1.1.0 // indirect
+	github.com/jinzhu/copier v0.4.0 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/prometheus/client_golang v1.18.0 // indirect
+	github.com/prometheus/client_model v0.5.0 // indirect
+	github.com/prometheus/common v0.46.0 // indirect
+	github.com/prometheus/procfs v0.12.0 // indirect
+	github.com/spf13/pflag v1.0.5 // indirect
+	github.com/stoewer/go-strcase v1.3.0 // indirect
+	go.etcd.io/etcd/api/v3 v3.5.11 // indirect
+	go.etcd.io/etcd/client/pkg/v3 v3.5.11 // indirect
+	go.etcd.io/etcd/client/v3 v3.5.11 // indirect
+	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
+	go.opentelemetry.io/otel v1.22.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect
+	go.opentelemetry.io/otel/metric v1.22.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.22.0 // indirect
+	go.opentelemetry.io/otel/trace v1.22.0 // indirect
+	go.opentelemetry.io/proto/otlp v1.1.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/oauth2 v0.17.0 // indirect
+	golang.org/x/sync v0.6.0 // indirect
+	golang.org/x/term v0.17.0 // indirect
+	golang.org/x/time v0.5.0 // indirect
+	google.golang.org/appengine v1.6.8 // indirect
+	google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	k8s.io/api v0.29.2 // indirect
+	k8s.io/apiextensions-apiserver v0.29.2 // indirect
+	k8s.io/apiserver v0.29.2 // indirect
+	k8s.io/client-go v0.29.2 // indirect
+	k8s.io/component-base v0.29.2 // indirect
+	k8s.io/kube-openapi v0.0.0-20240221221325-2ac9dc51f3f1 // indirect
+	sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect
+	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
+	sigs.k8s.io/kubectl-validate v0.0.2-0.20240102223437-fe143bcde89f // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+)
+
 require (
 	github.com/IGLOU-EU/go-wildcard v1.0.3 // indirect
 	github.com/aquilax/truncate v1.0.0 // indirect
@@ -23,7 +101,6 @@ require (
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/gopherjs/gopherjs v1.17.2 // indirect
 	github.com/jtolds/gls v4.20.0+incompatible // indirect
-	github.com/kr/text v0.2.0 // indirect
 	github.com/kyverno/kyverno v1.5.0-rc1.0.20240202083228-5f0d53fe3482 // indirect
 	github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea // indirect
 	golang.org/x/crypto v0.19.0 // indirect
@@ -31,7 +108,7 @@ require (
 	golang.org/x/net v0.21.0 // indirect
 	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
-	google.golang.org/protobuf v1.33.0 // indirect
+	google.golang.org/protobuf v1.33.0
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	k8s.io/klog/v2 v2.120.1 // indirect
 	k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect
diff --git a/go.sum b/go.sum
index 76105cf3..92f8f03c 100644
--- a/go.sum
+++ b/go.sum
@@ -1,37 +1,130 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM=
+cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
+cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
+cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
+cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
 github.com/IGLOU-EU/go-wildcard v1.0.3 h1:r8T46+8/9V1STciXJomTWRpPEv4nGJATDbJkdU0Nou0=
 github.com/IGLOU-EU/go-wildcard v1.0.3/go.mod h1:/qeV4QLmydCbwH0UMQJmXDryrFKJknWi/jjO8IiuQfY=
+github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
+github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
+github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
+github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
 github.com/aquilax/truncate v1.0.0 h1:UgIGS8U/aZ4JyOJ2h3xcF5cSQ06+gGBnjxH2RUHJe0U=
 github.com/aquilax/truncate v1.0.0/go.mod h1:BeMESIDMlvlS3bmg4BVvBbbZUNwWtS8uzYPAKXwwhLw=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
 github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
 github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
+github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
+github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU=
+github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
 github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
 github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
 github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
+github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
+github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
 github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
+github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
+github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
+github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
+github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
 github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+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.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
+github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
+github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ=
+github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
+github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU=
+github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 h1:OL2d27ueTKnlQJoqLW2fc9pWYulFnJYLWzomGV7HqZo=
 github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4/go.mod h1:Pw1H1OjSNHiqeuxAduB1BKYXIwFtsyrY47nEqSgEiCM=
+github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
+github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
 github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 h1:JYghRBlGCZyCF2wNUJ8W0cwaQdtpcssJ4CgC406g+WU=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM=
+github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
+github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
+github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
 github.com/jmespath-community/go-jmespath v1.1.2-0.20240117150817-e430401a2172 h1:XQYEhx+bEiWn6eiHFivu4wEHm91FoZ/gCvoLZK6Ze5Y=
 github.com/jmespath-community/go-jmespath v1.1.2-0.20240117150817-e430401a2172/go.mod h1:j4OeykGPBbhX3rw4AOPGXSmX2/zuWXktm704A4MtHFs=
+github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
+github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -44,63 +137,197 @@ github.com/kyverno/kyverno v1.5.0-rc1.0.20240202083228-5f0d53fe3482 h1:mGQbOhxoH
 github.com/kyverno/kyverno v1.5.0-rc1.0.20240202083228-5f0d53fe3482/go.mod h1:uEm7WtaqOsPP3Jx6EOkO2PjHu6vf0MFaMD6w1ol7hAQ=
 github.com/kyverno/kyverno-json v0.0.3-alpha.2 h1:uB/Nbwa1lz81wK+6RXD/0UjBJOwv9/RkhTPl4BlZRbI=
 github.com/kyverno/kyverno-json v0.0.3-alpha.2/go.mod h1:EmCRYvDrIbMSmFouwYTdDee37xpWsr4vWhiJsxBDXSc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
+github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
+github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
+github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
+github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
+github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
+github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
+github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
+github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
+github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/smarty/assertions v1.15.1 h1:812oFiXI+G55vxsFf+8bIZ1ux30qtkdqzKbEFwyX3Tk=
 github.com/smarty/assertions v1.15.1/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
 github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
 github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
+github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
+github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
 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/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
+github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI=
 github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h1:eNr558nEUjP8acGw8FFjTeWvSgU1stO7FAO6eknhHe4=
+go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
+go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.etcd.io/etcd/api/v3 v3.5.11 h1:B54KwXbWDHyD3XYAwprxNzTe7vlhR69LuBgZnMVvS7E=
+go.etcd.io/etcd/api/v3 v3.5.11/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
+go.etcd.io/etcd/client/v2 v2.305.10 h1:MrmRktzv/XF8CvtQt+P6wLUlURaNpSDJHFZhe//2QE4=
+go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA=
+go.etcd.io/etcd/client/v3 v3.5.11 h1:ajWtgoNSZJ1gmS8k+icvPtqsqEav+iUorF7b0qozgUU=
+go.etcd.io/etcd/client/v3 v3.5.11/go.mod h1:a6xQUEqFJ8vztO1agJh/KQKOMfFI8og52ZconzcDJwE=
+go.etcd.io/etcd/pkg/v3 v3.5.10 h1:WPR8K0e9kWl1gAhB5A7gEa5ZBTNkT9NdNWrR8Qpo1CM=
+go.etcd.io/etcd/pkg/v3 v3.5.10/go.mod h1:TKTuCKKcF1zxmfKWDkfz5qqYaE3JncKKZPFf8c1nFUs=
+go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA=
+go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc=
+go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg=
+go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
+go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
+go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ=
+go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
+go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
+go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw=
+go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
+go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
+go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
+go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
+go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
 golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
+golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
+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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
+golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
 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=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
+google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
+google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
+google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
+google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
+google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
 google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
 google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -108,15 +335,44 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
+k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
+k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg=
+k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8=
 k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
 k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
+k8s.io/apiserver v0.29.2 h1:+Z9S0dSNr+CjnVXQePG8TcBWHr3Q7BmAr7NraHvsMiQ=
+k8s.io/apiserver v0.29.2/go.mod h1:B0LieKVoyU7ykQvPFm7XSdIHaCHSzCzQWPFa5bqbeMQ=
+k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
+k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
+k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8=
+k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM=
 k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
 k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kms v0.29.2 h1:MDsbp98gSlEQs7K7dqLKNNTwKFQRYYvO4UOlBOjNy6Y=
+k8s.io/kms v0.29.2/go.mod h1:s/9RC4sYRZ/6Tn6yhNjbfJuZdb8LzlXhdlBnKizeFDo=
+k8s.io/kube-openapi v0.0.0-20240221221325-2ac9dc51f3f1 h1:rtdnaWfP40MTKv7izH81gkWpZB45pZrwIxyZdPSn1mI=
+k8s.io/kube-openapi v0.0.0-20240221221325-2ac9dc51f3f1/go.mod h1:Pa1PvrP7ACSkuX6I7KYomY6cmMA0Tx86waBhDUgoKPw=
 k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
 k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4=
+sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
+sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
+sigs.k8s.io/kubectl-validate v0.0.2-0.20240102223437-fe143bcde89f h1:RPwKaV6OnIKUoI+cU8E35rYXt1ez9mjF5p9cOz9OgqE=
+sigs.k8s.io/kubectl-validate v0.0.2-0.20240102223437-fe143bcde89f/go.mod h1:Y67xSi06L5XSl+jSGFamNoa117yq6SnN4yXIzWHWxU8=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff --git a/main.go b/main.go
index 65558a41..2d248500 100644
--- a/main.go
+++ b/main.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"context"
+
 	"fmt"
 	"io"
 	"log"
@@ -13,6 +14,12 @@ import (
 	"time"
 
 	authv3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
+	typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
+	jsonengine "github.com/kyverno/kyverno-envoy-plugin/pkg/json-engine"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/request"
+	"github.com/kyverno/kyverno-json/pkg/policy"
+	"github.com/spf13/cobra"
+	"go.uber.org/multierr"
 	"google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
@@ -26,34 +33,31 @@ type Servers struct {
 }
 
 type (
-	extAuthzServerV3 struct{}
+	extAuthzServerV3 struct {
+		policies []string
+	}
 )
 
-func NewServers() *Servers {
-	return &Servers{
-		grpcV3: &extAuthzServerV3{},
-	}
-}
+var policies []string
 
-func (s *Servers) startHTTPServer(ctx context.Context) {
-	s.httpServer = &http.Server{
-		Addr:    ":8000",
-		Handler: http.HandlerFunc(handler),
-	}
-	fmt.Println("Starting HTTP server on Port 8000")
-	go func() {
-		<-ctx.Done()
+func init() {
+	serveCmd.Flags().StringSliceVar(&policies, "policy", nil, "Path to kyverno-json policies")
+}
 
-		fmt.Println("HTTP server shutting down...")
-		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-		defer cancel()
-		if err := s.httpServer.Shutdown(ctx); err != nil && err != http.ErrServerClosed {
-			log.Fatal("Shutdown HTTP server:", err)
-		}
-	}()
+var serveCmd = &cobra.Command{
+	Use:   "serve",
+	Short: "Start the kyverno-envoy-plugin server",
+	Run: func(cmd *cobra.Command, args []string) {
+		srv := NewServers(policies)
+		startServers(srv)
+	},
+}
 
-	if err := s.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
-		log.Fatal("ListenAndServe: ", err)
+func NewServers(policies []string) *Servers {
+	return &Servers{
+		grpcV3: &extAuthzServerV3{
+			policies: policies,
+		},
 	}
 }
 
@@ -69,20 +73,79 @@ func handler(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *extAuthzServerV3) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.CheckResponse, error) {
+	// Parse request
 	attrs := req.GetAttributes()
 
-	// Print each attribute individually
-	for key, value := range attrs.GetRequest().GetHttp().GetHeaders() {
-		fmt.Printf("Header: %s = %s\n", key, value)
+	// Load policies from files
+	policies, err := policy.Load(s.policies...)
+	if err != nil {
+		log.Printf("Failed to load policies: %v", err)
+		return nil, err
+	}
+
+	resource, err := request.Convert(attrs)
+	if err != nil {
+		log.Printf("Error converting request: %v", err)
+		return nil, err
+	}
+
+	engine := jsonengine.New()
+	response := engine.Run(ctx, jsonengine.Request{
+		Resource: resource,
+		Policies: policies,
+	})
+
+	log.Printf("Request is initialized in kyvernojson engine .\n")
+
+	var violations []error
+
+	for _, policy := range response.Policies {
+		for _, rule := range policy.Rules {
+			if rule.Error != nil {
+				// If there is an error, add it to the violations error array
+				violations = append(violations, fmt.Errorf("%v", rule.Error))
+				log.Printf("Request violation: %v\n", rule.Error.Error())
+			} else if len(rule.Violations) != 0 {
+				// If there are violations, add them to the violations error array
+				for _, violation := range rule.Violations {
+					violations = append(violations, fmt.Errorf("%v", violation))
+				}
+				log.Printf("Request violation: %v\n", rule.Violations.Error())
+			} else {
+				// If the rule passed, log it but continue to the next rule/policy
+				log.Printf("Request passed the %v policy rule.\n", rule.Rule.Name)
+			}
+		}
 	}
-	// Print the entire struct with field names
-	fmt.Printf("Attributes: %+v\n", attrs)
 
-	// Implement your authorization logic here
-	// For now, allow all requests
+	if len(violations) == 0 {
+		return s.allow(), nil
+	} else {
+		// combiine all violations errors into a single error
+		denialReason := multierr.Combine(violations...).Error()
+		return s.deny(denialReason), nil
+	}
+
+}
+
+func (s *extAuthzServerV3) allow() *authv3.CheckResponse {
 	return &authv3.CheckResponse{
 		Status: &status.Status{Code: int32(codes.OK)},
-	}, nil
+	}
+}
+
+func (s *extAuthzServerV3) deny(denialReason string) *authv3.CheckResponse {
+	return &authv3.CheckResponse{
+		Status: &status.Status{
+			Code: int32(codes.PermissionDenied),
+		},
+		HttpResponse: &authv3.CheckResponse_DeniedResponse{
+			DeniedResponse: &authv3.DeniedHttpResponse{
+				Status: &typev3.HttpStatus{Code: typev3.StatusCode_Forbidden},
+				Body:   fmt.Sprintf("Request denied by Kyverno JSON engine. Reason: %s", denialReason),
+			},
+		},
+	}
 }
 
 func (s *Servers) startGRPCServer(ctx context.Context) {
@@ -107,9 +170,30 @@ func (s *Servers) startGRPCServer(ctx context.Context) {
 	}
 }
 
-func main() {
+func (s *Servers) startHTTPServer(ctx context.Context) {
+	s.httpServer = &http.Server{
+		Addr:    ":8000",
+		Handler: http.HandlerFunc(handler),
+	}
+	fmt.Println("Starting HTTP server on Port 8000")
+	go func() {
+		<-ctx.Done()
+
+		fmt.Println("HTTP server shutting down...")
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+		if err := s.httpServer.Shutdown(ctx); err != nil && err != http.ErrServerClosed {
+			log.Fatal("Shutdown HTTP server:", err)
+		}
+	}()
+
+	if err := s.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+		log.Fatal("ListenAndServe: ", err)
+	}
+}
+
+func startServers(srv *Servers) {
 	var group wait.Group
-	srv := NewServers()
 	func() {
 		ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
 		defer cancel()
@@ -119,3 +203,17 @@ func main() {
 	}()
 	group.Wait()
 }
+
+func main() {
+	var rootCmd = &cobra.Command{
+		Use:   "kyverno-envoy-plugin",
+		Short: "kyverno-envoy-plugin is a plugin for Envoy",
+	}
+
+	rootCmd.AddCommand(serveCmd)
+
+	if err := rootCmd.Execute(); err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+}
diff --git a/pkg/binding/binding.go b/pkg/binding/binding.go
new file mode 100644
index 00000000..2d610ba9
--- /dev/null
+++ b/pkg/binding/binding.go
@@ -0,0 +1,17 @@
+package binding
+
+import (
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/assert"
+	"github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+)
+
+func NewContextBindings(bindings binding.Bindings, value any, entries ...v1alpha1.ContextEntry) binding.Bindings {
+	var path *field.Path
+	path = path.Child("context")
+	for i, entry := range entries {
+		bindings = bindings.Register("$"+entry.Name, assert.NewContextBinding(path.Index(i), bindings, value, entry.Variable.Value))
+	}
+	return bindings
+}
diff --git a/pkg/engine/assert/assert.go b/pkg/engine/assert/assert.go
new file mode 100644
index 00000000..d261ddcc
--- /dev/null
+++ b/pkg/engine/assert/assert.go
@@ -0,0 +1,13 @@
+package assert
+
+import (
+	"context"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+)
+
+func Assert(ctx context.Context, path *field.Path, assertion Assertion, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	return assertion.assert(ctx, path, value, bindings, opts...)
+}
diff --git a/pkg/engine/assert/assertion.go b/pkg/engine/assert/assertion.go
new file mode 100644
index 00000000..2d777466
--- /dev/null
+++ b/pkg/engine/assert/assertion.go
@@ -0,0 +1,13 @@
+package assert
+
+import (
+	"context"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+)
+
+type Assertion interface {
+	assert(context.Context, *field.Path, any, binding.Bindings, ...template.Option) (field.ErrorList, error)
+}
diff --git a/pkg/engine/assert/binding.go b/pkg/engine/assert/binding.go
new file mode 100644
index 00000000..44b3fe4d
--- /dev/null
+++ b/pkg/engine/assert/binding.go
@@ -0,0 +1,31 @@
+package assert
+
+import (
+	"context"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+)
+
+func NewContextBinding(path *field.Path, bindings binding.Bindings, value any, entry any) binding.Binding {
+	return template.NewLazyBinding(
+		func() (any, error) {
+			expression := parseExpression(context.TODO(), entry)
+			if expression != nil && expression.engine != "" {
+				if expression.foreach {
+					return nil, field.Invalid(path.Child("variable"), entry, "foreach is not supported in context")
+				}
+				if expression.binding != "" {
+					return nil, field.Invalid(path.Child("variable"), entry, "binding is not supported in context")
+				}
+				projected, err := template.Execute(context.Background(), expression.statement, value, bindings)
+				if err != nil {
+					return nil, field.InternalError(path.Child("variable"), err)
+				}
+				return projected, nil
+			}
+			return entry, nil
+		},
+	)
+}
diff --git a/pkg/engine/assert/expression.go b/pkg/engine/assert/expression.go
new file mode 100644
index 00000000..d0372d1d
--- /dev/null
+++ b/pkg/engine/assert/expression.go
@@ -0,0 +1,65 @@
+package assert
+
+import (
+	"context"
+	"reflect"
+	"regexp"
+
+	reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
+)
+
+var (
+	foreachRegex = regexp.MustCompile(`^~(\w+)?\.(.*)`)
+	bindingRegex = regexp.MustCompile(`(.*)\s*->\s*(\w+)$`)
+	escapeRegex  = regexp.MustCompile(`^\\(.+)\\$`)
+	engineRegex  = regexp.MustCompile(`^\((?:(\w+):)?(.+)\)$`)
+)
+
+type expression struct {
+	foreach     bool
+	foreachName string
+	statement   string
+	binding     string
+	engine      string
+}
+
+func parseExpressionRegex(ctx context.Context, in string) *expression {
+	expression := &expression{}
+	// 1. match foreach
+	if match := foreachRegex.FindStringSubmatch(in); match != nil {
+		expression.foreach = true
+		expression.foreachName = match[1]
+		in = match[2]
+	}
+	// 2. match binding
+	if match := bindingRegex.FindStringSubmatch(in); match != nil {
+		expression.binding = match[2]
+		in = match[1]
+	}
+	// 3. match escape, if there's no escaping then match engine
+	if match := escapeRegex.FindStringSubmatch(in); match != nil {
+		in = match[1]
+	} else {
+		if match := engineRegex.FindStringSubmatch(in); match != nil {
+			expression.engine = match[1]
+			// account for default engine
+			if expression.engine == "" {
+				expression.engine = "jp"
+			}
+			in = match[2]
+		}
+	}
+	// parse statement
+	expression.statement = in
+	if expression.statement == "" {
+		return nil
+	}
+	return expression
+}
+
+func parseExpression(ctx context.Context, value any) *expression {
+	if reflectutils.GetKind(value) != reflect.String {
+		return nil
+	}
+	return parseExpressionRegex(ctx, reflect.ValueOf(value).String())
+}
diff --git a/pkg/engine/assert/parse.go b/pkg/engine/assert/parse.go
new file mode 100644
index 00000000..7226b8f2
--- /dev/null
+++ b/pkg/engine/assert/parse.go
@@ -0,0 +1,174 @@
+package assert
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	jpbinding "github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/match"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+)
+
+func Parse(ctx context.Context, assertion any) Assertion {
+	switch reflectutils.GetKind(assertion) {
+	case reflect.Slice:
+		node := sliceNode{}
+		valueOf := reflect.ValueOf(assertion)
+		for i := 0; i < valueOf.Len(); i++ {
+			node = append(node, Parse(ctx, valueOf.Index(i).Interface()))
+		}
+		return node
+	case reflect.Map:
+		node := mapNode{}
+		iter := reflect.ValueOf(assertion).MapRange()
+		for iter.Next() {
+			node[iter.Key().Interface()] = Parse(ctx, iter.Value().Interface())
+		}
+		return node
+	default:
+		return &scalarNode{rhs: assertion}
+	}
+}
+
+// mapNode is the assertion type represented by a map.
+// it is responsible for projecting the analysed resource and passing the result to the descendant
+type mapNode map[any]Assertion
+
+func (n mapNode) assert(ctx context.Context, path *field.Path, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	var errs field.ErrorList
+	for k, v := range n {
+		projection, err := project(ctx, k, value, bindings, opts...)
+		if err != nil {
+			return nil, field.InternalError(path.Child(fmt.Sprint(k)), err)
+		} else {
+			if projection.binding != "" {
+				bindings = bindings.Register("$"+projection.binding, jpbinding.NewBinding(projection.result))
+			}
+			if projection.foreach {
+				projectedKind := reflectutils.GetKind(projection.result)
+				if projectedKind == reflect.Slice {
+					valueOf := reflect.ValueOf(projection.result)
+					for i := 0; i < valueOf.Len(); i++ {
+						bindings := bindings
+						if projection.foreachName != "" {
+							bindings = bindings.Register("$"+projection.foreachName, jpbinding.NewBinding(i))
+						}
+						if _errs, err := v.assert(ctx, path.Child(fmt.Sprint(k)).Index(i), valueOf.Index(i).Interface(), bindings, opts...); err != nil {
+							return nil, err
+						} else {
+							errs = append(errs, _errs...)
+						}
+					}
+				} else if projectedKind == reflect.Map {
+					iter := reflect.ValueOf(projection.result).MapRange()
+					for iter.Next() {
+						key := iter.Key().Interface()
+						bindings := bindings
+						if projection.foreachName != "" {
+							bindings = bindings.Register("$"+projection.foreachName, jpbinding.NewBinding(key))
+						}
+						if _errs, err := v.assert(ctx, path.Child(fmt.Sprint(k)).Key(fmt.Sprint(key)), iter.Value().Interface(), bindings, opts...); err != nil {
+							return nil, err
+						} else {
+							errs = append(errs, _errs...)
+						}
+					}
+				} else {
+					return nil, field.TypeInvalid(path.Child(fmt.Sprint(k)), projection.result, "expected a slice or a map")
+				}
+			} else {
+				if _errs, err := v.assert(ctx, path.Child(fmt.Sprint(k)), projection.result, bindings, opts...); err != nil {
+					return nil, err
+				} else {
+					errs = append(errs, _errs...)
+				}
+			}
+		}
+	}
+	return errs, nil
+}
+
+// sliceNode is the assertion type represented by a slice.
+// it first compares the length of the analysed resource with the length of the descendants.
+// if lengths match all descendants are evaluated with their corresponding items.
+type sliceNode []Assertion
+
+func (n sliceNode) assert(ctx context.Context, path *field.Path, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	var errs field.ErrorList
+	if value == nil {
+		errs = append(errs, field.Invalid(path, value, "value is null"))
+	} else if reflectutils.GetKind(value) != reflect.Slice {
+		return nil, field.TypeInvalid(path, value, "expected a slice")
+	} else {
+		valueOf := reflect.ValueOf(value)
+		if valueOf.Len() != len(n) {
+			errs = append(errs, field.Invalid(path, value, "lengths of slices don't match"))
+		} else {
+			for i := range n {
+				if _errs, err := n[i].assert(ctx, path.Index(i), valueOf.Index(i).Interface(), bindings, opts...); err != nil {
+					return nil, err
+				} else {
+					errs = append(errs, _errs...)
+				}
+			}
+		}
+	}
+	return errs, nil
+}
+
+// scalarNode is a terminal type of assertion.
+// it receives a value and compares it with an expected value.
+// the expected value can be the result of an expression.
+type scalarNode struct {
+	rhs any
+}
+
+func (n *scalarNode) assert(ctx context.Context, path *field.Path, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	rhs := n.rhs
+	expression := parseExpression(ctx, rhs)
+	// we only project if the expression uses the engine syntax
+	// this is to avoid the case where the value is a map and the RHS is a string
+	if expression != nil && expression.engine != "" {
+		if expression.foreachName != "" {
+			return nil, field.Invalid(path, rhs, "foreach is not supported on the RHS")
+		}
+		if expression.binding != "" {
+			return nil, field.Invalid(path, rhs, "binding is not supported on the RHS")
+		}
+		projected, err := template.Execute(ctx, expression.statement, value, bindings, opts...)
+		if err != nil {
+			return nil, field.InternalError(path, err)
+		}
+		rhs = projected
+	}
+	var errs field.ErrorList
+	if match, err := match.Match(ctx, rhs, value); err != nil {
+		return nil, field.InternalError(path, err)
+	} else if !match {
+		errs = append(errs, field.Invalid(path, value, expectValueMessage(rhs)))
+	}
+	return errs, nil
+}
+
+func expectValueMessage(value any) string {
+	switch t := value.(type) {
+	case int64, int32, float64, float32, bool:
+		// use simple printer for simple types
+		return fmt.Sprintf("Expected value: %v", value)
+	case string:
+		return fmt.Sprintf("Expected value: %q", t)
+	case fmt.Stringer:
+		// anything that defines String() is better than raw struct
+		return fmt.Sprintf("Expected value: %s", t.String())
+	default:
+		// fallback to raw struct
+		// TODO: internal types have panic guards against json.Marshalling to prevent
+		// accidental use of internal types in external serialized form.  For now, use
+		// %#v, although it would be better to show a more expressive output in the future
+		return fmt.Sprintf("Expected value: %#v", value)
+	}
+}
diff --git a/pkg/engine/assert/project.go b/pkg/engine/assert/project.go
new file mode 100644
index 00000000..bfb01089
--- /dev/null
+++ b/pkg/engine/assert/project.go
@@ -0,0 +1,63 @@
+package assert
+
+import (
+	"context"
+	"reflect"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
+)
+
+type projection struct {
+	foreach     bool
+	foreachName string
+	binding     string
+	result      any
+}
+
+func project(ctx context.Context, key any, value any, bindings binding.Bindings, opts ...template.Option) (*projection, error) {
+	expression := parseExpression(ctx, key)
+	if expression != nil {
+		if expression.engine != "" {
+			projected, err := template.Execute(ctx, expression.statement, value, bindings, opts...)
+			if err != nil {
+				return nil, err
+			}
+			return &projection{
+				foreach:     expression.foreach,
+				foreachName: expression.foreachName,
+				binding:     expression.binding,
+				result:      projected,
+			}, nil
+		} else {
+			if reflectutils.GetKind(value) == reflect.Map {
+				mapValue := reflect.ValueOf(value).MapIndex(reflect.ValueOf(expression.statement))
+				var value any
+				if mapValue.IsValid() {
+					value = mapValue.Interface()
+				}
+				return &projection{
+					foreach:     expression.foreach,
+					foreachName: expression.foreachName,
+					binding:     expression.binding,
+					result:      value,
+				}, nil
+			}
+		}
+	}
+	if reflectutils.GetKind(value) == reflect.Map {
+		mapValue := reflect.ValueOf(value).MapIndex(reflect.ValueOf(key))
+		var value any
+		if mapValue.IsValid() {
+			value = mapValue.Interface()
+		}
+		return &projection{
+			result: value,
+		}, nil
+	}
+	// TODO is this an error ?
+	return &projection{
+		result: value,
+	}, nil
+}
diff --git a/pkg/engine/blocks/constant/constant.go b/pkg/engine/blocks/constant/constant.go
new file mode 100644
index 00000000..f8085592
--- /dev/null
+++ b/pkg/engine/blocks/constant/constant.go
@@ -0,0 +1,21 @@
+package constant
+
+import (
+	"context"
+
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine"
+)
+
+type constant[TREQUEST any, TRESPONSE any] struct {
+	response TRESPONSE
+}
+
+func (b *constant[TREQUEST, TRESPONSE]) Run(_ context.Context, _ TREQUEST) TRESPONSE {
+	return b.response
+}
+
+func New[TREQUEST any, TRESPONSE any](response TRESPONSE) engine.Engine[TREQUEST, TRESPONSE] {
+	return &constant[TREQUEST, TRESPONSE]{
+		response: response,
+	}
+}
diff --git a/pkg/engine/blocks/function/function.go b/pkg/engine/blocks/function/function.go
new file mode 100644
index 00000000..800fc341
--- /dev/null
+++ b/pkg/engine/blocks/function/function.go
@@ -0,0 +1,21 @@
+package function
+
+import (
+	"context"
+
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine"
+)
+
+type function[TREQUEST any, TRESPONSE any] struct {
+	function func(context.Context, TREQUEST) TRESPONSE
+}
+
+func (b *function[TREQUEST, TRESPONSE]) Run(ctx context.Context, request TREQUEST) TRESPONSE {
+	return b.function(ctx, request)
+}
+
+func New[TREQUEST any, TRESPONSE any](f func(context.Context, TREQUEST) TRESPONSE) engine.Engine[TREQUEST, TRESPONSE] {
+	return &function[TREQUEST, TRESPONSE]{
+		function: f,
+	}
+}
diff --git a/pkg/engine/builder/builder.go b/pkg/engine/builder/builder.go
new file mode 100644
index 00000000..8ee5524a
--- /dev/null
+++ b/pkg/engine/builder/builder.go
@@ -0,0 +1,25 @@
+package builder
+
+import (
+	"context"
+
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/blocks/constant"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/blocks/function"
+)
+
+type Engine[TREQUEST any, TRESPONSE any] struct {
+	engine.Engine[TREQUEST, TRESPONSE]
+}
+
+func new[TREQUEST any, TRESPONSE any](engine engine.Engine[TREQUEST, TRESPONSE]) Engine[TREQUEST, TRESPONSE] {
+	return Engine[TREQUEST, TRESPONSE]{engine}
+}
+
+func Constant[TREQUEST any, TRESPONSE any](response TRESPONSE) Engine[TREQUEST, TRESPONSE] {
+	return new(constant.New[TREQUEST](response))
+}
+
+func Function[TREQUEST any, TRESPONSE any](f func(context.Context, TREQUEST) TRESPONSE) Engine[TREQUEST, TRESPONSE] {
+	return new(function.New(f))
+}
diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go
new file mode 100644
index 00000000..167b6d8f
--- /dev/null
+++ b/pkg/engine/engine.go
@@ -0,0 +1,13 @@
+package engine
+
+import (
+	"context"
+)
+
+// TODO:
+// - tracing
+// - explain
+
+type Engine[TREQUEST any, TRESPONSE any] interface {
+	Run(context.Context, TREQUEST) TRESPONSE
+}
diff --git a/pkg/engine/match/match.go b/pkg/engine/match/match.go
new file mode 100644
index 00000000..afb21f16
--- /dev/null
+++ b/pkg/engine/match/match.go
@@ -0,0 +1,49 @@
+package match
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+
+	reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
+)
+
+func Match(ctx context.Context, expected, actual any) (bool, error) {
+	if expected != nil {
+		switch reflectutils.GetKind(expected) {
+		case reflect.Slice:
+			if reflectutils.GetKind(actual) != reflect.Slice {
+				return false, fmt.Errorf("invalid actual value, must be a slice, found %s", reflectutils.GetKind(actual))
+			}
+			if reflect.ValueOf(expected).Len() != reflect.ValueOf(actual).Len() {
+				return false, nil
+			}
+			for i := 0; i < reflect.ValueOf(expected).Len(); i++ {
+				if inner, err := Match(ctx, reflect.ValueOf(expected).Index(i).Interface(), reflect.ValueOf(actual).Index(i).Interface()); err != nil {
+					return false, err
+				} else if !inner {
+					return false, nil
+				}
+			}
+			return true, nil
+		case reflect.Map:
+			if reflectutils.GetKind(actual) != reflect.Map {
+				return false, fmt.Errorf("invalid actual value, must be a map, found %s", reflectutils.GetKind(actual))
+			}
+			iter := reflect.ValueOf(expected).MapRange()
+			for iter.Next() {
+				actualValue := reflect.ValueOf(actual).MapIndex(iter.Key())
+				if !actualValue.IsValid() {
+					return false, nil
+				}
+				if inner, err := Match(ctx, iter.Value().Interface(), actualValue.Interface()); err != nil {
+					return false, err
+				} else if !inner {
+					return false, nil
+				}
+			}
+			return true, nil
+		}
+	}
+	return reflectutils.MatchScalar(expected, actual)
+}
diff --git a/pkg/engine/template/binding.go b/pkg/engine/template/binding.go
new file mode 100644
index 00000000..51be6c32
--- /dev/null
+++ b/pkg/engine/template/binding.go
@@ -0,0 +1,38 @@
+package template
+
+import (
+	"sync"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+)
+
+type resolverFunc = func() (any, error)
+
+type lazyBinding struct {
+	resolver resolverFunc
+}
+
+func (b *lazyBinding) Value() (any, error) {
+	return b.resolver()
+}
+
+func NewLazyBinding(resolver resolverFunc) binding.Binding {
+	binding := &lazyBinding{}
+	lock := &sync.Mutex{}
+	binding.resolver = func() (any, error) {
+		lock.Lock()
+		defer lock.Unlock()
+		value, err := resolver()
+		binding.resolver = func() (any, error) {
+			return value, err
+		}
+		return binding.resolver()
+	}
+	return binding
+}
+
+func NewLazyBindingWithValue(value any) binding.Binding {
+	return NewLazyBinding(func() (any, error) {
+		return value, nil
+	})
+}
diff --git a/pkg/engine/template/functions.go b/pkg/engine/template/functions.go
new file mode 100644
index 00000000..9bbcdb11
--- /dev/null
+++ b/pkg/engine/template/functions.go
@@ -0,0 +1,19 @@
+package template
+
+import (
+	"context"
+
+	jpfunctions "github.com/jmespath-community/go-jmespath/pkg/functions"
+	plugin "github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template/functions"
+	"github.com/kyverno/kyverno-json/pkg/engine/template/functions"
+	kyvernofunctions "github.com/kyverno/kyverno-json/pkg/engine/template/kyverno"
+)
+
+func GetFunctions(ctx context.Context) []jpfunctions.FunctionEntry {
+	var funcs []jpfunctions.FunctionEntry
+	funcs = append(funcs, jpfunctions.GetDefaultFunctions()...)
+	funcs = append(funcs, functions.GetFunctions()...)
+	funcs = append(funcs, kyvernofunctions.GetBareFunctions()...)
+	funcs = append(funcs, plugin.GetFunctions()...)
+	return funcs
+}
diff --git a/pkg/functions/error.go b/pkg/engine/template/functions/error.go
similarity index 100%
rename from pkg/functions/error.go
rename to pkg/engine/template/functions/error.go
diff --git a/pkg/functions/functions.go b/pkg/engine/template/functions/functions.go
similarity index 100%
rename from pkg/functions/functions.go
rename to pkg/engine/template/functions/functions.go
diff --git a/pkg/functions/functions_test.go b/pkg/engine/template/functions/functions_test.go
similarity index 100%
rename from pkg/functions/functions_test.go
rename to pkg/engine/template/functions/functions_test.go
diff --git a/pkg/engine/template/options.go b/pkg/engine/template/options.go
new file mode 100644
index 00000000..8062622e
--- /dev/null
+++ b/pkg/engine/template/options.go
@@ -0,0 +1,38 @@
+package template
+
+import (
+	"context"
+
+	"github.com/jmespath-community/go-jmespath/pkg/interpreter"
+)
+
+var (
+	funcs         = GetFunctions(context.Background())
+	defaultCaller = interpreter.NewFunctionCaller(funcs...)
+)
+
+type Option func(options) options
+
+type options struct {
+	functionCaller interpreter.FunctionCaller
+}
+
+func WithFunctionCaller(functionCaller interpreter.FunctionCaller) Option {
+	return func(o options) options {
+		o.functionCaller = functionCaller
+		return o
+	}
+}
+
+func buildOptions(opts ...Option) options {
+	var o options
+	for _, opt := range opts {
+		if opt != nil {
+			o = opt(o)
+		}
+	}
+	if o.functionCaller == nil {
+		o.functionCaller = defaultCaller
+	}
+	return o
+}
diff --git a/pkg/engine/template/template.go b/pkg/engine/template/template.go
new file mode 100644
index 00000000..091d858e
--- /dev/null
+++ b/pkg/engine/template/template.go
@@ -0,0 +1,43 @@
+package template
+
+import (
+	"context"
+	"fmt"
+	"regexp"
+	"strings"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/jmespath-community/go-jmespath/pkg/interpreter"
+	"github.com/jmespath-community/go-jmespath/pkg/parsing"
+)
+
+var variable = regexp.MustCompile(`{{(.*?)}}`)
+
+func String(ctx context.Context, in string, value any, bindings binding.Bindings, opts ...Option) string {
+	groups := variable.FindAllStringSubmatch(in, -1)
+	for _, group := range groups {
+		statement := strings.TrimSpace(group[1])
+		result, err := Execute(ctx, statement, value, bindings, opts...)
+		if err != nil {
+			in = strings.ReplaceAll(in, group[0], fmt.Sprintf("ERR (%s - %s)", statement, err))
+		} else if result == nil {
+			in = strings.ReplaceAll(in, group[0], fmt.Sprintf("ERR (%s not found)", statement))
+		} else if result, ok := result.(string); !ok {
+			in = strings.ReplaceAll(in, group[0], fmt.Sprintf("ERR (%s not a string)", statement))
+		} else {
+			in = strings.ReplaceAll(in, group[0], result)
+		}
+	}
+	return in
+}
+
+func Execute(ctx context.Context, statement string, value any, bindings binding.Bindings, opts ...Option) (any, error) {
+	o := buildOptions(opts...)
+	vm := interpreter.NewInterpreter(nil, bindings)
+	parser := parsing.NewParser()
+	compiled, err := parser.Parse(statement)
+	if err != nil {
+		return nil, err
+	}
+	return vm.Execute(compiled, value, interpreter.WithFunctionCaller(o.functionCaller))
+}
diff --git a/pkg/engine/template/template_test.go b/pkg/engine/template/template_test.go
new file mode 100644
index 00000000..b55f965e
--- /dev/null
+++ b/pkg/engine/template/template_test.go
@@ -0,0 +1,136 @@
+package template
+
+import (
+	"context"
+	"reflect"
+	"testing"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+)
+
+func TestExecute_JWTDecode(t *testing.T) {
+	// Define a valid JWT token and secret key
+	validToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6Imd1ZXN0Iiwic3ViIjoiWVd4cFkyVT0ifQ.ja1bgvIt47393ba_WbSBm35NrUhdxM4mOVQN8iXz8lk"
+
+	// Define an invalid JWT token
+	invalidToken := "invalid.jwt.token"
+
+	tests := []struct {
+		name      string
+		statement string
+		value     any
+		bindings  binding.Bindings
+		opts      []Option
+		expected  any
+		shouldErr bool
+	}{
+		{
+			name:      "Valid JWT token",
+			statement: "jwt_decode(@ , 'secret')",
+			value:     validToken,
+			bindings:  nil,
+			opts:      nil,
+			expected: map[string]interface{}{
+				"header": map[string]interface{}{
+					"alg": "HS256",
+					"typ": "JWT",
+				},
+				"payload": map[string]interface{}{
+					"exp":  2.241081539e+09,
+					"nbf":  1.514851139e+09,
+					"role": "guest",
+					"sub":  "YWxpY2U=",
+				},
+				"sig": "6a61316267764974343733393362615f576253426d33354e72556864784d346d4f56514e3869587a386c6b",
+			},
+			shouldErr: false,
+		},
+		{
+			name:      "Invalid JWT token",
+			statement: "jwt_decode(@, 'secret')",
+			value:     invalidToken,
+			bindings:  nil,
+			opts:      nil,
+			expected:  nil,
+			shouldErr: true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			result, err := Execute(context.Background(), test.statement, test.value, test.bindings, test.opts...)
+			if test.shouldErr && err == nil {
+				t.Errorf("Expected error but got nil")
+			} else if !test.shouldErr && err != nil {
+				t.Errorf("Unexpected error: %v", err)
+			} else if !test.shouldErr && !equalMaps(result.(map[string]interface{}), test.expected.(map[string]interface{})) {
+				t.Errorf("Expected %v, but got %v", test.expected, result)
+			}
+		})
+	}
+}
+
+func TestExecute_JWTDecodepayloadrole(t *testing.T) {
+	// Define a valid JWT token and secret key
+	validToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6Imd1ZXN0Iiwic3ViIjoiWVd4cFkyVT0ifQ.ja1bgvIt47393ba_WbSBm35NrUhdxM4mOVQN8iXz8lk"
+
+	// Define an invalid JWT token
+	invalidToken := "invalid.jwt.token"
+
+	tests := []struct {
+		name      string
+		statement string
+		value     any
+		bindings  binding.Bindings
+		opts      []Option
+		expected  any
+		shouldErr bool
+	}{
+		{
+			name:      "Valid JWT token",
+			statement: "jwt_decode(@ , 'secret').payload.role",
+			value:     validToken,
+			bindings:  nil,
+			opts:      nil,
+			expected:  "guest",
+			shouldErr: false,
+		},
+		{
+			name:      "Invalid JWT token",
+			statement: "jwt_decode(@, 'secret').payload.role",
+			value:     invalidToken,
+			bindings:  nil,
+			opts:      nil,
+			expected:  nil,
+			shouldErr: true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			result, err := Execute(context.Background(), test.statement, test.value, test.bindings, test.opts...)
+			if test.shouldErr && err == nil {
+				t.Errorf("Expected error but got nil")
+			} else if !test.shouldErr && err != nil {
+				t.Errorf("Unexpected error: %v", err)
+			} else if !test.shouldErr && !reflect.DeepEqual(result.(string), test.expected.(string)) {
+				t.Errorf("Expected %v, but got %v", test.expected, result)
+			}
+		})
+	}
+}
+
+func equalMaps(m1, m2 map[string]interface{}) bool {
+	if len(m1) != len(m2) {
+		return false
+	}
+
+	for k, v1 := range m1 {
+		v2, ok := m2[k]
+		if !ok || !reflect.DeepEqual(v1, v2) {
+			return false
+		}
+	}
+
+	return true
+}
diff --git a/pkg/json-engine/engine.go b/pkg/json-engine/engine.go
new file mode 100644
index 00000000..e32187f2
--- /dev/null
+++ b/pkg/json-engine/engine.go
@@ -0,0 +1,146 @@
+package jsonengine
+
+import (
+	"context"
+	"fmt"
+
+	jpbinding "github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/builder"
+	template "github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/matching"
+	"github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
+)
+
+type Request struct {
+	Resource any
+	Policies []*v1alpha1.ValidatingPolicy
+}
+
+type Response struct {
+	Resource any
+	Policies []PolicyResponse
+}
+
+type PolicyResponse struct {
+	Policy *v1alpha1.ValidatingPolicy
+	Rules  []RuleResponse
+}
+
+type RuleResponse struct {
+	Rule       v1alpha1.ValidatingRule
+	Identifier string
+	Error      error
+	Violations matching.Results
+}
+
+// PolicyResult specifies state of a policy result
+type PolicyResult string
+
+const (
+	StatusPass PolicyResult = "pass"
+	StatusFail PolicyResult = "fail"
+	// StatusWarn  PolicyResult = "warn"
+	StatusError PolicyResult = "error"
+	// StatusSkip  PolicyResult = "skip"
+)
+
+func New() engine.Engine[Request, Response] {
+	type ruleRequest struct {
+		rule     v1alpha1.ValidatingRule
+		resource any
+		bindings jpbinding.Bindings
+	}
+	type policyRequest struct {
+		policy   *v1alpha1.ValidatingPolicy
+		resource any
+		bindings jpbinding.Bindings
+	}
+	ruleEngine := builder.
+		Function(func(ctx context.Context, r ruleRequest) []RuleResponse {
+			bindings := r.bindings.Register("$rule", jpbinding.NewBinding(r.rule))
+			bindings = binding.NewContextBindings(bindings, r.resource, r.rule.Context...)
+			identifier := ""
+			if r.rule.Identifier != "" {
+				result, err := template.Execute(context.Background(), r.rule.Identifier, r.resource, bindings)
+				if err != nil {
+					identifier = fmt.Sprintf("(error: %s)", err)
+				} else {
+					identifier = fmt.Sprint(result)
+				}
+			}
+			if r.rule.Match != nil {
+				errs, err := matching.Match(ctx, nil, r.rule.Match, r.resource, bindings)
+				if err != nil {
+					return []RuleResponse{{
+						Rule:       r.rule,
+						Identifier: identifier,
+						Error:      err,
+					}}
+				}
+				// didn't match
+				if len(errs) != 0 {
+					return nil
+				}
+			}
+			if r.rule.Exclude != nil {
+				errs, err := matching.Match(ctx, nil, r.rule.Exclude, r.resource, bindings)
+				if err != nil {
+					return []RuleResponse{{
+						Rule:       r.rule,
+						Identifier: identifier,
+						Error:      err,
+					}}
+				}
+				// matched
+				if len(errs) == 0 {
+					return nil
+				}
+			}
+			violations, err := matching.MatchAssert(ctx, nil, r.rule.Assert, r.resource, bindings)
+			if err != nil {
+				return []RuleResponse{{
+					Rule:       r.rule,
+					Identifier: identifier,
+					Error:      err,
+				}}
+			}
+			return []RuleResponse{{
+				Rule:       r.rule,
+				Identifier: identifier,
+				Violations: violations,
+			}}
+		})
+	policyEngine := builder.
+		Function(func(ctx context.Context, r policyRequest) PolicyResponse {
+			response := PolicyResponse{
+				Policy: r.policy,
+			}
+			bindings := r.bindings.Register("$policy", jpbinding.NewBinding(r.policy))
+			for _, rule := range r.policy.Spec.Rules {
+				response.Rules = append(response.Rules, ruleEngine.Run(ctx, ruleRequest{
+					rule:     rule,
+					resource: r.resource,
+					bindings: bindings.Register("$rule", jpbinding.NewBinding(rule)),
+				})...)
+			}
+			return response
+		})
+	resourceEngine := builder.
+		Function(func(ctx context.Context, r Request) Response {
+			response := Response{
+				Resource: r.Resource,
+			}
+			bindings := jpbinding.NewBindings().Register("$payload", jpbinding.NewBinding(r.Resource))
+			for _, policy := range r.Policies {
+				response.Policies = append(response.Policies, policyEngine.Run(ctx, policyRequest{
+					policy:   policy,
+					resource: r.Resource,
+					bindings: bindings,
+				}))
+			}
+			return response
+		})
+	return resourceEngine
+}
diff --git a/pkg/matching/match.go b/pkg/matching/match.go
new file mode 100644
index 00000000..bbc47341
--- /dev/null
+++ b/pkg/matching/match.go
@@ -0,0 +1,143 @@
+package matching
+
+import (
+	"context"
+	"strings"
+
+	"github.com/jmespath-community/go-jmespath/pkg/binding"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/assert"
+	"github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template"
+	"github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+)
+
+//nolint:errname
+type Result struct {
+	field.ErrorList
+	Message string
+}
+
+func (r Result) Error() string {
+	var lines []string
+	if r.Message != "" {
+		lines = append(lines, "-> "+r.Message)
+	}
+	for _, err := range r.ErrorList {
+		lines = append(lines, " -> "+err.Error())
+	}
+	return strings.Join(lines, "\n")
+}
+
+//nolint:errname
+type Results []Result
+
+func (r Results) Error() string {
+	var lines []string
+	for _, err := range r {
+		lines = append(lines, err.Error())
+	}
+	return strings.Join(lines, "\n")
+}
+
+// func MatchAssert(ctx context.Context, path *field.Path, match *v1alpha1.Assert, actual any, bindings binding.Bindings, opts ...template.Option) ([]error, error) {
+func MatchAssert(ctx context.Context, path *field.Path, match *v1alpha1.Assert, actual any, bindings binding.Bindings, opts ...template.Option) ([]Result, error) {
+	if match == nil || (len(match.Any) == 0 && len(match.All) == 0) {
+		return nil, field.Invalid(path, match, "an empty assert is not valid")
+	} else {
+		if len(match.Any) != 0 {
+			var fails []Result
+			path := path.Child("any")
+			for i, assertion := range match.Any {
+				checkFails, err := assert.Assert(ctx, path.Index(i).Child("check"), assert.Parse(ctx, assertion.Check.Value), actual, bindings, opts...)
+				if err != nil {
+					return fails, err
+				}
+				if len(checkFails) == 0 {
+					fails = nil
+					break
+				}
+				fail := Result{
+					ErrorList: checkFails,
+				}
+				if assertion.Message != "" {
+					fail.Message = template.String(ctx, assertion.Message, actual, bindings, opts...)
+				}
+				fails = append(fails, fail)
+			}
+			if fails != nil {
+				return fails, nil
+			}
+		}
+		if len(match.All) != 0 {
+			var fails []Result
+			path := path.Child("all")
+			for i, assertion := range match.All {
+				checkFails, err := assert.Assert(ctx, path.Index(i).Child("check"), assert.Parse(ctx, assertion.Check.Value), actual, bindings, opts...)
+				if err != nil {
+					return fails, err
+				}
+				if len(checkFails) > 0 {
+					fail := Result{
+						ErrorList: checkFails,
+					}
+					if assertion.Message != "" {
+						fail.Message = template.String(ctx, assertion.Message, actual, bindings, opts...)
+					}
+					fails = append(fails, fail)
+				}
+			}
+			return fails, nil
+		}
+		return nil, nil
+	}
+}
+
+func Match(ctx context.Context, path *field.Path, match *v1alpha1.Match, actual any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	if match == nil || (len(match.Any) == 0 && len(match.All) == 0) {
+		return nil, field.Invalid(path, match, "an empty match is not valid")
+	} else {
+		var errs field.ErrorList
+		if len(match.Any) != 0 {
+			_errs, err := MatchAny(ctx, path.Child("any"), match.Any, actual, bindings, opts...)
+			if err != nil {
+				return errs, err
+			}
+			errs = append(errs, _errs...)
+		}
+		if len(match.All) != 0 {
+			_errs, err := MatchAll(ctx, path.Child("all"), match.All, actual, bindings, opts...)
+			if err != nil {
+				return errs, err
+			}
+			errs = append(errs, _errs...)
+		}
+		return errs, nil
+	}
+}
+
+func MatchAny(ctx context.Context, path *field.Path, assertions []v1alpha1.Any, actual any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	var errs field.ErrorList
+	for i, assertion := range assertions {
+		_errs, err := assert.Assert(ctx, path.Index(i), assert.Parse(ctx, assertion.Value), actual, bindings, opts...)
+		if err != nil {
+			return errs, err
+		}
+		if len(_errs) == 0 {
+			return nil, nil
+		}
+		errs = append(errs, _errs...)
+	}
+	return errs, nil
+}
+
+func MatchAll(ctx context.Context, path *field.Path, assertions []v1alpha1.Any, actual any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
+	var errs field.ErrorList
+	for i, assertion := range assertions {
+		_errs, err := assert.Assert(ctx, path.Index(i), assert.Parse(ctx, assertion.Value), actual, bindings, opts...)
+		if err != nil {
+			return errs, err
+		}
+		errs = append(errs, _errs...)
+	}
+	return errs, nil
+}
diff --git a/pkg/request/request.go b/pkg/request/request.go
new file mode 100644
index 00000000..6bb70545
--- /dev/null
+++ b/pkg/request/request.go
@@ -0,0 +1,33 @@
+package request
+
+import (
+	"encoding/json"
+	"fmt"
+
+	authv3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
+	"google.golang.org/protobuf/encoding/protojson"
+)
+
+// Convert takes an AttributeContext and returns it as an any.
+// It marshals the AttributeContext to JSON and then unmarshals it into an any.
+func Convert(attrs *authv3.AttributeContext) (any, error) {
+	// Create a new Marshaler
+	marshaler := protojson.MarshalOptions{
+		Multiline:    true,
+		Indent:       "  ",
+		AllowPartial: true,
+	}
+
+	// Marshal the AttributeContext to JSON
+	jsonData, err := marshaler.Marshal(attrs)
+	if err != nil {
+		return nil, fmt.Errorf("maarshaling attributes to json failed: %w", err)
+	}
+
+	// Unmarshal the JSON into an any
+	var resource any
+	if err := json.Unmarshal(jsonData, &resource); err != nil {
+		return nil, err
+	}
+	return resource, nil
+}
diff --git a/pkg/scratch/scratch.go b/pkg/scratch/scratch.go
index b50f2dee..97d2ac69 100644
--- a/pkg/scratch/scratch.go
+++ b/pkg/scratch/scratch.go
@@ -7,7 +7,7 @@ import (
 	jpfunctions "github.com/jmespath-community/go-jmespath/pkg/functions"
 	"github.com/jmespath-community/go-jmespath/pkg/interpreter"
 	"github.com/jmespath-community/go-jmespath/pkg/parsing"
-	function "github.com/kyverno/kyverno-envoy-plugin/pkg/functions"
+	function "github.com/kyverno/kyverno-envoy-plugin/pkg/engine/template/functions"
 	"github.com/kyverno/kyverno-json/pkg/engine/template"
 )